From 3648f0a35dacfb893f3b2ba835ab37c2973a65af Mon Sep 17 00:00:00 2001 From: lucaslin Date: Wed, 6 May 2020 15:35:54 +0800 Subject: [PATCH] Broadcast ACTION_NETWORK_STATS_UPDATED in NetworkStatsHandler There is a corner case which may cause the deadlock: When NetworkStatsService tried to broadcast the intent, NetworkStatsService was waiting for a lock which was hold by ActivityManagerService. In the same time, ActivityManagerService was waiting for ActiveService#startServiceInnerLocked() to get a lock which was hold by ConnectivityService. ConnectivityService was waiting for a lock which was hold by BatteryStatsImpl. BatteryStatsImpl was waiting for a lock which was hold by NetworkStatsService, and the lock was locked by NetworkStatsService when NetworkStatsService tried to broadcast the intent. To prevent deadlock when broadcasting the intent in performPollLocked(), move the intent broadcasting from performPollLocked() to NetworkStatsHandler. Bug: 150418178 Bug: 155155473 Test: 1. Create the second user and see if the device will do factory reset or not. 2. Factory reset manually and see if there is a deadlock. Change-Id: Icf88d3e7a38562ab15187f6c71bc8fb0486d37c0 --- .../android/server/net/NetworkStatsService.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 34e8f62324..e21a01d204 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -178,6 +178,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // Perform polling, persist network, and register the global alert again. private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 2; private static final int MSG_UPDATE_IFACES = 3; + // A message for broadcasting ACTION_NETWORK_STATS_UPDATED in handler thread to prevent + // deadlock. + private static final int MSG_BROADCAST_NETWORK_STATS_UPDATED = 4; /** Flags to control detail level of poll event. */ private static final int FLAG_PERSIST_NETWORK = 0x1; @@ -386,6 +389,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { registerGlobalAlert(); break; } + case MSG_BROADCAST_NETWORK_STATS_UPDATED: { + final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED); + updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL, + READ_NETWORK_USAGE_HISTORY); + break; + } } } } @@ -1508,10 +1518,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } // finally, dispatch updated event to any listeners - final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED); - updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL, - READ_NETWORK_USAGE_HISTORY); + mHandler.sendMessage(mHandler.obtainMessage(MSG_BROADCAST_NETWORK_STATS_UPDATED)); Trace.traceEnd(TRACE_TAG_NETWORK); }