1 /* 2 * Copyright (C) 2019 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.networkstack.metrics; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.net.util.NetworkStackUtils; 22 import android.net.wifi.WifiInfo; 23 24 import com.android.internal.util.HexDump; 25 import com.android.server.connectivity.nano.CellularData; 26 import com.android.server.connectivity.nano.DataStallEventProto; 27 import com.android.server.connectivity.nano.DnsEvent; 28 import com.android.server.connectivity.nano.WifiData; 29 30 import com.google.protobuf.nano.MessageNano; 31 32 import java.util.ArrayList; 33 import java.util.Arrays; 34 import java.util.List; 35 import java.util.Objects; 36 37 /** 38 * Class to record the stats of detection level information for data stall. 39 * 40 * @hide 41 */ 42 public final class DataStallDetectionStats { 43 private static final int UNKNOWN_SIGNAL_STRENGTH = -1; 44 @NonNull 45 final byte[] mCellularInfo; 46 @NonNull 47 final byte[] mWifiInfo; 48 @NonNull 49 final byte[] mDns; 50 final int mEvaluationType; 51 final int mNetworkType; 52 DataStallDetectionStats(@ullable byte[] cell, @Nullable byte[] wifi, @NonNull int[] returnCode, @NonNull long[] dnsTime, int evalType, int netType)53 public DataStallDetectionStats(@Nullable byte[] cell, @Nullable byte[] wifi, 54 @NonNull int[] returnCode, @NonNull long[] dnsTime, int evalType, int netType) { 55 mCellularInfo = emptyCellDataIfNull(cell); 56 mWifiInfo = emptyWifiInfoIfNull(wifi); 57 58 DnsEvent dns = new DnsEvent(); 59 dns.dnsReturnCode = returnCode; 60 dns.dnsTime = dnsTime; 61 mDns = MessageNano.toByteArray(dns); 62 mEvaluationType = evalType; 63 mNetworkType = netType; 64 } 65 emptyCellDataIfNull(@ullable byte[] cell)66 private byte[] emptyCellDataIfNull(@Nullable byte[] cell) { 67 if (cell != null) return cell; 68 69 CellularData data = new CellularData(); 70 data.ratType = DataStallEventProto.RADIO_TECHNOLOGY_UNKNOWN; 71 data.networkMccmnc = ""; 72 data.simMccmnc = ""; 73 data.signalStrength = UNKNOWN_SIGNAL_STRENGTH; 74 return MessageNano.toByteArray(data); 75 } 76 emptyWifiInfoIfNull(@ullable byte[] wifi)77 private byte[] emptyWifiInfoIfNull(@Nullable byte[] wifi) { 78 if (wifi != null) return wifi; 79 80 WifiData data = new WifiData(); 81 data.wifiBand = DataStallEventProto.AP_BAND_UNKNOWN; 82 data.signalStrength = UNKNOWN_SIGNAL_STRENGTH; 83 return MessageNano.toByteArray(data); 84 } 85 86 @Override toString()87 public String toString() { 88 StringBuilder sb = new StringBuilder(); 89 sb.append("type: ").append(mNetworkType) 90 .append(", evaluation type: ") 91 .append(mEvaluationType) 92 .append(", wifi info: ") 93 .append(HexDump.toHexString(mWifiInfo)) 94 .append(", cell info: ") 95 .append(HexDump.toHexString(mCellularInfo)) 96 .append(", dns: ") 97 .append(HexDump.toHexString(mDns)); 98 return sb.toString(); 99 } 100 101 @Override equals(@ullable final Object o)102 public boolean equals(@Nullable final Object o) { 103 if (!(o instanceof DataStallDetectionStats)) return false; 104 final DataStallDetectionStats other = (DataStallDetectionStats) o; 105 return (mNetworkType == other.mNetworkType) 106 && (mEvaluationType == other.mEvaluationType) 107 && Arrays.equals(mWifiInfo, other.mWifiInfo) 108 && Arrays.equals(mCellularInfo, other.mCellularInfo) 109 && Arrays.equals(mDns, other.mDns); 110 } 111 112 @Override hashCode()113 public int hashCode() { 114 return Objects.hash(mNetworkType, mEvaluationType, mWifiInfo, mCellularInfo, mDns); 115 } 116 117 /** 118 * Utility to create an instance of {@Link DataStallDetectionStats} 119 * 120 * @hide 121 */ 122 public static class Builder { 123 @Nullable 124 private byte[] mCellularInfo; 125 @Nullable 126 private byte[] mWifiInfo; 127 @NonNull 128 private final List<Integer> mDnsReturnCode = new ArrayList<Integer>(); 129 @NonNull 130 private final List<Long> mDnsTimeStamp = new ArrayList<Long>(); 131 private int mEvaluationType; 132 private int mNetworkType; 133 134 /** 135 * Add a dns event into Builder. 136 * 137 * @param code the return code of the dns event. 138 * @param timeMs the elapsedRealtime in ms that the the dns event was received from netd. 139 * @return {@code this} {@link Builder} instance. 140 */ addDnsEvent(int code, long timeMs)141 public Builder addDnsEvent(int code, long timeMs) { 142 mDnsReturnCode.add(code); 143 mDnsTimeStamp.add(timeMs); 144 return this; 145 } 146 147 /** 148 * Set the dns evaluation type into Builder. 149 * 150 * @param type the return code of the dns event. 151 * @return {@code this} {@link Builder} instance. 152 */ setEvaluationType(int type)153 public Builder setEvaluationType(int type) { 154 mEvaluationType = type; 155 return this; 156 } 157 158 /** 159 * Set the network type into Builder. 160 * 161 * @param type the network type of the logged network. 162 * @return {@code this} {@link Builder} instance. 163 */ setNetworkType(int type)164 public Builder setNetworkType(int type) { 165 mNetworkType = type; 166 return this; 167 } 168 169 /** 170 * Set the wifi data into Builder. 171 * 172 * @param info a {@link WifiInfo} of the connected wifi network. 173 * @return {@code this} {@link Builder} instance. 174 */ setWiFiData(@ullable final WifiInfo info)175 public Builder setWiFiData(@Nullable final WifiInfo info) { 176 WifiData data = new WifiData(); 177 data.wifiBand = getWifiBand(info); 178 data.signalStrength = (info != null) ? info.getRssi() : UNKNOWN_SIGNAL_STRENGTH; 179 mWifiInfo = MessageNano.toByteArray(data); 180 return this; 181 } 182 getWifiBand(@ullable final WifiInfo info)183 private static int getWifiBand(@Nullable final WifiInfo info) { 184 if (info == null) return DataStallEventProto.AP_BAND_UNKNOWN; 185 186 int freq = info.getFrequency(); 187 // Refer to ScanResult.is5GHz() and ScanResult.is24GHz(). 188 if (freq > 4900 && freq < 5900) { 189 return DataStallEventProto.AP_BAND_5GHZ; 190 } else if (freq > 2400 && freq < 2500) { 191 return DataStallEventProto.AP_BAND_2GHZ; 192 } else { 193 return DataStallEventProto.AP_BAND_UNKNOWN; 194 } 195 } 196 197 /** 198 * Set the cellular data into Builder. 199 * 200 * @param radioType the radio technology of the logged cellular network. 201 * @param roaming a boolean indicates if logged cellular network is roaming or not. 202 * @param networkMccmnc the mccmnc of the camped network. 203 * @param simMccmnc the mccmnc of the sim. 204 * @return {@code this} {@link Builder} instance. 205 */ setCellData(int radioType, boolean roaming, @NonNull String networkMccmnc, @NonNull String simMccmnc, int ss)206 public Builder setCellData(int radioType, boolean roaming, 207 @NonNull String networkMccmnc, @NonNull String simMccmnc, int ss) { 208 CellularData data = new CellularData(); 209 data.ratType = radioType; 210 data.isRoaming = roaming; 211 data.networkMccmnc = networkMccmnc; 212 data.simMccmnc = simMccmnc; 213 data.signalStrength = ss; 214 mCellularInfo = MessageNano.toByteArray(data); 215 return this; 216 } 217 218 /** 219 * Create a new {@Link DataStallDetectionStats}. 220 */ build()221 public DataStallDetectionStats build() { 222 return new DataStallDetectionStats(mCellularInfo, mWifiInfo, 223 NetworkStackUtils.convertToIntArray(mDnsReturnCode), 224 NetworkStackUtils.convertToLongArray(mDnsTimeStamp), 225 mEvaluationType, mNetworkType); 226 } 227 } 228 } 229