diff options
4 files changed, 93 insertions, 22 deletions
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 5c11100f3417..25c96d14e9ad 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -71,7 +71,6 @@ import android.net.ProxyInfo; import android.net.RouteInfo; import android.net.UidRange; import android.net.Uri; -import android.net.metrics.DefaultNetworkEvent; import android.net.metrics.IpConnectivityLog; import android.net.metrics.NetworkEvent; import android.net.util.MultinetworkPolicyTracker; @@ -129,6 +128,7 @@ import com.android.internal.util.XmlUtils; import com.android.server.LocalServices; import com.android.server.am.BatteryStatsService; import com.android.server.connectivity.DataConnectionStats; +import com.android.server.connectivity.IpConnectivityMetrics; import com.android.server.connectivity.KeepaliveTracker; import com.android.server.connectivity.LingerMonitor; import com.android.server.connectivity.MockableSystemProperties; @@ -2283,7 +2283,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // Let rematchAllNetworksAndRequests() below record a new default network event // if there is a fallback. Taken together, the two form a X -> 0, 0 -> Y sequence // whose timestamps tell how long it takes to recover a default network. - logDefaultNetworkEvent(null, nai); + metricsLogger().defaultNetworkMetrics().logDefaultNetworkEvent(null, nai); } notifyIfacesChangedForNetworkStats(); // TODO - we shouldn't send CALLBACK_LOST to requests that can be satisfied @@ -5012,7 +5012,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // Notify system services that this network is up. makeDefault(newNetwork); // Log 0 -> X and Y -> X default network transitions, where X is the new default. - logDefaultNetworkEvent(newNetwork, oldDefaultNetwork); + metricsLogger().defaultNetworkMetrics().logDefaultNetworkEvent( + newNetwork, oldDefaultNetwork); // Have a new default network, release the transition wakelock in scheduleReleaseNetworkTransitionWakelock(); } @@ -5571,25 +5572,10 @@ public class ConnectivityService extends IConnectivityManager.Stub return ServiceManager.checkService(name) != null; } - private void logDefaultNetworkEvent(NetworkAgentInfo newNai, NetworkAgentInfo prevNai) { - int newNetid = NETID_UNSET; - int prevNetid = NETID_UNSET; - int[] transports = new int[0]; - boolean hadIPv4 = false; - boolean hadIPv6 = false; - - if (newNai != null) { - newNetid = newNai.network.netId; - transports = newNai.networkCapabilities.getTransportTypes(); - } - if (prevNai != null) { - prevNetid = prevNai.network.netId; - final LinkProperties lp = prevNai.linkProperties; - hadIPv4 = lp.hasIPv4Address() && lp.hasIPv4DefaultRoute(); - hadIPv6 = lp.hasGlobalIPv6Address() && lp.hasIPv6DefaultRoute(); - } - - mMetricsLog.log(new DefaultNetworkEvent(newNetid, transports, prevNetid, hadIPv4, hadIPv6)); + @VisibleForTesting + protected IpConnectivityMetrics.Logger metricsLogger() { + return checkNotNull(LocalServices.getService(IpConnectivityMetrics.Logger.class), + "no IpConnectivityMetrics service"); } private void logNetworkEvent(NetworkAgentInfo nai, int evtype) { diff --git a/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java b/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java new file mode 100644 index 000000000000..c7c00bb3b670 --- /dev/null +++ b/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.connectivity; + +import static android.net.ConnectivityManager.NETID_UNSET; + +import android.net.LinkProperties; +import android.net.metrics.DefaultNetworkEvent; +import android.net.metrics.IpConnectivityLog; + +/** + * Tracks events related to the default network for the purpose of default network metrics. + * {@hide} + */ +public class DefaultNetworkMetrics { + + private final IpConnectivityLog mMetricsLog = new IpConnectivityLog(); + + public void logDefaultNetworkEvent(NetworkAgentInfo newNai, NetworkAgentInfo prevNai) { + int newNetid = NETID_UNSET; + int prevNetid = NETID_UNSET; + int[] transports = new int[0]; + boolean hadIPv4 = false; + boolean hadIPv6 = false; + + if (newNai != null) { + newNetid = newNai.network.netId; + transports = newNai.networkCapabilities.getTransportTypes(); + } + if (prevNai != null) { + prevNetid = prevNai.network.netId; + final LinkProperties lp = prevNai.linkProperties; + hadIPv4 = lp.hasIPv4Address() && lp.hasIPv4DefaultRoute(); + hadIPv6 = lp.hasGlobalIPv6Address() && lp.hasIPv6DefaultRoute(); + } + + mMetricsLog.log(new DefaultNetworkEvent(newNetid, transports, prevNetid, hadIPv4, hadIPv6)); + } +} diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java index f2445fa36006..25e541f17baf 100644 --- a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java +++ b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java @@ -32,12 +32,15 @@ import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.Base64; import android.util.Log; + import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.RingBuffer; import com.android.internal.util.TokenBucket; +import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent; + import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; @@ -112,6 +115,9 @@ final public class IpConnectivityMetrics extends SystemService { private final ToIntFunction<Context> mCapacityGetter; + @VisibleForTesting + final DefaultNetworkMetrics mDefaultNetworkMetrics = new DefaultNetworkMetrics(); + public IpConnectivityMetrics(Context ctx, ToIntFunction<Context> capacityGetter) { super(ctx); mCapacityGetter = capacityGetter; @@ -135,6 +141,8 @@ final public class IpConnectivityMetrics extends SystemService { publishBinderService(SERVICE_NAME, impl); publishBinderService(mNetdListener.SERVICE_NAME, mNetdListener); + + LocalServices.addService(Logger.class, new LoggerImpl()); } } @@ -366,4 +374,15 @@ final public class IpConnectivityMetrics extends SystemService { map.put(ApfProgramEvent.class, new TokenBucket((int)DateUtils.MINUTE_IN_MILLIS, 50)); return map; } + + /** Direct non-Binder interface for event producer clients within the system servers. */ + public interface Logger { + DefaultNetworkMetrics defaultNetworkMetrics(); + } + + private class LoggerImpl implements Logger { + public DefaultNetworkMetrics defaultNetworkMetrics() { + return mDefaultNetworkMetrics; + } + } } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index c2cb66d5e60a..27a29b68e12d 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -104,6 +104,8 @@ import android.util.LogPrinter; import com.android.internal.util.WakeupMessage; import com.android.internal.util.test.BroadcastInterceptingContext; import com.android.internal.util.test.FakeSettingsProvider; +import com.android.server.connectivity.DefaultNetworkMetrics; +import com.android.server.connectivity.IpConnectivityMetrics; import com.android.server.connectivity.MockableSystemProperties; import com.android.server.connectivity.NetworkAgentInfo; import com.android.server.connectivity.NetworkMonitor; @@ -156,6 +158,9 @@ public class ConnectivityServiceTest { private MockNetworkAgent mEthernetNetworkAgent; private Context mContext; + @Mock IpConnectivityMetrics.Logger mMetricsService; + @Mock DefaultNetworkMetrics mDefaultNetworkMetrics; + // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods // do not go through ConnectivityService but talk to netd directly, so they don't automatically // reflect the state of our test ConnectivityService. @@ -805,6 +810,11 @@ public class ConnectivityServiceTest { return Context.ETHERNET_SERVICE.equals(name); } + @Override + protected IpConnectivityMetrics.Logger metricsLogger() { + return mMetricsService; + } + public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() { return mLastCreatedNetworkMonitor; } @@ -833,6 +843,9 @@ public class ConnectivityServiceTest { public void setUp() throws Exception { mContext = InstrumentationRegistry.getContext(); + MockitoAnnotations.initMocks(this); + when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics); + // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not. // http://b/25897652 . if (Looper.myLooper() == null) { |