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