1 /* 2 * Copyright (C) 2016 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 android.net.metrics; 18 19 import android.net.NetworkCapabilities; 20 import java.util.Arrays; 21 import com.android.internal.util.BitUtils; 22 23 /** 24 * A DNS event recorded by NetdEventListenerService. 25 * {@hide} 26 */ 27 final public class DnsEvent { 28 29 private static final int SIZE_LIMIT = 20000; 30 31 // Network id of the network associated with the event, or 0 if unspecified. 32 public final int netId; 33 // Transports of the network associated with the event, as defined in NetworkCapabilities. 34 // It is the caller responsability to ensure the value of transports does not change between 35 // calls to addResult. 36 public final long transports; 37 // The number of DNS queries recorded. Queries are stored in the structure-of-array style where 38 // the eventTypes, returnCodes, and latenciesMs arrays have the same length and the i-th event 39 // is spread across the three array at position i. 40 public int eventCount; 41 // The types of DNS queries as defined in INetdEventListener. 42 public byte[] eventTypes; 43 // Current getaddrinfo codes go from 1 to EAI_MAX = 15. gethostbyname returns errno, but there 44 // are fewer than 255 errno values. So we store the result code in a byte as well. 45 public byte[] returnCodes; 46 // Latencies in milliseconds of queries, stored as ints. 47 public int[] latenciesMs; 48 DnsEvent(int netId, long transports, int initialCapacity)49 public DnsEvent(int netId, long transports, int initialCapacity) { 50 this.netId = netId; 51 this.transports = transports; 52 eventTypes = new byte[initialCapacity]; 53 returnCodes = new byte[initialCapacity]; 54 latenciesMs = new int[initialCapacity]; 55 } 56 addResult(byte eventType, byte returnCode, int latencyMs)57 public void addResult(byte eventType, byte returnCode, int latencyMs) { 58 if (eventCount >= SIZE_LIMIT) { 59 // TODO: implement better rate limiting that does not biases metrics. 60 return; 61 } 62 if (eventCount == eventTypes.length) { 63 resize((int) (1.4 * eventCount)); 64 } 65 eventTypes[eventCount] = eventType; 66 returnCodes[eventCount] = returnCode; 67 latenciesMs[eventCount] = latencyMs; 68 eventCount++; 69 } 70 resize(int newLength)71 public void resize(int newLength) { 72 eventTypes = Arrays.copyOf(eventTypes, newLength); 73 returnCodes = Arrays.copyOf(returnCodes, newLength); 74 latenciesMs = Arrays.copyOf(latenciesMs, newLength); 75 } 76 77 @Override toString()78 public String toString() { 79 StringBuilder builder = new StringBuilder("DnsEvent(").append(netId).append(", "); 80 for (int t : BitUtils.unpackBits(transports)) { 81 builder.append(NetworkCapabilities.transportNameOf(t)).append(", "); 82 } 83 return builder.append(eventCount).append(" events)").toString(); 84 } 85 } 86