/* * 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.IntRange; 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; /** * The ratio between the received energy from the pilot signal CPICH per chip (Ec) to the * noise density (No). * Range: -24 dBm to 1 dBm. * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#UTRAN} * Reference: 3GPP TS 25.215 5.1.5 */ public static final int SIGNAL_MEASUREMENT_TYPE_ECNO = 9; /** @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, SIGNAL_MEASUREMENT_TYPE_ECNO }) @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 default hysteresis value in dB. * * @hide */ private static final int HYSTERESIS_DB_DEFAULT = 2; /** * Indicates the hysteresisDb value is not set and to be initialised to default value. * * @hide */ public static final int HYSTERESIS_DB_MINIMUM = 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; /** * Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_ECNO}. * * @hide */ public static final int SIGNAL_ECNO_MIN_VALUE = -24; /** * Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_ECNO}. * * @hide */ public static final int SIGNAL_ECNO_MAX_VALUE = 1; /** * The minimum number of thresholds allowed in each SignalThresholdInfo. * * @hide */ public static final int MINIMUM_NUMBER_OF_THRESHOLDS_ALLOWED = 1; /** * The maximum number of thresholds allowed in each SignalThresholdInfo. * * @hide */ public static final int MAXIMUM_NUMBER_OF_THRESHOLDS_ALLOWED = 4; /** * 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; 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_DEFAULT; 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 */ @NonNull public 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 */ @NonNull public 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 */ @NonNull public Builder setHysteresisMs(int hysteresisMs) { mHysteresisMs = hysteresisMs; return this; } /** * Set the interval in dB defining the required minimum magnitude change to report a * signal strength change. A value of zero disables dB-based hysteresis restrictions. * Note: *
Default hysteresis db value is 2. Minimum hysteresis db value allowed to set is 0.
* If hysteresis db value is not set, default hysteresis db value of 2 will be used.
*
* @param hysteresisDb the interval in dB
* @return the builder to facilitate the chaining
*/
@NonNull
public Builder setHysteresisDb(@IntRange(from = 0) int hysteresisDb) {
if (hysteresisDb < 0) {
throw new IllegalArgumentException("hysteresis db value should not be less than 0");
}
mHysteresisDb = hysteresisDb;
return this;
}
/**
* Set the signal strength thresholds of the corresponding signal measurement type.
*
* The range and unit must reference specific SignalMeasurementType. The length of the
* thresholds should between the numbers return from
* {@link #getMinimumNumberOfThresholdsAllowed()} and
* {@link #getMaximumNumberOfThresholdsAllowed()}. An IllegalArgumentException will throw
* otherwise.
*
* @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 #SIGNAL_MEASUREMENT_TYPE_ECNO
* @see #getThresholds() for more details on signal strength thresholds
*/
@NonNull
public Builder setThresholds(@NonNull int[] thresholds) {
return setThresholds(thresholds, false /*isSystem*/);
}
/**
* Set the signal strength thresholds for the corresponding signal measurement type.
*
* @param thresholds array of integer as the signal threshold values
* @param isSystem true is the caller is system which does not have restrictions on
* the length of thresholds array.
* @return the builder to facilitate the chaining
*
* @hide
*/
@NonNull
public Builder setThresholds(@NonNull int[] thresholds, boolean isSystem) {
Objects.requireNonNull(thresholds, "thresholds must not be null");
if (!isSystem
&& (thresholds.length < MINIMUM_NUMBER_OF_THRESHOLDS_ALLOWED
|| thresholds.length > MAXIMUM_NUMBER_OF_THRESHOLDS_ALLOWED)) {
throw new IllegalArgumentException(
"thresholds length must between "
+ MINIMUM_NUMBER_OF_THRESHOLDS_ALLOWED
+ " and "
+ MAXIMUM_NUMBER_OF_THRESHOLDS_ALLOWED);
}
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
*/
@NonNull
public 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
*/
@NonNull
public SignalThresholdInfo build() {
return new SignalThresholdInfo(
mRan,
mSignalMeasurementType,
mHysteresisMs,
mHysteresisDb,
mThresholds,
mIsEnabled);
}
}
/**
* Get the radio access network type.
*
* @return radio access network type
*/
@AccessNetworkConstants.RadioAccessNetworkType
public int getRadioAccessNetworkType() {
return mRan;
}
/**
* Get the signal measurement type.
*
* @return the SignalMeasurementType value
*/
@SignalMeasurementType
public int getSignalMeasurementType() {
return mSignalMeasurementType;
}
/** @hide */
public int getHysteresisMs() {
return mHysteresisMs;
}
/**
* Get measurement hysteresis db.
*
* @return hysteresis db value
*/
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
* @see #SIGNAL_MEASUREMENT_TYPE_ECNO
*/
@NonNull
public int[] getThresholds() {
return mThresholds.clone();
}
/**
* Get the minimum number of thresholds allowed in each SignalThresholdInfo.
*
* @return the minimum number of thresholds allowed
*/
public static int getMinimumNumberOfThresholdsAllowed() {
return MINIMUM_NUMBER_OF_THRESHOLDS_ALLOWED;
}
/**
* Get the maximum number of threshold allowed in each SignalThresholdInfo.
*
* @return the maximum number of thresholds allowed
*/
public static int getMaximumNumberOfThresholdsAllowed() {
return MAXIMUM_NUMBER_OF_THRESHOLDS_ALLOWED;
}
@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,
Arrays.hashCode(mThresholds),
mIsEnabled);
}
@NonNull
public static final Parcelable.Creator