1 /* 2 * Copyright (C) 2015 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.telephony; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.os.Parcel; 22 import android.os.Parcelable; 23 import android.os.SystemClock; 24 import android.util.Range; 25 26 import java.lang.annotation.Retention; 27 import java.lang.annotation.RetentionPolicy; 28 import java.util.ArrayList; 29 import java.util.List; 30 31 /** 32 * Reports modem activity information. 33 * @hide 34 */ 35 public final class ModemActivityInfo implements Parcelable { 36 /** 37 * Tx(transmit) power level. see power index below 38 * <ul> 39 * <li> index 0 = tx_power < 0dBm. </li> 40 * <li> index 1 = 0dBm < tx_power < 5dBm. </li> 41 * <li> index 2 = 5dBm < tx_power < 15dBm. </li> 42 * <li> index 3 = 15dBm < tx_power < 20dBm. </li> 43 * <li> index 4 = tx_power > 20dBm. </li> 44 * </ul> 45 */ 46 public static final int TX_POWER_LEVELS = 5; 47 /** 48 * Tx(transmit) power level 0: tx_power < 0dBm 49 */ 50 public static final int TX_POWER_LEVEL_0 = 0; 51 /** 52 * Tx(transmit) power level 1: 0dBm < tx_power < 5dBm 53 */ 54 public static final int TX_POWER_LEVEL_1 = 1; 55 /** 56 * Tx(transmit) power level 2: 5dBm < tx_power < 15dBm 57 */ 58 public static final int TX_POWER_LEVEL_2 = 2; 59 /** 60 * Tx(transmit) power level 3: 15dBm < tx_power < 20dBm. 61 */ 62 public static final int TX_POWER_LEVEL_3 = 3; 63 /** 64 * Tx(transmit) power level 4: tx_power > 20dBm 65 */ 66 public static final int TX_POWER_LEVEL_4 = 4; 67 68 /** @hide */ 69 @IntDef(prefix = {"TX_POWER_LEVEL_"}, value = { 70 TX_POWER_LEVEL_0, 71 TX_POWER_LEVEL_1, 72 TX_POWER_LEVEL_2, 73 TX_POWER_LEVEL_3, 74 TX_POWER_LEVEL_4, 75 }) 76 @Retention(RetentionPolicy.SOURCE) 77 public @interface TxPowerLevel {} 78 79 private static final Range<Integer>[] TX_POWER_RANGES = new Range[] { 80 new Range<>(Integer.MIN_VALUE, 0), 81 new Range<>(0, 5), 82 new Range<>(5, 15), 83 new Range<>(15, 20), 84 new Range<>(20, Integer.MAX_VALUE) 85 86 }; 87 88 private long mTimestamp; 89 private int mSleepTimeMs; 90 private int mIdleTimeMs; 91 private List<TransmitPower> mTransmitPowerInfo = new ArrayList<>(TX_POWER_LEVELS); 92 private int mRxTimeMs; 93 ModemActivityInfo(long timestamp, int sleepTimeMs, int idleTimeMs, @NonNull int[] txTimeMs, int rxTimeMs)94 public ModemActivityInfo(long timestamp, int sleepTimeMs, int idleTimeMs, 95 @NonNull int[] txTimeMs, int rxTimeMs) { 96 mTimestamp = timestamp; 97 mSleepTimeMs = sleepTimeMs; 98 mIdleTimeMs = idleTimeMs; 99 populateTransmitPowerRange(txTimeMs); 100 mRxTimeMs = rxTimeMs; 101 } 102 103 /** helper API to populate tx power range for each bucket **/ populateTransmitPowerRange(@onNull int[] transmitPowerMs)104 private void populateTransmitPowerRange(@NonNull int[] transmitPowerMs) { 105 int i = 0; 106 for ( ; i < Math.min(transmitPowerMs.length, TX_POWER_LEVELS); i++) { 107 mTransmitPowerInfo.add(i, new TransmitPower(TX_POWER_RANGES[i], transmitPowerMs[i])); 108 } 109 // Make sure that mTransmitPowerInfo is fully initialized. 110 for ( ; i < TX_POWER_LEVELS; i++) { 111 mTransmitPowerInfo.add(i, new TransmitPower(TX_POWER_RANGES[i], 0)); 112 } 113 } 114 115 @Override toString()116 public String toString() { 117 return "ModemActivityInfo{" 118 + " mTimestamp=" + mTimestamp 119 + " mSleepTimeMs=" + mSleepTimeMs 120 + " mIdleTimeMs=" + mIdleTimeMs 121 + " mTransmitPowerInfo[]=" + mTransmitPowerInfo.toString() 122 + " mRxTimeMs=" + mRxTimeMs 123 + "}"; 124 } 125 describeContents()126 public int describeContents() { 127 return 0; 128 } 129 130 public static final @android.annotation.NonNull Parcelable.Creator<ModemActivityInfo> CREATOR = 131 new Parcelable.Creator<ModemActivityInfo>() { 132 public ModemActivityInfo createFromParcel(Parcel in) { 133 long timestamp = in.readLong(); 134 int sleepTimeMs = in.readInt(); 135 int idleTimeMs = in.readInt(); 136 int[] txTimeMs = new int[TX_POWER_LEVELS]; 137 for (int i = 0; i < TX_POWER_LEVELS; i++) { 138 txTimeMs[i] = in.readInt(); 139 } 140 int rxTimeMs = in.readInt(); 141 return new ModemActivityInfo(timestamp, sleepTimeMs, idleTimeMs, 142 txTimeMs, rxTimeMs); 143 } 144 145 public ModemActivityInfo[] newArray(int size) { 146 return new ModemActivityInfo[size]; 147 } 148 }; 149 writeToParcel(Parcel dest, int flags)150 public void writeToParcel(Parcel dest, int flags) { 151 dest.writeLong(mTimestamp); 152 dest.writeInt(mSleepTimeMs); 153 dest.writeInt(mIdleTimeMs); 154 for (int i = 0; i < TX_POWER_LEVELS; i++) { 155 dest.writeInt(mTransmitPowerInfo.get(i).getTimeInMillis()); 156 } 157 dest.writeInt(mRxTimeMs); 158 } 159 160 /** 161 * @return milliseconds since boot, including mTimeInMillis spent in sleep. 162 * @see SystemClock#elapsedRealtime() 163 */ getTimestamp()164 public long getTimestamp() { 165 return mTimestamp; 166 } 167 168 /** @hide */ setTimestamp(long timestamp)169 public void setTimestamp(long timestamp) { 170 mTimestamp = timestamp; 171 } 172 173 /** 174 * @return an arrayList of {@link TransmitPower} with each element representing the total time where 175 * transmitter is awake time (in ms) for a given power range (in dbm). 176 * 177 * @see #TX_POWER_LEVELS 178 */ 179 @NonNull getTransmitPowerInfo()180 public List<TransmitPower> getTransmitPowerInfo() { 181 return mTransmitPowerInfo; 182 } 183 184 /** @hide */ setTransmitTimeMillis(int[] txTimeMs)185 public void setTransmitTimeMillis(int[] txTimeMs) { 186 populateTransmitPowerRange(txTimeMs); 187 } 188 189 /** @hide */ 190 @NonNull getTransmitTimeMillis()191 public int[] getTransmitTimeMillis() { 192 int[] transmitTimeMillis = new int[TX_POWER_LEVELS]; 193 for (int i = 0; i < transmitTimeMillis.length; i++) { 194 transmitTimeMillis[i] = mTransmitPowerInfo.get(i).getTimeInMillis(); 195 } 196 return transmitTimeMillis; 197 } 198 199 /** 200 * @return total mTimeInMillis (in ms) when modem is in a low power or sleep state. 201 */ getSleepTimeMillis()202 public int getSleepTimeMillis() { 203 return mSleepTimeMs; 204 } 205 206 /** @hide */ setSleepTimeMillis(int sleepTimeMillis)207 public void setSleepTimeMillis(int sleepTimeMillis) { 208 mSleepTimeMs = sleepTimeMillis; 209 } 210 211 /** 212 * @return total mTimeInMillis (in ms) when modem is awake but neither the transmitter nor receiver are 213 * active. 214 */ getIdleTimeMillis()215 public int getIdleTimeMillis() { 216 return mIdleTimeMs; 217 } 218 219 /** @hide */ setIdleTimeMillis(int idleTimeMillis)220 public void setIdleTimeMillis(int idleTimeMillis) { 221 mIdleTimeMs = idleTimeMillis; 222 } 223 224 /** 225 * @return rx(receive) mTimeInMillis in ms. 226 */ getReceiveTimeMillis()227 public int getReceiveTimeMillis() { 228 return mRxTimeMs; 229 } 230 231 /** @hide */ setReceiveTimeMillis(int rxTimeMillis)232 public void setReceiveTimeMillis(int rxTimeMillis) { 233 mRxTimeMs = rxTimeMillis; 234 } 235 236 /** 237 * Indicate if the ModemActivityInfo is invalid due to modem's invalid reporting. 238 * 239 * @return {@code true} if this {@link ModemActivityInfo} record is valid, 240 * {@code false} otherwise. 241 */ isValid()242 public boolean isValid() { 243 for (TransmitPower powerInfo : getTransmitPowerInfo()) { 244 if(powerInfo.getTimeInMillis() < 0) { 245 return false; 246 } 247 } 248 249 return ((getIdleTimeMillis() >= 0) && (getSleepTimeMillis() >= 0) 250 && (getReceiveTimeMillis() >= 0) && !isEmpty()); 251 } 252 isEmpty()253 private boolean isEmpty() { 254 for (TransmitPower txVal : getTransmitPowerInfo()) { 255 if(txVal.getTimeInMillis() != 0) { 256 return false; 257 } 258 } 259 260 return ((getIdleTimeMillis() == 0) && (getSleepTimeMillis() == 0) 261 && (getReceiveTimeMillis() == 0)); 262 } 263 264 /** 265 * Transmit power Information, including the power range in dbm and the total time (in ms) where 266 * the transmitter is active/awake for this power range. 267 * e.g, range: 0dbm(lower) ~ 5dbm(upper) 268 * time: 5ms 269 */ 270 public class TransmitPower { 271 private int mTimeInMillis; 272 private Range<Integer> mPowerRangeInDbm; 273 /** @hide */ TransmitPower(@onNull Range<Integer> range, int time)274 public TransmitPower(@NonNull Range<Integer> range, int time) { 275 this.mTimeInMillis = time; 276 this.mPowerRangeInDbm = range; 277 } 278 279 /** 280 * @return the total time in ms where the transmitter is active/wake for this power range 281 * {@link #getPowerRangeInDbm()}. 282 */ getTimeInMillis()283 public int getTimeInMillis() { 284 return mTimeInMillis; 285 } 286 287 /** 288 * @return the power range in dbm. e.g, range: 0dbm(lower) ~ 5dbm(upper) 289 */ 290 @NonNull getPowerRangeInDbm()291 public Range<Integer> getPowerRangeInDbm() { 292 return mPowerRangeInDbm; 293 } 294 295 @Override toString()296 public String toString() { 297 return "TransmitPower{" 298 + " mTimeInMillis=" + mTimeInMillis 299 + " mPowerRangeInDbm={" + mPowerRangeInDbm.getLower() 300 + "," + mPowerRangeInDbm.getUpper() 301 + "}}"; 302 } 303 } 304 } 305