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
This commit is contained in:
lucaslin
2020-05-06 15:35:54 +08:00
committed by Lucas Lin
parent 53c97ec4cf
commit 3648f0a35d

View File

@@ -178,6 +178,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
// Perform polling, persist network, and register the global alert again. // 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_PERFORM_POLL_REGISTER_ALERT = 2;
private static final int MSG_UPDATE_IFACES = 3; 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. */ /** Flags to control detail level of poll event. */
private static final int FLAG_PERSIST_NETWORK = 0x1; private static final int FLAG_PERSIST_NETWORK = 0x1;
@@ -386,6 +389,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
registerGlobalAlert(); registerGlobalAlert();
break; 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 // finally, dispatch updated event to any listeners
final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED); mHandler.sendMessage(mHandler.obtainMessage(MSG_BROADCAST_NETWORK_STATS_UPDATED));
updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL,
READ_NETWORK_USAGE_HISTORY);
Trace.traceEnd(TRACE_TAG_NETWORK); Trace.traceEnd(TRACE_TAG_NETWORK);
} }