diff --git a/telephony/java/android/telephony/ActivityStatsTechSpecificInfo.aidl b/telephony/java/android/telephony/ActivityStatsTechSpecificInfo.aidl new file mode 100644 index 0000000000000..542c6ad748a54 --- /dev/null +++ b/telephony/java/android/telephony/ActivityStatsTechSpecificInfo.aidl @@ -0,0 +1,20 @@ +/* +** +** Copyright 2022, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android.telephony; + +parcelable ActivityStatsTechSpecificInfo; diff --git a/telephony/java/android/telephony/ActivityStatsTechSpecificInfo.java b/telephony/java/android/telephony/ActivityStatsTechSpecificInfo.java new file mode 100644 index 0000000000000..e5a20ea0c3584 --- /dev/null +++ b/telephony/java/android/telephony/ActivityStatsTechSpecificInfo.java @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony; + +import android.annotation.DurationMillisLong; +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; +import android.telephony.ServiceState.FrequencyRange; + +import java.util.Arrays; +import java.util.Objects; + +/** + * Technology specific activity stats info. List of the activity stats for each RATs (2G, 3G, 4G and + * 5G) and frequency ranges (HIGH for sub6 and MMWAVE) in case of 5G. In case implementation doesn't + * have RAT specific activity stats then send only one activity stats info with RAT unknown. + * + * @hide + */ +public final class ActivityStatsTechSpecificInfo implements Parcelable { + private static final int TX_POWER_LEVELS = 5; + + private int mRat; + private int mFrequencyRange; + private int[] mTxTimeMs; + private int mRxTimeMs; + + /** @hide */ + public ActivityStatsTechSpecificInfo( + int rat, @FrequencyRange int frequencyRange, @NonNull int[] txTimeMs, int rxTimeMs) { + Objects.requireNonNull(txTimeMs); + if (txTimeMs.length != TX_POWER_LEVELS) { + throw new IllegalArgumentException("txTimeMs must have length == TX_POWER_LEVELS"); + } + mRat = rat; + mFrequencyRange = frequencyRange; + mTxTimeMs = txTimeMs; + mRxTimeMs = rxTimeMs; + } + + /** + * Returns the radio access technology for this activity stats info. + * + * The returned value is define in {@link AccessNetworkConstants.AccessNetworkType}; + * @hide + */ + public int getRat() { + return mRat; + } + + /** + * Returns the rough frequency range for this activity stats info. + * + * The returned value is define in {@link ServiceState.FrequencyRange}; + * @hide + */ + public @FrequencyRange int getFrequencyRange() { + return mFrequencyRange; + } + + /** + * Gets the amount of time the modem spent transmitting at a certain power level. + * + * @return The amount of time, in milliseconds, that the modem spent transmitting at the given + * power level. + */ + public @DurationMillisLong long getTransmitTimeMillis(int powerLevel) { + return mTxTimeMs[powerLevel]; + } + + /** + * @return The raw array of transmit power durations + * @hide + */ + @NonNull + public int[] getTransmitTimeMillis() { + return mTxTimeMs; + } + + /** + * Gets the amount of time (in milliseconds) when the modem is awake and receiving data. + * + * @return Time in milliseconds. + * @hide + */ + public @DurationMillisLong long getReceiveTimeMillis() { + return mRxTimeMs; + } + /** @hide */ + public void setRat(int rat) { + mRat = rat; + } + + /** @hide */ + public void setFrequencyRange(@FrequencyRange int frequencyRange) { + mFrequencyRange = frequencyRange; + } + + /** @hide */ + public void setReceiveTimeMillis(int receiveTimeMillis) { + mRxTimeMs = receiveTimeMillis; + } + + /** + * Provided for convenience, since the API surface needs to return longs but internal + * representations are ints. + * + * @hide + */ + public void setReceiveTimeMillis(long receiveTimeMillis) { + mRxTimeMs = (int) receiveTimeMillis; + } + + /** @hide */ + public void setTransmitTimeMillis(int[] txTimeMs) { + mTxTimeMs = Arrays.copyOf(txTimeMs, TX_POWER_LEVELS); + } + + /** @hide */ + public boolean isTxPowerValid() { + return Arrays.stream(mTxTimeMs).allMatch((i) -> i >= 0); + } + + /** @hide */ + public boolean isRxPowerValid() { + return getReceiveTimeMillis() >= 0; + } + + /** @hide */ + public boolean isTxPowerEmpty() { + boolean isTxPowerEmpty = + mTxTimeMs == null + || mTxTimeMs.length == 0 + || Arrays.stream(mTxTimeMs).allMatch((i) -> i == 0); + return isTxPowerEmpty; + } + + /** @hide */ + public boolean isRxPowerEmpty() { + return getReceiveTimeMillis() == 0; + } + + @Override + public int hashCode() { + int result = Objects.hash(mRat, mFrequencyRange, mRxTimeMs); + result = 31 * result + Arrays.hashCode(mTxTimeMs); + return result; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ActivityStatsTechSpecificInfo)) return false; + ActivityStatsTechSpecificInfo that = (ActivityStatsTechSpecificInfo) o; + return mRat == that.mRat + && mFrequencyRange == that.mFrequencyRange + && Arrays.equals(mTxTimeMs, that.mTxTimeMs) + && mRxTimeMs == that.mRxTimeMs; + } + + private static String ratToString(int type) { + switch (type) { + case AccessNetworkConstants.AccessNetworkType.UNKNOWN: + return "UNKNOWN"; + case AccessNetworkConstants.AccessNetworkType.GERAN: + return "GERAN"; + case AccessNetworkConstants.AccessNetworkType.UTRAN: + return "UTRAN"; + case AccessNetworkConstants.AccessNetworkType.EUTRAN: + return "EUTRAN"; + case AccessNetworkConstants.AccessNetworkType.CDMA2000: + return "CDMA2000"; + case AccessNetworkConstants.AccessNetworkType.IWLAN: + return "IWLAN"; + case AccessNetworkConstants.AccessNetworkType.NGRAN: + return "NGRAN"; + default: + return Integer.toString(type); + } + } + + @Override + public String toString() { + return new StringBuilder() + .append("{mRat=") + .append(ratToString(mRat)) + .append(",mFrequencyRange=") + .append(ServiceState.frequencyRangeToString(mFrequencyRange)) + .append(",mTxTimeMs[]=") + .append(Arrays.toString(mTxTimeMs)) + .append(",mRxTimeMs=") + .append(mRxTimeMs) + .append("}") + .toString(); + } + + /** + * {@link Parcelable#describeContents} + */ + public int describeContents() { + return 0; + } + + public static final @android.annotation.NonNull Parcelable.Creator< + ActivityStatsTechSpecificInfo> + CREATOR = + new Parcelable.Creator() { + public ActivityStatsTechSpecificInfo createFromParcel(@NonNull Parcel in) { + int rat = in.readInt(); + int frequencyRange = in.readInt(); + int[] txTimeMs = new int[TX_POWER_LEVELS]; + in.readIntArray(txTimeMs); + int rxTimeMs = in.readInt(); + return new ActivityStatsTechSpecificInfo( + rat, frequencyRange, txTimeMs, rxTimeMs); + } + + public ActivityStatsTechSpecificInfo[] newArray(int size) { + return new ActivityStatsTechSpecificInfo[size]; + } + }; + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(mRat); + dest.writeInt(mFrequencyRange); + dest.writeIntArray(mTxTimeMs); + dest.writeInt(mRxTimeMs); + } +} diff --git a/telephony/java/android/telephony/ModemActivityInfo.java b/telephony/java/android/telephony/ModemActivityInfo.java index ec6c25d1b8c69..730a9d183b8f2 100644 --- a/telephony/java/android/telephony/ModemActivityInfo.java +++ b/telephony/java/android/telephony/ModemActivityInfo.java @@ -25,6 +25,7 @@ import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; +import android.telephony.ServiceState.FrequencyRange; import android.util.Range; import java.lang.annotation.Retention; @@ -94,8 +95,10 @@ public final class ModemActivityInfo implements Parcelable { private long mTimestamp; private int mSleepTimeMs; private int mIdleTimeMs; - private int[] mTxTimeMs; - private int mRxTimeMs; + private int[] mTotalTxTimeMs; + private int mTotalRxTimeMs; + private int mSizeOfSpecificInfo; + private ActivityStatsTechSpecificInfo[] mActivityStatsTechSpecificInfo; /** * @hide @@ -110,8 +113,17 @@ public final class ModemActivityInfo implements Parcelable { mTimestamp = timestamp; mSleepTimeMs = sleepTimeMs; mIdleTimeMs = idleTimeMs; - mTxTimeMs = txTimeMs; - mRxTimeMs = rxTimeMs; + mTotalTxTimeMs = txTimeMs; + mTotalRxTimeMs = rxTimeMs; + + mActivityStatsTechSpecificInfo = new ActivityStatsTechSpecificInfo[1]; + mSizeOfSpecificInfo = mActivityStatsTechSpecificInfo.length; + mActivityStatsTechSpecificInfo[0] = + new ActivityStatsTechSpecificInfo( + AccessNetworkConstants.AccessNetworkType.UNKNOWN, + ServiceState.FREQUENCY_RANGE_UNKNOWN, + txTimeMs, + rxTimeMs); } /** @@ -124,14 +136,49 @@ public final class ModemActivityInfo implements Parcelable { this(timestamp, (int) sleepTimeMs, (int) idleTimeMs, txTimeMs, (int) rxTimeMs); } + /** @hide */ + public ModemActivityInfo(long timestamp, int sleepTimeMs, int idleTimeMs, + @NonNull ActivityStatsTechSpecificInfo[] activityStatsTechSpecificInfo) { + mTimestamp = timestamp; + mSleepTimeMs = sleepTimeMs; + mIdleTimeMs = idleTimeMs; + mActivityStatsTechSpecificInfo = activityStatsTechSpecificInfo; + mSizeOfSpecificInfo = mActivityStatsTechSpecificInfo.length; + mTotalTxTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS]; + for (int i = 0; i < getNumTxPowerLevels(); i++) { + for (int j = 0; j < getSpecificInfoLength(); j++) { + mTotalTxTimeMs[i] = mTotalTxTimeMs[i] + + (int) mActivityStatsTechSpecificInfo[j].getTransmitTimeMillis(i); + } + } + mTotalRxTimeMs = 0; + for (int i = 0; i < getSpecificInfoLength(); i++) { + mTotalRxTimeMs = + mTotalRxTimeMs + (int) mActivityStatsTechSpecificInfo[i].getReceiveTimeMillis(); + } + } + + /** + * Provided for convenience in manipulation since the API exposes long values but internal + * representations are ints. + * @hide + */ + public ModemActivityInfo(long timestamp, long sleepTimeMs, long idleTimeMs, + @NonNull ActivityStatsTechSpecificInfo[] activityStatsTechSpecificInfo) { + this(timestamp, (int) sleepTimeMs, (int) idleTimeMs, activityStatsTechSpecificInfo); + } + @Override public String toString() { return "ModemActivityInfo{" - + " mTimestamp=" + mTimestamp - + " mSleepTimeMs=" + mSleepTimeMs - + " mIdleTimeMs=" + mIdleTimeMs - + " mTxTimeMs[]=" + Arrays.toString(mTxTimeMs) - + " mRxTimeMs=" + mRxTimeMs + + " mTimestamp=" + + mTimestamp + + " mSleepTimeMs=" + + mSleepTimeMs + + " mIdleTimeMs=" + + mIdleTimeMs + + " mActivityStatsTechSpecificInfo=" + + Arrays.toString(mActivityStatsTechSpecificInfo) + "}"; } @@ -145,11 +192,17 @@ public final class ModemActivityInfo implements Parcelable { long timestamp = in.readLong(); int sleepTimeMs = in.readInt(); int idleTimeMs = in.readInt(); - int[] txTimeMs = new int[TX_POWER_LEVELS]; - in.readIntArray(txTimeMs); - int rxTimeMs = in.readInt(); - return new ModemActivityInfo(timestamp, sleepTimeMs, idleTimeMs, - txTimeMs, rxTimeMs); + Parcelable[] tempSpecifiers = + in.createTypedArray(ActivityStatsTechSpecificInfo.CREATOR); + ActivityStatsTechSpecificInfo[] activityStatsTechSpecificInfo; + activityStatsTechSpecificInfo = + new ActivityStatsTechSpecificInfo[tempSpecifiers.length]; + for (int i = 0; i < tempSpecifiers.length; i++) { + activityStatsTechSpecificInfo[i] = + (ActivityStatsTechSpecificInfo) tempSpecifiers[i]; + } + return new ModemActivityInfo( + timestamp, sleepTimeMs, idleTimeMs, activityStatsTechSpecificInfo); } public ModemActivityInfo[] newArray(int size) { @@ -165,15 +218,14 @@ public final class ModemActivityInfo implements Parcelable { dest.writeLong(mTimestamp); dest.writeInt(mSleepTimeMs); dest.writeInt(mIdleTimeMs); - dest.writeIntArray(mTxTimeMs); - dest.writeInt(mRxTimeMs); + dest.writeTypedArray(mActivityStatsTechSpecificInfo, flags); } /** * Gets the timestamp at which this modem activity info was recorded. * - * @return The timestamp, as returned by {@link SystemClock#elapsedRealtime()}, when this - * {@link ModemActivityInfo} was recorded. + * @return The timestamp, as returned by {@link SystemClock#elapsedRealtime()}, when this {@link + * ModemActivityInfo} was recorded. */ public @ElapsedRealtimeLong long getTimestampMillis() { return mTimestamp; @@ -188,14 +240,41 @@ public final class ModemActivityInfo implements Parcelable { * Gets the amount of time the modem spent transmitting at a certain power level. * * @param powerLevel The power level to query. - * @return The amount of time, in milliseconds, that the modem spent transmitting at the - * given power level. + * @return The amount of time, in milliseconds, that the modem spent transmitting at the given + * power level. */ public @DurationMillisLong long getTransmitDurationMillisAtPowerLevel( @TxPowerLevel int powerLevel) { - return mTxTimeMs[powerLevel]; + long txTimeMsAtPowerLevel = 0; + for (int i = 0; i < getSpecificInfoLength(); i++) { + txTimeMsAtPowerLevel += + mActivityStatsTechSpecificInfo[i].getTransmitTimeMillis(powerLevel); + } + return txTimeMsAtPowerLevel; } + /** @hide */ + public @DurationMillisLong long getTransmitDurationMillisAtPowerLevel( + @TxPowerLevel int powerLevel, int rat) { + for (int i = 0; i < getSpecificInfoLength(); i++) { + if (mActivityStatsTechSpecificInfo[i].getRat() == rat) { + return mActivityStatsTechSpecificInfo[i].getTransmitTimeMillis(powerLevel); + } + } + return 0; + } + + /** @hide */ + public @DurationMillisLong long getTransmitDurationMillisAtPowerLevel( + @TxPowerLevel int powerLevel, int rat, @FrequencyRange int freq) { + for (int i = 0; i < getSpecificInfoLength(); i++) { + if (mActivityStatsTechSpecificInfo[i].getRat() == rat + && mActivityStatsTechSpecificInfo[i].getFrequencyRange() == freq) { + return mActivityStatsTechSpecificInfo[i].getTransmitTimeMillis(powerLevel); + } + } + return 0; + } /** * Gets the range of transmit powers corresponding to a certain power level. * @@ -208,17 +287,64 @@ public final class ModemActivityInfo implements Parcelable { } /** @hide */ - public void setTransmitTimeMillis(int[] txTimeMs) { - mTxTimeMs = Arrays.copyOf(txTimeMs, TX_POWER_LEVELS); + public int getSpecificInfoRat(int index) { + return mActivityStatsTechSpecificInfo[index].getRat(); } + /** @hide */ + public int getSpecificInfoFrequencyRange(int index) { + return mActivityStatsTechSpecificInfo[index].getFrequencyRange(); + } + /** @hide */ + public void setTransmitTimeMillis(int[] txTimeMs) { + mTotalTxTimeMs = Arrays.copyOf(txTimeMs, TX_POWER_LEVELS); + } + /** @hide */ + public void setTransmitTimeMillis(int rat, int[] txTimeMs) { + for (int i = 0; i < getSpecificInfoLength(); i++) { + if (mActivityStatsTechSpecificInfo[i].getRat() == rat) { + mActivityStatsTechSpecificInfo[i].setTransmitTimeMillis(txTimeMs); + } + } + } + /** @hide */ + public void setTransmitTimeMillis(int rat, int freq, int[] txTimeMs) { + for (int i = 0; i < getSpecificInfoLength(); i++) { + if (mActivityStatsTechSpecificInfo[i].getRat() == rat + && mActivityStatsTechSpecificInfo[i].getFrequencyRange() == freq) { + mActivityStatsTechSpecificInfo[i].setTransmitTimeMillis(txTimeMs); + } + } + } /** * @return The raw array of transmit power durations * @hide */ @NonNull public int[] getTransmitTimeMillis() { - return mTxTimeMs; + return mTotalTxTimeMs; + } + + /** @hide */ + public int[] getTransmitTimeMillis(@AccessNetworkConstants.RadioAccessNetworkType int rat) { + for (int i = 0; i < mActivityStatsTechSpecificInfo.length; i++) { + if (mActivityStatsTechSpecificInfo[i].getRat() == rat) { + return mActivityStatsTechSpecificInfo[i].getTransmitTimeMillis(); + } + } + return new int[5]; + } + + /** @hide */ + public int[] getTransmitTimeMillis( + @AccessNetworkConstants.RadioAccessNetworkType int rat, @FrequencyRange int freq) { + for (int i = 0; i < mActivityStatsTechSpecificInfo.length; i++) { + if (mActivityStatsTechSpecificInfo[i].getRat() == rat + && mActivityStatsTechSpecificInfo[i].getFrequencyRange() == freq) { + return mActivityStatsTechSpecificInfo[i].getTransmitTimeMillis(); + } + } + return new int[5]; } /** @@ -238,6 +364,7 @@ public final class ModemActivityInfo implements Parcelable { /** * Provided for convenience, since the API surface needs to return longs but internal * representations are ints. + * * @hide */ public void setSleepTimeMillis(long sleepTimeMillis) { @@ -257,14 +384,63 @@ public final class ModemActivityInfo implements Parcelable { */ public @NonNull ModemActivityInfo getDelta(@NonNull ModemActivityInfo other) { int[] txTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS]; - for (int i = 0; i < ModemActivityInfo.TX_POWER_LEVELS; i++) { - txTimeMs[i] = other.mTxTimeMs[i] - mTxTimeMs[i]; + + ActivityStatsTechSpecificInfo[] mDeltaSpecificInfo; + mDeltaSpecificInfo = new ActivityStatsTechSpecificInfo[other.getSpecificInfoLength()]; + + boolean matched; + for (int i = 0; i < other.getSpecificInfoLength(); i++) { + matched = false; + for (int j = 0; j < getSpecificInfoLength(); j++) { + int rat = mActivityStatsTechSpecificInfo[j].getRat(); + if (rat == other.mActivityStatsTechSpecificInfo[i].getRat() && !matched) { + if (mActivityStatsTechSpecificInfo[j].getRat() + == AccessNetworkConstants.AccessNetworkType.NGRAN) { + if (other.mActivityStatsTechSpecificInfo[i].getFrequencyRange() + == mActivityStatsTechSpecificInfo[j].getFrequencyRange()) { + int freq = mActivityStatsTechSpecificInfo[j].getFrequencyRange(); + for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) { + txTimeMs[lvl] = + (int) (other.getTransmitDurationMillisAtPowerLevel( + lvl, rat, freq) + - getTransmitDurationMillisAtPowerLevel( + lvl, rat, freq)); + } + matched = true; + mDeltaSpecificInfo[i] = + new ActivityStatsTechSpecificInfo( + rat, + freq, + txTimeMs, + (int) (other.getReceiveTimeMillis(rat, freq) + - getReceiveTimeMillis(rat, freq))); + } + } else { + for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) { + txTimeMs[lvl] = + (int) (other.getTransmitDurationMillisAtPowerLevel(lvl, rat) + - getTransmitDurationMillisAtPowerLevel(lvl, rat)); + } + matched = true; + mDeltaSpecificInfo[i] = + new ActivityStatsTechSpecificInfo( + rat, + ServiceState.FREQUENCY_RANGE_UNKNOWN, + txTimeMs, + (int) (other.getReceiveTimeMillis(rat) + - getReceiveTimeMillis(rat))); + } + } + } + if (!matched) { + mDeltaSpecificInfo[i] = other.mActivityStatsTechSpecificInfo[i]; + } } - return new ModemActivityInfo(other.getTimestampMillis(), + return new ModemActivityInfo( + other.getTimestampMillis(), other.getSleepTimeMillis() - getSleepTimeMillis(), other.getIdleTimeMillis() - getIdleTimeMillis(), - txTimeMs, - other.getReceiveTimeMillis() - getReceiveTimeMillis()); + mDeltaSpecificInfo); } /** @@ -285,6 +461,7 @@ public final class ModemActivityInfo implements Parcelable { /** * Provided for convenience, since the API surface needs to return longs but internal * representations are ints. + * * @hide */ public void setIdleTimeMillis(long idleTimeMillis) { @@ -297,21 +474,66 @@ public final class ModemActivityInfo implements Parcelable { * @return Time in milliseconds. */ public @DurationMillisLong long getReceiveTimeMillis() { - return mRxTimeMs; + return mTotalRxTimeMs; + } + + /** @hide */ + public @DurationMillisLong long getReceiveTimeMillis(int rat) { + for (int i = 0; i < mActivityStatsTechSpecificInfo.length; i++) { + if (mActivityStatsTechSpecificInfo[i].getRat() == rat) { + return mActivityStatsTechSpecificInfo[i].getReceiveTimeMillis(); + } + } + return 0; + } + /** @hide */ + public @DurationMillisLong long getReceiveTimeMillis(int rat, int freq) { + for (int i = 0; i < mActivityStatsTechSpecificInfo.length; i++) { + if (mActivityStatsTechSpecificInfo[i].getRat() == rat + && mActivityStatsTechSpecificInfo[i].getFrequencyRange() == freq) { + return mActivityStatsTechSpecificInfo[i].getReceiveTimeMillis(); + } + } + return 0; } /** @hide */ public void setReceiveTimeMillis(int rxTimeMillis) { - mRxTimeMs = rxTimeMillis; + mTotalRxTimeMs = rxTimeMillis; } /** * Provided for convenience, since the API surface needs to return longs but internal * representations are ints. + * * @hide */ public void setReceiveTimeMillis(long receiveTimeMillis) { - mRxTimeMs = (int) receiveTimeMillis; + mTotalRxTimeMs = (int) receiveTimeMillis; + } + + /** @hide */ + public void setReceiveTimeMillis(int rat, long receiveTimeMillis) { + for (int i = 0; i < mActivityStatsTechSpecificInfo.length; i++) { + if (mActivityStatsTechSpecificInfo[i].getRat() == rat) { + mActivityStatsTechSpecificInfo[i].setReceiveTimeMillis(receiveTimeMillis); + } + } + } + + /** @hide */ + public void setReceiveTimeMillis(int rat, int freq, long receiveTimeMillis) { + for (int i = 0; i < mActivityStatsTechSpecificInfo.length; i++) { + if (mActivityStatsTechSpecificInfo[i].getRat() == rat + && mActivityStatsTechSpecificInfo[i].getFrequencyRange() == freq) { + mActivityStatsTechSpecificInfo[i].setReceiveTimeMillis(receiveTimeMillis); + } + } + } + + /** @hide */ + public int getSpecificInfoLength() { + return mSizeOfSpecificInfo; } /** @@ -323,23 +545,42 @@ public final class ModemActivityInfo implements Parcelable { */ @TestApi public boolean isValid() { - boolean isTxPowerValid = Arrays.stream(mTxTimeMs).allMatch((i) -> i >= 0); - - return isTxPowerValid && ((getIdleTimeMillis() >= 0) && (getSleepTimeMillis() >= 0) - && (getReceiveTimeMillis() >= 0) && !isEmpty()); + if (mActivityStatsTechSpecificInfo == null) { + return false; + } else { + boolean isTxPowerValid = true; + boolean isRxPowerValid = true; + for (int i = 0; i < getSpecificInfoLength(); i++) { + if (!mActivityStatsTechSpecificInfo[i].isTxPowerValid()) { + isTxPowerValid = false; + } + if (!mActivityStatsTechSpecificInfo[i].isRxPowerValid()) { + isRxPowerValid = false; + } + } + return isTxPowerValid + && isRxPowerValid + && ((getIdleTimeMillis() >= 0) && (getSleepTimeMillis() >= 0) && !isEmpty()); + } } /** @hide */ @TestApi public boolean isEmpty() { - boolean isTxPowerEmpty = mTxTimeMs == null || mTxTimeMs.length == 0 - || Arrays.stream(mTxTimeMs).allMatch((i) -> i == 0); - - return isTxPowerEmpty && ((getIdleTimeMillis() == 0) && (getSleepTimeMillis() == 0) - && (getReceiveTimeMillis() == 0)); + boolean isTxPowerEmpty = false; + boolean isRxPowerEmpty = false; + for (int i = 0; i < getSpecificInfoLength(); i++) { + if (mActivityStatsTechSpecificInfo[i].isTxPowerEmpty()) { + isTxPowerEmpty = true; + } + if (mActivityStatsTechSpecificInfo[i].isRxPowerEmpty()) { + isRxPowerEmpty = true; + } + } + return isTxPowerEmpty + && ((getIdleTimeMillis() == 0) && (getSleepTimeMillis() == 0) && isRxPowerEmpty); } - @Override public boolean equals(Object o) { if (this == o) return true; @@ -348,14 +589,15 @@ public final class ModemActivityInfo implements Parcelable { return mTimestamp == that.mTimestamp && mSleepTimeMs == that.mSleepTimeMs && mIdleTimeMs == that.mIdleTimeMs - && mRxTimeMs == that.mRxTimeMs - && Arrays.equals(mTxTimeMs, that.mTxTimeMs); + && mSizeOfSpecificInfo == that.mSizeOfSpecificInfo + && Arrays.equals( + mActivityStatsTechSpecificInfo, that.mActivityStatsTechSpecificInfo); } @Override public int hashCode() { - int result = Objects.hash(mTimestamp, mSleepTimeMs, mIdleTimeMs, mRxTimeMs); - result = 31 * result + Arrays.hashCode(mTxTimeMs); + int result = Objects.hash(mTimestamp, mSleepTimeMs, mIdleTimeMs, mTotalRxTimeMs); + result = 31 * result + Arrays.hashCode(mTotalTxTimeMs); return result; } }