300 lines
12 KiB
Java
300 lines
12 KiB
Java
/*
|
|
* 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.telephony;
|
|
|
|
import android.annotation.NonNull;
|
|
import android.annotation.Nullable;
|
|
import android.annotation.RequiresPermission;
|
|
import android.annotation.SystemApi;
|
|
import android.os.Binder;
|
|
import android.os.IBinder;
|
|
import android.os.Parcel;
|
|
import android.os.Parcelable;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Collection;
|
|
import java.util.Collections;
|
|
import java.util.Comparator;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Objects;
|
|
import java.util.Set;
|
|
|
|
/**
|
|
* Request used to register {@link SignalThresholdInfo} to be notified when the signal strength
|
|
* breach the specified thresholds.
|
|
*/
|
|
public final class SignalStrengthUpdateRequest implements Parcelable {
|
|
/**
|
|
* List of SignalThresholdInfo for the request.
|
|
*/
|
|
private final List<SignalThresholdInfo> mSignalThresholdInfos;
|
|
|
|
/**
|
|
* Whether the reporting is required for thresholds in the request while device is idle.
|
|
*/
|
|
private final boolean mIsReportingRequestedWhileIdle;
|
|
|
|
/**
|
|
* Whether the reporting requested for system thresholds while device is idle.
|
|
*
|
|
* System signal thresholds are loaded from carrier config items and mainly used for UI
|
|
* displaying. By default, they are ignored when device is idle. When setting the value to true,
|
|
* modem will continue reporting signal strength changes over the system signal thresholds even
|
|
* device is idle.
|
|
*
|
|
* This should only set to true by the system caller.
|
|
*/
|
|
private final boolean mIsSystemThresholdReportingRequestedWhileIdle;
|
|
|
|
/**
|
|
* A IBinder object as a token for server side to check if the request client is still living.
|
|
*/
|
|
private final IBinder mLiveToken;
|
|
|
|
private SignalStrengthUpdateRequest(
|
|
@Nullable List<SignalThresholdInfo> signalThresholdInfos,
|
|
boolean isReportingRequestedWhileIdle,
|
|
boolean isSystemThresholdReportingRequestedWhileIdle) {
|
|
validate(signalThresholdInfos, isSystemThresholdReportingRequestedWhileIdle);
|
|
|
|
mSignalThresholdInfos = signalThresholdInfos;
|
|
mIsReportingRequestedWhileIdle = isReportingRequestedWhileIdle;
|
|
mIsSystemThresholdReportingRequestedWhileIdle =
|
|
isSystemThresholdReportingRequestedWhileIdle;
|
|
mLiveToken = new Binder();
|
|
}
|
|
|
|
/**
|
|
* Builder class to create {@link SignalStrengthUpdateRequest} object.
|
|
*/
|
|
public static final class Builder {
|
|
private List<SignalThresholdInfo> mSignalThresholdInfos = null;
|
|
private boolean mIsReportingRequestedWhileIdle = false;
|
|
private boolean mIsSystemThresholdReportingRequestedWhileIdle = false;
|
|
|
|
/**
|
|
* Set the collection of SignalThresholdInfo for the builder object
|
|
*
|
|
* @param signalThresholdInfos the collection of SignalThresholdInfo
|
|
*
|
|
* @return the builder to facilitate the chaining
|
|
*/
|
|
public @NonNull Builder setSignalThresholdInfos(
|
|
@NonNull Collection<SignalThresholdInfo> signalThresholdInfos) {
|
|
Objects.requireNonNull(signalThresholdInfos,
|
|
"SignalThresholdInfo collection must not be null");
|
|
for (SignalThresholdInfo info : signalThresholdInfos) {
|
|
Objects.requireNonNull(info,
|
|
"SignalThresholdInfo in the collection must not be null");
|
|
}
|
|
|
|
mSignalThresholdInfos = new ArrayList<>(signalThresholdInfos);
|
|
// Sort the collection with RAN and then SignalMeasurementType ascending order, make the
|
|
// ordering not matter for equals
|
|
mSignalThresholdInfos.sort(
|
|
Comparator.comparingInt(SignalThresholdInfo::getRadioAccessNetworkType)
|
|
.thenComparing(SignalThresholdInfo::getSignalMeasurementType));
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Set the builder object if require reporting on thresholds in this request when device is
|
|
* idle.
|
|
*
|
|
* @param isReportingRequestedWhileIdle true if request reporting when device is idle
|
|
*
|
|
* @return the builder to facilitate the chaining
|
|
*/
|
|
public @NonNull Builder setReportingRequestedWhileIdle(
|
|
boolean isReportingRequestedWhileIdle) {
|
|
mIsReportingRequestedWhileIdle = isReportingRequestedWhileIdle;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Set the builder object if require reporting on the system thresholds when device is idle.
|
|
*
|
|
* <p>This is intended to be used by the system privileged caller only. When setting to
|
|
* {@code true}, signal strength update request through
|
|
* {@link TelephonyManager#setSignalStrengthUpdateRequest(SignalStrengthUpdateRequest)}
|
|
* will require permission
|
|
* {@link android.Manifest.permission#LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH}.
|
|
*
|
|
* @param isSystemThresholdReportingRequestedWhileIdle true if request reporting on the
|
|
* system thresholds when device is idle
|
|
* @return the builder to facilitate the chaining
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)
|
|
public @NonNull Builder setSystemThresholdReportingRequestedWhileIdle(
|
|
boolean isSystemThresholdReportingRequestedWhileIdle) {
|
|
mIsSystemThresholdReportingRequestedWhileIdle =
|
|
isSystemThresholdReportingRequestedWhileIdle;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Build a {@link SignalStrengthUpdateRequest} object.
|
|
*
|
|
* @return the SignalStrengthUpdateRequest object
|
|
*
|
|
* @throws IllegalArgumentException if the SignalThresholdInfo collection is empty size, the
|
|
* signal measurement type for the same RAN in the collection is not unique
|
|
*/
|
|
public @NonNull SignalStrengthUpdateRequest build() {
|
|
return new SignalStrengthUpdateRequest(mSignalThresholdInfos,
|
|
mIsReportingRequestedWhileIdle, mIsSystemThresholdReportingRequestedWhileIdle);
|
|
}
|
|
}
|
|
|
|
private SignalStrengthUpdateRequest(Parcel in) {
|
|
mSignalThresholdInfos = in.createTypedArrayList(SignalThresholdInfo.CREATOR);
|
|
mIsReportingRequestedWhileIdle = in.readBoolean();
|
|
mIsSystemThresholdReportingRequestedWhileIdle = in.readBoolean();
|
|
mLiveToken = in.readStrongBinder();
|
|
}
|
|
|
|
/**
|
|
* Get the collection of SignalThresholdInfo in the request.
|
|
*
|
|
* @return the collection of SignalThresholdInfo
|
|
*/
|
|
@NonNull
|
|
public Collection<SignalThresholdInfo> getSignalThresholdInfos() {
|
|
return Collections.unmodifiableList(mSignalThresholdInfos);
|
|
}
|
|
|
|
/**
|
|
* Get whether reporting is requested for the threshold in the request while device is idle.
|
|
*
|
|
* @return true if reporting requested while device is idle
|
|
*/
|
|
public boolean isReportingRequestedWhileIdle() {
|
|
return mIsReportingRequestedWhileIdle;
|
|
}
|
|
|
|
/**
|
|
* @return true if reporting requested for system thresholds while device is idle
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
public boolean isSystemThresholdReportingRequestedWhileIdle() {
|
|
return mIsSystemThresholdReportingRequestedWhileIdle;
|
|
}
|
|
|
|
/**
|
|
* @return the live token of the request
|
|
*
|
|
* @hide
|
|
*/
|
|
public @NonNull IBinder getLiveToken() {
|
|
return mLiveToken;
|
|
}
|
|
|
|
@Override
|
|
public int describeContents() {
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
|
dest.writeTypedList(mSignalThresholdInfos);
|
|
dest.writeBoolean(mIsReportingRequestedWhileIdle);
|
|
dest.writeBoolean(mIsSystemThresholdReportingRequestedWhileIdle);
|
|
dest.writeStrongBinder(mLiveToken);
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object other) {
|
|
if (this == other) return true;
|
|
|
|
if (!(other instanceof SignalStrengthUpdateRequest)) {
|
|
return false;
|
|
}
|
|
|
|
SignalStrengthUpdateRequest request = (SignalStrengthUpdateRequest) other;
|
|
return mSignalThresholdInfos.equals(request.mSignalThresholdInfos)
|
|
&& mIsReportingRequestedWhileIdle == request.mIsReportingRequestedWhileIdle
|
|
&& mIsSystemThresholdReportingRequestedWhileIdle
|
|
== request.mIsSystemThresholdReportingRequestedWhileIdle;
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return Objects.hash(mSignalThresholdInfos, mIsReportingRequestedWhileIdle,
|
|
mIsSystemThresholdReportingRequestedWhileIdle);
|
|
}
|
|
|
|
public static final @NonNull Parcelable.Creator<SignalStrengthUpdateRequest> CREATOR =
|
|
new Parcelable.Creator<SignalStrengthUpdateRequest>() {
|
|
@Override
|
|
public SignalStrengthUpdateRequest createFromParcel(Parcel source) {
|
|
return new SignalStrengthUpdateRequest(source);
|
|
}
|
|
|
|
@Override
|
|
public SignalStrengthUpdateRequest[] newArray(int size) {
|
|
return new SignalStrengthUpdateRequest[size];
|
|
}
|
|
};
|
|
|
|
@Override
|
|
public String toString() {
|
|
return new StringBuilder("SignalStrengthUpdateRequest{")
|
|
.append("mSignalThresholdInfos=")
|
|
.append(mSignalThresholdInfos)
|
|
.append(" mIsReportingRequestedWhileIdle=")
|
|
.append(mIsReportingRequestedWhileIdle)
|
|
.append(" mIsSystemThresholdReportingRequestedWhileIdle=")
|
|
.append(mIsSystemThresholdReportingRequestedWhileIdle)
|
|
.append(" mLiveToken")
|
|
.append(mLiveToken)
|
|
.append("}").toString();
|
|
}
|
|
|
|
/**
|
|
* Throw IAE if SignalThresholdInfo collection is null or empty,
|
|
* or the SignalMeasurementType for the same RAN in the collection is not unique.
|
|
*/
|
|
private static void validate(Collection<SignalThresholdInfo> infos,
|
|
boolean isSystemThresholdReportingRequestedWhileIdle) {
|
|
// System app (like Bluetooth) can specify the request to report system thresholds while
|
|
// device is idle (with permission protection). In this case, the request doesn't need to
|
|
// provide a non-empty list of SignalThresholdInfo which is only asked for public apps.
|
|
if (infos == null || (infos.isEmpty() && !isSystemThresholdReportingRequestedWhileIdle)) {
|
|
throw new IllegalArgumentException("SignalThresholdInfo collection is null or empty");
|
|
}
|
|
|
|
// Map from RAN to set of SignalMeasurementTypes
|
|
Map<Integer, Set<Integer>> ranToTypes = new HashMap<>(infos.size());
|
|
for (SignalThresholdInfo info : infos) {
|
|
final int ran = info.getRadioAccessNetworkType();
|
|
final int type = info.getSignalMeasurementType();
|
|
ranToTypes.putIfAbsent(ran, new HashSet<>());
|
|
if (!ranToTypes.get(ran).add(type)) {
|
|
throw new IllegalArgumentException(
|
|
"SignalMeasurementType " + type + " for RAN " + ran + " is not unique");
|
|
}
|
|
}
|
|
}
|
|
}
|