1 /* 2 * Copyright (C) 2024 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.server.power.stats; 18 19 import android.annotation.NonNull; 20 import android.os.PersistableBundle; 21 import android.telephony.ModemActivityInfo; 22 import android.util.Slog; 23 import android.util.SparseArray; 24 25 import com.android.internal.os.PowerStats; 26 27 /** 28 * Captures the positions and lengths of sections of the stats array, such as time-in-state, 29 * power usage estimates etc. 30 */ 31 class MobileRadioPowerStatsLayout extends PowerStatsLayout { 32 private static final String TAG = "MobileRadioPowerStatsLayout"; 33 private static final String EXTRA_DEVICE_SLEEP_TIME_POSITION = "dt-sleep"; 34 private static final String EXTRA_DEVICE_IDLE_TIME_POSITION = "dt-idle"; 35 private static final String EXTRA_DEVICE_SCAN_TIME_POSITION = "dt-scan"; 36 private static final String EXTRA_DEVICE_CALL_TIME_POSITION = "dt-call"; 37 private static final String EXTRA_DEVICE_CALL_POWER_POSITION = "dp-call"; 38 private static final String EXTRA_STATE_RX_TIME_POSITION = "srx"; 39 private static final String EXTRA_STATE_TX_TIMES_POSITION = "stx"; 40 private static final String EXTRA_STATE_TX_TIMES_COUNT = "stxc"; 41 private static final String EXTRA_UID_RX_BYTES_POSITION = "urxb"; 42 private static final String EXTRA_UID_TX_BYTES_POSITION = "utxb"; 43 private static final String EXTRA_UID_RX_PACKETS_POSITION = "urxp"; 44 private static final String EXTRA_UID_TX_PACKETS_POSITION = "utxp"; 45 46 private int mDeviceSleepTimePosition; 47 private int mDeviceIdleTimePosition; 48 private int mDeviceScanTimePosition; 49 private int mDeviceCallTimePosition; 50 private int mDeviceCallPowerPosition; 51 private int mStateRxTimePosition; 52 private int mStateTxTimesPosition; 53 private int mStateTxTimesCount; 54 private int mUidRxBytesPosition; 55 private int mUidTxBytesPosition; 56 private int mUidRxPacketsPosition; 57 private int mUidTxPacketsPosition; 58 MobileRadioPowerStatsLayout()59 MobileRadioPowerStatsLayout() { 60 } 61 MobileRadioPowerStatsLayout(@onNull PowerStats.Descriptor descriptor)62 MobileRadioPowerStatsLayout(@NonNull PowerStats.Descriptor descriptor) { 63 super(descriptor); 64 } 65 addDeviceMobileActivity()66 void addDeviceMobileActivity() { 67 mDeviceSleepTimePosition = addDeviceSection(1, "sleep"); 68 mDeviceIdleTimePosition = addDeviceSection(1, "idle"); 69 mDeviceScanTimePosition = addDeviceSection(1, "scan"); 70 mDeviceCallTimePosition = addDeviceSection(1, "call", FLAG_OPTIONAL); 71 } 72 addStateStats()73 void addStateStats() { 74 mStateRxTimePosition = addStateSection(1, "rx"); 75 mStateTxTimesCount = ModemActivityInfo.getNumTxPowerLevels(); 76 mStateTxTimesPosition = addStateSection(mStateTxTimesCount, "tx"); 77 } 78 addUidNetworkStats()79 void addUidNetworkStats() { 80 mUidRxPacketsPosition = addUidSection(1, "rx-pkts"); 81 mUidRxBytesPosition = addUidSection(1, "rx-B"); 82 mUidTxPacketsPosition = addUidSection(1, "tx-pkts"); 83 mUidTxBytesPosition = addUidSection(1, "tx-B"); 84 } 85 86 @Override addDeviceSectionPowerEstimate()87 public void addDeviceSectionPowerEstimate() { 88 super.addDeviceSectionPowerEstimate(); 89 // Printed as part of the PhoneCallPowerStatsProcessor 90 mDeviceCallPowerPosition = addDeviceSection(1, "call-power", FLAG_HIDDEN); 91 } 92 setDeviceSleepTime(long[] stats, long durationMillis)93 public void setDeviceSleepTime(long[] stats, long durationMillis) { 94 stats[mDeviceSleepTimePosition] = durationMillis; 95 } 96 getDeviceSleepTime(long[] stats)97 public long getDeviceSleepTime(long[] stats) { 98 return stats[mDeviceSleepTimePosition]; 99 } 100 setDeviceIdleTime(long[] stats, long durationMillis)101 public void setDeviceIdleTime(long[] stats, long durationMillis) { 102 stats[mDeviceIdleTimePosition] = durationMillis; 103 } 104 getDeviceIdleTime(long[] stats)105 public long getDeviceIdleTime(long[] stats) { 106 return stats[mDeviceIdleTimePosition]; 107 } 108 setDeviceScanTime(long[] stats, long durationMillis)109 public void setDeviceScanTime(long[] stats, long durationMillis) { 110 stats[mDeviceScanTimePosition] = durationMillis; 111 } 112 getDeviceScanTime(long[] stats)113 public long getDeviceScanTime(long[] stats) { 114 return stats[mDeviceScanTimePosition]; 115 } 116 setDeviceCallTime(long[] stats, long durationMillis)117 public void setDeviceCallTime(long[] stats, long durationMillis) { 118 stats[mDeviceCallTimePosition] = durationMillis; 119 } 120 getDeviceCallTime(long[] stats)121 public long getDeviceCallTime(long[] stats) { 122 return stats[mDeviceCallTimePosition]; 123 } 124 setDeviceCallPowerEstimate(long[] stats, double power)125 public void setDeviceCallPowerEstimate(long[] stats, double power) { 126 stats[mDeviceCallPowerPosition] = (long) (power * MILLI_TO_NANO_MULTIPLIER); 127 } 128 getDeviceCallPowerEstimate(long[] stats)129 public double getDeviceCallPowerEstimate(long[] stats) { 130 return stats[mDeviceCallPowerPosition] / MILLI_TO_NANO_MULTIPLIER; 131 } 132 setStateRxTime(long[] stats, long durationMillis)133 public void setStateRxTime(long[] stats, long durationMillis) { 134 stats[mStateRxTimePosition] = durationMillis; 135 } 136 getStateRxTime(long[] stats)137 public long getStateRxTime(long[] stats) { 138 return stats[mStateRxTimePosition]; 139 } 140 setStateTxTime(long[] stats, int level, int durationMillis)141 public void setStateTxTime(long[] stats, int level, int durationMillis) { 142 stats[mStateTxTimesPosition + level] = durationMillis; 143 } 144 getStateTxTime(long[] stats, int level)145 public long getStateTxTime(long[] stats, int level) { 146 return stats[mStateTxTimesPosition + level]; 147 } 148 setUidRxBytes(long[] stats, long count)149 public void setUidRxBytes(long[] stats, long count) { 150 stats[mUidRxBytesPosition] = count; 151 } 152 getUidRxBytes(long[] stats)153 public long getUidRxBytes(long[] stats) { 154 return stats[mUidRxBytesPosition]; 155 } 156 setUidTxBytes(long[] stats, long count)157 public void setUidTxBytes(long[] stats, long count) { 158 stats[mUidTxBytesPosition] = count; 159 } 160 getUidTxBytes(long[] stats)161 public long getUidTxBytes(long[] stats) { 162 return stats[mUidTxBytesPosition]; 163 } 164 setUidRxPackets(long[] stats, long count)165 public void setUidRxPackets(long[] stats, long count) { 166 stats[mUidRxPacketsPosition] = count; 167 } 168 getUidRxPackets(long[] stats)169 public long getUidRxPackets(long[] stats) { 170 return stats[mUidRxPacketsPosition]; 171 } 172 setUidTxPackets(long[] stats, long count)173 public void setUidTxPackets(long[] stats, long count) { 174 stats[mUidTxPacketsPosition] = count; 175 } 176 getUidTxPackets(long[] stats)177 public long getUidTxPackets(long[] stats) { 178 return stats[mUidTxPacketsPosition]; 179 } 180 181 /** 182 * Copies the elements of the stats array layout into <code>extras</code> 183 */ toExtras(PersistableBundle extras)184 public void toExtras(PersistableBundle extras) { 185 super.toExtras(extras); 186 extras.putInt(EXTRA_DEVICE_SLEEP_TIME_POSITION, mDeviceSleepTimePosition); 187 extras.putInt(EXTRA_DEVICE_IDLE_TIME_POSITION, mDeviceIdleTimePosition); 188 extras.putInt(EXTRA_DEVICE_SCAN_TIME_POSITION, mDeviceScanTimePosition); 189 extras.putInt(EXTRA_DEVICE_CALL_TIME_POSITION, mDeviceCallTimePosition); 190 extras.putInt(EXTRA_DEVICE_CALL_POWER_POSITION, mDeviceCallPowerPosition); 191 extras.putInt(EXTRA_STATE_RX_TIME_POSITION, mStateRxTimePosition); 192 extras.putInt(EXTRA_STATE_TX_TIMES_POSITION, mStateTxTimesPosition); 193 extras.putInt(EXTRA_STATE_TX_TIMES_COUNT, mStateTxTimesCount); 194 extras.putInt(EXTRA_UID_RX_BYTES_POSITION, mUidRxBytesPosition); 195 extras.putInt(EXTRA_UID_TX_BYTES_POSITION, mUidTxBytesPosition); 196 extras.putInt(EXTRA_UID_RX_PACKETS_POSITION, mUidRxPacketsPosition); 197 extras.putInt(EXTRA_UID_TX_PACKETS_POSITION, mUidTxPacketsPosition); 198 } 199 200 /** 201 * Retrieves elements of the stats array layout from <code>extras</code> 202 */ fromExtras(PersistableBundle extras)203 public void fromExtras(PersistableBundle extras) { 204 super.fromExtras(extras); 205 mDeviceSleepTimePosition = extras.getInt(EXTRA_DEVICE_SLEEP_TIME_POSITION); 206 mDeviceIdleTimePosition = extras.getInt(EXTRA_DEVICE_IDLE_TIME_POSITION); 207 mDeviceScanTimePosition = extras.getInt(EXTRA_DEVICE_SCAN_TIME_POSITION); 208 mDeviceCallTimePosition = extras.getInt(EXTRA_DEVICE_CALL_TIME_POSITION); 209 mDeviceCallPowerPosition = extras.getInt(EXTRA_DEVICE_CALL_POWER_POSITION); 210 mStateRxTimePosition = extras.getInt(EXTRA_STATE_RX_TIME_POSITION); 211 mStateTxTimesPosition = extras.getInt(EXTRA_STATE_TX_TIMES_POSITION); 212 mStateTxTimesCount = extras.getInt(EXTRA_STATE_TX_TIMES_COUNT); 213 mUidRxBytesPosition = extras.getInt(EXTRA_UID_RX_BYTES_POSITION); 214 mUidTxBytesPosition = extras.getInt(EXTRA_UID_TX_BYTES_POSITION); 215 mUidRxPacketsPosition = extras.getInt(EXTRA_UID_RX_PACKETS_POSITION); 216 mUidTxPacketsPosition = extras.getInt(EXTRA_UID_TX_PACKETS_POSITION); 217 } 218 addRxTxTimesForRat(SparseArray<long[]> stateStats, int networkType, int freqRange, long rxTime, int[] txTime)219 public void addRxTxTimesForRat(SparseArray<long[]> stateStats, int networkType, int freqRange, 220 long rxTime, int[] txTime) { 221 if (txTime.length != mStateTxTimesCount) { 222 Slog.wtf(TAG, "Invalid TX time array size: " + txTime.length); 223 return; 224 } 225 226 boolean nonZero = false; 227 if (rxTime != 0) { 228 nonZero = true; 229 } else { 230 for (int i = txTime.length - 1; i >= 0; i--) { 231 if (txTime[i] != 0) { 232 nonZero = true; 233 break; 234 } 235 } 236 } 237 238 if (!nonZero) { 239 return; 240 } 241 242 int rat = MobileRadioPowerStatsCollector.mapRadioAccessNetworkTypeToRadioAccessTechnology( 243 networkType); 244 int stateKey = MobileRadioPowerStatsCollector.makeStateKey(rat, freqRange); 245 long[] stats = stateStats.get(stateKey); 246 if (stats == null) { 247 stats = new long[getStateStatsArrayLength()]; 248 stateStats.put(stateKey, stats); 249 } 250 251 stats[mStateRxTimePosition] += rxTime; 252 for (int i = mStateTxTimesCount - 1; i >= 0; i--) { 253 stats[mStateTxTimesPosition + i] += txTime[i]; 254 } 255 } 256 } 257