Add the LCE system API

Add the link capacity estimate system API.
Remove the system API of getCarrierBandwidth() and CarrierBandwidth as
they are replaced by the new LCE system API in PhoneStateListener.

Bug: 180434672
Bug: 176814680
Test: manual test of the new LCE system API in LinkBandwidthEstimator
Test: atest -c PhoneStateListenerTest
Change-Id: Id613dc152e524045a89295e5dd03171b22377e16
This commit is contained in:
Kai Shi
2021-01-19 11:00:03 -08:00
parent 1fcb030d0e
commit df3e93af96
11 changed files with 351 additions and 38 deletions

View File

@@ -10941,6 +10941,19 @@ package android.telephony {
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ImsiEncryptionInfo> CREATOR;
}
public final class LinkCapacityEstimate implements android.os.Parcelable {
ctor public LinkCapacityEstimate(int, int, int);
method public int describeContents();
method public int getDownlinkCapacityKbps();
method public int getType();
method public int getUplinkCapacityKbps();
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.LinkCapacityEstimate> CREATOR;
field public static final int INVALID = -1; // 0xffffffff
field public static final int LCE_TYPE_COMBINED = 2; // 0x2
field public static final int LCE_TYPE_PRIMARY = 0; // 0x0
field public static final int LCE_TYPE_SECONDARY = 1; // 0x1
}
public final class LteVopsSupportInfo implements android.os.Parcelable {
ctor public LteVopsSupportInfo(int, int);
method public int describeContents();
@@ -11453,6 +11466,7 @@ package android.telephony {
field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int EVENT_EMERGENCY_NUMBER_LIST_CHANGED = 25; // 0x19
field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED = 28; // 0x1c
field @RequiresPermission(android.Manifest.permission.READ_CALL_LOG) public static final int EVENT_LEGACY_CALL_STATE_CHANGED = 36; // 0x24
field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_LINK_CAPACITY_ESTIMATE_CHANGED = 37; // 0x25
field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int EVENT_MESSAGE_WAITING_INDICATOR_CHANGED = 3; // 0x3
field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int EVENT_OEM_HOOK_RAW = 15; // 0xf
field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int EVENT_OUTGOING_EMERGENCY_CALL = 29; // 0x1d
@@ -11483,6 +11497,10 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onDataEnabledChanged(boolean, int);
}
public static interface TelephonyCallback.LinkCapacityEstimateChangedListener {
method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onLinkCapacityEstimateChanged(@NonNull java.util.List<android.telephony.LinkCapacityEstimate>);
}
public static interface TelephonyCallback.OutgoingEmergencyCallListener {
method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber, int);
}
@@ -11554,7 +11572,6 @@ package android.telephony {
method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getAndUpdateDefaultRespondViaMessageApplication();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallForwarding(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CallForwardingInfoCallback);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallWaitingStatus(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierBandwidth getCarrierBandwidth();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int);

View File

@@ -1261,6 +1261,8 @@ public class PhoneStateListener {
// default implementation empty
}
/**
* The callback methods need to be called on the handler thread where
* this object was created. If the binder did that for us it'd be nice.
@@ -1579,6 +1581,11 @@ public class PhoneStateListener {
public void onAllowedNetworkTypesChanged(int reason, long allowedNetworkType) {
// default implementation empty
}
public void onLinkCapacityEstimateChanged(
List<LinkCapacityEstimate> linkCapacityEstimateList) {
// default implementation empty
}
}
private void log(String s) {

View File

@@ -565,6 +565,21 @@ public class TelephonyCallback {
@RequiresPermission(android.Manifest.permission.READ_CALL_LOG)
public static final int EVENT_LEGACY_CALL_STATE_CHANGED = 36;
/**
* Event for changes to the link capacity estimate (LCE)
*
* <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
*
* @see LinkCapacityEstimateChangedListener#onLinkCapacityEstimateChanged
*
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
public static final int EVENT_LINK_CAPACITY_ESTIMATE_CHANGED = 37;
/**
* @hide
*/
@@ -604,7 +619,8 @@ public class TelephonyCallback {
EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED,
EVENT_DATA_ENABLED_CHANGED,
EVENT_ALLOWED_NETWORK_TYPE_LIST_CHANGED,
EVENT_LEGACY_CALL_STATE_CHANGED
EVENT_LEGACY_CALL_STATE_CHANGED,
EVENT_LINK_CAPACITY_ESTIMATE_CHANGED
})
@Retention(RetentionPolicy.SOURCE)
public @interface TelephonyEvent {
@@ -1370,6 +1386,25 @@ public class TelephonyCallback {
@TelephonyManager.DataEnabledReason int reason);
}
/**
* Interface for link capacity estimate changed listener.
*
* @hide
*/
@SystemApi
public interface LinkCapacityEstimateChangedListener {
/**
* Callback invoked when the link capacity estimate (LCE) changes
*
* @param linkCapacityEstimateList a list of {@link LinkCapacityEstimate}
* The list size is at least 1.
* In case of a dual connected network, the list size could be 2.
* Use {@link LinkCapacityEstimate#getType()} to get the type of each element.
*/
@RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
void onLinkCapacityEstimateChanged(
@NonNull List<LinkCapacityEstimate> linkCapacityEstimateList);
}
/**
* The callback methods need to be called on the handler thread where
@@ -1718,5 +1753,16 @@ public class TelephonyCallback {
() -> listener.onAllowedNetworkTypesChanged(reason,
allowedNetworkType)));
}
public void onLinkCapacityEstimateChanged(
List<LinkCapacityEstimate> linkCapacityEstimateList) {
LinkCapacityEstimateChangedListener listener =
(LinkCapacityEstimateChangedListener) mTelephonyCallbackWeakRef.get();
if (listener == null) return;
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(() -> listener.onLinkCapacityEstimateChanged(
linkCapacityEstimateList)));
}
}
}

View File

@@ -842,9 +842,23 @@ public class TelephonyRegistryManager {
}
}
/**
* Notify that the link capacity estimate has changed.
* @param slotIndex for the phone object that gets the updated link capacity estimate
* @param subId for subscription that gets the updated link capacity estimate
* @param linkCapacityEstimateList a list of {@link LinkCapacityEstimate}
*/
public void notifyLinkCapacityEstimateChanged(int slotIndex, int subId,
List<LinkCapacityEstimate> linkCapacityEstimateList) {
try {
sRegistry.notifyLinkCapacityEstimateChanged(slotIndex, subId, linkCapacityEstimateList);
} catch (RemoteException ex) {
// system server crash
}
}
public @NonNull Set<Integer> getEventsFromCallback(
@NonNull TelephonyCallback telephonyCallback) {
Set<Integer> eventList = new ArraySet<>();
if (telephonyCallback instanceof TelephonyCallback.ServiceStateListener) {
@@ -976,6 +990,10 @@ public class TelephonyRegistryManager {
eventList.add(TelephonyCallback.EVENT_ALLOWED_NETWORK_TYPE_LIST_CHANGED);
}
if (telephonyCallback instanceof TelephonyCallback.LinkCapacityEstimateChangedListener) {
eventList.add(TelephonyCallback.EVENT_LINK_CAPACITY_ESTIMATE_CHANGED);
}
return eventList;
}

View File

@@ -21,6 +21,7 @@ import android.telephony.CallAttributes;
import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.DataConnectionRealTimeInfo;
import android.telephony.LinkCapacityEstimate;
import android.telephony.TelephonyDisplayInfo;
import android.telephony.PhoneCapability;
import android.telephony.PhysicalChannelConfig;
@@ -73,4 +74,5 @@ oneway interface IPhoneStateListener {
void onPhysicalChannelConfigChanged(in List<PhysicalChannelConfig> configs);
void onDataEnabledChanged(boolean enabled, int reason);
void onAllowedNetworkTypesChanged(in int reason, in long allowedNetworkType);
void onLinkCapacityEstimateChanged(in List<LinkCapacityEstimate> linkCapacityEstimateList);
}

View File

@@ -23,6 +23,7 @@ import android.telephony.BarringInfo;
import android.telephony.CallQuality;
import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.LinkCapacityEstimate;
import android.telephony.TelephonyDisplayInfo;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.PhoneCapability;
@@ -96,4 +97,6 @@ interface ITelephonyRegistry {
in List<PhysicalChannelConfig> configs);
void notifyDataEnabled(in int phoneId, int subId, boolean enabled, int reason);
void notifyAllowedNetworkTypesChanged(in int phoneId, in int subId, in int reason, in long allowedNetworkType);
void notifyLinkCapacityEstimateChanged(in int phoneId, in int subId,
in List<LinkCapacityEstimate> linkCapacityEstimateList);
}

