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.DurationMillisLong; 20 import android.annotation.ElapsedRealtimeLong; 21 import android.annotation.IntDef; 22 import android.annotation.NonNull; 23 import android.annotation.SystemApi; 24 import android.annotation.TestApi; 25 import android.os.Parcel; 26 import android.os.Parcelable; 27 import android.os.SystemClock; 28 import android.telephony.ServiceState.FrequencyRange; 29 import android.util.Range; 30 31 import java.lang.annotation.Retention; 32 import java.lang.annotation.RetentionPolicy; 33 import java.util.Arrays; 34 import java.util.Objects; 35 36 /** 37 * Contains information about the modem's activity. May be useful for power stats reporting. 38 * @hide 39 */ 40 @android.ravenwood.annotation.RavenwoodKeepWholeClass 41 @SystemApi 42 public final class ModemActivityInfo implements Parcelable { 43 private static final int TX_POWER_LEVELS = 5; 44 45 /** 46 * Corresponds to transmit power of less than 0dBm. 47 */ 48 public static final int TX_POWER_LEVEL_0 = 0; 49 50 /** 51 * Corresponds to transmit power between 0dBm and 5dBm. 52 */ 53 public static final int TX_POWER_LEVEL_1 = 1; 54 55 /** 56 * Corresponds to transmit power between 5dBm and 15dBm. 57 */ 58 public static final int TX_POWER_LEVEL_2 = 2; 59 60 /** 61 * Corresponds to transmit power between 15dBm and 20dBm. 62 */ 63 public static final int TX_POWER_LEVEL_3 = 3; 64 65 /** 66 * Corresponds to transmit power above 20dBm. 67 */ 68 public static final int TX_POWER_LEVEL_4 = 4; 69 70 /** 71 * The number of transmit power levels. Fixed by HAL definition. 72 */ getNumTxPowerLevels()73 public static int getNumTxPowerLevels() { 74 return TX_POWER_LEVELS; 75 } 76 77 /** @hide */ 78 @IntDef(prefix = {"TX_POWER_LEVEL_"}, value = { 79 TX_POWER_LEVEL_0, 80 TX_POWER_LEVEL_1, 81 TX_POWER_LEVEL_2, 82 TX_POWER_LEVEL_3, 83 TX_POWER_LEVEL_4, 84 }) 85 @Retention(RetentionPolicy.SOURCE) 86 public @interface TxPowerLevel {} 87 88 private static final Range<Integer>[] TX_POWER_RANGES = new Range[] { 89 new Range<>(Integer.MIN_VALUE, 0), 90 new Range<>(0, 5), 91 new Range<>(5, 15), 92 new Range<>(15, 20), 93 new Range<>(20, Integer.MAX_VALUE) 94 }; 95 96 private long mTimestamp; 97 private int mSleepTimeMs; 98 private int mIdleTimeMs; 99 private int[] mTotalTxTimeMs; 100 private int mTotalRxTimeMs; 101 private int mSizeOfSpecificInfo; 102 private ActivityStatsTechSpecificInfo[] mActivityStatsTechSpecificInfo; 103 104 /** 105 * @hide 106 */ 107 @TestApi ModemActivityInfo(long timestamp, int sleepTimeMs, int idleTimeMs, @NonNull int[] txTimeMs, int rxTimeMs)108 public ModemActivityInfo(long timestamp, int sleepTimeMs, int idleTimeMs, 109 @NonNull int[] txTimeMs, int rxTimeMs) { 110 Objects.requireNonNull(txTimeMs); 111 if (txTimeMs.length != TX_POWER_LEVELS) { 112 throw new IllegalArgumentException("txTimeMs must have length == TX_POWER_LEVELS"); 113 } 114 mTimestamp = timestamp; 115 mSleepTimeMs = sleepTimeMs; 116 mIdleTimeMs = idleTimeMs; 117 mTotalTxTimeMs = txTimeMs; 118 mTotalRxTimeMs = rxTimeMs; 119 120 mActivityStatsTechSpecificInfo = new ActivityStatsTechSpecificInfo[1]; 121 mSizeOfSpecificInfo = mActivityStatsTechSpecificInfo.length; 122 mActivityStatsTechSpecificInfo[0] = 123 new ActivityStatsTechSpecificInfo( 124 AccessNetworkConstants.AccessNetworkType.UNKNOWN, 125 ServiceState.FREQUENCY_RANGE_UNKNOWN, 126 txTimeMs, 127 rxTimeMs); 128 } 129 130 /** 131 * Provided for convenience in manipulation since the API exposes long values but internal 132 * representations are ints. 133 * @hide 134 */ ModemActivityInfo(long timestamp, long sleepTimeMs, long idleTimeMs, @NonNull int[] txTimeMs, long rxTimeMs)135 public ModemActivityInfo(long timestamp, long sleepTimeMs, long idleTimeMs, 136 @NonNull int[] txTimeMs, long rxTimeMs) { 137 this(timestamp, (int) sleepTimeMs, (int) idleTimeMs, txTimeMs, (int) rxTimeMs); 138 } 139 140 /** @hide */ ModemActivityInfo(long timestamp, int sleepTimeMs, int idleTimeMs, @NonNull ActivityStatsTechSpecificInfo[] activityStatsTechSpecificInfo)141 public ModemActivityInfo(long timestamp, int sleepTimeMs, int idleTimeMs, 142 @NonNull ActivityStatsTechSpecificInfo[] activityStatsTechSpecificInfo) { 143 mTimestamp = timestamp; 144 mSleepTimeMs = sleepTimeMs; 145 mIdleTimeMs = idleTimeMs; 146 mActivityStatsTechSpecificInfo = activityStatsTechSpecificInfo; 147 mSizeOfSpecificInfo = mActivityStatsTechSpecificInfo.length; 148 mTotalTxTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS]; 149 for (int i = 0; i < getNumTxPowerLevels(); i++) { 150 for (int j = 0; j < getSpecificInfoLength(); j++) { 151 mTotalTxTimeMs[i] = mTotalTxTimeMs[i] 152 + (int) mActivityStatsTechSpecificInfo[j].getTransmitTimeMillis(i); 153 } 154 } 155 mTotalRxTimeMs = 0; 156 for (int i = 0; i < getSpecificInfoLength(); i++) { 157 mTotalRxTimeMs = 158 mTotalRxTimeMs + (int) mActivityStatsTechSpecificInfo[i].getReceiveTimeMillis(); 159 } 160 } 161 162 /** 163 * Provided for convenience in manipulation since the API exposes long values but internal 164 * representations are ints. 165 * @hide 166 */ ModemActivityInfo(long timestamp, long sleepTimeMs, long idleTimeMs, @NonNull ActivityStatsTechSpecificInfo[] activityStatsTechSpecificInfo)167 public ModemActivityInfo(long timestamp, long sleepTimeMs, long idleTimeMs, 168 @NonNull ActivityStatsTechSpecificInfo[] activityStatsTechSpecificInfo) { 169 this(timestamp, (int) sleepTimeMs, (int) idleTimeMs, activityStatsTechSpecificInfo); 170 } 171 172 @Override toString()173 public String toString() { 174 return "ModemActivityInfo{" 175 + " mTimestamp=" 176 + mTimestamp 177 + " mSleepTimeMs=" 178 + mSleepTimeMs 179 + " mIdleTimeMs=" 180 + mIdleTimeMs 181 + " mActivityStatsTechSpecificInfo=" 182 + Arrays.toString(mActivityStatsTechSpecificInfo) 183 + "}"; 184 } 185 describeContents()186 public int describeContents() { 187 return 0; 188 } 189 190 public static final @android.annotation.NonNull Parcelable.Creator<ModemActivityInfo> CREATOR = 191 new Parcelable.Creator<ModemActivityInfo>() { 192 public ModemActivityInfo createFromParcel(@NonNull Parcel in) { 193 long timestamp = in.readLong(); 194 int sleepTimeMs = in.readInt(); 195 int idleTimeMs = in.readInt(); 196 Parcelable[] tempSpecifiers = 197 in.createTypedArray(ActivityStatsTechSpecificInfo.CREATOR); 198 ActivityStatsTechSpecificInfo[] activityStatsTechSpecificInfo; 199 activityStatsTechSpecificInfo = 200 new ActivityStatsTechSpecificInfo[tempSpecifiers.length]; 201 for (int i = 0; i < tempSpecifiers.length; i++) { 202 activityStatsTechSpecificInfo[i] = 203 (ActivityStatsTechSpecificInfo) tempSpecifiers[i]; 204 } 205 return new ModemActivityInfo( 206 timestamp, sleepTimeMs, idleTimeMs, activityStatsTechSpecificInfo); 207 } 208 209 public ModemActivityInfo[] newArray(int size) { 210 return new ModemActivityInfo[size]; 211 } 212 }; 213 214 /** 215 * @param dest The Parcel in which the object should be written. 216 * @param flags Additional flags about how the object should be written. 217 */ writeToParcel(@onNull Parcel dest, int flags)218 public void writeToParcel(@NonNull Parcel dest, int flags) { 219 dest.writeLong(mTimestamp); 220 dest.writeInt(mSleepTimeMs); 221 dest.writeInt(mIdleTimeMs); 222 dest.writeTypedArray(mActivityStatsTechSpecificInfo, flags); 223 } 224 225 /** 226 * Gets the timestamp at which this modem activity info was recorded. 227 * 228 * @return The timestamp, as returned by {@link SystemClock#elapsedRealtime()}, when this {@link 229 * ModemActivityInfo} was recorded. 230 */ getTimestampMillis()231 public @ElapsedRealtimeLong long getTimestampMillis() { 232 return mTimestamp; 233 } 234 235 /** @hide */ setTimestamp(long timestamp)236 public void setTimestamp(long timestamp) { 237 mTimestamp = timestamp; 238 } 239 240 /** 241 * Gets the amount of time the modem spent transmitting at a certain power level. 242 * 243 * @param powerLevel The power level to query. 244 * @return The amount of time, in milliseconds, that the modem spent transmitting at the given 245 * power level. 246 */ getTransmitDurationMillisAtPowerLevel( @xPowerLevel int powerLevel)247 public @DurationMillisLong long getTransmitDurationMillisAtPowerLevel( 248 @TxPowerLevel int powerLevel) { 249 long txTimeMsAtPowerLevel = 0; 250 for (int i = 0; i < getSpecificInfoLength(); i++) { 251 txTimeMsAtPowerLevel += 252 mActivityStatsTechSpecificInfo[i].getTransmitTimeMillis(powerLevel); 253 } 254 return txTimeMsAtPowerLevel; 255 } 256 257 /** @hide */ getTransmitDurationMillisAtPowerLevel( @xPowerLevel int powerLevel, int rat)258 public @DurationMillisLong long getTransmitDurationMillisAtPowerLevel( 259 @TxPowerLevel int powerLevel, int rat) { 260 for (int i = 0; i < getSpecificInfoLength(); i++) { 261 if (mActivityStatsTechSpecificInfo[i].getRat() == rat) { 262 return mActivityStatsTechSpecificInfo[i].getTransmitTimeMillis(powerLevel); 263 } 264 } 265 return 0; 266 } 267 268 /** @hide */ getTransmitDurationMillisAtPowerLevel( @xPowerLevel int powerLevel, int rat, @FrequencyRange int freq)269 public @DurationMillisLong long getTransmitDurationMillisAtPowerLevel( 270 @TxPowerLevel int powerLevel, int rat, @FrequencyRange int freq) { 271 for (int i = 0; i < getSpecificInfoLength(); i++) { 272 if (mActivityStatsTechSpecificInfo[i].getRat() == rat 273 && mActivityStatsTechSpecificInfo[i].getFrequencyRange() == freq) { 274 return mActivityStatsTechSpecificInfo[i].getTransmitTimeMillis(powerLevel); 275 } 276 } 277 return 0; 278 } 279 /** 280 * Gets the range of transmit powers corresponding to a certain power level. 281 * 282 * @param powerLevel The power level to query 283 * @return A {@link Range} object representing the range of intensities (in dBm) to which this 284 * power level corresponds. 285 */ getTransmitPowerRange(@xPowerLevel int powerLevel)286 public @NonNull Range<Integer> getTransmitPowerRange(@TxPowerLevel int powerLevel) { 287 return TX_POWER_RANGES[powerLevel]; 288 } 289 290 /** @hide */ getSpecificInfoRat(int index)291 public int getSpecificInfoRat(int index) { 292 return mActivityStatsTechSpecificInfo[index].getRat(); 293 } 294 295 /** @hide */ getSpecificInfoFrequencyRange(int index)296 public int getSpecificInfoFrequencyRange(int index) { 297 return mActivityStatsTechSpecificInfo[index].getFrequencyRange(); 298 } 299 /** @hide */ setTransmitTimeMillis(int[] txTimeMs)300 public void setTransmitTimeMillis(int[] txTimeMs) { 301 mTotalTxTimeMs = Arrays.copyOf(txTimeMs, TX_POWER_LEVELS); 302 } 303 /** @hide */ setTransmitTimeMillis(int rat, int[] txTimeMs)304 public void setTransmitTimeMillis(int rat, int[] txTimeMs) { 305 for (int i = 0; i < getSpecificInfoLength(); i++) { 306 if (mActivityStatsTechSpecificInfo[i].getRat() == rat) { 307 mActivityStatsTechSpecificInfo[i].setTransmitTimeMillis(txTimeMs); 308 } 309 } 310 } 311 /** @hide */ setTransmitTimeMillis(int rat, int freq, int[] txTimeMs)312 public void setTransmitTimeMillis(int rat, int freq, int[] txTimeMs) { 313 for (int i = 0; i < getSpecificInfoLength(); i++) { 314 if (mActivityStatsTechSpecificInfo[i].getRat() == rat 315 && mActivityStatsTechSpecificInfo[i].getFrequencyRange() == freq) { 316 mActivityStatsTechSpecificInfo[i].setTransmitTimeMillis(txTimeMs); 317 } 318 } 319 } 320 /** 321 * @return The raw array of transmit power durations 322 * @hide 323 */ 324 @NonNull getTransmitTimeMillis()325 public int[] getTransmitTimeMillis() { 326 return mTotalTxTimeMs; 327 } 328 329 /** @hide */ getTransmitTimeMillis(@ccessNetworkConstants.RadioAccessNetworkType int rat)330 public int[] getTransmitTimeMillis(@AccessNetworkConstants.RadioAccessNetworkType int rat) { 331 for (int i = 0; i < mActivityStatsTechSpecificInfo.length; i++) { 332 if (mActivityStatsTechSpecificInfo[i].getRat() == rat) { 333 return mActivityStatsTechSpecificInfo[i].getTransmitTimeMillis(); 334 } 335 } 336 return new int[5]; 337 } 338 339 /** @hide */ getTransmitTimeMillis( @ccessNetworkConstants.RadioAccessNetworkType int rat, @FrequencyRange int freq)340 public int[] getTransmitTimeMillis( 341 @AccessNetworkConstants.RadioAccessNetworkType int rat, @FrequencyRange int freq) { 342 for (int i = 0; i < mActivityStatsTechSpecificInfo.length; i++) { 343 if (mActivityStatsTechSpecificInfo[i].getRat() == rat 344 && mActivityStatsTechSpecificInfo[i].getFrequencyRange() == freq) { 345 return mActivityStatsTechSpecificInfo[i].getTransmitTimeMillis(); 346 } 347 } 348 return new int[5]; 349 } 350 351 /** 352 * Gets the amount of time (in milliseconds) when the modem is in a low power or sleep state. 353 * 354 * @return Time in milliseconds. 355 */ getSleepTimeMillis()356 public @DurationMillisLong long getSleepTimeMillis() { 357 return mSleepTimeMs; 358 } 359 360 /** @hide */ setSleepTimeMillis(int sleepTimeMillis)361 public void setSleepTimeMillis(int sleepTimeMillis) { 362 mSleepTimeMs = sleepTimeMillis; 363 } 364 365 /** 366 * Provided for convenience, since the API surface needs to return longs but internal 367 * representations are ints. 368 * 369 * @hide 370 */ setSleepTimeMillis(long sleepTimeMillis)371 public void setSleepTimeMillis(long sleepTimeMillis) { 372 mSleepTimeMs = (int) sleepTimeMillis; 373 } 374 375 /** 376 * Computes the difference between this instance of {@link ModemActivityInfo} and another 377 * instance. 378 * 379 * This method should be used to compute the amount of activity that has happened between two 380 * samples of modem activity taken at separate times. The sample passed in as an argument to 381 * this method should be the one that's taken later in time (and therefore has more activity). 382 * @param other The other instance of {@link ModemActivityInfo} to diff against. 383 * @return An instance of {@link ModemActivityInfo} representing the difference in modem 384 * activity. 385 */ getDelta(@onNull ModemActivityInfo other)386 public @NonNull ModemActivityInfo getDelta(@NonNull ModemActivityInfo other) { 387 ActivityStatsTechSpecificInfo[] mDeltaSpecificInfo; 388 mDeltaSpecificInfo = new ActivityStatsTechSpecificInfo[other.getSpecificInfoLength()]; 389 390 boolean matched; 391 for (int i = 0; i < other.getSpecificInfoLength(); i++) { 392 matched = false; 393 for (int j = 0; j < getSpecificInfoLength(); j++) { 394 int rat = mActivityStatsTechSpecificInfo[j].getRat(); 395 if (rat == other.mActivityStatsTechSpecificInfo[i].getRat() && !matched) { 396 if (mActivityStatsTechSpecificInfo[j].getRat() 397 == AccessNetworkConstants.AccessNetworkType.NGRAN) { 398 if (other.mActivityStatsTechSpecificInfo[i].getFrequencyRange() 399 == mActivityStatsTechSpecificInfo[j].getFrequencyRange()) { 400 int freq = mActivityStatsTechSpecificInfo[j].getFrequencyRange(); 401 int[] txTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS]; 402 for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) { 403 txTimeMs[lvl] = 404 (int) (other.getTransmitDurationMillisAtPowerLevel( 405 lvl, rat, freq) 406 - getTransmitDurationMillisAtPowerLevel( 407 lvl, rat, freq)); 408 } 409 matched = true; 410 mDeltaSpecificInfo[i] = 411 new ActivityStatsTechSpecificInfo( 412 rat, 413 freq, 414 txTimeMs, 415 (int) (other.getReceiveTimeMillis(rat, freq) 416 - getReceiveTimeMillis(rat, freq))); 417 } 418 } else { 419 int[] txTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS]; 420 for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) { 421 txTimeMs[lvl] = 422 (int) (other.getTransmitDurationMillisAtPowerLevel(lvl, rat) 423 - getTransmitDurationMillisAtPowerLevel(lvl, rat)); 424 } 425 matched = true; 426 mDeltaSpecificInfo[i] = 427 new ActivityStatsTechSpecificInfo( 428 rat, 429 ServiceState.FREQUENCY_RANGE_UNKNOWN, 430 txTimeMs, 431 (int) (other.getReceiveTimeMillis(rat) 432 - getReceiveTimeMillis(rat))); 433 } 434 } 435 } 436 if (!matched) { 437 mDeltaSpecificInfo[i] = other.mActivityStatsTechSpecificInfo[i]; 438 } 439 } 440 return new ModemActivityInfo( 441 other.getTimestampMillis(), 442 other.getSleepTimeMillis() - getSleepTimeMillis(), 443 other.getIdleTimeMillis() - getIdleTimeMillis(), 444 mDeltaSpecificInfo); 445 } 446 447 /** 448 * Gets the amount of time (in milliseconds) when the modem is awake but neither transmitting 449 * nor receiving. 450 * 451 * @return Time in milliseconds. 452 */ getIdleTimeMillis()453 public @DurationMillisLong long getIdleTimeMillis() { 454 return mIdleTimeMs; 455 } 456 457 /** @hide */ setIdleTimeMillis(int idleTimeMillis)458 public void setIdleTimeMillis(int idleTimeMillis) { 459 mIdleTimeMs = idleTimeMillis; 460 } 461 462 /** 463 * Provided for convenience, since the API surface needs to return longs but internal 464 * representations are ints. 465 * 466 * @hide 467 */ setIdleTimeMillis(long idleTimeMillis)468 public void setIdleTimeMillis(long idleTimeMillis) { 469 mIdleTimeMs = (int) idleTimeMillis; 470 } 471 472 /** 473 * Gets the amount of time (in milliseconds) when the modem is awake and receiving data. 474 * 475 * @return Time in milliseconds. 476 */ getReceiveTimeMillis()477 public @DurationMillisLong long getReceiveTimeMillis() { 478 return mTotalRxTimeMs; 479 } 480 481 /** @hide */ getReceiveTimeMillis(int rat)482 public @DurationMillisLong long getReceiveTimeMillis(int rat) { 483 for (int i = 0; i < mActivityStatsTechSpecificInfo.length; i++) { 484 if (mActivityStatsTechSpecificInfo[i].getRat() == rat) { 485 return mActivityStatsTechSpecificInfo[i].getReceiveTimeMillis(); 486 } 487 } 488 return 0; 489 } 490 /** @hide */ getReceiveTimeMillis(int rat, int freq)491 public @DurationMillisLong long getReceiveTimeMillis(int rat, int freq) { 492 for (int i = 0; i < mActivityStatsTechSpecificInfo.length; i++) { 493 if (mActivityStatsTechSpecificInfo[i].getRat() == rat 494 && mActivityStatsTechSpecificInfo[i].getFrequencyRange() == freq) { 495 return mActivityStatsTechSpecificInfo[i].getReceiveTimeMillis(); 496 } 497 } 498 return 0; 499 } 500 501 /** @hide */ setReceiveTimeMillis(int rxTimeMillis)502 public void setReceiveTimeMillis(int rxTimeMillis) { 503 mTotalRxTimeMs = rxTimeMillis; 504 } 505 506 /** 507 * Provided for convenience, since the API surface needs to return longs but internal 508 * representations are ints. 509 * 510 * @hide 511 */ setReceiveTimeMillis(long receiveTimeMillis)512 public void setReceiveTimeMillis(long receiveTimeMillis) { 513 mTotalRxTimeMs = (int) receiveTimeMillis; 514 } 515 516 /** @hide */ setReceiveTimeMillis(int rat, long receiveTimeMillis)517 public void setReceiveTimeMillis(int rat, long receiveTimeMillis) { 518 for (int i = 0; i < mActivityStatsTechSpecificInfo.length; i++) { 519 if (mActivityStatsTechSpecificInfo[i].getRat() == rat) { 520 mActivityStatsTechSpecificInfo[i].setReceiveTimeMillis(receiveTimeMillis); 521 } 522 } 523 } 524 525 /** @hide */ setReceiveTimeMillis(int rat, int freq, long receiveTimeMillis)526 public void setReceiveTimeMillis(int rat, int freq, long receiveTimeMillis) { 527 for (int i = 0; i < mActivityStatsTechSpecificInfo.length; i++) { 528 if (mActivityStatsTechSpecificInfo[i].getRat() == rat 529 && mActivityStatsTechSpecificInfo[i].getFrequencyRange() == freq) { 530 mActivityStatsTechSpecificInfo[i].setReceiveTimeMillis(receiveTimeMillis); 531 } 532 } 533 } 534 535 /** @hide */ getSpecificInfoLength()536 public int getSpecificInfoLength() { 537 return mSizeOfSpecificInfo; 538 } 539 540 /** 541 * Indicates if the modem has reported valid {@link ModemActivityInfo}. 542 * 543 * @return {@code true} if this {@link ModemActivityInfo} record is valid, 544 * {@code false} otherwise. 545 * @hide 546 */ 547 @TestApi isValid()548 public boolean isValid() { 549 if (mActivityStatsTechSpecificInfo == null) { 550 return false; 551 } else { 552 boolean isTxPowerValid = true; 553 boolean isRxPowerValid = true; 554 for (int i = 0; i < getSpecificInfoLength(); i++) { 555 if (!mActivityStatsTechSpecificInfo[i].isTxPowerValid()) { 556 isTxPowerValid = false; 557 } 558 if (!mActivityStatsTechSpecificInfo[i].isRxPowerValid()) { 559 isRxPowerValid = false; 560 } 561 } 562 return isTxPowerValid 563 && isRxPowerValid 564 && ((getIdleTimeMillis() >= 0) && (getSleepTimeMillis() >= 0) && !isEmpty()); 565 } 566 } 567 568 /** @hide */ 569 @TestApi isEmpty()570 public boolean isEmpty() { 571 boolean isTxPowerEmpty = true; 572 boolean isRxPowerEmpty = true; 573 for (int i = 0; i < getSpecificInfoLength(); i++) { 574 if (!mActivityStatsTechSpecificInfo[i].isTxPowerEmpty()) { 575 isTxPowerEmpty = false; 576 } 577 if (!mActivityStatsTechSpecificInfo[i].isRxPowerEmpty()) { 578 isRxPowerEmpty = false; 579 } 580 } 581 return isTxPowerEmpty 582 && ((getIdleTimeMillis() == 0) && (getSleepTimeMillis() == 0) && isRxPowerEmpty); 583 } 584 585 @Override equals(Object o)586 public boolean equals(Object o) { 587 if (this == o) return true; 588 if (o == null || getClass() != o.getClass()) return false; 589 ModemActivityInfo that = (ModemActivityInfo) o; 590 return mTimestamp == that.mTimestamp 591 && mSleepTimeMs == that.mSleepTimeMs 592 && mIdleTimeMs == that.mIdleTimeMs 593 && mSizeOfSpecificInfo == that.mSizeOfSpecificInfo 594 && Arrays.equals( 595 mActivityStatsTechSpecificInfo, that.mActivityStatsTechSpecificInfo); 596 } 597 598 @Override hashCode()599 public int hashCode() { 600 int result = Objects.hash(mTimestamp, mSleepTimeMs, mIdleTimeMs, mTotalRxTimeMs); 601 result = 31 * result + Arrays.hashCode(mTotalTxTimeMs); 602 return result; 603 } 604 } 605