Don't over-acquire NPMS locks.

We only need to hold mNetworkPoliciesSecondLock when working with
subscription plans; before this CL we could end up acquiring the two
NPMS locks out of order, resulting in a deadlock.

Also annotate objects in NSS that require mStatsLock to be held.

Test: builds, boots
Bug: 65268076
Change-Id: I06497564424316ef895dc8dceba72ae784781dc3
This commit is contained in:
Jeff Sharkey
2017-09-01 11:27:13 -06:00
parent 2f0f8f418f
commit 5f1befb42e

View File

@@ -124,6 +124,7 @@ import android.util.SparseIntArray;
import android.util.TrustedTime; import android.util.TrustedTime;
import android.util.proto.ProtoOutputStream; import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.net.VpnInfo; import com.android.internal.net.VpnInfo;
import com.android.internal.util.ArrayUtils; import com.android.internal.util.ArrayUtils;
@@ -241,12 +242,17 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private final DropBoxNonMonotonicObserver mNonMonotonicObserver = private final DropBoxNonMonotonicObserver mNonMonotonicObserver =
new DropBoxNonMonotonicObserver(); new DropBoxNonMonotonicObserver();
@GuardedBy("mStatsLock")
private NetworkStatsRecorder mDevRecorder; private NetworkStatsRecorder mDevRecorder;
@GuardedBy("mStatsLock")
private NetworkStatsRecorder mXtRecorder; private NetworkStatsRecorder mXtRecorder;
@GuardedBy("mStatsLock")
private NetworkStatsRecorder mUidRecorder; private NetworkStatsRecorder mUidRecorder;
@GuardedBy("mStatsLock")
private NetworkStatsRecorder mUidTagRecorder; private NetworkStatsRecorder mUidTagRecorder;
/** Cached {@link #mXtRecorder} stats. */ /** Cached {@link #mXtRecorder} stats. */
@GuardedBy("mStatsLock")
private NetworkStatsCollection mXtStatsCached; private NetworkStatsCollection mXtStatsCached;
/** Current counter sets for each UID. */ /** Current counter sets for each UID. */
@@ -328,15 +334,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
return; return;
} }
synchronized (mStatsLock) {
// create data recorders along with historical rotators // create data recorders along with historical rotators
mDevRecorder = buildRecorder(PREFIX_DEV, mSettings.getDevConfig(), false); mDevRecorder = buildRecorder(PREFIX_DEV, mSettings.getDevConfig(), false);
mXtRecorder = buildRecorder(PREFIX_XT, mSettings.getXtConfig(), false); mXtRecorder = buildRecorder(PREFIX_XT, mSettings.getXtConfig(), false);
mUidRecorder = buildRecorder(PREFIX_UID, mSettings.getUidConfig(), false); mUidRecorder = buildRecorder(PREFIX_UID, mSettings.getUidConfig(), false);
mUidTagRecorder = buildRecorder(PREFIX_UID_TAG, mSettings.getUidTagConfig(), true); mUidTagRecorder = buildRecorder(PREFIX_UID_TAG, mSettings.getUidTagConfig(), true);
updatePersistThresholds(); updatePersistThresholdsLocked();
synchronized (mStatsLock) {
// upgrade any legacy stats, migrating them to rotated files // upgrade any legacy stats, migrating them to rotated files
maybeUpgradeLegacyStatsLocked(); maybeUpgradeLegacyStatsLocked();
@@ -674,10 +680,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
int flags, int fields, @NetworkStatsAccess.Level int accessLevel, int callingUid) { int flags, int fields, @NetworkStatsAccess.Level int accessLevel, int callingUid) {
// We've been using pure XT stats long enough that we no longer need to // We've been using pure XT stats long enough that we no longer need to
// splice DEV and XT together. // splice DEV and XT together.
return mXtStatsCached.getHistory(template, resolveSubscriptionPlan(template, flags), final SubscriptionPlan augmentPlan = resolveSubscriptionPlan(template, flags);
synchronized (mStatsLock) {
return mXtStatsCached.getHistory(template, augmentPlan,
UID_ALL, SET_ALL, TAG_NONE, fields, Long.MIN_VALUE, Long.MAX_VALUE, UID_ALL, SET_ALL, TAG_NONE, fields, Long.MIN_VALUE, Long.MAX_VALUE,
accessLevel, callingUid); accessLevel, callingUid);
} }
}
@Override @Override
public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) { public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
@@ -813,7 +822,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
synchronized (mStatsLock) { synchronized (mStatsLock) {
if (!mSystemReady) return; if (!mSystemReady) return;
updatePersistThresholds(); updatePersistThresholdsLocked();
mDevRecorder.maybePersistLocked(currentTime); mDevRecorder.maybePersistLocked(currentTime);
mXtRecorder.maybePersistLocked(currentTime); mXtRecorder.maybePersistLocked(currentTime);
@@ -869,7 +878,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
* reflect current {@link #mPersistThreshold} value. Always defers to * reflect current {@link #mPersistThreshold} value. Always defers to
* {@link Global} values when defined. * {@link Global} values when defined.
*/ */
private void updatePersistThresholds() { private void updatePersistThresholdsLocked() {
mDevRecorder.setPersistThreshold(mSettings.getDevPersistBytes(mPersistThreshold)); mDevRecorder.setPersistThreshold(mSettings.getDevPersistBytes(mPersistThreshold));
mXtRecorder.setPersistThreshold(mSettings.getXtPersistBytes(mPersistThreshold)); mXtRecorder.setPersistThreshold(mSettings.getXtPersistBytes(mPersistThreshold));
mUidRecorder.setPersistThreshold(mSettings.getUidPersistBytes(mPersistThreshold)); mUidRecorder.setPersistThreshold(mSettings.getUidPersistBytes(mPersistThreshold));
@@ -1311,7 +1320,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
synchronized (mStatsLock) { synchronized (mStatsLock) {
if (args.length > 0 && "--proto".equals(args[0])) { if (args.length > 0 && "--proto".equals(args[0])) {
// In this case ignore all other arguments. // In this case ignore all other arguments.
dumpProto(fd); dumpProtoLocked(fd);
return; return;
} }
@@ -1387,7 +1396,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
} }
} }
private void dumpProto(FileDescriptor fd) { private void dumpProtoLocked(FileDescriptor fd) {
final ProtoOutputStream proto = new ProtoOutputStream(fd); final ProtoOutputStream proto = new ProtoOutputStream(fd);
// TODO Right now it writes all history. Should it limit to the "since-boot" log? // TODO Right now it writes all history. Should it limit to the "since-boot" log?