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.network.CellConnectionStatus; 21 import android.hardware.radio.network.CellIdentityLte; 22 import android.hardware.radio.network.CellIdentityWcdma; 23 import android.hardware.radio.network.CellInfo; 24 import android.hardware.radio.network.CellInfoLte; 25 import android.hardware.radio.network.CellInfoRatSpecificInfo; 26 import android.hardware.radio.network.CellInfoWcdma; 27 import android.hardware.radio.network.LteSignalStrength; 28 import android.hardware.radio.network.OperatorInfo; 29 import android.hardware.radio.network.WcdmaSignalStrength; 30 import android.util.Log; 31 import android.util.Xml; 32 33 import org.xmlpull.v1.XmlPullParser; 34 import org.xmlpull.v1.XmlPullParserException; 35 36 import java.io.IOException; 37 import java.io.InputStream; 38 import java.util.ArrayList; 39 40 public class MockNetworkConfig { 41 private static final String TAG = "MockNetworkConfig"; 42 43 private static final String MOCK_NETWORK_TAG = "MockNetwork"; 44 private static final String MOCK_NETWORK_PROFILE_TAG = "MockNetworkProfile"; 45 private static final String MOCK_CELL_PROPERTY_TAG = "MockCellProperty"; 46 private static final String MOCK_CELL_IDENTITY_TAG = "MockCellIdentity"; 47 private static final String MOCK_CELL_SIGNAL_STRENGTH_TAG = "MockCellSignalStrength"; 48 49 private final Context mContext; 50 private MockCellProperty mMockCellProperty; 51 private ArrayList<MockNetworkProfile> mMockNetworkProfiles = 52 new ArrayList<MockNetworkProfile>(); 53 54 private int mCarrierId; 55 56 private static class MockCellProperty { 57 private String[] mEHPlmnList; 58 private String[] mAllowRoamingList; 59 MockCellProperty(XmlPullParser parser)60 MockCellProperty(XmlPullParser parser) { 61 try { 62 loadCellProperty(parser); 63 } catch (Exception e) { 64 Log.e(TAG, "Failed to loadCellProperty: " + e); 65 } 66 } 67 loadCellProperty(XmlPullParser parser)68 private void loadCellProperty(XmlPullParser parser) 69 throws IOException, XmlPullParserException { 70 int outerDepth = parser.getDepth(); 71 int type; 72 73 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 74 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 75 String parameter = parser.getName(); 76 if (parameter == null || type == XmlPullParser.END_TAG) { 77 continue; 78 } 79 80 switch (parameter) { 81 case "EHPLMNLIST": 82 mEHPlmnList = parser.nextText().replace(" ", "").split(","); 83 break; 84 case "AllowRoamingList": 85 mAllowRoamingList = parser.nextText().replace(" ", "").split(","); 86 break; 87 default: 88 Log.d(TAG, "Cell property: " + parameter + " Not Support"); 89 break; 90 } 91 } 92 } 93 getEHPlmnList()94 public String[] getEHPlmnList() { 95 return mEHPlmnList; 96 } 97 getAllowRoamingList()98 public String[] getAllowRoamingList() { 99 return mAllowRoamingList; 100 } 101 } 102 103 private static class MockNetworkProfile { 104 private int mId; 105 private String mRat; 106 private CellInfo mCell; 107 MockNetworkProfile(XmlPullParser parser)108 MockNetworkProfile(XmlPullParser parser) { 109 mId = Integer.parseInt(parser.getAttributeValue(null, "id").trim()); 110 Log.d(TAG, "Load: " + mId); 111 mRat = parser.getAttributeValue(null, "rat").trim(); 112 String connectionStatus = parser.getAttributeValue(null, "connection"); 113 114 mCell = new CellInfo(); 115 mCell.registered = false; 116 117 if (connectionStatus != null && connectionStatus.trim().equals("primary")) { 118 mCell.connectionStatus = CellConnectionStatus.PRIMARY_SERVING; 119 } else { 120 mCell.connectionStatus = CellConnectionStatus.SECONDARY_SERVING; 121 } 122 mCell.ratSpecificInfo = new CellInfoRatSpecificInfo(); 123 124 loadNetworkCellParameters(parser); 125 } 126 loadLteCellIdentity(XmlPullParser parser, CellInfoLte lte)127 private void loadLteCellIdentity(XmlPullParser parser, CellInfoLte lte) 128 throws IOException, XmlPullParserException { 129 int outerDepth = parser.getDepth(); 130 int type; 131 132 lte.cellIdentityLte = new CellIdentityLte(); 133 lte.cellIdentityLte.operatorNames = new OperatorInfo(); 134 lte.cellIdentityLte.additionalPlmns = new String[0]; 135 lte.cellIdentityLte.bands = new int[0]; 136 137 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 138 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 139 String parameter = parser.getName(); 140 if (parameter == null || type == XmlPullParser.END_TAG) { 141 continue; 142 } 143 144 switch (parameter) { 145 case "MCC": 146 lte.cellIdentityLte.mcc = parser.nextText().trim(); 147 break; 148 case "MNC": 149 lte.cellIdentityLte.mnc = parser.nextText().trim(); 150 break; 151 case "CI": 152 lte.cellIdentityLte.ci = Integer.parseInt(parser.nextText().trim()); 153 break; 154 case "PCI": 155 lte.cellIdentityLte.pci = Integer.parseInt(parser.nextText().trim()); 156 break; 157 case "TAC": 158 lte.cellIdentityLte.tac = Integer.parseInt(parser.nextText().trim()); 159 break; 160 case "EARFCN": 161 lte.cellIdentityLte.earfcn = Integer.parseInt(parser.nextText().trim()); 162 break; 163 case "BANDWIDTH": 164 lte.cellIdentityLte.bandwidth = Integer.parseInt(parser.nextText().trim()); 165 break; 166 case "OperatorInfo": 167 // lte.cellIdentityLte.operatorNames = new OperatorInfo(); 168 break; 169 case "AlphaLong": 170 lte.cellIdentityLte.operatorNames.alphaLong = parser.nextText().trim(); 171 break; 172 case "AlphaShort": 173 lte.cellIdentityLte.operatorNames.alphaShort = parser.nextText().trim(); 174 break; 175 case "OperatorNumeric": 176 lte.cellIdentityLte.operatorNames.operatorNumeric = 177 parser.nextText().trim(); 178 break; 179 default: 180 Log.d(TAG, "LTE Cell Identity: " + parameter + " Not Support"); 181 break; 182 } 183 } 184 } 185 loadLteSignalStrength(XmlPullParser parser, CellInfoLte lte)186 private void loadLteSignalStrength(XmlPullParser parser, CellInfoLte lte) 187 throws IOException, XmlPullParserException { 188 int outerDepth = parser.getDepth(); 189 int type; 190 191 lte.signalStrengthLte = new LteSignalStrength(); 192 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 193 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 194 String parameter = parser.getName(); 195 if (parameter == null || type == XmlPullParser.END_TAG) { 196 continue; 197 } 198 199 switch (parameter) { 200 case "SignalStrength": 201 lte.signalStrengthLte.signalStrength = 202 Integer.parseInt(parser.nextText().trim()); 203 break; 204 case "RSRP": 205 lte.signalStrengthLte.rsrp = Integer.parseInt(parser.nextText().trim()); 206 break; 207 case "RSRQ": 208 lte.signalStrengthLte.rsrq = Integer.parseInt(parser.nextText().trim()); 209 break; 210 case "RSSNR": 211 lte.signalStrengthLte.rssnr = Integer.parseInt(parser.nextText().trim()); 212 break; 213 case "CQI": 214 lte.signalStrengthLte.cqi = Integer.parseInt(parser.nextText().trim()); 215 break; 216 case "TimingAdvance": 217 lte.signalStrengthLte.timingAdvance = 218 Integer.parseInt(parser.nextText().trim()); 219 break; 220 case "CqiTableIndex": 221 lte.signalStrengthLte.cqiTableIndex = 222 Integer.parseInt(parser.nextText().trim()); 223 break; 224 default: 225 Log.d(TAG, "LTE Cell Signal: " + parameter + " Not Support"); 226 break; 227 } 228 } 229 } 230 loadLteCellInfo(XmlPullParser parser, CellInfoLte lte)231 private void loadLteCellInfo(XmlPullParser parser, CellInfoLte lte) 232 throws IOException, XmlPullParserException { 233 int outerDepth = parser.getDepth(); 234 int type; 235 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 236 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 237 String name = parser.getName(); 238 if (name == null) { 239 continue; 240 } 241 242 if (MOCK_CELL_IDENTITY_TAG.equals(name)) { 243 loadLteCellIdentity(parser, lte); 244 Log.d(TAG, "LTE Cell ID: " + lte.cellIdentityLte.toString()); 245 } else if (MOCK_CELL_SIGNAL_STRENGTH_TAG.equals(name)) { 246 loadLteSignalStrength(parser, lte); 247 Log.d(TAG, "LTE Cell Signal: " + lte.signalStrengthLte.toString()); 248 } 249 } 250 } 251 loadWcdmaCellIdentity(XmlPullParser parser, CellInfoWcdma wcdma)252 private void loadWcdmaCellIdentity(XmlPullParser parser, CellInfoWcdma wcdma) 253 throws IOException, XmlPullParserException { 254 int outerDepth = parser.getDepth(); 255 int type; 256 257 wcdma.cellIdentityWcdma = new CellIdentityWcdma(); 258 wcdma.cellIdentityWcdma.operatorNames = new OperatorInfo(); 259 wcdma.cellIdentityWcdma.additionalPlmns = new String[0]; 260 261 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 262 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 263 String parameter = parser.getName(); 264 if (parameter == null || type == XmlPullParser.END_TAG) { 265 continue; 266 } 267 268 switch (parameter) { 269 case "MCC": 270 wcdma.cellIdentityWcdma.mcc = parser.nextText().trim(); 271 break; 272 case "MNC": 273 wcdma.cellIdentityWcdma.mnc = parser.nextText().trim(); 274 break; 275 case "LAC": 276 wcdma.cellIdentityWcdma.lac = Integer.parseInt(parser.nextText().trim()); 277 break; 278 case "CID": 279 wcdma.cellIdentityWcdma.cid = Integer.parseInt(parser.nextText().trim()); 280 break; 281 case "PSC": 282 wcdma.cellIdentityWcdma.psc = Integer.parseInt(parser.nextText().trim()); 283 break; 284 case "UARFCN": 285 wcdma.cellIdentityWcdma.uarfcn = Integer.parseInt(parser.nextText().trim()); 286 break; 287 case "OperatorInfo": 288 // lte.cellIdentityLte.operatorNames = new OperatorInfo(); 289 break; 290 case "AlphaLong": 291 wcdma.cellIdentityWcdma.operatorNames.alphaLong = parser.nextText().trim(); 292 break; 293 case "AlphaShort": 294 wcdma.cellIdentityWcdma.operatorNames.alphaShort = parser.nextText().trim(); 295 break; 296 case "OperatorNumeric": 297 wcdma.cellIdentityWcdma.operatorNames.operatorNumeric = 298 parser.nextText().trim(); 299 break; 300 default: 301 Log.d(TAG, "WCDMA Cell Identity: " + parameter + " Not Support"); 302 break; 303 } 304 } 305 } 306 loadWcdmaSignalStrength(XmlPullParser parser, CellInfoWcdma wcdma)307 private void loadWcdmaSignalStrength(XmlPullParser parser, CellInfoWcdma wcdma) 308 throws IOException, XmlPullParserException { 309 int outerDepth = parser.getDepth(); 310 int type; 311 312 wcdma.signalStrengthWcdma = new WcdmaSignalStrength(); 313 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 314 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 315 String parameter = parser.getName(); 316 if (parameter == null || type == XmlPullParser.END_TAG) { 317 continue; 318 } 319 320 switch (parameter) { 321 case "SignalStrength": 322 wcdma.signalStrengthWcdma.signalStrength = 323 Integer.parseInt(parser.nextText().trim()); 324 break; 325 case "BitErrorRate": 326 wcdma.signalStrengthWcdma.bitErrorRate = 327 Integer.parseInt(parser.nextText().trim()); 328 break; 329 case "RSCP": 330 wcdma.signalStrengthWcdma.rscp = Integer.parseInt(parser.nextText().trim()); 331 break; 332 case "ECNO": 333 wcdma.signalStrengthWcdma.ecno = Integer.parseInt(parser.nextText().trim()); 334 break; 335 default: 336 Log.d(TAG, "WCDMA Cell Signal: " + parameter + " Not Support"); 337 break; 338 } 339 } 340 } 341 loadWcdmaCellInfo(XmlPullParser parser, CellInfoWcdma wcdma)342 private void loadWcdmaCellInfo(XmlPullParser parser, CellInfoWcdma wcdma) 343 throws IOException, XmlPullParserException { 344 int outerDepth = parser.getDepth(); 345 int type; 346 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 347 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 348 String name = parser.getName(); 349 if (name == null) { 350 continue; 351 } 352 353 if (MOCK_CELL_IDENTITY_TAG.equals(name)) { 354 loadWcdmaCellIdentity(parser, wcdma); 355 Log.d(TAG, "WCDMA Cell ID: " + wcdma.cellIdentityWcdma.toString()); 356 } else if (MOCK_CELL_SIGNAL_STRENGTH_TAG.equals(name)) { 357 loadWcdmaSignalStrength(parser, wcdma); 358 Log.d(TAG, "WCDMA Cell Signal: " + wcdma.signalStrengthWcdma.toString()); 359 } 360 } 361 } 362 loadNetworkCellParameters(XmlPullParser parser)363 private void loadNetworkCellParameters(XmlPullParser parser) { 364 try { 365 switch (mRat) { 366 case "LTE": 367 CellInfoLte lte = new CellInfoLte(); 368 loadLteCellInfo(parser, lte); 369 mCell.ratSpecificInfo.setLte(lte); 370 break; 371 case "WCDMA": 372 CellInfoWcdma wcdma = new CellInfoWcdma(); 373 loadWcdmaCellInfo(parser, wcdma); 374 mCell.ratSpecificInfo.setWcdma(wcdma); 375 break; 376 default: 377 Log.e(TAG, "RAT " + mRat + " Cell Parameter Not Support"); 378 break; 379 } 380 } catch (Exception e) { 381 Log.e(TAG, "Failed to loadNetworkCellParameters: " + e); 382 } 383 } 384 getCell()385 public CellInfo getCell() { 386 return mCell; 387 } 388 } 389 MockNetworkConfig(Context context)390 public MockNetworkConfig(Context context) { 391 mContext = context; 392 } 393 readConfigFromXml(XmlPullParser parser)394 private void readConfigFromXml(XmlPullParser parser) 395 throws IOException, XmlPullParserException { 396 int type; 397 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { 398 String name = parser.getName(); 399 switch (type) { 400 case XmlPullParser.START_TAG: 401 if (MOCK_NETWORK_TAG.equals(name)) { 402 mCarrierId = 403 Integer.parseInt( 404 parser.getAttributeValue(null, "carrierid").trim()); 405 } else if (MOCK_NETWORK_PROFILE_TAG.equals(name)) { 406 mMockNetworkProfiles.add(new MockNetworkProfile(parser)); 407 } else if (MOCK_CELL_PROPERTY_TAG.equals(name)) { 408 mMockCellProperty = new MockCellProperty(parser); 409 } else { 410 Log.e(TAG, "Type " + name + " Not Support."); 411 } 412 break; 413 case XmlPullParser.END_TAG: 414 break; 415 } 416 } 417 } 418 getConfigFromAssets(String fileName)419 public void getConfigFromAssets(String fileName) { 420 try { 421 XmlPullParser parser = Xml.newPullParser(); 422 InputStream input = mContext.getAssets().open(fileName); 423 parser.setInput(input, "utf-8"); 424 readConfigFromXml(parser); 425 input.close(); 426 } catch (Exception e) { 427 Log.e(TAG, "Failed to read config: " + e); 428 } 429 } 430 getCarrierId()431 public int getCarrierId() { 432 return mCarrierId; 433 } 434 getEHPlmnList()435 public String[] getEHPlmnList() { 436 return mMockCellProperty.getEHPlmnList(); 437 } 438 getAllowRoamingList()439 public String[] getAllowRoamingList() { 440 return mMockCellProperty.getAllowRoamingList(); 441 } 442 getCellNum()443 public int getCellNum() { 444 return mMockNetworkProfiles.size(); 445 } 446 getCellInfo(int index)447 public CellInfo getCellInfo(int index) { 448 if (index > getCellNum()) { 449 return null; 450 } 451 return mMockNetworkProfiles.get(index).getCell(); 452 } 453 } 454