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