From 7929484dbf0f6eda75641f8b965d3ed5fa1fed52 Mon Sep 17 00:00:00 2001 From: Jeremy Joslin Date: Wed, 3 Dec 2014 17:15:28 -0800 Subject: [PATCH] Don't send the same PendingIntent more than once. Fixing a bug where a NetworkRequest's PendingIntent can be sent more than once when networks are rematched before the intent completes. Added a small delay before removing the request to give the receiving client an opportunity to put in its own request. The delay value is configurable via Settings.Secure. Bug: 18614074 Change-Id: Iac7c5e5a04f42f2b6794e9e22349cc631bebeab7 --- core/java/android/provider/Settings.java | 10 +++++++++ .../android/server/ConnectivityService.java | 21 +++++++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 0c036d5117f3c..0062eb2bed4cb 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -4348,6 +4348,16 @@ public final class Settings { public static final String WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS = Global.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS; + /** + * The number of milliseconds to hold on to a PendingIntent based request. This delay gives + * the receivers of the PendingIntent an opportunity to make a new network request before + * the Network satisfying the request is potentially removed. + * + * @hide + */ + public static final String CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS = + "connectivity_release_pending_intent_delay_ms"; + /** * Whether background data usage is allowed. * diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 348aa1bb5c9d3..a110964c0e4bf 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -215,6 +215,10 @@ public class ConnectivityService extends IConnectivityManager.Stub private static final int SAMPLE_INTERVAL_ELAPSED_REQUEST_CODE = 0; + // How long to delay to removal of a pending intent based request. + // See Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS + private final int mReleasePendingIntentDelayMs; + private PendingIntent mSampleIntervalElapsedIntent; // Set network sampling interval at 12 minutes, this way, even if the timers get @@ -645,6 +649,9 @@ public class ConnectivityService extends IConnectivityManager.Stub loge("Error setting defaultDns using " + dns); } + mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(), + Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000); + mContext = checkNotNull(context, "missing Context"); mNetd = checkNotNull(netManager, "missing INetworkManagementService"); mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager"); @@ -3409,6 +3416,7 @@ public class ConnectivityService extends IConnectivityManager.Stub final NetworkRequest request; final PendingIntent mPendingIntent; + boolean mPendingIntentSent; private final IBinder mBinder; final int mPid; final int mUid; @@ -3530,6 +3538,12 @@ public class ConnectivityService extends IConnectivityManager.Stub return networkRequest; } + private void releasePendingNetworkRequestWithDelay(PendingIntent operation) { + mHandler.sendMessageDelayed( + mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT, + getCallingUid(), 0, operation), mReleasePendingIntentDelayMs); + } + @Override public void releasePendingNetworkRequest(PendingIntent operation) { mHandler.sendMessage(mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT, @@ -3843,10 +3857,11 @@ public class ConnectivityService extends IConnectivityManager.Stub private void sendPendingIntentForRequest(NetworkRequestInfo nri, NetworkAgentInfo networkAgent, int notificationType) { - if (notificationType == ConnectivityManager.CALLBACK_AVAILABLE) { + if (notificationType == ConnectivityManager.CALLBACK_AVAILABLE && !nri.mPendingIntentSent) { Intent intent = new Intent(); intent.putExtra(ConnectivityManager.EXTRA_NETWORK, networkAgent.network); intent.putExtra(ConnectivityManager.EXTRA_NETWORK_REQUEST, nri.request); + nri.mPendingIntentSent = true; sendIntent(nri.mPendingIntent, intent); } // else not handled @@ -3870,7 +3885,9 @@ public class ConnectivityService extends IConnectivityManager.Stub String resultData, Bundle resultExtras) { if (DBG) log("Finished sending " + pendingIntent); mPendingIntentWakeLock.release(); - releasePendingNetworkRequest(pendingIntent); + // Release with a delay so the receiving client has an opportunity to put in its + // own request. + releasePendingNetworkRequestWithDelay(pendingIntent); } private void callCallbackForRequest(NetworkRequestInfo nri,