1 /* 2 * Copyright (C) 2022 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 android.telephony.mockmodem; 18 19 import android.content.Context; 20 import android.hardware.radio.RadioError; 21 import android.hardware.radio.data.DataCallFailCause; 22 import android.hardware.radio.data.DataProfileInfo; 23 import android.hardware.radio.data.LinkAddress; 24 import android.hardware.radio.data.PdpProtocolType; 25 import android.hardware.radio.data.Qos; 26 import android.hardware.radio.data.QosSession; 27 import android.hardware.radio.data.SetupDataCallResult; 28 import android.hardware.radio.data.SliceInfo; 29 import android.hardware.radio.data.TrafficDescriptor; 30 import android.util.Log; 31 32 import java.util.ArrayList; 33 import java.util.Arrays; 34 import java.util.Iterator; 35 import java.util.List; 36 37 public class MockDataService { 38 private static final String TAG = "MockDataService"; 39 private String mTag; 40 private Context mContext; 41 42 // Data Profile 43 List<DataProfileInfo> mDataProfileInfo = new ArrayList<>(); 44 DataProfileInfo mInitialAttachProfile; 45 int mInitialAttachProfileId; 46 47 // setup data call 48 public static final int APN_TYPE_IMS = 0; 49 public static final int APN_TYPE_DEFAULT = 1; 50 public static final int PHONE0 = 0; 51 public static final int PHONE1 = 1; 52 53 SetupDataCallResult mSetupDataCallResultIms = new SetupDataCallResult(); 54 SetupDataCallResult mSetupDataCallResultDefault = new SetupDataCallResult(); 55 56 // data call list 57 static List<SetupDataCallResult> sDataCallLists = new ArrayList<>(); 58 59 // Supported capability in physical layer 60 static List<String> sSupportedCapabilities = new ArrayList<>(); 61 62 /* Mock Data Config XML TAG definition */ 63 private static final String MOCK_DATA_CONFIG_TAG = "MockDataConfig"; 64 private static final String MOCK_CUTTLEFISH_CONFIG_TAG = "CuttlefishConfig"; 65 private static final String MOCK_CUTTLEFISH_TYPE = "Cuttlefish"; 66 private static final String MOCK_INTERFACE_NAME_TAG = "InterfaceName"; 67 private static final String MOCK_IP_ADDRESS_TAG = "IpAddress"; 68 private static final String MOCK_DNS_ADDRESS_TAG = "DnsAddress"; 69 private static final String MOCK_GATEWAY_ADDRESS_TAG = "GatewayAddress"; 70 private static final String MOCK_MTU_V4_TAG = "MtuV4"; 71 72 // Setup data call result parameteres 73 int mDataCallFailCause; 74 int mSuggestedRetryTime; 75 int mImsCid; 76 int mImsType; 77 String mImsIfname; 78 String mImsAddress; 79 String[] mImsGateways; 80 String[] mImsPcscf; 81 int mImsMtuV4; 82 int mImsMtuV6; 83 int mInternetCid; 84 int mInternetType; 85 String mInternetIfname; 86 String mInternetAddress; 87 String[] mInternetDnses; 88 String[] mInternetGateways; 89 int mInternetMtuV4; 90 int mInternetMtuV6; 91 int mAddressProperties; 92 long mLaDeprecationTime; 93 long mLaExpirationTime; 94 Qos mDefaultQos; 95 QosSession[] mQosSessions; 96 byte mHandoverFailureMode; 97 int mPduSessionId; 98 SliceInfo mSliceInfo; 99 TrafficDescriptor[] mTrafficDescriptors; 100 private final Object mDataCallListLock = new Object(); 101 LinkAddress[] mImsLinkAddress; 102 LinkAddress[] mDefaultLinkAddress; 103 int mPhoneId; 104 MockDataService(Context context, int instanceId)105 public MockDataService(Context context, int instanceId) { 106 mTag = TAG + "-" + instanceId; 107 mContext = context; 108 mPhoneId = instanceId; 109 initializeParameter(); 110 } 111 112 /* Default value definition */ initializeParameter()113 private void initializeParameter() { 114 this.mDataCallFailCause = DataCallFailCause.NONE; 115 this.mSuggestedRetryTime = -1; 116 117 this.mImsType = PdpProtocolType.IP; 118 this.mImsIfname = "mock_network0"; 119 this.mImsAddress = "192.168.66.2"; 120 this.mImsGateways = new String[] {"0.0.0.0"}; 121 this.mImsPcscf = new String[] {"192.168.66.100", "192.168.66.101"}; 122 this.mImsMtuV4 = 1280; 123 this.mImsMtuV6 = 0; 124 this.mImsLinkAddress = new LinkAddress[1]; 125 126 this.mInternetType = PdpProtocolType.IP; 127 this.mInternetIfname = "mock_network1"; 128 this.mInternetAddress = "192.168.66.1"; 129 this.mInternetDnses = new String[] {"8.8.8.8"}; 130 this.mInternetGateways = new String[] {"0.0.0.0"}; 131 this.mInternetMtuV4 = 1280; 132 this.mInternetMtuV6 = 0; 133 this.mDefaultLinkAddress = new LinkAddress[1]; 134 135 this.mAddressProperties = LinkAddress.ADDRESS_PROPERTY_NONE; 136 this.mLaDeprecationTime = 0x7FFFFFFF; 137 this.mLaExpirationTime = 0x7FFFFFFF; 138 139 this.mDefaultQos = new Qos(); 140 this.mQosSessions = new QosSession[0]; 141 this.mHandoverFailureMode = 142 SetupDataCallResult.HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER; 143 this.mPduSessionId = 0; 144 this.mSliceInfo = null; 145 this.mTrafficDescriptors = new TrafficDescriptor[0]; 146 } 147 setDataProfileInfo(DataProfileInfo[] dataProfilesInfo)148 public int setDataProfileInfo(DataProfileInfo[] dataProfilesInfo) { 149 int result = RadioError.NONE; 150 if (dataProfilesInfo != null) { 151 mDataProfileInfo.clear(); 152 for (DataProfileInfo dp : dataProfilesInfo) { 153 mDataProfileInfo.add(dp); 154 Log.d(mTag, "setDataProfileInfo: profileId=" + dp.profileId + ", " + dp.apn); 155 } 156 return result; 157 } 158 return RadioError.INVALID_ARGUMENTS; 159 } 160 setInitialAttachProfile(DataProfileInfo dataProfileInfo)161 public int setInitialAttachProfile(DataProfileInfo dataProfileInfo) { 162 int result = RadioError.NONE; 163 if (dataProfileInfo != null) { 164 Log.d(mTag, "setInitialAttachProfile: profileId=" + dataProfileInfo.profileId); 165 mInitialAttachProfile = dataProfileInfo; 166 mInitialAttachProfileId = dataProfileInfo.profileId; 167 return result; 168 } 169 return RadioError.INVALID_ARGUMENTS; 170 } 171 setupDataCall(int apnType)172 SetupDataCallResult setupDataCall(int apnType) { 173 checkExistDataCall(apnType); 174 175 SetupDataCallResult dc = new SetupDataCallResult(); 176 dc.cause = this.mDataCallFailCause; 177 dc.suggestedRetryTime = this.mSuggestedRetryTime; 178 179 dc.active = SetupDataCallResult.DATA_CONNECTION_STATUS_ACTIVE; 180 LinkAddress[] arrayLinkAddress = new LinkAddress[1]; 181 LinkAddress linkAddress = new LinkAddress(); 182 183 switch (apnType) { 184 case APN_TYPE_IMS: 185 dc.cid = this.mImsCid; 186 dc.type = this.mImsType; 187 dc.ifname = this.mImsIfname; 188 linkAddress.address = this.mImsAddress; 189 linkAddress.addressProperties = this.mAddressProperties; 190 linkAddress.deprecationTime = this.mLaDeprecationTime; 191 linkAddress.expirationTime = this.mLaExpirationTime; 192 arrayLinkAddress[0] = linkAddress; 193 dc.addresses = this.mImsLinkAddress; 194 dc.gateways = this.mImsGateways; 195 dc.pcscf = this.mImsPcscf; 196 dc.mtuV4 = this.mImsMtuV4; 197 dc.mtuV6 = this.mImsMtuV6; 198 break; 199 case APN_TYPE_DEFAULT: 200 dc.cid = this.mInternetCid; 201 dc.type = this.mInternetType; 202 dc.ifname = this.mInternetIfname; 203 linkAddress.address = this.mInternetAddress; 204 linkAddress.addressProperties = this.mAddressProperties; 205 linkAddress.deprecationTime = this.mLaDeprecationTime; 206 linkAddress.expirationTime = this.mLaExpirationTime; 207 arrayLinkAddress[0] = linkAddress; 208 dc.addresses = this.mDefaultLinkAddress; 209 dc.dnses = this.mInternetDnses; 210 dc.gateways = this.mInternetGateways; 211 dc.mtuV4 = this.mInternetMtuV4; 212 dc.mtuV6 = this.mInternetMtuV6; 213 break; 214 default: 215 Log.d(mTag, "Unexpected APN type: " + apnType); 216 return new SetupDataCallResult(); 217 } 218 dc.defaultQos = this.mDefaultQos; 219 dc.qosSessions = this.mQosSessions; 220 dc.handoverFailureMode = this.mHandoverFailureMode; 221 dc.pduSessionId = this.mPduSessionId; 222 dc.sliceInfo = this.mSliceInfo; 223 dc.trafficDescriptors = this.mTrafficDescriptors; 224 synchronized (mDataCallListLock) { 225 sDataCallLists.add(dc); 226 } 227 return dc; 228 } 229 230 /** 231 * Get current data call list 232 * 233 * @return The SetupDataCallResult array list. 234 */ getDataCallList()235 List<SetupDataCallResult> getDataCallList() { 236 List<SetupDataCallResult> dataCallLists; 237 synchronized (mDataCallListLock) { 238 dataCallLists = sDataCallLists; 239 } 240 return dataCallLists; 241 } 242 deactivateDataCall(int cid, int reason)243 void deactivateDataCall(int cid, int reason) { 244 synchronized (mDataCallListLock) { 245 Iterator<SetupDataCallResult> it = sDataCallLists.iterator(); 246 while (it.hasNext()) { 247 SetupDataCallResult dc = it.next(); 248 if (dc.cid == cid) { 249 it.remove(); 250 } 251 } 252 } 253 } 254 checkExistDataCall(int apnType)255 void checkExistDataCall(int apnType) { 256 synchronized (mDataCallListLock) { 257 int cid = (apnType == APN_TYPE_IMS) ? mImsCid : mInternetCid; 258 Iterator<SetupDataCallResult> it = sDataCallLists.iterator(); 259 while (it.hasNext()) { 260 SetupDataCallResult dc = it.next(); 261 if (dc.cid == cid) { 262 it.remove(); 263 } 264 } 265 } 266 } 267 convertToMtuV4(String mtuv4)268 private int convertToMtuV4(String mtuv4) { 269 int value = 0; 270 try { 271 value = Integer.parseInt(mtuv4); 272 } catch (NumberFormatException ex) { 273 Log.e(mTag, "Exception error: " + ex); 274 } 275 return value; 276 } 277 getInterfaceName(String string)278 private String getInterfaceName(String string) { 279 String interfaceName = ""; 280 try { 281 interfaceName = string.split("InterfaceName: ")[1].split(" LinkAddresses")[0]; 282 Log.d(mTag, "getInterfaceName: " + interfaceName); 283 } catch (Exception e) { 284 Log.e(mTag, "Exception error: " + e); 285 } 286 return interfaceName; 287 } 288 getIpAddress(String string)289 private LinkAddress[] getIpAddress(String string) { 290 String[] ipaddress = new String[] {}; 291 LinkAddress[] arrayLinkAddress = new LinkAddress[0]; 292 try { 293 ipaddress = 294 string.split("LinkAddresses: \\[ ")[1].split(" ] DnsAddresses")[0].split(","); 295 arrayLinkAddress = new LinkAddress[ipaddress.length]; 296 for (int idx = 0; idx < ipaddress.length; idx++) { 297 if (ipaddress[idx].equals("LinkAddresses: [ ]")) { 298 throw new Exception("Not valid ip address"); 299 } 300 LinkAddress linkAddress = new LinkAddress(); 301 linkAddress.address = ipaddress[idx]; 302 linkAddress.addressProperties = this.mAddressProperties; 303 linkAddress.deprecationTime = this.mLaDeprecationTime; 304 linkAddress.expirationTime = this.mLaExpirationTime; 305 arrayLinkAddress[idx] = linkAddress; 306 Log.d(mTag, "getIpAddress:" + linkAddress.address); 307 } 308 } catch (Exception e) { 309 Log.e(mTag, "Exception error: " + e); 310 } 311 return arrayLinkAddress; 312 } 313 getDnses(String string)314 private String[] getDnses(String string) { 315 String[] dnses = new String[] {}; 316 try { 317 dnses = 318 string.split("DnsAddresses: \\[ ")[1] 319 .split(" ] Domains:")[0] 320 .replace("/", "") 321 .split(","); 322 Log.d(mTag, "getDnses: " + Arrays.toString(dnses)); 323 } catch (Exception e) { 324 Log.e(mTag, "Exception error: " + e); 325 } 326 return dnses; 327 } 328 getGateways(String string)329 private String[] getGateways(String string) { 330 ArrayList<String> gateways = new ArrayList<String>(); 331 try { 332 gateways.add( 333 string.split("Routes: \\[ ")[1] 334 .split("-> ")[1] 335 .split(" ")[0]); 336 Log.d(mTag, "getGateways: " + gateways); 337 } catch (Exception e) { 338 Log.e(mTag, "Exception error: " + e); 339 } 340 return gateways.toArray(new String[gateways.size()]); 341 } 342 getMtu(String string)343 private int getMtu(String string) { 344 String mtu = ""; 345 try { 346 mtu = string.split(" MTU: ")[1].split(" TcpBufferSizes:")[0]; 347 Log.d(mTag, "getMtu: " + mtu); 348 } catch (Exception e) { 349 Log.e(mTag, "Exception error: " + e); 350 } 351 return Integer.valueOf(mtu); 352 } 353 getPcscf(String string)354 private String[] getPcscf(String string) { 355 String[] pcscf = new String[] {}; 356 try { 357 pcscf = 358 string.split(" PcscfAddresses: \\[ ")[1] 359 .split(" ] Domains:")[0] 360 .replace("/", "") 361 .split(","); 362 Log.d(mTag, "getPcscf: " + Arrays.toString(pcscf)); 363 } catch (Exception e) { 364 Log.e(mTag, "Exception error: " + e); 365 } 366 return pcscf; 367 } 368 getCapabilities(String string)369 private String getCapabilities(String string) { 370 String capabilities = ""; 371 try { 372 capabilities = string.trim().split("Capabilities:")[1].split("LinkUpBandwidth")[0]; 373 Log.d(mTag, "getCapabilities: " + capabilities); 374 } catch (Exception e) { 375 Log.e(mTag, "getCapabilities(): Exception error: " + e); 376 } 377 return capabilities; 378 } 379 getCid(String string)380 private int getCid(String string) { 381 int cid = 0; 382 try { 383 String strCid = string.split("WWAN cid=")[1].split("WLAN cid")[0].trim(); 384 cid = Integer.parseInt(strCid); 385 Log.d(mTag, "getCid: " + strCid); 386 } catch (Exception e) { 387 Log.e(mTag, "getCid(): Exception error: " + e); 388 } 389 return cid; 390 } 391 setBridgeTheDataConnection(String string)392 public synchronized void setBridgeTheDataConnection(String string) { 393 try { 394 String[] lines = new String[] {}; 395 String line = 396 string.split("DataNetworkController-" + mPhoneId)[1] 397 .split("All telephony network requests:")[0]; 398 if (line.contains("curState=ConnectedState")) { 399 lines = line.split(("curState=ConnectedState")); 400 } 401 for (String str : lines) { 402 String capabilities = getCapabilities(str); 403 if (capabilities.contains("INTERNET")) { 404 Log.d(mTag, "[internet]:" + str); 405 sSupportedCapabilities.add("internet"); 406 this.mInternetCid = getCid(str); 407 this.mInternetIfname = getInterfaceName(str); 408 this.mDefaultLinkAddress = getIpAddress(str); 409 this.mInternetDnses = getDnses(str); 410 this.mInternetGateways = getGateways(str); 411 this.mInternetMtuV4 = getMtu(str); 412 this.mInternetMtuV6 = getMtu(str); 413 } else if (capabilities.contains("IMS")) { 414 Log.d(mTag, "[ims]:" + str); 415 sSupportedCapabilities.add("ims"); 416 this.mImsCid = getCid(str); 417 this.mImsIfname = getInterfaceName(str); 418 this.mImsLinkAddress = getIpAddress(str); 419 this.mImsGateways = getGateways(str); 420 this.mImsPcscf = getPcscf(str); 421 this.mImsMtuV4 = getMtu(str); 422 this.mImsMtuV6 = getMtu(str); 423 } 424 } 425 } catch (Exception e) { 426 Log.e(mTag, "Exception error: [No NetworkAgentInfo]" + e); 427 } 428 } 429 resetCapability()430 public synchronized void resetCapability() { 431 sSupportedCapabilities = new ArrayList<>(); 432 } 433 isSupportedCapability(String capability)434 public synchronized boolean isSupportedCapability(String capability) { 435 for (String cap : sSupportedCapabilities) { 436 Log.d(mTag, "Supported Capability:" + cap + ", Requested Capability:" + capability); 437 if (cap.contains(capability)) { 438 return true; 439 } 440 } 441 return false; 442 } 443 setDataCallFailCause(int failcause)444 public synchronized void setDataCallFailCause(int failcause) { 445 this.mDataCallFailCause = failcause; 446 } 447 setSuggestedRetryTime(int retrytime)448 public synchronized void setSuggestedRetryTime(int retrytime) { 449 this.mSuggestedRetryTime = retrytime; 450 } 451 setImsMtuV4(int mtusize)452 public synchronized void setImsMtuV4(int mtusize) { 453 this.mImsMtuV4 = mtusize; 454 } 455 setImsMtuV6(int mtusize)456 public synchronized void setImsMtuV6(int mtusize) { 457 this.mImsMtuV6 = mtusize; 458 } 459 setInternetMtuV4(int mtusize)460 public synchronized void setInternetMtuV4(int mtusize) { 461 this.mInternetMtuV4 = mtusize; 462 } 463 setInternetMtuV6(int mtusize)464 public synchronized void setInternetMtuV6(int mtusize) { 465 this.mInternetMtuV6 = mtusize; 466 } 467 } 468