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