Loading services/core/java/com/android/server/ConnectivityService.java +22 −22 Original line number Diff line number Diff line Loading @@ -2726,9 +2726,9 @@ public class ConnectivityService extends IConnectivityManager.Stub pw.println(nai.requestAt(i).toString()); } pw.decreaseIndent(); pw.println("Lingered:"); pw.println("Inactivity Timers:"); pw.increaseIndent(); nai.dumpLingerTimers(pw); nai.dumpInactivityTimers(pw); pw.decreaseIndent(); pw.decreaseIndent(); } Loading Loading @@ -3323,27 +3323,27 @@ public class ConnectivityService extends IConnectivityManager.Stub } /** * Updates the linger state from the network requests inside the NAI. * Updates the inactivity state from the network requests inside the NAI. * @param nai the agent info to update * @param now the timestamp of the event causing this update * @return whether the network was lingered as a result of this update * @return whether the network was inactive as a result of this update */ private boolean updateLingerState(@NonNull final NetworkAgentInfo nai, final long now) { // 1. Update the linger timer. If it's changed, reschedule or cancel the alarm. // 2. If the network was lingering and there are now requests, unlinger it. private boolean updateInactivityState(@NonNull final NetworkAgentInfo nai, final long now) { // 1. Update the inactivity timer. If it's changed, reschedule or cancel the alarm. // 2. If the network was inactive and there are now requests, unset inactive. // 3. If this network is unneeded (which implies it is not lingering), and there is at least // one lingered request, start lingering. nai.updateLingerTimer(); // one lingered request, set inactive. nai.updateInactivityTimer(); if (nai.isLingering() && nai.numForegroundNetworkRequests() > 0) { if (DBG) log("Unlingering " + nai.toShortString()); nai.unlinger(); if (DBG) log("Unsetting inactive " + nai.toShortString()); nai.unsetInactive(); logNetworkEvent(nai, NetworkEvent.NETWORK_UNLINGER); } else if (unneeded(nai, UnneededFor.LINGER) && nai.getLingerExpiry() > 0) { } else if (unneeded(nai, UnneededFor.LINGER) && nai.getInactivityExpiry() > 0) { if (DBG) { final int lingerTime = (int) (nai.getLingerExpiry() - now); log("Lingering " + nai.toShortString() + " for " + lingerTime + "ms"); final int lingerTime = (int) (nai.getInactivityExpiry() - now); log("Setting inactive " + nai.toShortString() + " for " + lingerTime + "ms"); } nai.linger(); nai.setInactive(); logNetworkEvent(nai, NetworkEvent.NETWORK_LINGER); return true; } Loading Loading @@ -3481,7 +3481,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } } } nai.clearLingerState(); nai.clearInactivityState(); // TODO: mLegacyTypeTracker.remove seems redundant given there's a full rematch right after. // Currently, deleting it breaks tests that check for the default network disconnecting. // Find out why, fix the rematch code, and delete this. Loading Loading @@ -3823,7 +3823,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // If there are still lingered requests on this network, don't tear it down, // but resume lingering instead. final long now = SystemClock.elapsedRealtime(); if (updateLingerState(nai, now)) { if (updateInactivityState(nai, now)) { notifyNetworkLosing(nai, now); } if (unneeded(nai, UnneededFor.TEARDOWN)) { Loading Loading @@ -7238,7 +7238,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // If we get here it means that the last linger timeout for this network expired. So there // must be no other active linger timers, and we must stop lingering. oldNetwork.clearLingerState(); oldNetwork.clearInactivityState(); if (unneeded(oldNetwork, UnneededFor.TEARDOWN)) { // Tear the network down. Loading Loading @@ -7651,7 +7651,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // if the state has not changed : the source of truth is controlled with // NetworkAgentInfo#lingerRequest and NetworkAgentInfo#unlingerRequest, which have been // called while rematching the individual networks above. if (updateLingerState(nai, now)) { if (updateInactivityState(nai, now)) { lingeredNetworks.add(nai); } } Loading @@ -7678,7 +7678,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // Tear down all unneeded networks. for (NetworkAgentInfo nai : mNetworkAgentInfos) { if (unneeded(nai, UnneededFor.TEARDOWN)) { if (nai.getLingerExpiry() > 0) { if (nai.getInactivityExpiry() > 0) { // This network has active linger timers and no requests, but is not // lingering. Linger it. // Loading @@ -7686,7 +7686,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // and became unneeded due to another network improving its score to the // point where this network will no longer be able to satisfy any requests // even if it validates. if (updateLingerState(nai, now)) { if (updateInactivityState(nai, now)) { notifyNetworkLosing(nai, now); } } else { Loading Loading @@ -7963,7 +7963,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // Notify the requests on this NAI that the network is now lingered. private void notifyNetworkLosing(@NonNull final NetworkAgentInfo nai, final long now) { final int lingerTime = (int) (nai.getLingerExpiry() - now); final int lingerTime = (int) (nai.getInactivityExpiry() - now); notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOSING, lingerTime); } Loading services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +59 −53 Original line number Diff line number Diff line Loading @@ -210,23 +210,23 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { // network is taken down. This usually only happens to the default network. Lingering ends with // either the linger timeout expiring and the network being taken down, or the network // satisfying a request again. public static class LingerTimer implements Comparable<LingerTimer> { public static class InactivityTimer implements Comparable<InactivityTimer> { public final int requestId; public final long expiryMs; public LingerTimer(int requestId, long expiryMs) { public InactivityTimer(int requestId, long expiryMs) { this.requestId = requestId; this.expiryMs = expiryMs; } public boolean equals(Object o) { if (!(o instanceof LingerTimer)) return false; LingerTimer other = (LingerTimer) o; if (!(o instanceof InactivityTimer)) return false; InactivityTimer other = (InactivityTimer) o; return (requestId == other.requestId) && (expiryMs == other.expiryMs); } public int hashCode() { return Objects.hash(requestId, expiryMs); } public int compareTo(LingerTimer other) { public int compareTo(InactivityTimer other) { return (expiryMs != other.expiryMs) ? Long.compare(expiryMs, other.expiryMs) : Integer.compare(requestId, other.requestId); Loading Loading @@ -269,30 +269,31 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { */ public static final int ARG_AGENT_SUCCESS = 1; // All linger timers for this network, sorted by expiry time. A linger timer is added whenever // All inactivity timers for this network, sorted by expiry time. A timer is added whenever // a request is moved to a network with a better score, regardless of whether the network is or // was lingering or not. // TODO: determine if we can replace this with a smaller or unsorted data structure. (e.g., // SparseLongArray) combined with the timestamp of when the last timer is scheduled to fire. private final SortedSet<LingerTimer> mLingerTimers = new TreeSet<>(); private final SortedSet<InactivityTimer> mInactivityTimers = new TreeSet<>(); // For fast lookups. Indexes into mLingerTimers by request ID. private final SparseArray<LingerTimer> mLingerTimerForRequest = new SparseArray<>(); // For fast lookups. Indexes into mInactivityTimers by request ID. private final SparseArray<InactivityTimer> mInactivityTimerForRequest = new SparseArray<>(); // Linger expiry timer. Armed whenever mLingerTimers is non-empty, regardless of whether the // network is lingering or not. Always set to the expiry of the LingerTimer that expires last. // When the timer fires, all linger state is cleared, and if the network has no requests, it is // torn down. private WakeupMessage mLingerMessage; // Inactivity expiry timer. Armed whenever mInactivityTimers is non-empty, regardless of // whether the network is inactive or not. Always set to the expiry of the mInactivityTimers // that expires last. When the timer fires, all inactivity state is cleared, and if the network // has no requests, it is torn down. private WakeupMessage mInactivityMessage; // Linger expiry. Holds the expiry time of the linger timer, or 0 if the timer is not armed. private long mLingerExpiryMs; // Inactivity expiry. Holds the expiry time of the inactivity timer, or 0 if the timer is not // armed. private long mInactivityExpiryMs; // Whether the network is lingering or not. Must be maintained separately from the above because // Whether the network is inactive or not. Must be maintained separately from the above because // it depends on the state of other networks and requests, which only ConnectivityService knows. // (Example: we don't linger a network if it would become the best for a NetworkRequest if it // validated). private boolean mLingering; private boolean mInactive; // This represents the quality of the network with no clear scale. private int mScore; Loading Loading @@ -898,17 +899,17 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { * ConnectivityService when the request is moved to another network with a higher score. */ public void lingerRequest(int requestId, long now, long duration) { if (mLingerTimerForRequest.get(requestId) != null) { if (mInactivityTimerForRequest.get(requestId) != null) { // Cannot happen. Once a request is lingering on a particular network, we cannot // re-linger it unless that network becomes the best for that request again, in which // case we should have unlingered it. Log.wtf(TAG, toShortString() + ": request " + requestId + " already lingered"); } final long expiryMs = now + duration; LingerTimer timer = new LingerTimer(requestId, expiryMs); if (VDBG) Log.d(TAG, "Adding LingerTimer " + timer + " to " + toShortString()); mLingerTimers.add(timer); mLingerTimerForRequest.put(requestId, timer); InactivityTimer timer = new InactivityTimer(requestId, expiryMs); if (VDBG) Log.d(TAG, "Adding InactivityTimer " + timer + " to " + toShortString()); mInactivityTimers.add(timer); mInactivityTimerForRequest.put(requestId, timer); } /** Loading @@ -916,23 +917,25 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { * Returns true if the given requestId was lingering on this network, false otherwise. */ public boolean unlingerRequest(int requestId) { LingerTimer timer = mLingerTimerForRequest.get(requestId); InactivityTimer timer = mInactivityTimerForRequest.get(requestId); if (timer != null) { if (VDBG) Log.d(TAG, "Removing LingerTimer " + timer + " from " + toShortString()); mLingerTimers.remove(timer); mLingerTimerForRequest.remove(requestId); if (VDBG) { Log.d(TAG, "Removing InactivityTimer " + timer + " from " + toShortString()); } mInactivityTimers.remove(timer); mInactivityTimerForRequest.remove(requestId); return true; } return false; } public long getLingerExpiry() { return mLingerExpiryMs; public long getInactivityExpiry() { return mInactivityExpiryMs; } public void updateLingerTimer() { long newExpiry = mLingerTimers.isEmpty() ? 0 : mLingerTimers.last().expiryMs; if (newExpiry == mLingerExpiryMs) return; public void updateInactivityTimer() { long newExpiry = mInactivityTimers.isEmpty() ? 0 : mInactivityTimers.last().expiryMs; if (newExpiry == mInactivityExpiryMs) return; // Even if we're going to reschedule the timer, cancel it first. This is because the // semantics of WakeupMessage guarantee that if cancel is called then the alarm will Loading @@ -940,49 +943,52 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { // WakeupMessage makes no such guarantees about rescheduling a message, so if mLingerMessage // has already been dispatched, rescheduling to some time in the future won't stop it // from calling its callback immediately. if (mLingerMessage != null) { mLingerMessage.cancel(); mLingerMessage = null; if (mInactivityMessage != null) { mInactivityMessage.cancel(); mInactivityMessage = null; } if (newExpiry > 0) { mLingerMessage = new WakeupMessage( mInactivityMessage = new WakeupMessage( mContext, mHandler, "NETWORK_LINGER_COMPLETE." + network.getNetId() /* cmdName */, EVENT_NETWORK_LINGER_COMPLETE /* cmd */, 0 /* arg1 (unused) */, 0 /* arg2 (unused) */, this /* obj (NetworkAgentInfo) */); mLingerMessage.schedule(newExpiry); mInactivityMessage.schedule(newExpiry); } mLingerExpiryMs = newExpiry; mInactivityExpiryMs = newExpiry; } public void linger() { mLingering = true; public void setInactive() { mInactive = true; } public void unlinger() { mLingering = false; public void unsetInactive() { mInactive = false; } public boolean isLingering() { return mLingering; return mInactive; } public void clearLingerState() { if (mLingerMessage != null) { mLingerMessage.cancel(); mLingerMessage = null; public void clearInactivityState() { if (mInactivityMessage != null) { mInactivityMessage.cancel(); mInactivityMessage = null; } mLingerTimers.clear(); mLingerTimerForRequest.clear(); updateLingerTimer(); // Sets mLingerExpiryMs, cancels and nulls out mLingerMessage. mLingering = false; mInactivityTimers.clear(); mInactivityTimerForRequest.clear(); // Sets mInactivityExpiryMs, cancels and nulls out mInactivityMessage. updateInactivityTimer(); mInactive = false; } public void dumpLingerTimers(PrintWriter pw) { for (LingerTimer timer : mLingerTimers) { pw.println(timer); } public void dumpInactivityTimers(PrintWriter pw) { for (InactivityTimer timer : mInactivityTimers) { pw.println(timer); } } /** Loading Loading
services/core/java/com/android/server/ConnectivityService.java +22 −22 Original line number Diff line number Diff line Loading @@ -2726,9 +2726,9 @@ public class ConnectivityService extends IConnectivityManager.Stub pw.println(nai.requestAt(i).toString()); } pw.decreaseIndent(); pw.println("Lingered:"); pw.println("Inactivity Timers:"); pw.increaseIndent(); nai.dumpLingerTimers(pw); nai.dumpInactivityTimers(pw); pw.decreaseIndent(); pw.decreaseIndent(); } Loading Loading @@ -3323,27 +3323,27 @@ public class ConnectivityService extends IConnectivityManager.Stub } /** * Updates the linger state from the network requests inside the NAI. * Updates the inactivity state from the network requests inside the NAI. * @param nai the agent info to update * @param now the timestamp of the event causing this update * @return whether the network was lingered as a result of this update * @return whether the network was inactive as a result of this update */ private boolean updateLingerState(@NonNull final NetworkAgentInfo nai, final long now) { // 1. Update the linger timer. If it's changed, reschedule or cancel the alarm. // 2. If the network was lingering and there are now requests, unlinger it. private boolean updateInactivityState(@NonNull final NetworkAgentInfo nai, final long now) { // 1. Update the inactivity timer. If it's changed, reschedule or cancel the alarm. // 2. If the network was inactive and there are now requests, unset inactive. // 3. If this network is unneeded (which implies it is not lingering), and there is at least // one lingered request, start lingering. nai.updateLingerTimer(); // one lingered request, set inactive. nai.updateInactivityTimer(); if (nai.isLingering() && nai.numForegroundNetworkRequests() > 0) { if (DBG) log("Unlingering " + nai.toShortString()); nai.unlinger(); if (DBG) log("Unsetting inactive " + nai.toShortString()); nai.unsetInactive(); logNetworkEvent(nai, NetworkEvent.NETWORK_UNLINGER); } else if (unneeded(nai, UnneededFor.LINGER) && nai.getLingerExpiry() > 0) { } else if (unneeded(nai, UnneededFor.LINGER) && nai.getInactivityExpiry() > 0) { if (DBG) { final int lingerTime = (int) (nai.getLingerExpiry() - now); log("Lingering " + nai.toShortString() + " for " + lingerTime + "ms"); final int lingerTime = (int) (nai.getInactivityExpiry() - now); log("Setting inactive " + nai.toShortString() + " for " + lingerTime + "ms"); } nai.linger(); nai.setInactive(); logNetworkEvent(nai, NetworkEvent.NETWORK_LINGER); return true; } Loading Loading @@ -3481,7 +3481,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } } } nai.clearLingerState(); nai.clearInactivityState(); // TODO: mLegacyTypeTracker.remove seems redundant given there's a full rematch right after. // Currently, deleting it breaks tests that check for the default network disconnecting. // Find out why, fix the rematch code, and delete this. Loading Loading @@ -3823,7 +3823,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // If there are still lingered requests on this network, don't tear it down, // but resume lingering instead. final long now = SystemClock.elapsedRealtime(); if (updateLingerState(nai, now)) { if (updateInactivityState(nai, now)) { notifyNetworkLosing(nai, now); } if (unneeded(nai, UnneededFor.TEARDOWN)) { Loading Loading @@ -7238,7 +7238,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // If we get here it means that the last linger timeout for this network expired. So there // must be no other active linger timers, and we must stop lingering. oldNetwork.clearLingerState(); oldNetwork.clearInactivityState(); if (unneeded(oldNetwork, UnneededFor.TEARDOWN)) { // Tear the network down. Loading Loading @@ -7651,7 +7651,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // if the state has not changed : the source of truth is controlled with // NetworkAgentInfo#lingerRequest and NetworkAgentInfo#unlingerRequest, which have been // called while rematching the individual networks above. if (updateLingerState(nai, now)) { if (updateInactivityState(nai, now)) { lingeredNetworks.add(nai); } } Loading @@ -7678,7 +7678,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // Tear down all unneeded networks. for (NetworkAgentInfo nai : mNetworkAgentInfos) { if (unneeded(nai, UnneededFor.TEARDOWN)) { if (nai.getLingerExpiry() > 0) { if (nai.getInactivityExpiry() > 0) { // This network has active linger timers and no requests, but is not // lingering. Linger it. // Loading @@ -7686,7 +7686,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // and became unneeded due to another network improving its score to the // point where this network will no longer be able to satisfy any requests // even if it validates. if (updateLingerState(nai, now)) { if (updateInactivityState(nai, now)) { notifyNetworkLosing(nai, now); } } else { Loading Loading @@ -7963,7 +7963,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // Notify the requests on this NAI that the network is now lingered. private void notifyNetworkLosing(@NonNull final NetworkAgentInfo nai, final long now) { final int lingerTime = (int) (nai.getLingerExpiry() - now); final int lingerTime = (int) (nai.getInactivityExpiry() - now); notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOSING, lingerTime); } Loading
services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +59 −53 Original line number Diff line number Diff line Loading @@ -210,23 +210,23 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { // network is taken down. This usually only happens to the default network. Lingering ends with // either the linger timeout expiring and the network being taken down, or the network // satisfying a request again. public static class LingerTimer implements Comparable<LingerTimer> { public static class InactivityTimer implements Comparable<InactivityTimer> { public final int requestId; public final long expiryMs; public LingerTimer(int requestId, long expiryMs) { public InactivityTimer(int requestId, long expiryMs) { this.requestId = requestId; this.expiryMs = expiryMs; } public boolean equals(Object o) { if (!(o instanceof LingerTimer)) return false; LingerTimer other = (LingerTimer) o; if (!(o instanceof InactivityTimer)) return false; InactivityTimer other = (InactivityTimer) o; return (requestId == other.requestId) && (expiryMs == other.expiryMs); } public int hashCode() { return Objects.hash(requestId, expiryMs); } public int compareTo(LingerTimer other) { public int compareTo(InactivityTimer other) { return (expiryMs != other.expiryMs) ? Long.compare(expiryMs, other.expiryMs) : Integer.compare(requestId, other.requestId); Loading Loading @@ -269,30 +269,31 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { */ public static final int ARG_AGENT_SUCCESS = 1; // All linger timers for this network, sorted by expiry time. A linger timer is added whenever // All inactivity timers for this network, sorted by expiry time. A timer is added whenever // a request is moved to a network with a better score, regardless of whether the network is or // was lingering or not. // TODO: determine if we can replace this with a smaller or unsorted data structure. (e.g., // SparseLongArray) combined with the timestamp of when the last timer is scheduled to fire. private final SortedSet<LingerTimer> mLingerTimers = new TreeSet<>(); private final SortedSet<InactivityTimer> mInactivityTimers = new TreeSet<>(); // For fast lookups. Indexes into mLingerTimers by request ID. private final SparseArray<LingerTimer> mLingerTimerForRequest = new SparseArray<>(); // For fast lookups. Indexes into mInactivityTimers by request ID. private final SparseArray<InactivityTimer> mInactivityTimerForRequest = new SparseArray<>(); // Linger expiry timer. Armed whenever mLingerTimers is non-empty, regardless of whether the // network is lingering or not. Always set to the expiry of the LingerTimer that expires last. // When the timer fires, all linger state is cleared, and if the network has no requests, it is // torn down. private WakeupMessage mLingerMessage; // Inactivity expiry timer. Armed whenever mInactivityTimers is non-empty, regardless of // whether the network is inactive or not. Always set to the expiry of the mInactivityTimers // that expires last. When the timer fires, all inactivity state is cleared, and if the network // has no requests, it is torn down. private WakeupMessage mInactivityMessage; // Linger expiry. Holds the expiry time of the linger timer, or 0 if the timer is not armed. private long mLingerExpiryMs; // Inactivity expiry. Holds the expiry time of the inactivity timer, or 0 if the timer is not // armed. private long mInactivityExpiryMs; // Whether the network is lingering or not. Must be maintained separately from the above because // Whether the network is inactive or not. Must be maintained separately from the above because // it depends on the state of other networks and requests, which only ConnectivityService knows. // (Example: we don't linger a network if it would become the best for a NetworkRequest if it // validated). private boolean mLingering; private boolean mInactive; // This represents the quality of the network with no clear scale. private int mScore; Loading Loading @@ -898,17 +899,17 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { * ConnectivityService when the request is moved to another network with a higher score. */ public void lingerRequest(int requestId, long now, long duration) { if (mLingerTimerForRequest.get(requestId) != null) { if (mInactivityTimerForRequest.get(requestId) != null) { // Cannot happen. Once a request is lingering on a particular network, we cannot // re-linger it unless that network becomes the best for that request again, in which // case we should have unlingered it. Log.wtf(TAG, toShortString() + ": request " + requestId + " already lingered"); } final long expiryMs = now + duration; LingerTimer timer = new LingerTimer(requestId, expiryMs); if (VDBG) Log.d(TAG, "Adding LingerTimer " + timer + " to " + toShortString()); mLingerTimers.add(timer); mLingerTimerForRequest.put(requestId, timer); InactivityTimer timer = new InactivityTimer(requestId, expiryMs); if (VDBG) Log.d(TAG, "Adding InactivityTimer " + timer + " to " + toShortString()); mInactivityTimers.add(timer); mInactivityTimerForRequest.put(requestId, timer); } /** Loading @@ -916,23 +917,25 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { * Returns true if the given requestId was lingering on this network, false otherwise. */ public boolean unlingerRequest(int requestId) { LingerTimer timer = mLingerTimerForRequest.get(requestId); InactivityTimer timer = mInactivityTimerForRequest.get(requestId); if (timer != null) { if (VDBG) Log.d(TAG, "Removing LingerTimer " + timer + " from " + toShortString()); mLingerTimers.remove(timer); mLingerTimerForRequest.remove(requestId); if (VDBG) { Log.d(TAG, "Removing InactivityTimer " + timer + " from " + toShortString()); } mInactivityTimers.remove(timer); mInactivityTimerForRequest.remove(requestId); return true; } return false; } public long getLingerExpiry() { return mLingerExpiryMs; public long getInactivityExpiry() { return mInactivityExpiryMs; } public void updateLingerTimer() { long newExpiry = mLingerTimers.isEmpty() ? 0 : mLingerTimers.last().expiryMs; if (newExpiry == mLingerExpiryMs) return; public void updateInactivityTimer() { long newExpiry = mInactivityTimers.isEmpty() ? 0 : mInactivityTimers.last().expiryMs; if (newExpiry == mInactivityExpiryMs) return; // Even if we're going to reschedule the timer, cancel it first. This is because the // semantics of WakeupMessage guarantee that if cancel is called then the alarm will Loading @@ -940,49 +943,52 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { // WakeupMessage makes no such guarantees about rescheduling a message, so if mLingerMessage // has already been dispatched, rescheduling to some time in the future won't stop it // from calling its callback immediately. if (mLingerMessage != null) { mLingerMessage.cancel(); mLingerMessage = null; if (mInactivityMessage != null) { mInactivityMessage.cancel(); mInactivityMessage = null; } if (newExpiry > 0) { mLingerMessage = new WakeupMessage( mInactivityMessage = new WakeupMessage( mContext, mHandler, "NETWORK_LINGER_COMPLETE." + network.getNetId() /* cmdName */, EVENT_NETWORK_LINGER_COMPLETE /* cmd */, 0 /* arg1 (unused) */, 0 /* arg2 (unused) */, this /* obj (NetworkAgentInfo) */); mLingerMessage.schedule(newExpiry); mInactivityMessage.schedule(newExpiry); } mLingerExpiryMs = newExpiry; mInactivityExpiryMs = newExpiry; } public void linger() { mLingering = true; public void setInactive() { mInactive = true; } public void unlinger() { mLingering = false; public void unsetInactive() { mInactive = false; } public boolean isLingering() { return mLingering; return mInactive; } public void clearLingerState() { if (mLingerMessage != null) { mLingerMessage.cancel(); mLingerMessage = null; public void clearInactivityState() { if (mInactivityMessage != null) { mInactivityMessage.cancel(); mInactivityMessage = null; } mLingerTimers.clear(); mLingerTimerForRequest.clear(); updateLingerTimer(); // Sets mLingerExpiryMs, cancels and nulls out mLingerMessage. mLingering = false; mInactivityTimers.clear(); mInactivityTimerForRequest.clear(); // Sets mInactivityExpiryMs, cancels and nulls out mInactivityMessage. updateInactivityTimer(); mInactive = false; } public void dumpLingerTimers(PrintWriter pw) { for (LingerTimer timer : mLingerTimers) { pw.println(timer); } public void dumpInactivityTimers(PrintWriter pw) { for (InactivityTimer timer : mInactivityTimers) { pw.println(timer); } } /** Loading