blob: 4fb6607a6b08fd4bc3cded8a7758f951e8ffe1be [file] [log] [blame]
Hugo Benichi64901e52017-10-19 14:42:40 +09001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.connectivity;
18
Hugo Benichi64901e52017-10-19 14:42:40 +090019import android.net.LinkProperties;
20import android.net.metrics.DefaultNetworkEvent;
Hugo Benichi380a0632017-10-20 09:25:29 +090021import android.os.SystemClock;
Hugo Benichi64901e52017-10-19 14:42:40 +090022
Hugo Benichi1193a9c2017-10-19 14:58:15 +090023import com.android.internal.annotations.GuardedBy;
Hugo Benichi380a0632017-10-20 09:25:29 +090024import com.android.internal.util.BitUtils;
25import com.android.internal.util.RingBuffer;
Hugo Benichi1193a9c2017-10-19 14:58:15 +090026import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
27
28import java.io.PrintWriter;
29import java.util.ArrayList;
30import java.util.List;
31
Hugo Benichi64901e52017-10-19 14:42:40 +090032/**
33 * Tracks events related to the default network for the purpose of default network metrics.
34 * {@hide}
35 */
36public class DefaultNetworkMetrics {
37
Hugo Benichi1193a9c2017-10-19 14:58:15 +090038 private static final int ROLLING_LOG_SIZE = 64;
Hugo Benichi64901e52017-10-19 14:42:40 +090039
Hugo Benichi380a0632017-10-20 09:25:29 +090040 public final long creationTimeMs = SystemClock.elapsedRealtime();
41
Hugo Benichi1193a9c2017-10-19 14:58:15 +090042 // Event buffer used for metrics upload. The buffer is cleared when events are collected.
43 @GuardedBy("this")
44 private final List<DefaultNetworkEvent> mEvents = new ArrayList<>();
Hugo Benichi64901e52017-10-19 14:42:40 +090045
Hugo Benichi380a0632017-10-20 09:25:29 +090046 // Rolling event buffer used for dumpsys and bugreports.
47 @GuardedBy("this")
48 private final RingBuffer<DefaultNetworkEvent> mEventsLog =
49 new RingBuffer(DefaultNetworkEvent.class, ROLLING_LOG_SIZE);
50
51 // Information about the current status of the default network.
52 @GuardedBy("this")
53 private DefaultNetworkEvent mCurrentDefaultNetwork;
Hugo Benichi71a1b532017-12-06 13:28:09 +090054 // True if the current default network has been validated.
Hugo Benichi380a0632017-10-20 09:25:29 +090055 @GuardedBy("this")
56 private boolean mIsCurrentlyValid;
57 @GuardedBy("this")
58 private long mLastValidationTimeMs;
59 // Transport information about the last default network.
60 @GuardedBy("this")
61 private int mLastTransports;
62
63 public DefaultNetworkMetrics() {
64 newDefaultNetwork(creationTimeMs, null);
65 }
66
Hugo Benichi1193a9c2017-10-19 14:58:15 +090067 public synchronized void listEvents(PrintWriter pw) {
Hugo Benichi380a0632017-10-20 09:25:29 +090068 pw.println("default network events:");
Hugo Benichi1193a9c2017-10-19 14:58:15 +090069 long localTimeMs = System.currentTimeMillis();
Hugo Benichi380a0632017-10-20 09:25:29 +090070 long timeMs = SystemClock.elapsedRealtime();
71 for (DefaultNetworkEvent ev : mEventsLog.toArray()) {
72 printEvent(localTimeMs, pw, ev);
Hugo Benichi1193a9c2017-10-19 14:58:15 +090073 }
Hugo Benichi380a0632017-10-20 09:25:29 +090074 mCurrentDefaultNetwork.updateDuration(timeMs);
Hugo Benichi71a1b532017-12-06 13:28:09 +090075 // When printing default network events for bug reports, update validation time
76 // and refresh the last validation timestmap for future validation time updates.
Hugo Benichi380a0632017-10-20 09:25:29 +090077 if (mIsCurrentlyValid) {
78 updateValidationTime(timeMs);
79 mLastValidationTimeMs = timeMs;
80 }
81 printEvent(localTimeMs, pw, mCurrentDefaultNetwork);
Hugo Benichi1193a9c2017-10-19 14:58:15 +090082 }
83
Mike Mad2672bd2020-01-15 15:57:20 -080084 /**
Mike Mae19df932020-01-22 01:36:32 -080085 * Convert events in the ring buffer to a list of IpConnectivityEvent protos
Mike Mad2672bd2020-01-15 15:57:20 -080086 */
Mike Mae19df932020-01-22 01:36:32 -080087 public synchronized List<IpConnectivityEvent> listEventsAsProto() {
88 List<IpConnectivityEvent> list = new ArrayList<>();
Hugo Benichi380a0632017-10-20 09:25:29 +090089 for (DefaultNetworkEvent ev : mEventsLog.toArray()) {
Mike Mae19df932020-01-22 01:36:32 -080090 list.add(IpConnectivityEventBuilder.toProto(ev));
Hugo Benichi1193a9c2017-10-19 14:58:15 +090091 }
Mike Mae19df932020-01-22 01:36:32 -080092 return list;
Hugo Benichi1193a9c2017-10-19 14:58:15 +090093 }
94
95 public synchronized void flushEvents(List<IpConnectivityEvent> out) {
96 for (DefaultNetworkEvent ev : mEvents) {
97 out.add(IpConnectivityEventBuilder.toProto(ev));
98 }
99 mEvents.clear();
100 }
101
Hugo Benichi380a0632017-10-20 09:25:29 +0900102 public synchronized void logDefaultNetworkValidity(long timeMs, boolean isValid) {
Hugo Benichi71a1b532017-12-06 13:28:09 +0900103 // Transition from valid to invalid: update validity duration since last update
Hugo Benichi380a0632017-10-20 09:25:29 +0900104 if (!isValid && mIsCurrentlyValid) {
105 mIsCurrentlyValid = false;
106 updateValidationTime(timeMs);
Hugo Benichi64901e52017-10-19 14:42:40 +0900107 }
108
Hugo Benichi71a1b532017-12-06 13:28:09 +0900109 // Transition from invalid to valid: simply mark the validation timestamp.
Hugo Benichi380a0632017-10-20 09:25:29 +0900110 if (isValid && !mIsCurrentlyValid) {
111 mIsCurrentlyValid = true;
112 mLastValidationTimeMs = timeMs;
113 }
114 }
115
116 private void updateValidationTime(long timeMs) {
117 mCurrentDefaultNetwork.validatedMs += timeMs - mLastValidationTimeMs;
118 }
119
120 public synchronized void logDefaultNetworkEvent(
121 long timeMs, NetworkAgentInfo newNai, NetworkAgentInfo oldNai) {
122 logCurrentDefaultNetwork(timeMs, oldNai);
123 newDefaultNetwork(timeMs, newNai);
124 }
125
126 private void logCurrentDefaultNetwork(long timeMs, NetworkAgentInfo oldNai) {
Hugo Benichi71a1b532017-12-06 13:28:09 +0900127 if (mIsCurrentlyValid) {
128 updateValidationTime(timeMs);
129 }
Hugo Benichi380a0632017-10-20 09:25:29 +0900130 DefaultNetworkEvent ev = mCurrentDefaultNetwork;
131 ev.updateDuration(timeMs);
132 ev.previousTransports = mLastTransports;
133 // oldNai is null if the system had no default network before the transition.
134 if (oldNai != null) {
135 // The system acquired a new default network.
136 fillLinkInfo(ev, oldNai);
137 ev.finalScore = oldNai.getCurrentScore();
Hugo Benichi380a0632017-10-20 09:25:29 +0900138 }
139 // Only change transport of the previous default network if the event currently logged
140 // corresponds to an existing default network, and not to the absence of a default network.
141 // This allows to log pairs of transports for successive default networks regardless of
142 // whether or not the system experienced a period without any default network.
143 if (ev.transports != 0) {
144 mLastTransports = ev.transports;
145 }
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900146 mEvents.add(ev);
Hugo Benichi380a0632017-10-20 09:25:29 +0900147 mEventsLog.append(ev);
148 }
149
150 private void newDefaultNetwork(long timeMs, NetworkAgentInfo newNai) {
151 DefaultNetworkEvent ev = new DefaultNetworkEvent(timeMs);
152 ev.durationMs = timeMs;
153 // newNai is null if the system has no default network after the transition.
154 if (newNai != null) {
155 fillLinkInfo(ev, newNai);
156 ev.initialScore = newNai.getCurrentScore();
157 if (newNai.lastValidated) {
Hugo Benichibb16b752017-12-14 09:56:04 +0900158 mIsCurrentlyValid = true;
159 mLastValidationTimeMs = timeMs;
Hugo Benichi380a0632017-10-20 09:25:29 +0900160 }
Hugo Benichi71a1b532017-12-06 13:28:09 +0900161 } else {
162 mIsCurrentlyValid = false;
Hugo Benichi380a0632017-10-20 09:25:29 +0900163 }
164 mCurrentDefaultNetwork = ev;
165 }
166
167 private static void fillLinkInfo(DefaultNetworkEvent ev, NetworkAgentInfo nai) {
168 LinkProperties lp = nai.linkProperties;
169 ev.netId = nai.network().netId;
170 ev.transports |= BitUtils.packBits(nai.networkCapabilities.getTransportTypes());
paulhud9736de2019-03-08 16:35:20 +0800171 ev.ipv4 |= lp.hasIpv4Address() && lp.hasIpv4DefaultRoute();
172 ev.ipv6 |= lp.hasGlobalIpv6Address() && lp.hasIpv6DefaultRoute();
Hugo Benichi380a0632017-10-20 09:25:29 +0900173 }
174
175 private static void printEvent(long localTimeMs, PrintWriter pw, DefaultNetworkEvent ev) {
176 long localCreationTimeMs = localTimeMs - ev.durationMs;
177 pw.println(String.format("%tT.%tL: %s", localCreationTimeMs, localCreationTimeMs, ev));
Hugo Benichi64901e52017-10-19 14:42:40 +0900178 }
179}