blob: ec6c25d1b8c69449830bdd0fe4709fad83a5d8a4 [file] [log] [blame]
/*
* Copyright (C) 2015 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.ElapsedRealtimeLong;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
import android.util.Range;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.Objects;
/**
* Contains information about the modem's activity. May be useful for power stats reporting.
* @hide
*/
@SystemApi
public final class ModemActivityInfo implements Parcelable {
private static final int TX_POWER_LEVELS = 5;
/**
* Corresponds to transmit power of less than 0dBm.
*/
public static final int TX_POWER_LEVEL_0 = 0;
/**
* Corresponds to transmit power between 0dBm and 5dBm.
*/
public static final int TX_POWER_LEVEL_1 = 1;
/**
* Corresponds to transmit power between 5dBm and 15dBm.
*/
public static final int TX_POWER_LEVEL_2 = 2;
/**
* Corresponds to transmit power between 15dBm and 20dBm.
*/
public static final int TX_POWER_LEVEL_3 = 3;
/**
* Corresponds to transmit power above 20dBm.
*/
public static final int TX_POWER_LEVEL_4 = 4;
/**
* The number of transmit power levels. Fixed by HAL definition.
*/
public static int getNumTxPowerLevels() {
return TX_POWER_LEVELS;
}
/** @hide */
@IntDef(prefix = {"TX_POWER_LEVEL_"}, value = {
TX_POWER_LEVEL_0,
TX_POWER_LEVEL_1,
TX_POWER_LEVEL_2,
TX_POWER_LEVEL_3,
TX_POWER_LEVEL_4,
})
@Retention(RetentionPolicy.SOURCE)
public @interface TxPowerLevel {}
private static final Range<Integer>[] TX_POWER_RANGES = new Range[] {
new Range<>(Integer.MIN_VALUE, 0),
new Range<>(0, 5),
new Range<>(5, 15),
new Range<>(15, 20),
new Range<>(20, Integer.MAX_VALUE)
};
private long mTimestamp;
private int mSleepTimeMs;
private int mIdleTimeMs;
private int[] mTxTimeMs;
private int mRxTimeMs;
/**
* @hide
*/
@TestApi
public ModemActivityInfo(long timestamp, int sleepTimeMs, int idleTimeMs,
@NonNull int[] txTimeMs, int rxTimeMs) {
Objects.requireNonNull(txTimeMs);
if (txTimeMs.length != TX_POWER_LEVELS) {
throw new IllegalArgumentException("txTimeMs must have length == TX_POWER_LEVELS");
}
mTimestamp = timestamp;
mSleepTimeMs = sleepTimeMs;
mIdleTimeMs = idleTimeMs;
mTxTimeMs = txTimeMs;
mRxTimeMs = rxTimeMs;
}
/**
* 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 int[] txTimeMs, long rxTimeMs) {
this(timestamp, (int) sleepTimeMs, (int) idleTimeMs, txTimeMs, (int) rxTimeMs);
}
@Override
public String toString() {
return "ModemActivityInfo{"
+ " mTimestamp=" + mTimestamp
+ " mSleepTimeMs=" + mSleepTimeMs
+ " mIdleTimeMs=" + mIdleTimeMs
+ " mTxTimeMs[]=" + Arrays.toString(mTxTimeMs)
+ " mRxTimeMs=" + mRxTimeMs
+ "}";
}
public int describeContents() {
return 0;
}
public static final @android.annotation.NonNull Parcelable.Creator<ModemActivityInfo> CREATOR =
new Parcelable.Creator<ModemActivityInfo>() {
public ModemActivityInfo createFromParcel(@NonNull Parcel in) {
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);
}
public ModemActivityInfo[] newArray(int size) {
return new ModemActivityInfo[size];
}
};
/**
* @param dest The Parcel in which the object should be written.
* @param flags Additional flags about how the object should be written.
*/
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeLong(mTimestamp);
dest.writeInt(mSleepTimeMs);
dest.writeInt(mIdleTimeMs);
dest.writeIntArray(mTxTimeMs);
dest.writeInt(mRxTimeMs);
}
/**
* 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.
*/
public @ElapsedRealtimeLong long getTimestampMillis() {
return mTimestamp;
}
/** @hide */
public void setTimestamp(long timestamp) {
mTimestamp = timestamp;
}
/**
* 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.
*/
public @DurationMillisLong long getTransmitDurationMillisAtPowerLevel(
@TxPowerLevel int powerLevel) {
return mTxTimeMs[powerLevel];
}
/**
* Gets the range of transmit powers corresponding to a certain power level.
*
* @param powerLevel The power level to query
* @return A {@link Range} object representing the range of intensities (in dBm) to which this
* power level corresponds.
*/
public @NonNull Range<Integer> getTransmitPowerRange(@TxPowerLevel int powerLevel) {
return TX_POWER_RANGES[powerLevel];
}
/** @hide */
public void setTransmitTimeMillis(int[] txTimeMs) {
mTxTimeMs = Arrays.copyOf(txTimeMs, TX_POWER_LEVELS);
}
/**
* @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 in a low power or sleep state.
*
* @return Time in milliseconds.
*/
public @DurationMillisLong long getSleepTimeMillis() {
return mSleepTimeMs;
}
/** @hide */
public void setSleepTimeMillis(int sleepTimeMillis) {
mSleepTimeMs = sleepTimeMillis;
}
/**
* Provided for convenience, since the API surface needs to return longs but internal
* representations are ints.
* @hide
*/
public void setSleepTimeMillis(long sleepTimeMillis) {
mSleepTimeMs = (int) sleepTimeMillis;
}
/**
* Computes the difference between this instance of {@link ModemActivityInfo} and another
* instance.
*
* This method should be used to compute the amount of activity that has happened between two
* samples of modem activity taken at separate times. The sample passed in as an argument to
* this method should be the one that's taken later in time (and therefore has more activity).
* @param other The other instance of {@link ModemActivityInfo} to diff against.
* @return An instance of {@link ModemActivityInfo} representing the difference in modem
* activity.
*/
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];
}
return new ModemActivityInfo(other.getTimestampMillis(),
other.getSleepTimeMillis() - getSleepTimeMillis(),
other.getIdleTimeMillis() - getIdleTimeMillis(),
txTimeMs,
other.getReceiveTimeMillis() - getReceiveTimeMillis());
}
/**
* Gets the amount of time (in milliseconds) when the modem is awake but neither transmitting
* nor receiving.
*
* @return Time in milliseconds.
*/
public @DurationMillisLong long getIdleTimeMillis() {
return mIdleTimeMs;
}
/** @hide */
public void setIdleTimeMillis(int idleTimeMillis) {
mIdleTimeMs = idleTimeMillis;
}
/**
* Provided for convenience, since the API surface needs to return longs but internal
* representations are ints.
* @hide
*/
public void setIdleTimeMillis(long idleTimeMillis) {
mIdleTimeMs = (int) idleTimeMillis;
}
/**
* Gets the amount of time (in milliseconds) when the modem is awake and receiving data.
*
* @return Time in milliseconds.
*/
public @DurationMillisLong long getReceiveTimeMillis() {
return mRxTimeMs;
}
/** @hide */
public void setReceiveTimeMillis(int rxTimeMillis) {
mRxTimeMs = 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;
}
/**
* Indicates if the modem has reported valid {@link ModemActivityInfo}.
*
* @return {@code true} if this {@link ModemActivityInfo} record is valid,
* {@code false} otherwise.
* @hide
*/
@TestApi
public boolean isValid() {
boolean isTxPowerValid = Arrays.stream(mTxTimeMs).allMatch((i) -> i >= 0);
return isTxPowerValid && ((getIdleTimeMillis() >= 0) && (getSleepTimeMillis() >= 0)
&& (getReceiveTimeMillis() >= 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));
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ModemActivityInfo that = (ModemActivityInfo) o;
return mTimestamp == that.mTimestamp
&& mSleepTimeMs == that.mSleepTimeMs
&& mIdleTimeMs == that.mIdleTimeMs
&& mRxTimeMs == that.mRxTimeMs
&& Arrays.equals(mTxTimeMs, that.mTxTimeMs);
}
@Override
public int hashCode() {
int result = Objects.hash(mTimestamp, mSleepTimeMs, mIdleTimeMs, mRxTimeMs);
result = 31 * result + Arrays.hashCode(mTxTimeMs);
return result;
}
}