/* * Copyright (C) 2020 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.telecom; import android.annotation.ElapsedRealtimeLong; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.SystemApi; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import java.util.Objects; /** * This class represents the quality report that bluetooth framework sends * whenever there's a bad voice quality is detected from their side. * It is sent as part of a call event via {@link Call#sendCallEvent(String, Bundle)} * associated with extra EXTRA_BLUETOOTH_CALL_QUALITY_REPORT. * Note that this report will be sent only during an active voice/voip call. * @hide */ @SystemApi public final class BluetoothCallQualityReport implements Parcelable { /** * Event that is sent via {@link Call#sendCallEvent(String, Bundle)} for a call quality report */ public static final String EVENT_BLUETOOTH_CALL_QUALITY_REPORT = "android.telecom.event.BLUETOOTH_CALL_QUALITY_REPORT"; /** * Extra key sent with {@link Call#sendCallEvent(String, Bundle)} */ public static final String EXTRA_BLUETOOTH_CALL_QUALITY_REPORT = "android.telecom.extra.BLUETOOTH_CALL_QUALITY_REPORT"; private final long mSentTimestampMillis; private final boolean mChoppyVoice; private final int mRssiDbm; private final int mSnrDb; private final int mRetransmittedPacketsCount; private final int mPacketsNotReceivedCount; private final int mNegativeAcknowledgementCount; /** * @return Time in milliseconds since the epoch. Designates when report was sent. * Used to determine whether this report arrived too late to be useful. */ public @ElapsedRealtimeLong long getSentTimestampMillis() { return mSentTimestampMillis; } /** * When the bluetooth controller detects factors that cause choppy voice, * the controller reports an (e)SCO Voice Choppy event to the host * @return {@code true} when we receive (e)SCO Voice Choppy event from the controller */ public boolean isChoppyVoice() { return mChoppyVoice; } /** * @return Received Signal Strength Indication (RSSI) value in dBm. * This value shall be an absolute received signal strength value. */ public @IntRange(from = -127, to = 20) int getRssiDbm() { return mRssiDbm; } /** * @return Signal-to-Noise Ratio (SNR) value in dB. * The controller shall provide the average SNR of all the channels currently used by the link. */ public int getSnrDb() { return mSnrDb; } /** * @return The number of retransmissions since the last event. * This count shall be reset after it is reported. */ public @IntRange(from = 0) int getRetransmittedPacketsCount() { return mRetransmittedPacketsCount; } /** * @return No RX count since the last event. * The count increases when no packet is received at the scheduled time slot or the received * packet is corrupted. * This count shall be reset after it is reported. */ public @IntRange(from = 0) int getPacketsNotReceivedCount() { return mPacketsNotReceivedCount; } /** * @return NAK (Negative Acknowledge) count since the last event. * This count shall be reset after it is reported. */ public @IntRange(from = 0) int getNegativeAcknowledgementCount() { return mNegativeAcknowledgementCount; } // // Parcelable implementation // @Override public int describeContents() { return 0; } @Override public void writeToParcel(@NonNull Parcel out, int flags) { out.writeLong(mSentTimestampMillis); out.writeBoolean(mChoppyVoice); out.writeInt(mRssiDbm); out.writeInt(mSnrDb); out.writeInt(mRetransmittedPacketsCount); out.writeInt(mPacketsNotReceivedCount); out.writeInt(mNegativeAcknowledgementCount); } public static final @android.annotation.NonNull Creator CREATOR = new Creator() { @Override public BluetoothCallQualityReport createFromParcel(Parcel in) { return new BluetoothCallQualityReport(in); } @Override public BluetoothCallQualityReport[] newArray(int size) { return new BluetoothCallQualityReport[size]; } }; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; BluetoothCallQualityReport that = (BluetoothCallQualityReport) o; return mSentTimestampMillis == that.mSentTimestampMillis && mChoppyVoice == that.mChoppyVoice && mRssiDbm == that.mRssiDbm && mSnrDb == that.mSnrDb && mRetransmittedPacketsCount == that.mRetransmittedPacketsCount && mPacketsNotReceivedCount == that.mPacketsNotReceivedCount && mNegativeAcknowledgementCount == that.mNegativeAcknowledgementCount; } @Override public int hashCode() { return Objects.hash(mSentTimestampMillis, mChoppyVoice, mRssiDbm, mSnrDb, mRetransmittedPacketsCount, mPacketsNotReceivedCount, mNegativeAcknowledgementCount); } /** * Builder class for {@link ConnectionRequest} */ public static final class Builder { private long mSentTimestampMillis; private boolean mChoppyVoice; private int mRssiDbm; private int mSnrDb; private int mRetransmittedPacketsCount; private int mPacketsNotReceivedCount; private int mNegativeAcknowledgementCount; public Builder() { } /** * Set the time when report was sent in milliseconds since the epoch. * @param sentTimestampMillis */ public @NonNull Builder setSentTimestampMillis(long sentTimestampMillis) { mSentTimestampMillis = sentTimestampMillis; return this; } /** * Set if bluetooth hardware detects voice is choppy * @param choppyVoice */ public @NonNull Builder setChoppyVoice(boolean choppyVoice) { mChoppyVoice = choppyVoice; return this; } /** * Set Received Signal Strength Indication (RSSI) value in dBm. * @param rssiDbm */ public @NonNull Builder setRssiDbm(int rssiDbm) { mRssiDbm = rssiDbm; return this; } /** * Set Signal-to-Noise Ratio (SNR) value in dB. * @param snrDb */ public @NonNull Builder setSnrDb(int snrDb) { mSnrDb = snrDb; return this; } /** * Set The number of retransmissions since the last event. * @param retransmittedPacketsCount */ public @NonNull Builder setRetransmittedPacketsCount( int retransmittedPacketsCount) { mRetransmittedPacketsCount = retransmittedPacketsCount; return this; } /** * Set No RX count since the last event. * @param packetsNotReceivedCount */ public @NonNull Builder setPacketsNotReceivedCount( int packetsNotReceivedCount) { mPacketsNotReceivedCount = packetsNotReceivedCount; return this; } /** * Set NAK (Negative Acknowledge) count since the last event. * @param negativeAcknowledgementCount */ public @NonNull Builder setNegativeAcknowledgementCount( int negativeAcknowledgementCount) { mNegativeAcknowledgementCount = negativeAcknowledgementCount; return this; } /** * Build the {@link BluetoothCallQualityReport} * @return Result of the builder */ public @NonNull BluetoothCallQualityReport build() { return new BluetoothCallQualityReport(this); } } private BluetoothCallQualityReport(Parcel in) { mSentTimestampMillis = in.readLong(); mChoppyVoice = in.readBoolean(); mRssiDbm = in.readInt(); mSnrDb = in.readInt(); mRetransmittedPacketsCount = in.readInt(); mPacketsNotReceivedCount = in.readInt(); mNegativeAcknowledgementCount = in.readInt(); } private BluetoothCallQualityReport(Builder builder) { mSentTimestampMillis = builder.mSentTimestampMillis; mChoppyVoice = builder.mChoppyVoice; mRssiDbm = builder.mRssiDbm; mSnrDb = builder.mSnrDb; mRetransmittedPacketsCount = builder.mRetransmittedPacketsCount; mPacketsNotReceivedCount = builder.mPacketsNotReceivedCount; mNegativeAcknowledgementCount = builder.mNegativeAcknowledgementCount; } }