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 package com.android.server.wifi; 17 18 import android.os.BatteryStatsManager; 19 import android.os.connectivity.WifiBatteryStats; 20 import android.text.format.DateUtils; 21 22 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiPowerStats; 23 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiRadioUsage; 24 25 import java.io.PrintWriter; 26 import java.text.DecimalFormat; 27 28 /** 29 * WifiPowerMetrics holds the wifi power metrics and converts them to WifiPowerStats proto buf. 30 * This proto buf is included in the Wifi proto buf. 31 */ 32 public class WifiPowerMetrics { 33 34 private static final String TAG = "WifiPowerMetrics"; 35 36 /* BatteryStats API */ 37 private final BatteryStatsManager mBatteryStats; 38 WifiPowerMetrics(BatteryStatsManager batteryStats)39 public WifiPowerMetrics(BatteryStatsManager batteryStats) { 40 mBatteryStats = batteryStats; 41 } 42 43 /** 44 * Build WifiPowerStats proto 45 * A snapshot of Wifi statistics in Batterystats is obtained. Due to reboots multiple correlated 46 * logs may be uploaded in a day. Resolution is on the server side. The log with longest 47 * duration is picked. 48 * @return WifiPowerStats 49 */ buildProto()50 public WifiPowerStats buildProto() { 51 WifiPowerStats m = new WifiPowerStats(); 52 WifiBatteryStats stats = getStats(); 53 if (stats != null) { 54 m.loggingDurationMs = stats.getLoggingDurationMillis(); 55 m.energyConsumedMah = stats.getEnergyConsumedMaMillis() 56 / ((double) DateUtils.HOUR_IN_MILLIS); 57 m.idleTimeMs = stats.getIdleTimeMillis(); 58 m.rxTimeMs = stats.getRxTimeMillis(); 59 m.txTimeMs = stats.getTxTimeMillis(); 60 m.wifiKernelActiveTimeMs = stats.getKernelActiveTimeMillis(); 61 m.numPacketsTx = stats.getNumPacketsTx(); 62 m.numBytesTx = stats.getNumBytesTx(); 63 m.numPacketsRx = stats.getNumPacketsRx(); 64 m.numBytesRx = stats.getNumBytesRx(); 65 m.sleepTimeMs = stats.getSleepTimeMillis(); 66 m.scanTimeMs = stats.getScanTimeMillis(); 67 m.monitoredRailEnergyConsumedMah = stats.getMonitoredRailChargeConsumedMaMillis() 68 / ((double) DateUtils.HOUR_IN_MILLIS); 69 } 70 return m; 71 } 72 73 /** 74 * Build WifiRadioUsage proto 75 * A snapshot of Wifi statistics in Batterystats is obtained. Due to reboots multiple correlated 76 * logs may be uploaded in a day. Server side should analyze based the ratio of collected 77 * properties over the total logging duration (ie. |scanTimeMs| / |loggingDurationMs|) 78 * 79 * This proto contains additional wifi usage data that are not directly related to power 80 * calculations. 81 * @return WifiRadioUsage 82 */ buildWifiRadioUsageProto()83 public WifiRadioUsage buildWifiRadioUsageProto() { 84 WifiRadioUsage m = new WifiRadioUsage(); 85 WifiBatteryStats stats = getStats(); 86 if (stats != null) { 87 m.loggingDurationMs = stats.getLoggingDurationMillis(); 88 m.scanTimeMs = stats.getScanTimeMillis(); 89 } 90 return m; 91 } 92 93 /** 94 * Dump all WifiPowerStats to console (pw) 95 * @param pw 96 */ dump(PrintWriter pw)97 public void dump(PrintWriter pw) { 98 WifiPowerStats s = buildProto(); 99 if (s!=null) { 100 pw.println("Wifi power metrics:"); 101 pw.println("Logging duration (time on battery): " + s.loggingDurationMs); 102 pw.println("Energy consumed by wifi (mAh): " + s.energyConsumedMah); 103 pw.println("Amount of time wifi is in idle (ms): " + s.idleTimeMs); 104 pw.println("Amount of time wifi is in rx (ms): " + s.rxTimeMs); 105 pw.println("Amount of time wifi is in tx (ms): " + s.txTimeMs); 106 pw.println("Amount of time kernel is active because of wifi data (ms): " 107 + s.wifiKernelActiveTimeMs); 108 pw.println("Amount of time wifi is in sleep (ms): " + s.sleepTimeMs); 109 pw.println("Amount of time wifi is scanning (ms): " + s.scanTimeMs); 110 pw.println("Number of packets sent (tx): " + s.numPacketsTx); 111 pw.println("Number of bytes sent (tx): " + s.numBytesTx); 112 pw.println("Number of packets received (rx): " + s.numPacketsRx); 113 pw.println("Number of bytes sent (rx): " + s.numBytesRx); 114 pw.println("Energy consumed across measured wifi rails (mAh): " 115 + new DecimalFormat("#.##").format(s.monitoredRailEnergyConsumedMah)); 116 } 117 WifiRadioUsage wifiRadioUsage = buildWifiRadioUsageProto(); 118 pw.println("Wifi radio usage metrics:"); 119 pw.println("Logging duration (time on battery): " + wifiRadioUsage.loggingDurationMs); 120 pw.println("Amount of time wifi is in scan mode while on battery (ms): " 121 + wifiRadioUsage.scanTimeMs); 122 } 123 124 /** 125 * Get wifi stats from batterystats 126 * @return WifiBatteryStats 127 */ getStats()128 private WifiBatteryStats getStats() { 129 return mBatteryStats.getWifiBatteryStats(); 130 } 131 } 132