1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony; 18 19 import android.net.KeepalivePacketData; 20 import android.net.LinkProperties; 21 import android.os.AsyncResult; 22 import android.os.Message; 23 import android.os.RemoteException; 24 import android.telephony.Rlog; 25 import android.telephony.data.DataProfile; 26 import android.telephony.data.NetworkSliceInfo; 27 import android.telephony.data.TrafficDescriptor; 28 29 import java.net.Inet4Address; 30 import java.net.Inet6Address; 31 import java.net.InetAddress; 32 import java.util.ArrayList; 33 34 /** 35 * A holder for IRadioData. 36 * Use getAidl to get IRadioData and call the AIDL implementations of the HAL APIs. 37 */ 38 public class RadioDataProxy extends RadioServiceProxy { 39 private static final String TAG = "RadioDataProxy"; 40 private volatile android.hardware.radio.data.IRadioData mDataProxy = null; 41 42 /** 43 * Set IRadioData as the AIDL implementation for RadioServiceProxy 44 * @param halVersion Radio HAL version 45 * @param data IRadioData implementation 46 * 47 * @return updated HAL version 48 */ setAidl(HalVersion halVersion, android.hardware.radio.data.IRadioData data)49 public HalVersion setAidl(HalVersion halVersion, android.hardware.radio.data.IRadioData data) { 50 HalVersion version = halVersion; 51 try { 52 version = RIL.getServiceHalVersion(data.getInterfaceVersion()); 53 } catch (RemoteException e) { 54 Rlog.e(TAG, "setAidl: " + e); 55 } 56 mHalVersion = version; 57 mDataProxy = data; 58 mIsAidl = true; 59 60 Rlog.d(TAG, "AIDL initialized mHalVersion=" + mHalVersion); 61 return mHalVersion; 62 } 63 64 /** 65 * Get the AIDL implementation of RadioDataProxy 66 * @return IRadioData implementation 67 */ getAidl()68 public android.hardware.radio.data.IRadioData getAidl() { 69 return mDataProxy; 70 } 71 72 /** 73 * Reset RadioDataProxy 74 */ 75 @Override clear()76 public void clear() { 77 super.clear(); 78 mDataProxy = null; 79 } 80 81 /** 82 * Check whether a RadioData implementation exists 83 * @return true if there is neither a HIDL nor AIDL implementation 84 */ 85 @Override isEmpty()86 public boolean isEmpty() { 87 return mRadioProxy == null && mDataProxy == null; 88 } 89 90 /** 91 * Call IRadioData#allocatePduSessionId 92 * @param serial Serial number of request 93 * @throws RemoteException 94 */ allocatePduSessionId(int serial)95 public void allocatePduSessionId(int serial) throws RemoteException { 96 if (isEmpty() || mHalVersion.less(RIL.RADIO_HAL_VERSION_1_6)) return; 97 if (isAidl()) { 98 mDataProxy.allocatePduSessionId(serial); 99 } else { 100 ((android.hardware.radio.V1_6.IRadio) mRadioProxy).allocatePduSessionId(serial); 101 } 102 } 103 104 /** 105 * Call IRadioData#cancelHandover 106 * @param serial Serial number of request 107 * @param callId Identifier associated with the data call 108 * @throws RemoteException 109 */ cancelHandover(int serial, int callId)110 public void cancelHandover(int serial, int callId) throws RemoteException { 111 if (isEmpty() || mHalVersion.less(RIL.RADIO_HAL_VERSION_1_6)) return; 112 if (isAidl()) { 113 mDataProxy.cancelHandover(serial, callId); 114 } else { 115 ((android.hardware.radio.V1_6.IRadio) mRadioProxy).cancelHandover(serial, callId); 116 } 117 } 118 119 /** 120 * Call IRadioData#deactivateDataCall 121 * @param serial Serial number of request 122 * @param cid The connection ID 123 * @param reason Data disconnect reason 124 * @throws RemoteException 125 */ deactivateDataCall(int serial, int cid, int reason)126 public void deactivateDataCall(int serial, int cid, int reason) throws RemoteException { 127 if (isEmpty()) return; 128 if (isAidl()) { 129 mDataProxy.deactivateDataCall(serial, cid, reason); 130 } else { 131 mRadioProxy.deactivateDataCall_1_2(serial, cid, reason); 132 } 133 } 134 135 /** 136 * Call IRadioData#getDataCallList 137 * @param serial Serial number of request 138 * @throws RemoteException 139 */ getDataCallList(int serial)140 public void getDataCallList(int serial) throws RemoteException { 141 if (isEmpty()) return; 142 if (isAidl()) { 143 mDataProxy.getDataCallList(serial); 144 } else if (mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_6)) { 145 ((android.hardware.radio.V1_6.IRadio) mRadioProxy).getDataCallList_1_6(serial); 146 } else { 147 mRadioProxy.getDataCallList(serial); 148 } 149 } 150 151 /** 152 * Call IRadioData#getSlicingConfig 153 * @param serial Serial number of request 154 * @throws RemoteException 155 */ getSlicingConfig(int serial)156 public void getSlicingConfig(int serial) throws RemoteException { 157 if (isEmpty() || mHalVersion.less(RIL.RADIO_HAL_VERSION_1_6)) return; 158 if (isAidl()) { 159 mDataProxy.getSlicingConfig(serial); 160 } else { 161 ((android.hardware.radio.V1_6.IRadio) mRadioProxy).getSlicingConfig(serial); 162 } 163 } 164 165 /** 166 * Call IRadioData#releasePduSessionId 167 * @param serial Serial number of request 168 * @param id PDU session ID to release 169 * @throws RemoteException 170 */ releasePduSessionId(int serial, int id)171 public void releasePduSessionId(int serial, int id) throws RemoteException { 172 if (isEmpty() || mHalVersion.less(RIL.RADIO_HAL_VERSION_1_6)) return; 173 if (isAidl()) { 174 mDataProxy.releasePduSessionId(serial, id); 175 } else { 176 ((android.hardware.radio.V1_6.IRadio) mRadioProxy).releasePduSessionId(serial, id); 177 } 178 } 179 180 /** 181 * Call IRadioData#responseAcknowledgement 182 * @throws RemoteException 183 */ 184 @Override responseAcknowledgement()185 public void responseAcknowledgement() throws RemoteException { 186 if (isEmpty()) return; 187 if (isAidl()) { 188 mDataProxy.responseAcknowledgement(); 189 } else { 190 mRadioProxy.responseAcknowledgement(); 191 } 192 } 193 194 /** 195 * Call IRadioData#setDataAllowed 196 * @param serial Serial number of request 197 * @param allow Whether to allow or disallow data calls 198 * @throws RemoteException 199 */ setDataAllowed(int serial, boolean allow)200 public void setDataAllowed(int serial, boolean allow) throws RemoteException { 201 if (isEmpty()) return; 202 if (isAidl()) { 203 mDataProxy.setDataAllowed(serial, allow); 204 } else { 205 mRadioProxy.setDataAllowed(serial, allow); 206 } 207 } 208 209 /** 210 * Call IRadioData#setDataProfile 211 * @param serial Serial number of request 212 * @param profiles Array of DataProfiles to set 213 * @throws RemoteException 214 */ setDataProfile(int serial, DataProfile[] profiles)215 public void setDataProfile(int serial, DataProfile[] profiles) throws RemoteException { 216 if (isEmpty()) return; 217 if (isAidl()) { 218 android.hardware.radio.data.DataProfileInfo[] dpis = 219 new android.hardware.radio.data.DataProfileInfo[profiles.length]; 220 for (int i = 0; i < profiles.length; i++) { 221 dpis[i] = RILUtils.convertToHalDataProfile(profiles[i]); 222 } 223 mDataProxy.setDataProfile(serial, dpis); 224 } else if (mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_5)) { 225 ArrayList<android.hardware.radio.V1_5.DataProfileInfo> dpis = new ArrayList<>(); 226 for (DataProfile dp : profiles) { 227 dpis.add(RILUtils.convertToHalDataProfile15(dp)); 228 } 229 ((android.hardware.radio.V1_5.IRadio) mRadioProxy).setDataProfile_1_5(serial, dpis); 230 } else { 231 ArrayList<android.hardware.radio.V1_4.DataProfileInfo> dpis = new ArrayList<>(); 232 for (DataProfile dp : profiles) { 233 dpis.add(RILUtils.convertToHalDataProfile14(dp)); 234 } 235 mRadioProxy.setDataProfile_1_4(serial, dpis); 236 } 237 } 238 239 /** 240 * Call IRadioData#setDataThrottling 241 * @param serial Serial number of request 242 * @param dataThrottlingAction DataThrottlingAction as defined in DataThrottlingAction.aidl 243 * @param completionDurationMillis Window in ms in which the requested throttling action has to 244 * be achieved. 245 * @throws RemoteException 246 */ setDataThrottling(int serial, byte dataThrottlingAction, long completionDurationMillis)247 public void setDataThrottling(int serial, byte dataThrottlingAction, 248 long completionDurationMillis) throws RemoteException { 249 if (isEmpty() || mHalVersion.less(RIL.RADIO_HAL_VERSION_1_6)) return; 250 if (isAidl()) { 251 mDataProxy.setDataThrottling(serial, dataThrottlingAction, completionDurationMillis); 252 } else { 253 ((android.hardware.radio.V1_6.IRadio) mRadioProxy).setDataThrottling(serial, 254 dataThrottlingAction, completionDurationMillis); 255 } 256 } 257 258 /** 259 * Call IRadioData#setInitialAttachApn 260 * @param serial Serial number of request 261 * @param dataProfile Data profile containing APN settings 262 * @throws RemoteException 263 */ setInitialAttachApn(int serial, DataProfile dataProfile)264 public void setInitialAttachApn(int serial, DataProfile dataProfile) 265 throws RemoteException { 266 if (isEmpty()) return; 267 if (isAidl()) { 268 mDataProxy.setInitialAttachApn(serial, RILUtils.convertToHalDataProfile(dataProfile)); 269 } else if (mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_5)) { 270 ((android.hardware.radio.V1_5.IRadio) mRadioProxy).setInitialAttachApn_1_5(serial, 271 RILUtils.convertToHalDataProfile15(dataProfile)); 272 } else { 273 mRadioProxy.setInitialAttachApn_1_4(serial, 274 RILUtils.convertToHalDataProfile14(dataProfile)); 275 } 276 } 277 278 /** 279 * Call IRadioData#setupDataCall 280 * @param serial Serial number of request 281 * @param accessNetwork Access network to setup the data call 282 * @param dataProfileInfo Data profile info 283 * @param roamingAllowed Whether or not data roaming is allowed by the user 284 * @param reason Request reason 285 * @param linkProperties LinkProperties containing address and DNS info 286 * @param pduSessionId The PDU session ID to be used for this data call 287 * @param sliceInfo SliceInfo to be used for the data connection when a handover occurs from 288 * EPDG to 5G 289 * @param trafficDescriptor TrafficDescriptor for which the data connection needs to be 290 * established 291 * @param matchAllRuleAllowed Whether or not the default match-all URSP rule for this request 292 * is allowed 293 * @throws RemoteException 294 */ setupDataCall(int serial, int accessNetwork, DataProfile dataProfileInfo, boolean roamingAllowed, int reason, LinkProperties linkProperties, int pduSessionId, NetworkSliceInfo sliceInfo, TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed)295 public void setupDataCall(int serial, int accessNetwork, DataProfile dataProfileInfo, 296 boolean roamingAllowed, int reason, LinkProperties linkProperties, int pduSessionId, 297 NetworkSliceInfo sliceInfo, TrafficDescriptor trafficDescriptor, 298 boolean matchAllRuleAllowed) throws RemoteException { 299 if (isEmpty()) return; 300 ArrayList<String> addresses = new ArrayList<>(); 301 ArrayList<String> dnses = new ArrayList<>(); 302 String[] dnsesArr; 303 if (linkProperties != null) { 304 for (InetAddress address : linkProperties.getAddresses()) { 305 addresses.add(address.getHostAddress()); 306 } 307 dnsesArr = new String[linkProperties.getDnsServers().size()]; 308 for (int i = 0; i < linkProperties.getDnsServers().size(); i++) { 309 dnses.add(linkProperties.getDnsServers().get(i).getHostAddress()); 310 dnsesArr[i] = linkProperties.getDnsServers().get(i).getHostAddress(); 311 } 312 } else { 313 dnsesArr = new String[0]; 314 } 315 if (isAidl()) { 316 // Create a new DataProfile to set the TrafficDescriptor 317 DataProfile dp = new DataProfile.Builder() 318 .setType(dataProfileInfo.getType()) 319 .setPreferred(dataProfileInfo.isPreferred()) 320 .setTrafficDescriptor(trafficDescriptor) 321 .setApnSetting(dataProfileInfo.getApnSetting()) 322 .build(); 323 mDataProxy.setupDataCall(serial, accessNetwork, RILUtils.convertToHalDataProfile(dp), 324 roamingAllowed, reason, RILUtils.convertToHalLinkProperties(linkProperties), 325 dnsesArr, pduSessionId, RILUtils.convertToHalSliceInfoAidl(sliceInfo), 326 matchAllRuleAllowed); 327 } else if (mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_6)) { 328 ((android.hardware.radio.V1_6.IRadio) mRadioProxy).setupDataCall_1_6(serial, 329 accessNetwork, RILUtils.convertToHalDataProfile15(dataProfileInfo), 330 roamingAllowed, reason, RILUtils.convertToHalLinkProperties15(linkProperties), 331 dnses, pduSessionId, RILUtils.convertToHalSliceInfo(sliceInfo), 332 RILUtils.convertToHalTrafficDescriptor(trafficDescriptor), 333 matchAllRuleAllowed); 334 } else if (mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_5)) { 335 ((android.hardware.radio.V1_5.IRadio) mRadioProxy).setupDataCall_1_5(serial, 336 accessNetwork, RILUtils.convertToHalDataProfile15(dataProfileInfo), 337 roamingAllowed, reason, RILUtils.convertToHalLinkProperties15(linkProperties), 338 dnses); 339 } else { 340 mRadioProxy.setupDataCall_1_4(serial, accessNetwork, 341 RILUtils.convertToHalDataProfile14(dataProfileInfo), 342 roamingAllowed, reason, addresses, dnses); 343 } 344 } 345 346 /** 347 * Call IRadioData#startHandover 348 * @param serial Serial number of request 349 * @param callId Identifier of the data call 350 * @throws RemoteException 351 */ startHandover(int serial, int callId)352 public void startHandover(int serial, int callId) throws RemoteException { 353 if (isEmpty() || mHalVersion.less(RIL.RADIO_HAL_VERSION_1_6)) return; 354 if (isAidl()) { 355 mDataProxy.startHandover(serial, callId); 356 } else { 357 ((android.hardware.radio.V1_6.IRadio) mRadioProxy).startHandover(serial, callId); 358 } 359 } 360 361 /** 362 * Call IRadioData#startKeepalive 363 * @param serial Serial number of request 364 * @param contextId Context ID for the data call 365 * @param packetData Keepalive packet data 366 * @param intervalMillis Max keepalive interval in ms 367 * @param result Result to return in case of invalid arguments 368 * @throws RemoteException 369 */ startKeepalive(int serial, int contextId, KeepalivePacketData packetData, int intervalMillis, Message result)370 public void startKeepalive(int serial, int contextId, KeepalivePacketData packetData, 371 int intervalMillis, Message result) throws RemoteException { 372 if (isEmpty()) return; 373 if (isAidl()) { 374 android.hardware.radio.data.KeepaliveRequest req = 375 new android.hardware.radio.data.KeepaliveRequest(); 376 req.cid = contextId; 377 378 if (packetData.getDstAddress() instanceof Inet4Address) { 379 req.type = android.hardware.radio.data.KeepaliveRequest.TYPE_NATT_IPV4; 380 } else if (packetData.getDstAddress() instanceof Inet6Address) { 381 req.type = android.hardware.radio.data.KeepaliveRequest.TYPE_NATT_IPV6; 382 } else { 383 AsyncResult.forMessage(result, null, 384 CommandException.fromRilErrno(RILConstants.INVALID_ARGUMENTS)); 385 result.sendToTarget(); 386 return; 387 } 388 389 final InetAddress srcAddress = packetData.getSrcAddress(); 390 final InetAddress dstAddress = packetData.getDstAddress(); 391 byte[] sourceAddress = new byte[srcAddress.getAddress().length]; 392 for (int i = 0; i < sourceAddress.length; i++) { 393 sourceAddress[i] = srcAddress.getAddress()[i]; 394 } 395 req.sourceAddress = sourceAddress; 396 req.sourcePort = packetData.getSrcPort(); 397 byte[] destinationAddress = new byte[dstAddress.getAddress().length]; 398 for (int i = 0; i < destinationAddress.length; i++) { 399 destinationAddress[i] = dstAddress.getAddress()[i]; 400 } 401 req.destinationAddress = destinationAddress; 402 req.destinationPort = packetData.getDstPort(); 403 req.maxKeepaliveIntervalMillis = intervalMillis; 404 405 mDataProxy.startKeepalive(serial, req); 406 } else { 407 android.hardware.radio.V1_1.KeepaliveRequest req = 408 new android.hardware.radio.V1_1.KeepaliveRequest(); 409 410 req.cid = contextId; 411 412 if (packetData.getDstAddress() instanceof Inet4Address) { 413 req.type = android.hardware.radio.V1_1.KeepaliveType.NATT_IPV4; 414 } else if (packetData.getDstAddress() instanceof Inet6Address) { 415 req.type = android.hardware.radio.V1_1.KeepaliveType.NATT_IPV6; 416 } else { 417 AsyncResult.forMessage(result, null, 418 CommandException.fromRilErrno(RILConstants.INVALID_ARGUMENTS)); 419 result.sendToTarget(); 420 return; 421 } 422 423 final InetAddress srcAddress = packetData.getSrcAddress(); 424 final InetAddress dstAddress = packetData.getDstAddress(); 425 RILUtils.appendPrimitiveArrayToArrayList( 426 srcAddress.getAddress(), req.sourceAddress); 427 req.sourcePort = packetData.getSrcPort(); 428 RILUtils.appendPrimitiveArrayToArrayList( 429 dstAddress.getAddress(), req.destinationAddress); 430 req.destinationPort = packetData.getDstPort(); 431 req.maxKeepaliveIntervalMillis = intervalMillis; 432 433 mRadioProxy.startKeepalive(serial, req); 434 } 435 } 436 437 /** 438 * Call IRadioData#stopKeepalive 439 * @param serial Serial number of request 440 * @param sessionHandle The handle that was provided by startKeepaliveResponse 441 * @throws RemoteException 442 */ stopKeepalive(int serial, int sessionHandle)443 public void stopKeepalive(int serial, int sessionHandle) throws RemoteException { 444 if (isEmpty()) return; 445 if (isAidl()) { 446 mDataProxy.stopKeepalive(serial, sessionHandle); 447 } else { 448 mRadioProxy.stopKeepalive(serial, sessionHandle); 449 } 450 } 451 } 452