View File

@@ -60,6 +60,7 @@ import android.telephony.CellSignalStrengthNr;
import android.telephony.CellSignalStrengthTdscdma;
import android.telephony.CellSignalStrengthWcdma;
import android.telephony.DisconnectCause;
import android.telephony.LinkCapacityEstimate;
import android.telephony.LocationAccessPolicy;
import android.telephony.PhoneCapability;
import android.telephony.PhoneStateListener;
@@ -321,6 +322,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
private int[] mAllowedNetworkTypeReason;
private long[] mAllowedNetworkTypeValue;
private List<List<LinkCapacityEstimate>> mLinkCapacityEstimateLists;
/**
* Per-phone map of precise data connection state. The key of the map is the pair of transport
* type and APN setting. This is the cache to prevent redundant callbacks to the listeners.
@@ -351,6 +354,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
TelephonyCallback.EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED);
REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add(
TelephonyCallback.EVENT_DATA_ENABLED_CHANGED);
REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add(
TelephonyCallback.EVENT_LINK_CAPACITY_ESTIMATE_CHANGED);
}
private boolean isLocationPermissionRequired(Set<Integer> events) {
@@ -539,6 +544,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
cutListToSize(mPreciseDataConnectionStates, mNumPhones);
cutListToSize(mBarringInfo, mNumPhones);
cutListToSize(mPhysicalChannelConfigs, mNumPhones);
cutListToSize(mLinkCapacityEstimateLists, mNumPhones);
return;
}
@@ -577,6 +583,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig.Builder().build());
mAllowedNetworkTypeReason[i] = -1;
mAllowedNetworkTypeValue[i] = -1;
mLinkCapacityEstimateLists.add(i, new ArrayList<>());
}
}
@@ -640,6 +647,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mAllowedNetworkTypeValue = new long[numPhones];
mIsDataEnabled = new boolean[numPhones];
mDataEnabledReason = new int[numPhones];
mLinkCapacityEstimateLists = new ArrayList<>();
for (int i = 0; i < numPhones; i++) {
mCallState[i] = TelephonyManager.CALL_STATE_IDLE;
@@ -675,6 +683,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig.Builder().build());
mAllowedNetworkTypeReason[i] = -1;
mAllowedNetworkTypeValue[i] = -1;
mLinkCapacityEstimateLists.add(i, new ArrayList<>());
}
mAppOps = mContext.getSystemService(AppOpsManager.class);
@@ -1182,6 +1191,17 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
remove(r.binder);
}
}
if (events.contains(
TelephonyCallback.EVENT_LINK_CAPACITY_ESTIMATE_CHANGED)) {
try {
if (mLinkCapacityEstimateLists.get(phoneId) != null) {
r.callback.onLinkCapacityEstimateChanged(mLinkCapacityEstimateLists
.get(phoneId));
}
} catch (RemoteException ex) {
remove(r.binder);
}
}
}
}
}
@@ -2492,6 +2512,42 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
/**
* Notify that the link capacity estimate has changed.
* @param phoneId the phone id.
* @param subId the subscription id.
* @param linkCapacityEstimateList a list of {@link LinkCapacityEstimate}
*/
public void notifyLinkCapacityEstimateChanged(int phoneId, int subId,
List<LinkCapacityEstimate> linkCapacityEstimateList) {
if (!checkNotifyPermission("notifyLinkCapacityEstimateChanged()")) {
return;
}
if (VDBG) {
log("notifyLinkCapacityEstimateChanged: linkCapacityEstimateList ="
+ linkCapacityEstimateList);
}
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mLinkCapacityEstimateLists.set(phoneId, linkCapacityEstimateList);
for (Record r : mRecords) {
if (r.matchTelephonyCallbackEvent(
TelephonyCallback.EVENT_LINK_CAPACITY_ESTIMATE_CHANGED)
&& idMatch(r.subId, subId, phoneId)) {
try {
r.callback.onLinkCapacityEstimateChanged(linkCapacityEstimateList);
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
}
}
}
handleRemoveListLocked();
}
}
@Override
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
@@ -2538,6 +2594,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
pw.println("mDataEnabledReason=" + mDataEnabledReason);
pw.println("mAllowedNetworkTypeReason=" + mAllowedNetworkTypeReason[i]);
pw.println("mAllowedNetworkTypeValue=" + mAllowedNetworkTypeValue[i]);
pw.println("mLinkCapacityEstimateList=" + mLinkCapacityEstimateLists.get(i));
pw.decreaseIndent();
}
pw.println("mCarrierNetworkChangeState=" + mCarrierNetworkChangeState);

