From 471b62a6b8b3bc3b52dc1b95f1afb152bd6df1c1 Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Thu, 30 Mar 2017 23:18:10 +0900 Subject: [PATCH] ConnectivityService: simplify WakeLock management This patch simplifies wakelock management by acknowledging that only one acquisition at most is in flight at any time. This allows to remove the serial number associated with wakelock acquisition and to avoid double release when regaining a default network. Example of $ adb shell dumpsys connectivity logs: NetTransition WakeLock activity (most recent first): 03-31 00:15:13.816 - RELEASE (EVENT_CLEAR_NET_TRANSITION_WAKELOCK) 03-31 00:14:59.216 - ACQUIRE for NetworkAgentInfo [WIFI () - 101] 03-31 00:09:05.799 - RELEASE (EVENT_EXPIRE_NET_TRANSITION_WAKELOCK) 03-31 00:08:05.738 - ACQUIRE for NetworkAgentInfo [WIFI () - 100] Test: watched wakelock section $ adb shell dumpsys connectivity while turning on and off Wifi (with no other network). Bug: 36703718 Change-Id: I899b0816c0e41b3991d9540e9b9a604914ff673a --- .../android/server/ConnectivityService.java | 78 +++++++++---------- 1 file changed, 35 insertions(+), 43 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 13a6cd6300..d325ea7a97 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -411,7 +411,6 @@ public class ConnectivityService extends IConnectivityManager.Stub private Intent mInitialBroadcast; private PowerManager.WakeLock mNetTransitionWakeLock; - private int mNetTransitionWakeLockSerialNumber; private int mNetTransitionWakeLockTimeout; private final PowerManager.WakeLock mPendingIntentWakeLock; @@ -2395,7 +2394,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (nai.isSatisfyingRequest(mDefaultRequest.requestId)) { removeDataActivityTracking(nai); notifyLockdownVpn(nai); - requestNetworkTransitionWakelock(nai.name()); + ensureNetworkTransitionWakelock(nai.name()); } mLegacyTypeTracker.remove(nai, wasDefault); rematchAllNetworksAndRequests(null, 0); @@ -2842,7 +2841,7 @@ public class ConnectivityService extends IConnectivityManager.Stub switch (msg.what) { case EVENT_EXPIRE_NET_TRANSITION_WAKELOCK: case EVENT_CLEAR_NET_TRANSITION_WAKELOCK: { - handleNetworkTransitionWakelockRelease(msg.what, msg.arg1); + handleReleaseNetworkTransitionWakelock(msg.what); break; } case EVENT_APPLY_GLOBAL_HTTP_PROXY: { @@ -3065,44 +3064,46 @@ public class ConnectivityService extends IConnectivityManager.Stub // This will automatically be cleared after X seconds or a new default network // becomes CONNECTED, whichever happens first. The timer is started by the // first caller and not restarted by subsequent callers. - private void requestNetworkTransitionWakelock(String forWhom) { - int serialNum = 0; + private void ensureNetworkTransitionWakelock(String forWhom) { synchronized (this) { - if (mNetTransitionWakeLock.isHeld()) return; - serialNum = ++mNetTransitionWakeLockSerialNumber; + if (mNetTransitionWakeLock.isHeld()) { + return; + } mNetTransitionWakeLock.acquire(); - mWakelockLogs.log(String.format("ACQUIRE %d for %s", serialNum, forWhom)); } - mHandler.sendMessageDelayed(mHandler.obtainMessage( - EVENT_EXPIRE_NET_TRANSITION_WAKELOCK, serialNum, 0), - mNetTransitionWakeLockTimeout); - return; + mWakelockLogs.log("ACQUIRE for " + forWhom); + Message msg = mHandler.obtainMessage(EVENT_EXPIRE_NET_TRANSITION_WAKELOCK); + mHandler.sendMessageDelayed(msg, mNetTransitionWakeLockTimeout); } - private void handleNetworkTransitionWakelockRelease(int eventId, int wantSerialNumber) { - final int serialNumber; - final boolean isHeld; - final boolean release; + // Called when we gain a new default network to release the network transition wakelock in a + // second, to allow a grace period for apps to reconnect over the new network. Pending expiry + // message is cancelled. + private void scheduleReleaseNetworkTransitionWakelock() { synchronized (this) { - serialNumber = mNetTransitionWakeLockSerialNumber; - isHeld = mNetTransitionWakeLock.isHeld(); - release = (wantSerialNumber == serialNumber) && isHeld; - if (release) { - mNetTransitionWakeLock.release(); + if (!mNetTransitionWakeLock.isHeld()) { + return; // expiry message released the lock first. } } - final String result; - if (release) { - result = "released"; - } else if (!isHeld) { - result = "already released"; - } else { - result = String.format("not released (serial number was %d)", serialNumber); + // Cancel self timeout on wakelock hold. + mHandler.removeMessages(EVENT_EXPIRE_NET_TRANSITION_WAKELOCK); + Message msg = mHandler.obtainMessage(EVENT_CLEAR_NET_TRANSITION_WAKELOCK); + mHandler.sendMessageDelayed(msg, 1000); + } + + // Called when either message of ensureNetworkTransitionWakelock or + // scheduleReleaseNetworkTransitionWakelock is processed. + private void handleReleaseNetworkTransitionWakelock(int eventId) { + String event = eventName(eventId); + synchronized (this) { + if (!mNetTransitionWakeLock.isHeld()) { + mWakelockLogs.log(String.format("RELEASE: already released (%s)", event)); + Slog.w(TAG, "expected Net Transition WakeLock to be held"); + return; + } + mNetTransitionWakeLock.release(); } - String msg = String.format( - "RELEASE %d by %s: %s", wantSerialNumber, eventName(eventId), result); - mWakelockLogs.log(msg); - if (DBG) log(msg); + mWakelockLogs.log(String.format("RELEASE (%s)", event)); } // 100 percent is full good, 0 is full bad. @@ -4925,17 +4926,8 @@ public class ConnectivityService extends IConnectivityManager.Stub makeDefault(newNetwork); // Log 0 -> X and Y -> X default network transitions, where X is the new default. logDefaultNetworkEvent(newNetwork, oldDefaultNetwork); - synchronized (ConnectivityService.this) { - // have a new default network, release the transition wakelock in - // a second if it's held. The second pause is to allow apps - // to reconnect over the new network - if (mNetTransitionWakeLock.isHeld()) { - mHandler.sendMessageDelayed(mHandler.obtainMessage( - EVENT_CLEAR_NET_TRANSITION_WAKELOCK, - mNetTransitionWakeLockSerialNumber, 0), - 1000); - } - } + // Have a new default network, release the transition wakelock in + scheduleReleaseNetworkTransitionWakelock(); } if (!newNetwork.networkCapabilities.equalRequestableCapabilities(nc)) {