1 /* 2 * Copyright (C) 2023 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 17 package com.android.metrics; 18 19 import static com.android.metrics.NetworkNsdReported.Builder; 20 21 import android.stats.connectivity.MdnsQueryResult; 22 import android.stats.connectivity.NsdEventType; 23 24 import com.android.internal.annotations.VisibleForTesting; 25 import com.android.server.ConnectivityStatsLog; 26 27 import java.util.Random; 28 29 /** 30 * Class to record the NetworkNsdReported into statsd. Each client should create this class to 31 * report its data. 32 */ 33 public class NetworkNsdReportedMetrics { 34 // The upper bound for the random number used in metrics data sampling determines the possible 35 // sample rate. 36 private static final int RANDOM_NUMBER_UPPER_BOUND = 1000; 37 // The client id. 38 private final int mClientId; 39 private final Dependencies mDependencies; 40 private final Random mRandom; 41 NetworkNsdReportedMetrics(int clientId)42 public NetworkNsdReportedMetrics(int clientId) { 43 this(clientId, new Dependencies()); 44 } 45 46 @VisibleForTesting NetworkNsdReportedMetrics(int clientId, Dependencies dependencies)47 NetworkNsdReportedMetrics(int clientId, Dependencies dependencies) { 48 mClientId = clientId; 49 mDependencies = dependencies; 50 mRandom = dependencies.makeRandomGenerator(); 51 } 52 53 /** 54 * Dependencies of NetworkNsdReportedMetrics, for injection in tests. 55 */ 56 public static class Dependencies { 57 58 /** 59 * @see ConnectivityStatsLog 60 */ statsWrite(NetworkNsdReported event)61 public void statsWrite(NetworkNsdReported event) { 62 ConnectivityStatsLog.write(ConnectivityStatsLog.NETWORK_NSD_REPORTED, 63 event.getIsLegacy(), 64 event.getClientId(), 65 event.getTransactionId(), 66 event.getIsKnownService(), 67 event.getType().getNumber(), 68 event.getEventDurationMillisec(), 69 event.getQueryResult().getNumber(), 70 event.getFoundServiceCount(), 71 event.getFoundCallbackCount(), 72 event.getLostCallbackCount(), 73 event.getRepliedRequestsCount(), 74 event.getSentQueryCount(), 75 event.getSentPacketCount(), 76 event.getConflictDuringProbingCount(), 77 event.getConflictAfterProbingCount(), 78 event.getRandomNumber()); 79 } 80 81 /** 82 * @see Random 83 */ makeRandomGenerator()84 public Random makeRandomGenerator() { 85 return new Random(); 86 } 87 } 88 makeReportedBuilder(boolean isLegacy, int transactionId)89 private Builder makeReportedBuilder(boolean isLegacy, int transactionId) { 90 final Builder builder = NetworkNsdReported.newBuilder(); 91 builder.setIsLegacy(isLegacy); 92 builder.setClientId(mClientId); 93 builder.setRandomNumber(mRandom.nextInt(RANDOM_NUMBER_UPPER_BOUND)); 94 builder.setTransactionId(transactionId); 95 return builder; 96 } 97 98 /** 99 * Report service registration succeeded metric data. 100 * 101 * @param isLegacy Whether this call is using legacy backend. 102 * @param transactionId The transaction id of service registration. 103 * @param durationMs The duration of service registration success. 104 */ reportServiceRegistrationSucceeded(boolean isLegacy, int transactionId, long durationMs)105 public void reportServiceRegistrationSucceeded(boolean isLegacy, int transactionId, 106 long durationMs) { 107 final Builder builder = makeReportedBuilder(isLegacy, transactionId); 108 builder.setType(NsdEventType.NET_REGISTER); 109 builder.setQueryResult(MdnsQueryResult.MQR_SERVICE_REGISTERED); 110 builder.setEventDurationMillisec(durationMs); 111 mDependencies.statsWrite(builder.build()); 112 } 113 114 /** 115 * Report service registration failed metric data. 116 * 117 * @param isLegacy Whether this call is using legacy backend. 118 * @param transactionId The transaction id of service registration. 119 * @param durationMs The duration of service registration failed. 120 */ reportServiceRegistrationFailed(boolean isLegacy, int transactionId, long durationMs)121 public void reportServiceRegistrationFailed(boolean isLegacy, int transactionId, 122 long durationMs) { 123 final Builder builder = makeReportedBuilder(isLegacy, transactionId); 124 builder.setType(NsdEventType.NET_REGISTER); 125 builder.setQueryResult(MdnsQueryResult.MQR_SERVICE_REGISTRATION_FAILED); 126 builder.setEventDurationMillisec(durationMs); 127 mDependencies.statsWrite(builder.build()); 128 } 129 130 /** 131 * Report service unregistration success metric data. 132 * 133 * @param isLegacy Whether this call is using legacy backend. 134 * @param transactionId The transaction id of service registration. 135 * @param durationMs The duration of service stayed registered. 136 * @param repliedRequestsCount The replied request count of this service before unregistered it. 137 * @param sentPacketCount The total sent packet count of this service before unregistered it. 138 * @param conflictDuringProbingCount The number of conflict during probing. 139 * @param conflictAfterProbingCount The number of conflict after probing. 140 */ reportServiceUnregistration(boolean isLegacy, int transactionId, long durationMs, int repliedRequestsCount, int sentPacketCount, int conflictDuringProbingCount, int conflictAfterProbingCount)141 public void reportServiceUnregistration(boolean isLegacy, int transactionId, long durationMs, 142 int repliedRequestsCount, int sentPacketCount, int conflictDuringProbingCount, 143 int conflictAfterProbingCount) { 144 final Builder builder = makeReportedBuilder(isLegacy, transactionId); 145 builder.setType(NsdEventType.NET_REGISTER); 146 builder.setQueryResult(MdnsQueryResult.MQR_SERVICE_UNREGISTERED); 147 builder.setEventDurationMillisec(durationMs); 148 builder.setRepliedRequestsCount(repliedRequestsCount); 149 builder.setSentPacketCount(sentPacketCount); 150 builder.setConflictDuringProbingCount(conflictDuringProbingCount); 151 builder.setConflictAfterProbingCount(conflictAfterProbingCount); 152 mDependencies.statsWrite(builder.build()); 153 } 154 155 /** 156 * Report service discovery started metric data. 157 * 158 * @param isLegacy Whether this call is using legacy backend. 159 * @param transactionId The transaction id of service discovery. 160 */ reportServiceDiscoveryStarted(boolean isLegacy, int transactionId)161 public void reportServiceDiscoveryStarted(boolean isLegacy, int transactionId) { 162 final Builder builder = makeReportedBuilder(isLegacy, transactionId); 163 builder.setType(NsdEventType.NET_DISCOVER); 164 builder.setQueryResult(MdnsQueryResult.MQR_SERVICE_DISCOVERY_STARTED); 165 mDependencies.statsWrite(builder.build()); 166 } 167 168 /** 169 * Report service discovery failed metric data. 170 * 171 * @param isLegacy Whether this call is using legacy backend. 172 * @param transactionId The transaction id of service discovery. 173 * @param durationMs The duration of service discovery failed. 174 */ reportServiceDiscoveryFailed(boolean isLegacy, int transactionId, long durationMs)175 public void reportServiceDiscoveryFailed(boolean isLegacy, int transactionId, 176 long durationMs) { 177 final Builder builder = makeReportedBuilder(isLegacy, transactionId); 178 builder.setType(NsdEventType.NET_DISCOVER); 179 builder.setQueryResult(MdnsQueryResult.MQR_SERVICE_DISCOVERY_FAILED); 180 builder.setEventDurationMillisec(durationMs); 181 mDependencies.statsWrite(builder.build()); 182 } 183 184 /** 185 * Report service discovery stop metric data. 186 * 187 * @param isLegacy Whether this call is using legacy backend. 188 * @param transactionId The transaction id of service discovery. 189 * @param durationMs The duration of discovering services. 190 * @param foundCallbackCount The count of found service callbacks before stop discovery. 191 * @param lostCallbackCount The count of lost service callbacks before stop discovery. 192 * @param servicesCount The count of found services. 193 * @param sentQueryCount The count of sent queries before stop discovery. 194 */ reportServiceDiscoveryStop(boolean isLegacy, int transactionId, long durationMs, int foundCallbackCount, int lostCallbackCount, int servicesCount, int sentQueryCount, boolean isServiceFromCache)195 public void reportServiceDiscoveryStop(boolean isLegacy, int transactionId, long durationMs, 196 int foundCallbackCount, int lostCallbackCount, int servicesCount, int sentQueryCount, 197 boolean isServiceFromCache) { 198 final Builder builder = makeReportedBuilder(isLegacy, transactionId); 199 builder.setType(NsdEventType.NET_DISCOVER); 200 builder.setQueryResult(MdnsQueryResult.MQR_SERVICE_DISCOVERY_STOP); 201 builder.setEventDurationMillisec(durationMs); 202 builder.setFoundCallbackCount(foundCallbackCount); 203 builder.setLostCallbackCount(lostCallbackCount); 204 builder.setFoundServiceCount(servicesCount); 205 builder.setSentQueryCount(sentQueryCount); 206 builder.setIsKnownService(isServiceFromCache); 207 mDependencies.statsWrite(builder.build()); 208 } 209 210 /** 211 * Report service resolution success metric data. 212 * 213 * @param isLegacy Whether this call is using legacy backend. 214 * @param transactionId The transaction id of service resolution. 215 * @param durationMs The duration of resolving services. 216 * @param isServiceFromCache Whether the resolved service is from cache. 217 * @param sentQueryCount The count of sent queries during resolving. 218 */ reportServiceResolved(boolean isLegacy, int transactionId, long durationMs, boolean isServiceFromCache, int sentQueryCount)219 public void reportServiceResolved(boolean isLegacy, int transactionId, long durationMs, 220 boolean isServiceFromCache, int sentQueryCount) { 221 final Builder builder = makeReportedBuilder(isLegacy, transactionId); 222 builder.setType(NsdEventType.NET_RESOLVE); 223 builder.setQueryResult(MdnsQueryResult.MQR_SERVICE_RESOLVED); 224 builder.setEventDurationMillisec(durationMs); 225 builder.setIsKnownService(isServiceFromCache); 226 builder.setSentQueryCount(sentQueryCount); 227 mDependencies.statsWrite(builder.build()); 228 } 229 230 /** 231 * Report service resolution failed metric data. 232 * 233 * @param isLegacy Whether this call is using legacy backend. 234 * @param transactionId The transaction id of service resolution. 235 * @param durationMs The duration of service resolution failed. 236 */ reportServiceResolutionFailed(boolean isLegacy, int transactionId, long durationMs)237 public void reportServiceResolutionFailed(boolean isLegacy, int transactionId, 238 long durationMs) { 239 final Builder builder = makeReportedBuilder(isLegacy, transactionId); 240 builder.setType(NsdEventType.NET_RESOLVE); 241 builder.setQueryResult(MdnsQueryResult.MQR_SERVICE_RESOLUTION_FAILED); 242 builder.setEventDurationMillisec(durationMs); 243 mDependencies.statsWrite(builder.build()); 244 } 245 246 /** 247 * Report service resolution stop metric data. 248 * 249 * @param isLegacy Whether this call is using legacy backend. 250 * @param transactionId The transaction id of service resolution. 251 * @param durationMs The duration before stop resolving the service. 252 * @param sentQueryCount The count of sent queries during resolving. 253 */ reportServiceResolutionStop(boolean isLegacy, int transactionId, long durationMs, int sentQueryCount)254 public void reportServiceResolutionStop(boolean isLegacy, int transactionId, long durationMs, 255 int sentQueryCount) { 256 final Builder builder = makeReportedBuilder(isLegacy, transactionId); 257 builder.setType(NsdEventType.NET_RESOLVE); 258 builder.setQueryResult(MdnsQueryResult.MQR_SERVICE_RESOLUTION_STOP); 259 builder.setEventDurationMillisec(durationMs); 260 builder.setSentQueryCount(sentQueryCount); 261 mDependencies.statsWrite(builder.build()); 262 } 263 264 /** 265 * Report service info callback registered metric data. 266 * 267 * @param transactionId The transaction id of service info callback registration. 268 */ reportServiceInfoCallbackRegistered(int transactionId)269 public void reportServiceInfoCallbackRegistered(int transactionId) { 270 // service info callback is always using new backend. 271 final Builder builder = makeReportedBuilder(false /* isLegacy */, transactionId); 272 builder.setType(NsdEventType.NET_SERVICE_INFO_CALLBACK); 273 builder.setQueryResult(MdnsQueryResult.MQR_SERVICE_INFO_CALLBACK_REGISTERED); 274 mDependencies.statsWrite(builder.build()); 275 } 276 277 /** 278 * Report service info callback registration failed metric data. 279 * 280 * @param transactionId The transaction id of service callback registration. 281 */ reportServiceInfoCallbackRegistrationFailed(int transactionId)282 public void reportServiceInfoCallbackRegistrationFailed(int transactionId) { 283 // service info callback is always using new backend. 284 final Builder builder = makeReportedBuilder(false /* isLegacy */, transactionId); 285 builder.setType(NsdEventType.NET_SERVICE_INFO_CALLBACK); 286 builder.setQueryResult(MdnsQueryResult.MQR_SERVICE_INFO_CALLBACK_REGISTRATION_FAILED); 287 mDependencies.statsWrite(builder.build()); 288 } 289 290 /** 291 * Report service callback unregistered metric data. 292 * 293 * @param transactionId The transaction id of service callback registration. 294 * @param durationMs The duration of service callback stayed registered. 295 * @param updateCallbackCount The count of service update callbacks during this registration. 296 * @param lostCallbackCount The count of service lost callbacks during this registration. 297 * @param isServiceFromCache Whether the resolved service is from cache. 298 * @param sentQueryCount The count of sent queries during this registration. 299 */ reportServiceInfoCallbackUnregistered(int transactionId, long durationMs, int updateCallbackCount, int lostCallbackCount, boolean isServiceFromCache, int sentQueryCount)300 public void reportServiceInfoCallbackUnregistered(int transactionId, long durationMs, 301 int updateCallbackCount, int lostCallbackCount, boolean isServiceFromCache, 302 int sentQueryCount) { 303 // service info callback is always using new backend. 304 final Builder builder = makeReportedBuilder(false /* isLegacy */, transactionId); 305 builder.setType(NsdEventType.NET_SERVICE_INFO_CALLBACK); 306 builder.setQueryResult(MdnsQueryResult.MQR_SERVICE_INFO_CALLBACK_UNREGISTERED); 307 builder.setEventDurationMillisec(durationMs); 308 builder.setFoundCallbackCount(updateCallbackCount); 309 builder.setLostCallbackCount(lostCallbackCount); 310 builder.setIsKnownService(isServiceFromCache); 311 builder.setSentQueryCount(sentQueryCount); 312 mDependencies.statsWrite(builder.build()); 313 } 314 } 315