View File

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2021 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;
parcelable LinkCapacityEstimate;

View File

@@ -0,0 +1,179 @@
/*
* Copyright (C) 2021 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.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
* Link Capacity Estimate from the modem
* @hide
*/
@SystemApi
public final class LinkCapacityEstimate implements Parcelable {
/** A value indicates that the capacity estimate is not available */
public static final int INVALID = -1;
/**
* LCE for the primary network
*/
public static final int LCE_TYPE_PRIMARY = 0;
/**
* LCE for the secondary network
*/
public static final int LCE_TYPE_SECONDARY = 1;
/**
* Combined LCE for primary network and secondary network reported by the legacy modem
*/
public static final int LCE_TYPE_COMBINED = 2;
/** @hide */
@IntDef(prefix = { "LCE_TYPE_" }, value = {
LCE_TYPE_PRIMARY,
LCE_TYPE_SECONDARY,
LCE_TYPE_COMBINED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface LceType {}
private final @LceType int mType;
/** Downlink capacity estimate in kbps */
private final int mDownlinkCapacityKbps;
/** Uplink capacity estimate in kbps */
private final int mUplinkCapacityKbps;
/**
* Constructor for link capacity estimate
*/
public LinkCapacityEstimate(@LceType int type,
int downlinkCapacityKbps, int uplinkCapacityKbps) {
mDownlinkCapacityKbps = downlinkCapacityKbps;
mUplinkCapacityKbps = uplinkCapacityKbps;
mType = type;
}
/**
* @hide
*/
public LinkCapacityEstimate(Parcel in) {
mDownlinkCapacityKbps = in.readInt();
mUplinkCapacityKbps = in.readInt();
mType = in.readInt();
}
/**
* Retrieves the type of LCE
* @return The type of link capacity estimate
*/
public @LceType int getType() {
return mType;
}
/**
* Retrieves the downlink bandwidth in Kbps.
* This will be {@link #INVALID} if the network is not connected
* @return The estimated first hop downstream (network to device) bandwidth.
*/
public int getDownlinkCapacityKbps() {
return mDownlinkCapacityKbps;
}
/**
* Retrieves the uplink bandwidth in Kbps.
* This will be {@link #INVALID} if the network is not connected
*
* @return The estimated first hop upstream (device to network) bandwidth.
*/
public int getUplinkCapacityKbps() {
return mUplinkCapacityKbps;
}
@Override
public String toString() {
return new StringBuilder()
.append("{mType=")
.append(mType)
.append(", mDownlinkCapacityKbps=")
.append(mDownlinkCapacityKbps)
.append(", mUplinkCapacityKbps=")
.append(mUplinkCapacityKbps)
.append("}")
.toString();
}
/**
* {@link Parcelable#describeContents}
*/
public int describeContents() {
return 0;
}
/**
* {@link Parcelable#writeToParcel}
* @hide
*/
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mDownlinkCapacityKbps);
dest.writeInt(mUplinkCapacityKbps);
dest.writeInt(mType);
}
@Override
public boolean equals(@Nullable Object o) {
if (o == null || !(o instanceof LinkCapacityEstimate) || hashCode() != o.hashCode()) {
return false;
}
if (this == o) {
return true;
}
LinkCapacityEstimate that = (LinkCapacityEstimate) o;
return mDownlinkCapacityKbps == that.mDownlinkCapacityKbps
&& mUplinkCapacityKbps == that.mUplinkCapacityKbps
&& mType == that.mType;
}
@Override
public int hashCode() {
return Objects.hash(mDownlinkCapacityKbps, mUplinkCapacityKbps, mType);
}
public static final
@android.annotation.NonNull Parcelable.Creator<LinkCapacityEstimate> CREATOR =
new Parcelable.Creator() {
public LinkCapacityEstimate createFromParcel(Parcel in) {
return new LinkCapacityEstimate(in);
}
public LinkCapacityEstimate[] newArray(int size) {
return new LinkCapacityEstimate[size];
}
};
}

