452 lines
18 KiB
Java
452 lines
18 KiB
Java
/*
|
|
* 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 com.android.internal.telephony;
|
|
|
|
import android.net.KeepalivePacketData;
|
|
import android.net.LinkProperties;
|
|
import android.os.AsyncResult;
|
|
import android.os.Message;
|
|
import android.os.RemoteException;
|
|
import android.telephony.Rlog;
|
|
import android.telephony.data.DataProfile;
|
|
import android.telephony.data.NetworkSliceInfo;
|
|
import android.telephony.data.TrafficDescriptor;
|
|
|
|
import java.net.Inet4Address;
|
|
import java.net.Inet6Address;
|
|
import java.net.InetAddress;
|
|
import java.util.ArrayList;
|
|
|
|
/**
|
|
* A holder for IRadioData.
|
|
* Use getAidl to get IRadioData and call the AIDL implementations of the HAL APIs.
|
|
*/
|
|
public class RadioDataProxy extends RadioServiceProxy {
|
|
private static final String TAG = "RadioDataProxy";
|
|
private volatile android.hardware.radio.data.IRadioData mDataProxy = null;
|
|
|
|
/**
|
|
* Set IRadioData as the AIDL implementation for RadioServiceProxy
|
|
* @param halVersion Radio HAL version
|
|
* @param data IRadioData implementation
|
|
*
|
|
* @return updated HAL version
|
|
*/
|
|
public HalVersion setAidl(HalVersion halVersion, android.hardware.radio.data.IRadioData data) {
|
|
HalVersion version = halVersion;
|
|
try {
|
|
version = RIL.getServiceHalVersion(data.getInterfaceVersion());
|
|
} catch (RemoteException e) {
|
|
Rlog.e(TAG, "setAidl: " + e);
|
|
}
|
|
mHalVersion = version;
|
|
mDataProxy = data;
|
|
mIsAidl = true;
|
|
|
|
Rlog.d(TAG, "AIDL initialized mHalVersion=" + mHalVersion);
|
|
return mHalVersion;
|
|
}
|
|
|
|
/**
|
|
* Get the AIDL implementation of RadioDataProxy
|
|
* @return IRadioData implementation
|
|
*/
|
|
public android.hardware.radio.data.IRadioData getAidl() {
|
|
return mDataProxy;
|
|
}
|
|
|
|
/**
|
|
* Reset RadioDataProxy
|
|
*/
|
|
@Override
|
|
public void clear() {
|
|
super.clear();
|
|
mDataProxy = null;
|
|
}
|
|
|
|
/**
|
|
* Check whether a RadioData implementation exists
|
|
* @return true if there is neither a HIDL nor AIDL implementation
|
|
*/
|
|
@Override
|
|
public boolean isEmpty() {
|
|
return mRadioProxy == null && mDataProxy == null;
|
|
}
|
|
|
|
/**
|
|
* Call IRadioData#allocatePduSessionId
|
|
* @param serial Serial number of request
|
|
* @throws RemoteException
|
|
*/
|
|
public void allocatePduSessionId(int serial) throws RemoteException {
|
|
if (isEmpty() || mHalVersion.less(RIL.RADIO_HAL_VERSION_1_6)) return;
|
|
if (isAidl()) {
|
|
mDataProxy.allocatePduSessionId(serial);
|
|
} else {
|
|
((android.hardware.radio.V1_6.IRadio) mRadioProxy).allocatePduSessionId(serial);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Call IRadioData#cancelHandover
|
|
* @param serial Serial number of request
|
|
* @param callId Identifier associated with the data call
|
|
* @throws RemoteException
|
|
*/
|
|
public void cancelHandover(int serial, int callId) throws RemoteException {
|
|
if (isEmpty() || mHalVersion.less(RIL.RADIO_HAL_VERSION_1_6)) return;
|
|
if (isAidl()) {
|
|
mDataProxy.cancelHandover(serial, callId);
|
|
} else {
|
|
((android.hardware.radio.V1_6.IRadio) mRadioProxy).cancelHandover(serial, callId);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Call IRadioData#deactivateDataCall
|
|
* @param serial Serial number of request
|
|
* @param cid The connection ID
|
|
* @param reason Data disconnect reason
|
|
* @throws RemoteException
|
|
*/
|
|
public void deactivateDataCall(int serial, int cid, int reason) throws RemoteException {
|
|
if (isEmpty()) return;
|
|
if (isAidl()) {
|
|
mDataProxy.deactivateDataCall(serial, cid, reason);
|
|
} else {
|
|
mRadioProxy.deactivateDataCall_1_2(serial, cid, reason);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Call IRadioData#getDataCallList
|
|
* @param serial Serial number of request
|
|
* @throws RemoteException
|
|
*/
|
|
public void getDataCallList(int serial) throws RemoteException {
|
|
if (isEmpty()) return;
|
|
if (isAidl()) {
|
|
mDataProxy.getDataCallList(serial);
|
|
} else if (mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_6)) {
|
|
((android.hardware.radio.V1_6.IRadio) mRadioProxy).getDataCallList_1_6(serial);
|
|
} else {
|
|
mRadioProxy.getDataCallList(serial);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Call IRadioData#getSlicingConfig
|
|
* @param serial Serial number of request
|
|
* @throws RemoteException
|
|
*/
|
|
public void getSlicingConfig(int serial) throws RemoteException {
|
|
if (isEmpty() || mHalVersion.less(RIL.RADIO_HAL_VERSION_1_6)) return;
|
|
if (isAidl()) {
|
|
mDataProxy.getSlicingConfig(serial);
|
|
} else {
|
|
((android.hardware.radio.V1_6.IRadio) mRadioProxy).getSlicingConfig(serial);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Call IRadioData#releasePduSessionId
|
|
* @param serial Serial number of request
|
|
* @param id PDU session ID to release
|
|
* @throws RemoteException
|
|
*/
|
|
public void releasePduSessionId(int serial, int id) throws RemoteException {
|
|
if (isEmpty() || mHalVersion.less(RIL.RADIO_HAL_VERSION_1_6)) return;
|
|
if (isAidl()) {
|
|
mDataProxy.releasePduSessionId(serial, id);
|
|
} else {
|
|
((android.hardware.radio.V1_6.IRadio) mRadioProxy).releasePduSessionId(serial, id);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Call IRadioData#responseAcknowledgement
|
|
* @throws RemoteException
|
|
*/
|
|
@Override
|
|
public void responseAcknowledgement() throws RemoteException {
|
|
if (isEmpty()) return;
|
|
if (isAidl()) {
|
|
mDataProxy.responseAcknowledgement();
|
|
} else {
|
|
mRadioProxy.responseAcknowledgement();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Call IRadioData#setDataAllowed
|
|
* @param serial Serial number of request
|
|
* @param allow Whether to allow or disallow data calls
|
|
* @throws RemoteException
|
|
*/
|
|
public void setDataAllowed(int serial, boolean allow) throws RemoteException {
|
|
if (isEmpty()) return;
|
|
if (isAidl()) {
|
|
mDataProxy.setDataAllowed(serial, allow);
|
|
} else {
|
|
mRadioProxy.setDataAllowed(serial, allow);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Call IRadioData#setDataProfile
|
|
* @param serial Serial number of request
|
|
* @param profiles Array of DataProfiles to set
|
|
* @throws RemoteException
|
|
*/
|
|
public void setDataProfile(int serial, DataProfile[] profiles) throws RemoteException {
|
|
if (isEmpty()) return;
|
|
if (isAidl()) {
|
|
android.hardware.radio.data.DataProfileInfo[] dpis =
|
|
new android.hardware.radio.data.DataProfileInfo[profiles.length];
|
|
for (int i = 0; i < profiles.length; i++) {
|
|
dpis[i] = RILUtils.convertToHalDataProfile(profiles[i]);
|
|
}
|
|
mDataProxy.setDataProfile(serial, dpis);
|
|
} else if (mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_5)) {
|
|
ArrayList<android.hardware.radio.V1_5.DataProfileInfo> dpis = new ArrayList<>();
|
|
for (DataProfile dp : profiles) {
|
|
dpis.add(RILUtils.convertToHalDataProfile15(dp));
|
|
}
|
|
((android.hardware.radio.V1_5.IRadio) mRadioProxy).setDataProfile_1_5(serial, dpis);
|
|
} else {
|
|
ArrayList<android.hardware.radio.V1_4.DataProfileInfo> dpis = new ArrayList<>();
|
|
for (DataProfile dp : profiles) {
|
|
dpis.add(RILUtils.convertToHalDataProfile14(dp));
|
|
}
|
|
mRadioProxy.setDataProfile_1_4(serial, dpis);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Call IRadioData#setDataThrottling
|
|
* @param serial Serial number of request
|
|
* @param dataThrottlingAction DataThrottlingAction as defined in DataThrottlingAction.aidl
|
|
* @param completionDurationMillis Window in ms in which the requested throttling action has to
|
|
* be achieved.
|
|
* @throws RemoteException
|
|
*/
|
|
public void setDataThrottling(int serial, byte dataThrottlingAction,
|
|
long completionDurationMillis) throws RemoteException {
|
|
if (isEmpty() || mHalVersion.less(RIL.RADIO_HAL_VERSION_1_6)) return;
|
|
if (isAidl()) {
|
|
mDataProxy.setDataThrottling(serial, dataThrottlingAction, completionDurationMillis);
|
|
} else {
|
|
((android.hardware.radio.V1_6.IRadio) mRadioProxy).setDataThrottling(serial,
|
|
dataThrottlingAction, completionDurationMillis);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Call IRadioData#setInitialAttachApn
|
|
* @param serial Serial number of request
|
|
* @param dataProfile Data profile containing APN settings
|
|
* @throws RemoteException
|
|
*/
|
|
public void setInitialAttachApn(int serial, DataProfile dataProfile)
|
|
throws RemoteException {
|
|
if (isEmpty()) return;
|
|
if (isAidl()) {
|
|
mDataProxy.setInitialAttachApn(serial, RILUtils.convertToHalDataProfile(dataProfile));
|
|
} else if (mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_5)) {
|
|
((android.hardware.radio.V1_5.IRadio) mRadioProxy).setInitialAttachApn_1_5(serial,
|
|
RILUtils.convertToHalDataProfile15(dataProfile));
|
|
} else {
|
|
mRadioProxy.setInitialAttachApn_1_4(serial,
|
|
RILUtils.convertToHalDataProfile14(dataProfile));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Call IRadioData#setupDataCall
|
|
* @param serial Serial number of request
|
|
* @param accessNetwork Access network to setup the data call
|
|
* @param dataProfileInfo Data profile info
|
|
* @param roamingAllowed Whether or not data roaming is allowed by the user
|
|
* @param reason Request reason
|
|
* @param linkProperties LinkProperties containing address and DNS info
|
|
* @param pduSessionId The PDU session ID to be used for this data call
|
|
* @param sliceInfo SliceInfo to be used for the data connection when a handover occurs from
|
|
* EPDG to 5G
|
|
* @param trafficDescriptor TrafficDescriptor for which the data connection needs to be
|
|
* established
|
|
* @param matchAllRuleAllowed Whether or not the default match-all URSP rule for this request
|
|
* is allowed
|
|
* @throws RemoteException
|
|
*/
|
|
public void setupDataCall(int serial, int accessNetwork, DataProfile dataProfileInfo,
|
|
boolean roamingAllowed, int reason, LinkProperties linkProperties, int pduSessionId,
|
|
NetworkSliceInfo sliceInfo, TrafficDescriptor trafficDescriptor,
|
|
boolean matchAllRuleAllowed) throws RemoteException {
|
|
if (isEmpty()) return;
|
|
ArrayList<String> addresses = new ArrayList<>();
|
|
ArrayList<String> dnses = new ArrayList<>();
|
|
String[] dnsesArr;
|
|
if (linkProperties != null) {
|
|
for (InetAddress address : linkProperties.getAddresses()) {
|
|
addresses.add(address.getHostAddress());
|
|
}
|
|
dnsesArr = new String[linkProperties.getDnsServers().size()];
|
|
for (int i = 0; i < linkProperties.getDnsServers().size(); i++) {
|
|
dnses.add(linkProperties.getDnsServers().get(i).getHostAddress());
|
|
dnsesArr[i] = linkProperties.getDnsServers().get(i).getHostAddress();
|
|
}
|
|
} else {
|
|
dnsesArr = new String[0];
|
|
}
|
|
if (isAidl()) {
|
|
// Create a new DataProfile to set the TrafficDescriptor
|
|
DataProfile dp = new DataProfile.Builder()
|
|
.setType(dataProfileInfo.getType())
|
|
.setPreferred(dataProfileInfo.isPreferred())
|
|
.setTrafficDescriptor(trafficDescriptor)
|
|
.setApnSetting(dataProfileInfo.getApnSetting())
|
|
.build();
|
|
mDataProxy.setupDataCall(serial, accessNetwork, RILUtils.convertToHalDataProfile(dp),
|
|
roamingAllowed, reason, RILUtils.convertToHalLinkProperties(linkProperties),
|
|
dnsesArr, pduSessionId, RILUtils.convertToHalSliceInfoAidl(sliceInfo),
|
|
matchAllRuleAllowed);
|
|
} else if (mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_6)) {
|
|
((android.hardware.radio.V1_6.IRadio) mRadioProxy).setupDataCall_1_6(serial,
|
|
accessNetwork, RILUtils.convertToHalDataProfile15(dataProfileInfo),
|
|
roamingAllowed, reason, RILUtils.convertToHalLinkProperties15(linkProperties),
|
|
dnses, pduSessionId, RILUtils.convertToHalSliceInfo(sliceInfo),
|
|
RILUtils.convertToHalTrafficDescriptor(trafficDescriptor),
|
|
matchAllRuleAllowed);
|
|
} else if (mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_5)) {
|
|
((android.hardware.radio.V1_5.IRadio) mRadioProxy).setupDataCall_1_5(serial,
|
|
accessNetwork, RILUtils.convertToHalDataProfile15(dataProfileInfo),
|
|
roamingAllowed, reason, RILUtils.convertToHalLinkProperties15(linkProperties),
|
|
dnses);
|
|
} else {
|
|
mRadioProxy.setupDataCall_1_4(serial, accessNetwork,
|
|
RILUtils.convertToHalDataProfile14(dataProfileInfo),
|
|
roamingAllowed, reason, addresses, dnses);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Call IRadioData#startHandover
|
|
* @param serial Serial number of request
|
|
* @param callId Identifier of the data call
|
|
* @throws RemoteException
|
|
*/
|
|
public void startHandover(int serial, int callId) throws RemoteException {
|
|
if (isEmpty() || mHalVersion.less(RIL.RADIO_HAL_VERSION_1_6)) return;
|
|
if (isAidl()) {
|
|
mDataProxy.startHandover(serial, callId);
|
|
} else {
|
|
((android.hardware.radio.V1_6.IRadio) mRadioProxy).startHandover(serial, callId);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Call IRadioData#startKeepalive
|
|
* @param serial Serial number of request
|
|
* @param contextId Context ID for the data call
|
|
* @param packetData Keepalive packet data
|
|
* @param intervalMillis Max keepalive interval in ms
|
|
* @param result Result to return in case of invalid arguments
|
|
* @throws RemoteException
|
|
*/
|
|
public void startKeepalive(int serial, int contextId, KeepalivePacketData packetData,
|
|
int intervalMillis, Message result) throws RemoteException {
|
|
if (isEmpty()) return;
|
|
if (isAidl()) {
|
|
android.hardware.radio.data.KeepaliveRequest req =
|
|
new android.hardware.radio.data.KeepaliveRequest();
|
|
req.cid = contextId;
|
|
|
|
if (packetData.getDstAddress() instanceof Inet4Address) {
|
|
req.type = android.hardware.radio.data.KeepaliveRequest.TYPE_NATT_IPV4;
|
|
} else if (packetData.getDstAddress() instanceof Inet6Address) {
|
|
req.type = android.hardware.radio.data.KeepaliveRequest.TYPE_NATT_IPV6;
|
|
} else {
|
|
AsyncResult.forMessage(result, null,
|
|
CommandException.fromRilErrno(RILConstants.INVALID_ARGUMENTS));
|
|
result.sendToTarget();
|
|
return;
|
|
}
|
|
|
|
final InetAddress srcAddress = packetData.getSrcAddress();
|
|
final InetAddress dstAddress = packetData.getDstAddress();
|
|
byte[] sourceAddress = new byte[srcAddress.getAddress().length];
|
|
for (int i = 0; i < sourceAddress.length; i++) {
|
|
sourceAddress[i] = srcAddress.getAddress()[i];
|
|
}
|
|
req.sourceAddress = sourceAddress;
|
|
req.sourcePort = packetData.getSrcPort();
|
|
byte[] destinationAddress = new byte[dstAddress.getAddress().length];
|
|
for (int i = 0; i < destinationAddress.length; i++) {
|
|
destinationAddress[i] = dstAddress.getAddress()[i];
|
|
}
|
|
req.destinationAddress = destinationAddress;
|
|
req.destinationPort = packetData.getDstPort();
|
|
req.maxKeepaliveIntervalMillis = intervalMillis;
|
|
|
|
mDataProxy.startKeepalive(serial, req);
|
|
} else {
|
|
android.hardware.radio.V1_1.KeepaliveRequest req =
|
|
new android.hardware.radio.V1_1.KeepaliveRequest();
|
|
|
|
req.cid = contextId;
|
|
|
|
if (packetData.getDstAddress() instanceof Inet4Address) {
|
|
req.type = android.hardware.radio.V1_1.KeepaliveType.NATT_IPV4;
|
|
} else if (packetData.getDstAddress() instanceof Inet6Address) {
|
|
req.type = android.hardware.radio.V1_1.KeepaliveType.NATT_IPV6;
|
|
} else {
|
|
AsyncResult.forMessage(result, null,
|
|
CommandException.fromRilErrno(RILConstants.INVALID_ARGUMENTS));
|
|
result.sendToTarget();
|
|
return;
|
|
}
|
|
|
|
final InetAddress srcAddress = packetData.getSrcAddress();
|
|
final InetAddress dstAddress = packetData.getDstAddress();
|
|
RILUtils.appendPrimitiveArrayToArrayList(
|
|
srcAddress.getAddress(), req.sourceAddress);
|
|
req.sourcePort = packetData.getSrcPort();
|
|
RILUtils.appendPrimitiveArrayToArrayList(
|
|
dstAddress.getAddress(), req.destinationAddress);
|
|
req.destinationPort = packetData.getDstPort();
|
|
req.maxKeepaliveIntervalMillis = intervalMillis;
|
|
|
|
mRadioProxy.startKeepalive(serial, req);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Call IRadioData#stopKeepalive
|
|
* @param serial Serial number of request
|
|
* @param sessionHandle The handle that was provided by startKeepaliveResponse
|
|
* @throws RemoteException
|
|
*/
|
|
public void stopKeepalive(int serial, int sessionHandle) throws RemoteException {
|
|
if (isEmpty()) return;
|
|
if (isAidl()) {
|
|
mDataProxy.stopKeepalive(serial, sessionHandle);
|
|
} else {
|
|
mRadioProxy.stopKeepalive(serial, sessionHandle);
|
|
}
|
|
}
|
|
}
|