blob: bb9c0da3f8d41f9496e3ebc53cf4092cb3431b5b [file] [log] [blame]
/*
* Copyright (C) 2019 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.IntDef;
import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.Objects;
/**
* Defines the threshold value of the signal strength.
*/
public final class SignalThresholdInfo implements Parcelable {
/**
* Unknown signal measurement type.
*/
public static final int SIGNAL_MEASUREMENT_TYPE_UNKNOWN = 0;
/**
* Received Signal Strength Indication.
* Range: -113 dBm and -51 dBm
* Used RAN: {@link AccessNetworkConstants.AccessNetworkType#GERAN},
* {@link AccessNetworkConstants.AccessNetworkType#CDMA2000}
* Reference: 3GPP TS 27.007 section 8.5.
*/
public static final int SIGNAL_MEASUREMENT_TYPE_RSSI = 1;
/**
* Received Signal Code Power.
* Range: -120 dBm to -25 dBm;
* Used RAN: {@link AccessNetworkConstants.AccessNetworkType#UTRAN}
* Reference: 3GPP TS 25.123, section 9.1.1.1
*/
public static final int SIGNAL_MEASUREMENT_TYPE_RSCP = 2;
/**
* Reference Signal Received Power.
* Range: -140 dBm to -44 dBm;
* Used RAN: {@link AccessNetworkConstants.AccessNetworkType#EUTRAN}
* Reference: 3GPP TS 36.133 9.1.4
*/
public static final int SIGNAL_MEASUREMENT_TYPE_RSRP = 3;
/**
* Reference Signal Received Quality
* Range: -34 dB to 3 dB;
* Used RAN: {@link AccessNetworkConstants.AccessNetworkType#EUTRAN}
* Reference: 3GPP TS 36.133 9.1.7
*/
public static final int SIGNAL_MEASUREMENT_TYPE_RSRQ = 4;
/**
* Reference Signal Signal to Noise Ratio
* Range: -20 dB to 30 dB;
* Used RAN: {@link AccessNetworkConstants.AccessNetworkType#EUTRAN}
*/
public static final int SIGNAL_MEASUREMENT_TYPE_RSSNR = 5;
/**
* 5G SS reference signal received power.
* Range: -140 dBm to -44 dBm.
* Used RAN: {@link AccessNetworkConstants.AccessNetworkType#NGRAN}
* Reference: 3GPP TS 38.215.
*/
public static final int SIGNAL_MEASUREMENT_TYPE_SSRSRP = 6;
/**
* 5G SS reference signal received quality.
* Range: -43 dB to 20 dB.
* Used RAN: {@link AccessNetworkConstants.AccessNetworkType#NGRAN}
* Reference: 3GPP TS 38.133 section 10.1.11.1.
*/
public static final int SIGNAL_MEASUREMENT_TYPE_SSRSRQ = 7;
/**
* 5G SS signal-to-noise and interference ratio.
* Range: -23 dB to 40 dB
* Used RAN: {@link AccessNetworkConstants.AccessNetworkType#NGRAN}
* Reference: 3GPP TS 38.215 section 5.1.*, 3GPP TS 38.133 section 10.1.16.1.
*/
public static final int SIGNAL_MEASUREMENT_TYPE_SSSINR = 8;
/** @hide */
@IntDef(prefix = {"SIGNAL_MEASUREMENT_TYPE_"}, value = {
SIGNAL_MEASUREMENT_TYPE_UNKNOWN,
SIGNAL_MEASUREMENT_TYPE_RSSI,
SIGNAL_MEASUREMENT_TYPE_RSCP,
SIGNAL_MEASUREMENT_TYPE_RSRP,
SIGNAL_MEASUREMENT_TYPE_RSRQ,
SIGNAL_MEASUREMENT_TYPE_RSSNR,
SIGNAL_MEASUREMENT_TYPE_SSRSRP,
SIGNAL_MEASUREMENT_TYPE_SSRSRQ,
SIGNAL_MEASUREMENT_TYPE_SSSINR
})
@Retention(RetentionPolicy.SOURCE)
public @interface SignalMeasurementType {
}
@SignalMeasurementType
private final int mSignalMeasurementType;
/**
* A hysteresis time in milliseconds to prevent flapping.
* A value of 0 disables hysteresis
*/
private final int mHysteresisMs;
/**
* An interval in dB defining the required magnitude change between reports.
* hysteresisDb must be smaller than the smallest threshold delta.
* An interval value of 0 disables hysteresis.
*/
private final int mHysteresisDb;
/**
* List of threshold values.
* Range and unit must reference specific SignalMeasurementType
* The threshold values for which to apply criteria.
* A vector size of 0 disables the use of thresholds for reporting.
*/
private final int[] mThresholds;
/**
* {@code true} means modem must trigger the report based on the criteria;
* {@code false} means modem must not trigger the report based on the criteria.
*/
private final boolean mIsEnabled;
/**
* The radio access network type associated with the signal thresholds.
*/
@AccessNetworkConstants.RadioAccessNetworkType
private final int mRan;
/**
* Indicates the hysteresisMs is disabled.
*
* @hide
*/
public static final int HYSTERESIS_MS_DISABLED = 0;
/**
* Indicates the hysteresisDb is disabled.
*
* @hide
*/
public static final int HYSTERESIS_DB_DISABLED = 0;
/**
* Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSSI}.
*
* @hide
*/
public static final int SIGNAL_RSSI_MIN_VALUE = -113;
/**
* Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSSI}.
*
* @hide
*/
public static final int SIGNAL_RSSI_MAX_VALUE = -51;
/**
* Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSCP}.
*
* @hide
*/
public static final int SIGNAL_RSCP_MIN_VALUE = -120;
/**
* Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSCP}.
*
* @hide
*/
public static final int SIGNAL_RSCP_MAX_VALUE = -25;
/**
* Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSRP}.
*
* @hide
*/
public static final int SIGNAL_RSRP_MIN_VALUE = -140;
/**
* Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSRP}.
*
* @hide
*/
public static final int SIGNAL_RSRP_MAX_VALUE = -44;
/**
* Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSRQ}.
*
* @hide
*/
public static final int SIGNAL_RSRQ_MIN_VALUE = -34;
/**
* Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSRQ}.
*
* @hide
*/
public static final int SIGNAL_RSRQ_MAX_VALUE = 3;
/**
* Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSSNR}.
*
* @hide
*/
public static final int SIGNAL_RSSNR_MIN_VALUE = -20;
/**
* Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSSNR}.
*
* @hide
*/
public static final int SIGNAL_RSSNR_MAX_VALUE = 30;
/**
* Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_SSRSRP}.
*
* @hide
*/
public static final int SIGNAL_SSRSRP_MIN_VALUE = -140;
/**
* Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_SSRSRP}.
*
* @hide
*/
public static final int SIGNAL_SSRSRP_MAX_VALUE = -44;
/**
* Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_SSRSRQ}.
*
* @hide
*/
public static final int SIGNAL_SSRSRQ_MIN_VALUE = -43;
/**
* Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_SSRSRQ}.
*
* @hide
*/
public static final int SIGNAL_SSRSRQ_MAX_VALUE = 20;
/**
* Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_SSSINR}.
*
* @hide
*/
public static final int SIGNAL_SSSINR_MIN_VALUE = -23;
/**
* Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_SSSINR}.
*
* @hide
*/
public static final int SIGNAL_SSSINR_MAX_VALUE = 40;
/**
* Constructor
*
* @param ran Radio Access Network type
* @param signalMeasurementType Signal Measurement Type
* @param hysteresisMs hysteresisMs
* @param hysteresisDb hysteresisDb
* @param thresholds threshold value
* @param isEnabled isEnabled
*/
private SignalThresholdInfo(@AccessNetworkConstants.RadioAccessNetworkType int ran,
@SignalMeasurementType int signalMeasurementType, int hysteresisMs, int hysteresisDb,
@NonNull int[] thresholds, boolean isEnabled) {
Objects.requireNonNull(thresholds, "thresholds must not be null");
validateRanWithMeasurementType(ran, signalMeasurementType);
validateThresholdRange(signalMeasurementType, thresholds);
mRan = ran;
mSignalMeasurementType = signalMeasurementType;
mHysteresisMs = hysteresisMs < 0 ? HYSTERESIS_MS_DISABLED : hysteresisMs;
mHysteresisDb = hysteresisDb < 0 ? HYSTERESIS_DB_DISABLED : hysteresisDb;
mThresholds = thresholds;
mIsEnabled = isEnabled;
}
/**
* Builder class to create {@link SignalThresholdInfo} objects.
*/
public static final class Builder {
private int mRan = AccessNetworkConstants.AccessNetworkType.UNKNOWN;
private int mSignalMeasurementType = SIGNAL_MEASUREMENT_TYPE_UNKNOWN;
private int mHysteresisMs = HYSTERESIS_MS_DISABLED;
private int mHysteresisDb = HYSTERESIS_DB_DISABLED;
private int[] mThresholds = null;
private boolean mIsEnabled = false;
/**
* Set the radio access network type for the builder instance.
*
* @param ran The radio access network type
* @return the builder to facilitate the chaining
*/
public @NonNull Builder setRadioAccessNetworkType(
@AccessNetworkConstants.RadioAccessNetworkType int ran) {
mRan = ran;
return this;
}
/**
* Set the signal measurement type for the builder instance.
*
* @param signalMeasurementType The signal measurement type
* @return the builder to facilitate the chaining
*/
public @NonNull Builder setSignalMeasurementType(
@SignalMeasurementType int signalMeasurementType) {
mSignalMeasurementType = signalMeasurementType;
return this;
}
/**
* Set the hysteresis time in milliseconds to prevent flapping. A value of 0 disables
* hysteresis.
*
* @param hysteresisMs the hysteresis time in milliseconds
* @return the builder to facilitate the chaining
* @hide
*/
public @NonNull Builder setHysteresisMs(int hysteresisMs) {
mHysteresisMs = hysteresisMs;
return this;
}
/**
* Set the interval in dB defining the required magnitude change between reports. A value of
* zero disabled dB-based hysteresis restrictions.
*
* @param hysteresisDb the interval in dB
* @return the builder to facilitate the chaining
* @hide
*/
public @NonNull Builder setHysteresisDb(int hysteresisDb) {
mHysteresisDb = hysteresisDb;
return this;
}
/**
* Set the signal strength thresholds of the corresponding signal measurement type.
*
* The range and unit must reference specific SignalMeasurementType.
*
* @param thresholds array of integer as the signal threshold values
* @return the builder to facilitate the chaining
*
* @see #SIGNAL_MEASUREMENT_TYPE_RSSI
* @see #SIGNAL_MEASUREMENT_TYPE_RSCP
* @see #SIGNAL_MEASUREMENT_TYPE_RSRP
* @see #SIGNAL_MEASUREMENT_TYPE_RSRQ
* @see #SIGNAL_MEASUREMENT_TYPE_RSSNR
* @see #SIGNAL_MEASUREMENT_TYPE_SSRSRP
* @see #SIGNAL_MEASUREMENT_TYPE_SSRSRQ
* @see #SIGNAL_MEASUREMENT_TYPE_SSSINR
* @see #getThresholds() for more details on signal strength thresholds
*/
public @NonNull Builder setThresholds(@NonNull int[] thresholds) {
Objects.requireNonNull(thresholds, "thresholds must not be null");
mThresholds = thresholds.clone();
Arrays.sort(mThresholds);
return this;
}
/**
* Set if the modem should trigger the report based on the criteria.
*
* @param isEnabled true if the modem should trigger the report based on the criteria
* @return the builder to facilitate the chaining
* @hide
*/
public @NonNull Builder setIsEnabled(boolean isEnabled) {
mIsEnabled = isEnabled;
return this;
}
/**
* Build {@link SignalThresholdInfo} object.
*
* @return the SignalThresholdInfo object build out
*
* @throws IllegalArgumentException if the signal measurement type is invalid, any value in
* the thresholds is out of range, or the RAN is not allowed to set with the signal
* measurement type
*/
public @NonNull SignalThresholdInfo build() {
return new SignalThresholdInfo(mRan, mSignalMeasurementType, mHysteresisMs,
mHysteresisDb, mThresholds, mIsEnabled);
}
}
/**
* Get the radio access network type.
*
* @return radio access network type
*/
public @AccessNetworkConstants.RadioAccessNetworkType int getRadioAccessNetworkType() {
return mRan;
}
/**
* Get the signal measurement type.
*
* @return the SignalMeasurementType value
*/
public @SignalMeasurementType int getSignalMeasurementType() {
return mSignalMeasurementType;
}
/** @hide */
public int getHysteresisMs() {
return mHysteresisMs;
}
/** @hide */
public int getHysteresisDb() {
return mHysteresisDb;
}
/** @hide */
public boolean isEnabled() {
return mIsEnabled;
}
/**
* Get the signal strength thresholds.
*
* Signal strength thresholds are a list of integer used for suggesting signal level and signal
* reporting criteria. The range and unit must reference specific SignalMeasurementType.
*
* Please refer to https://source.android.com/devices/tech/connect/signal-strength on how signal
* strength thresholds are used for signal strength reporting.
*
* @return array of integer of the signal thresholds
*
* @see #SIGNAL_MEASUREMENT_TYPE_RSSI
* @see #SIGNAL_MEASUREMENT_TYPE_RSCP
* @see #SIGNAL_MEASUREMENT_TYPE_RSRP
* @see #SIGNAL_MEASUREMENT_TYPE_RSRQ
* @see #SIGNAL_MEASUREMENT_TYPE_RSSNR
* @see #SIGNAL_MEASUREMENT_TYPE_SSRSRP
* @see #SIGNAL_MEASUREMENT_TYPE_SSRSRQ
* @see #SIGNAL_MEASUREMENT_TYPE_SSSINR
*/
public @NonNull int[] getThresholds() {
return mThresholds.clone();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeInt(mRan);
out.writeInt(mSignalMeasurementType);
out.writeInt(mHysteresisMs);
out.writeInt(mHysteresisDb);
out.writeIntArray(mThresholds);
out.writeBoolean(mIsEnabled);
}
private SignalThresholdInfo(Parcel in) {
mRan = in.readInt();
mSignalMeasurementType = in.readInt();
mHysteresisMs = in.readInt();
mHysteresisDb = in.readInt();
mThresholds = in.createIntArray();
mIsEnabled = in.readBoolean();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof SignalThresholdInfo)) {
return false;
}
SignalThresholdInfo other = (SignalThresholdInfo) o;
return mRan == other.mRan
&& mSignalMeasurementType == other.mSignalMeasurementType
&& mHysteresisMs == other.mHysteresisMs
&& mHysteresisDb == other.mHysteresisDb
&& Arrays.equals(mThresholds, other.mThresholds)
&& mIsEnabled == other.mIsEnabled;
}
@Override
public int hashCode() {
return Objects.hash(mRan, mSignalMeasurementType, mHysteresisMs, mHysteresisDb, mThresholds,
mIsEnabled);
}
public static final @NonNull Parcelable.Creator<SignalThresholdInfo> CREATOR =
new Parcelable.Creator<SignalThresholdInfo>() {
@Override
public SignalThresholdInfo createFromParcel(Parcel in) {
return new SignalThresholdInfo(in);
}
@Override
public SignalThresholdInfo[] newArray(int size) {
return new SignalThresholdInfo[size];
}
};
@Override
public String toString() {
return new StringBuilder("SignalThresholdInfo{")
.append("mRan=").append(mRan)
.append(" mSignalMeasurementType=").append(mSignalMeasurementType)
.append(" mHysteresisMs=").append(mHysteresisMs)
.append(" mHysteresisDb=").append(mHysteresisDb)
.append(" mThresholds=").append(Arrays.toString(mThresholds))
.append(" mIsEnabled=").append(mIsEnabled)
.append("}").toString();
}
/**
* Return true if signal measurement type is valid and the threshold value is in range.
*/
private static boolean isValidThreshold(@SignalMeasurementType int type, int threshold) {
switch (type) {
case SIGNAL_MEASUREMENT_TYPE_RSSI:
return threshold >= SIGNAL_RSSI_MIN_VALUE && threshold <= SIGNAL_RSSI_MAX_VALUE;
case SIGNAL_MEASUREMENT_TYPE_RSCP:
return threshold >= SIGNAL_RSCP_MIN_VALUE && threshold <= SIGNAL_RSCP_MAX_VALUE;
case SIGNAL_MEASUREMENT_TYPE_RSRP:
return threshold >= SIGNAL_RSRP_MIN_VALUE && threshold <= SIGNAL_RSRP_MAX_VALUE;
case SIGNAL_MEASUREMENT_TYPE_RSRQ:
return threshold >= SIGNAL_RSRQ_MIN_VALUE && threshold <= SIGNAL_RSRQ_MAX_VALUE;
case SIGNAL_MEASUREMENT_TYPE_RSSNR:
return threshold >= SIGNAL_RSSNR_MIN_VALUE && threshold <= SIGNAL_RSSNR_MAX_VALUE;
case SIGNAL_MEASUREMENT_TYPE_SSRSRP:
return threshold >= SIGNAL_SSRSRP_MIN_VALUE && threshold <= SIGNAL_SSRSRP_MAX_VALUE;
case SIGNAL_MEASUREMENT_TYPE_SSRSRQ:
return threshold >= SIGNAL_SSRSRQ_MIN_VALUE && threshold <= SIGNAL_SSRSRQ_MAX_VALUE;
case SIGNAL_MEASUREMENT_TYPE_SSSINR:
return threshold >= SIGNAL_SSSINR_MIN_VALUE && threshold <= SIGNAL_SSSINR_MAX_VALUE;
default:
return false;
}
}
/**
* Return true if the radio access type is allowed to set with the measurement type.
*/
private static boolean isValidRanWithMeasurementType(
@AccessNetworkConstants.RadioAccessNetworkType int ran,
@SignalMeasurementType int type) {
switch (type) {
case SIGNAL_MEASUREMENT_TYPE_RSSI:
return ran == AccessNetworkConstants.AccessNetworkType.GERAN
|| ran == AccessNetworkConstants.AccessNetworkType.CDMA2000;
case SIGNAL_MEASUREMENT_TYPE_RSCP:
return ran == AccessNetworkConstants.AccessNetworkType.UTRAN;
case SIGNAL_MEASUREMENT_TYPE_RSRP:
case SIGNAL_MEASUREMENT_TYPE_RSRQ:
case SIGNAL_MEASUREMENT_TYPE_RSSNR:
return ran == AccessNetworkConstants.AccessNetworkType.EUTRAN;
case SIGNAL_MEASUREMENT_TYPE_SSRSRP:
case SIGNAL_MEASUREMENT_TYPE_SSRSRQ:
case SIGNAL_MEASUREMENT_TYPE_SSSINR:
return ran == AccessNetworkConstants.AccessNetworkType.NGRAN;
default:
return false;
}
}
private void validateRanWithMeasurementType(
@AccessNetworkConstants.RadioAccessNetworkType int ran,
@SignalMeasurementType int signalMeasurement) {
if (!isValidRanWithMeasurementType(ran, signalMeasurement)) {
throw new IllegalArgumentException(
"invalid RAN: " + ran + " with signal measurement type: " + signalMeasurement);
}
}
private void validateThresholdRange(@SignalMeasurementType int signalMeasurement,
int[] thresholds) {
for (int threshold : thresholds) {
if (!isValidThreshold(signalMeasurement, threshold)) {
throw new IllegalArgumentException(
"invalid signal measurement type: " + signalMeasurement
+ " with threshold: " + threshold);
}
}
}
}