View File

@@ -14502,34 +14502,6 @@ public class TelephonyManager {
return PinResult.getDefaultFailedResult();
}
/**
* Get carrier bandwidth. In case of Dual connected network this will report
* bandwidth per primary and secondary network. It is possible that
* some modems may not fill secondary carrier bandwidth.
* @return CarrierBandwidth with bandwidth of both primary and secondary carrier.
* @throws IllegalStateException if the Telephony process is not currently available.
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@NonNull
public CarrierBandwidth getCarrierBandwidth() {
try {
ITelephony service = getITelephony();
if (service != null) {
return service.getCarrierBandwidth(getSubId());
} else {
throw new IllegalStateException("telephony service is null.");
}
} catch (RemoteException ex) {
Log.e(TAG, "getCarrierBandwidth RemoteException", ex);
ex.rethrowFromSystemServer();
}
//Should not reach. Adding return statement to make compiler happy
return null;
}
/**
* Called when userActivity is signalled in the power manager.
* This should only be called from system Uid.

View File

@@ -31,7 +31,6 @@ import android.service.carrier.CarrierIdentifier;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telephony.CallForwardingInfo;
import android.telephony.CarrierBandwidth;
import android.telephony.CarrierRestrictionRules;
import android.telephony.CellIdentity;
import android.telephony.CellInfo;
@@ -2237,12 +2236,6 @@ interface ITelephony {
*/
boolean isNrDualConnectivityEnabled(int subId);
/**
* Get carrier bandwidth per primary and secondary carrier
* @return CarrierBandwidth with bandwidth of both primary and secondary carrier.
*/
CarrierBandwidth getCarrierBandwidth(int subId);
/**
* Checks whether the device supports the given capability on the radio interface.
*