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