1 /* 2 * Copyright (C) 2019 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 package com.android.ons; 17 18 import static org.junit.Assert.assertThrows; 19 import static org.mockito.Mockito.any; 20 import static org.mockito.Mockito.doReturn; 21 import static org.mockito.Mockito.never; 22 import static org.mockito.Mockito.times; 23 import static org.mockito.Mockito.verify; 24 import static org.mockito.Mockito.when; 25 26 import android.compat.testing.PlatformCompatChangeRule; 27 import android.content.BroadcastReceiver; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.content.pm.PackageManager; 31 import android.os.Build; 32 import android.os.Looper; 33 import android.os.RemoteException; 34 import android.os.UserManager; 35 import android.platform.test.flag.junit.SetFlagsRule; 36 import android.telephony.AvailableNetworkInfo; 37 import android.telephony.CarrierConfigManager; 38 import android.telephony.SubscriptionInfo; 39 import android.telephony.SubscriptionManager; 40 import android.telephony.TelephonyFrameworkInitializer; 41 import android.telephony.TelephonyManager; 42 import android.util.Log; 43 44 import androidx.test.runner.AndroidJUnit4; 45 46 import com.android.internal.telephony.IOns; 47 import com.android.internal.telephony.ISetOpportunisticDataCallback; 48 import com.android.internal.telephony.IUpdateAvailableNetworksCallback; 49 import com.android.internal.telephony.flags.Flags; 50 51 import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges; 52 53 import org.junit.After; 54 import org.junit.Before; 55 import org.junit.Rule; 56 import org.junit.Test; 57 import org.junit.rules.TestRule; 58 import org.junit.runner.RunWith; 59 import org.mockito.ArgumentCaptor; 60 import org.mockito.Mock; 61 62 import java.lang.reflect.Field; 63 import java.util.ArrayList; 64 import java.util.HashMap; 65 66 @RunWith(AndroidJUnit4.class) 67 public class OpportunisticNetworkServiceTest extends ONSBaseTest { 68 // SetFlagsRule will be used for Telephony feature flag 69 @Rule 70 public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); 71 @Rule 72 public TestRule compatChangeRule = new PlatformCompatChangeRule(); 73 74 private static final String TAG = "ONSTest"; 75 private String pkgForDebug; 76 private String pkgForFeature; 77 private int mResult; 78 private IOns iOpportunisticNetworkService; 79 private Looper mLooper; 80 private OpportunisticNetworkService mOpportunisticNetworkService; 81 private static final String CARRIER_APP_CONFIG_NAME = "carrierApp"; 82 private static final String SYSTEM_APP_CONFIG_NAME = "systemApp"; 83 84 @Mock 85 private HashMap<String, ONSConfigInput> mockONSConfigInputHashMap; 86 @Mock 87 private ONSProfileSelector mockProfileSelector; 88 @Mock 89 private CarrierConfigManager mCarrierConfigManager; 90 @Mock 91 private ONSProfileActivator mONSProfileActivator; 92 @Mock 93 private UserManager mUserManager; 94 @Mock 95 private Context mMockContext; 96 @Mock 97 private PackageManager mPackageManager; 98 99 @Before setUp()100 public void setUp() throws Exception { 101 super.setUp("ONSTest"); 102 pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; 103 pkgForFeature = mContext != null ? mContext.getAttributionTag() : null; 104 Intent intent = new Intent(mContext, OpportunisticNetworkService.class); 105 new Thread(new Runnable() { 106 @Override 107 public void run() { 108 Looper.prepare(); 109 mOpportunisticNetworkService = new OpportunisticNetworkService(); 110 mOpportunisticNetworkService.initialize(mContext); 111 mOpportunisticNetworkService.mSubscriptionManager = mSubscriptionManager; 112 mOpportunisticNetworkService.mPackageManager = mPackageManager; 113 for (int retry = 2; retry > 0; retry--) { 114 115 iOpportunisticNetworkService = (IOns) mOpportunisticNetworkService.onBind(null); 116 117 if (iOpportunisticNetworkService != null) { 118 break; 119 } 120 121 try { 122 Thread.sleep(100); 123 } catch (Exception e) { 124 Log.e(TAG, e.toString()); 125 } 126 } 127 mLooper = Looper.myLooper(); 128 setReady(true); 129 Looper.loop(); 130 } 131 }).start(); 132 waitUntilReady(300); 133 134 // In order not to affect the existing implementation, define a telephony feature 135 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_DATA)) 136 .thenReturn(true); 137 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)) 138 .thenReturn(true); 139 } 140 141 @After tearDown()142 public void tearDown() throws Exception { 143 super.tearDown(); 144 mOpportunisticNetworkService.onDestroy(); 145 if (mLooper != null) { 146 mLooper.quit(); 147 mLooper.getThread().join(); 148 } 149 } 150 151 @Test testCheckEnable()152 public void testCheckEnable() { 153 boolean isEnable = true; 154 try { 155 iOpportunisticNetworkService.setEnable(false, pkgForDebug); 156 isEnable = iOpportunisticNetworkService.isEnabled(pkgForDebug); 157 } catch (RemoteException ex) { 158 Log.e(TAG, "RemoteException", ex); 159 } 160 assertEquals(false, isEnable); 161 } 162 163 @Test testHandleSimStateChange()164 public void testHandleSimStateChange() { 165 mResult = -1; 166 ArrayList<String> mccMncs = new ArrayList<>(); 167 mccMncs.add("310210"); 168 AvailableNetworkInfo availableNetworkInfo = new AvailableNetworkInfo(1, 1, mccMncs, 169 new ArrayList<Integer>()); 170 ArrayList<AvailableNetworkInfo> availableNetworkInfos = 171 new ArrayList<AvailableNetworkInfo>(); 172 availableNetworkInfos.add(availableNetworkInfo); 173 IUpdateAvailableNetworksCallback mCallback = new IUpdateAvailableNetworksCallback.Stub() { 174 @Override 175 public void onComplete(int result) { 176 mResult = result; 177 Log.d(TAG, "result: " + result); 178 } 179 }; 180 ONSConfigInput onsConfigInput = new ONSConfigInput(availableNetworkInfos, mCallback); 181 onsConfigInput.setPrimarySub(1); 182 onsConfigInput.setPreferredDataSub(availableNetworkInfos.get(0).getSubId()); 183 ArrayList<SubscriptionInfo> subscriptionInfos = new ArrayList<SubscriptionInfo>(); 184 185 // Case 1: There is no Carrier app using ONS. 186 doReturn(null).when(mockONSConfigInputHashMap).get(CARRIER_APP_CONFIG_NAME); 187 mOpportunisticNetworkService.mIsEnabled = true; 188 mOpportunisticNetworkService.mONSConfigInputHashMap = mockONSConfigInputHashMap; 189 mOpportunisticNetworkService.handleSimStateChange(); 190 waitForMs(500); 191 verify(mockONSConfigInputHashMap, never()).get(SYSTEM_APP_CONFIG_NAME); 192 193 // Case 2: There is a Carrier app using ONS and no System app input. 194 doReturn(subscriptionInfos).when(mSubscriptionManager).getActiveSubscriptionInfoList(false); 195 doReturn(onsConfigInput).when(mockONSConfigInputHashMap).get(CARRIER_APP_CONFIG_NAME); 196 doReturn(null).when(mockONSConfigInputHashMap).get(SYSTEM_APP_CONFIG_NAME); 197 mOpportunisticNetworkService.mIsEnabled = true; 198 mOpportunisticNetworkService.mONSConfigInputHashMap = mockONSConfigInputHashMap; 199 mOpportunisticNetworkService.handleSimStateChange(); 200 waitForMs(50); 201 verify(mockONSConfigInputHashMap,times(1)).get(SYSTEM_APP_CONFIG_NAME); 202 } 203 204 @Test testSystemPreferredDataWhileCarrierAppIsActive()205 public void testSystemPreferredDataWhileCarrierAppIsActive() { 206 mResult = -1; 207 ArrayList<String> mccMncs = new ArrayList<>(); 208 mccMncs.add("310210"); 209 AvailableNetworkInfo availableNetworkInfo = new AvailableNetworkInfo(1, 1, mccMncs, 210 new ArrayList<Integer>()); 211 ArrayList<AvailableNetworkInfo> availableNetworkInfos = 212 new ArrayList<AvailableNetworkInfo>(); 213 availableNetworkInfos.add(availableNetworkInfo); 214 IUpdateAvailableNetworksCallback mCallback = new IUpdateAvailableNetworksCallback.Stub() { 215 @Override 216 public void onComplete(int result) { 217 mResult = result; 218 Log.d(TAG, "result: " + result); 219 } 220 }; 221 ONSConfigInput onsConfigInput = new ONSConfigInput(availableNetworkInfos, mCallback); 222 onsConfigInput.setPrimarySub(1); 223 onsConfigInput.setPreferredDataSub(availableNetworkInfos.get(0).getSubId()); 224 ArrayList<SubscriptionInfo> subscriptionInfos = new ArrayList<SubscriptionInfo>(); 225 226 doReturn(subscriptionInfos).when(mSubscriptionManager).getActiveSubscriptionInfoList(false); 227 doReturn(onsConfigInput).when(mockONSConfigInputHashMap).get(CARRIER_APP_CONFIG_NAME); 228 mOpportunisticNetworkService.mIsEnabled = true; 229 mOpportunisticNetworkService.mONSConfigInputHashMap = mockONSConfigInputHashMap; 230 231 mResult = -1; 232 ISetOpportunisticDataCallback callbackStub = new ISetOpportunisticDataCallback.Stub() { 233 @Override 234 public void onComplete(int result) { 235 Log.d(TAG, "callbackStub, mResult end:" + result); 236 mResult = result; 237 } 238 }; 239 240 try { 241 IOns onsBinder = (IOns)mOpportunisticNetworkService.onBind(null); 242 onsBinder.setPreferredDataSubscriptionId( 243 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false, callbackStub, 244 pkgForDebug); 245 } catch (RemoteException ex) { 246 Log.e(TAG, "RemoteException", ex); 247 } 248 waitForMs(50); 249 assertEquals(TelephonyManager.SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED, mResult); 250 } 251 252 @Test testSetPreferredDataSubscriptionId()253 public void testSetPreferredDataSubscriptionId() { 254 mResult = -1; 255 ISetOpportunisticDataCallback callbackStub = new ISetOpportunisticDataCallback.Stub() { 256 @Override 257 public void onComplete(int result) { 258 Log.d(TAG, "callbackStub, mResult end:" + result); 259 mResult = result; 260 } 261 }; 262 263 try { 264 assertNotNull(iOpportunisticNetworkService); 265 iOpportunisticNetworkService.setPreferredDataSubscriptionId(5, false, callbackStub, 266 pkgForDebug); 267 } catch (RemoteException ex) { 268 Log.e(TAG, "RemoteException", ex); 269 } 270 assertEquals( 271 TelephonyManager.SET_OPPORTUNISTIC_SUB_NO_OPPORTUNISTIC_SUB_AVAILABLE, mResult); 272 } 273 274 @Test testGetPreferredDataSubscriptionId()275 public void testGetPreferredDataSubscriptionId() { 276 assertNotNull(iOpportunisticNetworkService); 277 mResult = -1; 278 try { 279 mResult = iOpportunisticNetworkService.getPreferredDataSubscriptionId(pkgForDebug, 280 pkgForFeature); 281 Log.d(TAG, "testGetPreferredDataSubscriptionId: " + mResult); 282 assertNotNull(mResult); 283 } catch (RemoteException ex) { 284 Log.e(TAG, "RemoteException", ex); 285 } 286 } 287 288 @Test testUpdateAvailableNetworksWithInvalidArguments()289 public void testUpdateAvailableNetworksWithInvalidArguments() { 290 mResult = -1; 291 IUpdateAvailableNetworksCallback mCallback = new IUpdateAvailableNetworksCallback.Stub() { 292 @Override 293 public void onComplete(int result) { 294 Log.d(TAG, "mResult end:" + result); 295 mResult = result; 296 } 297 }; 298 299 ArrayList<String> mccMncs = new ArrayList<>(); 300 mccMncs.add("310210"); 301 AvailableNetworkInfo availableNetworkInfo = new AvailableNetworkInfo(1, 1, mccMncs, 302 new ArrayList<Integer>()); 303 ArrayList<AvailableNetworkInfo> availableNetworkInfos = new ArrayList<>(); 304 availableNetworkInfos.add(availableNetworkInfo); 305 306 try { 307 iOpportunisticNetworkService.updateAvailableNetworks(availableNetworkInfos, mCallback, 308 pkgForDebug); 309 } catch (RemoteException ex) { 310 Log.e(TAG, "RemoteException", ex); 311 } 312 assertEquals( 313 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE, mResult); 314 } 315 316 @Test testUpdateAvailableNetworksWithSuccess()317 public void testUpdateAvailableNetworksWithSuccess() { 318 mResult = -1; 319 IUpdateAvailableNetworksCallback mCallback = new IUpdateAvailableNetworksCallback.Stub() { 320 @Override 321 public void onComplete(int result) { 322 Log.d(TAG, "mResult end:" + result); 323 mResult = result; 324 } 325 }; 326 ArrayList<AvailableNetworkInfo> availableNetworkInfos = new ArrayList<>(); 327 try { 328 iOpportunisticNetworkService.setEnable(false, pkgForDebug); 329 iOpportunisticNetworkService.updateAvailableNetworks(availableNetworkInfos, mCallback, 330 pkgForDebug); 331 } catch (RemoteException ex) { 332 Log.e(TAG, "RemoteException", ex); 333 } 334 assertEquals(TelephonyManager.UPDATE_AVAILABLE_NETWORKS_SUCCESS, mResult); 335 } 336 337 @Test testPriorityRuleOfActivatingAvailableNetworks()338 public void testPriorityRuleOfActivatingAvailableNetworks() { 339 ArrayList<String> mccMncs = new ArrayList<>(); 340 mccMncs.add("310210"); 341 AvailableNetworkInfo availableNetworkInfo = new AvailableNetworkInfo(1, 1, mccMncs, 342 new ArrayList<Integer>()); 343 ArrayList<AvailableNetworkInfo> availableNetworkInfos = 344 new ArrayList<AvailableNetworkInfo>(); 345 availableNetworkInfos.add(availableNetworkInfo); 346 mResult = -1; 347 IUpdateAvailableNetworksCallback mCallback = new IUpdateAvailableNetworksCallback.Stub() { 348 @Override 349 public void onComplete(int result) { 350 mResult = result; 351 Log.d(TAG, "result: " + result); 352 } 353 }; 354 ONSConfigInput onsConfigInput = new ONSConfigInput(availableNetworkInfos, mCallback); 355 onsConfigInput.setPrimarySub(1); 356 onsConfigInput.setPreferredDataSub(availableNetworkInfos.get(0).getSubId()); 357 doReturn(onsConfigInput).when(mockONSConfigInputHashMap).get(CARRIER_APP_CONFIG_NAME); 358 doReturn(true).when(mockProfileSelector).hasOpprotunisticSub(any()); 359 doReturn(false).when(mockProfileSelector).containStandaloneOppSubs(any()); 360 mOpportunisticNetworkService.mIsEnabled = true; 361 mOpportunisticNetworkService.mONSConfigInputHashMap = mockONSConfigInputHashMap; 362 mOpportunisticNetworkService.mProfileSelector = mockProfileSelector; 363 364 // Assume carrier app has updated available networks at first. 365 // Then system app updated available networks which is not standalone. 366 try { 367 IOns onsBinder = (IOns) mOpportunisticNetworkService.onBind(null); 368 onsBinder.updateAvailableNetworks(availableNetworkInfos, mCallback, pkgForDebug); 369 } catch (RemoteException ex) { 370 Log.e(TAG, "RemoteException", ex); 371 } 372 verify(mockProfileSelector, never()).startProfileSelection(any(), any()); 373 374 // System app updated available networks which contain standalone network. 375 doReturn(true).when(mockProfileSelector).containStandaloneOppSubs(any()); 376 try { 377 IOns onsBinder = (IOns) mOpportunisticNetworkService.onBind(null); 378 onsBinder.updateAvailableNetworks(availableNetworkInfos, mCallback, pkgForDebug); 379 } catch (RemoteException ex) { 380 Log.e(TAG, "RemoteException", ex); 381 } 382 verify(mockProfileSelector, times(1)).startProfileSelection(any(), any()); 383 384 // System app updated available networks which equal to null. 385 // Case1: start carrier app request, if there is a carrier app request. 386 availableNetworkInfos.clear(); 387 try { 388 IOns onsBinder = (IOns) mOpportunisticNetworkService.onBind(null); 389 onsBinder.updateAvailableNetworks(availableNetworkInfos, mCallback, pkgForDebug); 390 } catch (RemoteException ex) { 391 Log.e(TAG, "RemoteException", ex); 392 } 393 verify(mockProfileSelector, times(2)).startProfileSelection(any(), any()); 394 395 // System app updated available networks which equal to null. 396 // Case2: stop profile selection, if there is no any carrier app request. 397 doReturn(null).when(mockONSConfigInputHashMap).get(CARRIER_APP_CONFIG_NAME); 398 try { 399 IOns onsBinder = (IOns) mOpportunisticNetworkService.onBind(null); 400 onsBinder.updateAvailableNetworks(availableNetworkInfos, mCallback, pkgForDebug); 401 } catch (RemoteException ex) { 402 Log.e(TAG, "RemoteException", ex); 403 } 404 verify(mockProfileSelector, times(1)).stopProfileSelection(any()); 405 } 406 407 @Test testCarrierConfigChangedUnlocked()408 public void testCarrierConfigChangedUnlocked() { 409 mOpportunisticNetworkService.mUserManager = mUserManager; 410 mOpportunisticNetworkService.mONSProfileActivator = mONSProfileActivator; 411 mOpportunisticNetworkService.mCarrierConfigManager = mCarrierConfigManager; 412 mOpportunisticNetworkService.registerCarrierConfigChangListener(); 413 mOpportunisticNetworkService.mContext = mMockContext; 414 415 CarrierConfigManager.CarrierConfigChangeListener CarrierConfigChangeListener; 416 417 final ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerCaptor = 418 ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class); 419 420 verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(), 421 listenerCaptor.capture()); 422 CarrierConfigChangeListener = listenerCaptor.getAllValues().get(0); 423 424 // CarrierConfigChange in lock state 425 when(mUserManager.isUserUnlocked()).thenReturn(false); 426 CarrierConfigChangeListener.onCarrierConfigChanged(0, 0, 0, 0); 427 verify(mONSProfileActivator, never()).handleCarrierConfigChange(); 428 429 // handle CarrierConfigChange when state is changed from lock to unlock 430 final ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor = 431 ArgumentCaptor.forClass(BroadcastReceiver.class); 432 433 verify(mMockContext).registerReceiver(broadcastReceiverCaptor.capture(), any()); 434 broadcastReceiverCaptor.getValue().onReceive(mMockContext, 435 new Intent(Intent.ACTION_USER_UNLOCKED)); 436 verify(mONSProfileActivator, times(1)).handleCarrierConfigChange(); 437 438 // CarrierConfigChange in Unlock state 439 when(mUserManager.isUserUnlocked()).thenReturn(true); 440 CarrierConfigChangeListener.onCarrierConfigChanged(0, 0, 0, 0); 441 verify(mONSProfileActivator, times(2)).handleCarrierConfigChange(); 442 } 443 444 @Test 445 @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING}) testTelephonyFeatureAndCompatChanges()446 public void testTelephonyFeatureAndCompatChanges() throws Exception { 447 mSetFlagsRule.enableFlags(Flags.FLAG_ENFORCE_TELEPHONY_FEATURE_MAPPING_FOR_PUBLIC_APIS); 448 449 ArrayList<String> mccMncs = new ArrayList<>(); 450 mccMncs.add("310210"); 451 AvailableNetworkInfo availableNetworkInfo = new AvailableNetworkInfo(1, 1, mccMncs, 452 new ArrayList<Integer>()); 453 ArrayList<AvailableNetworkInfo> availableNetworkInfos = new ArrayList<>(); 454 availableNetworkInfos.add(availableNetworkInfo); 455 456 // Enabled FeatureFlags and ENABLE_FEATURE_MAPPING, telephony features are defined 457 try { 458 // FEATURE_TELEPHONY_DATA 459 iOpportunisticNetworkService.setPreferredDataSubscriptionId( 460 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false, null, pkgForDebug); 461 iOpportunisticNetworkService.getPreferredDataSubscriptionId(pkgForDebug, pkgForFeature); 462 463 // FEATURE_TELEPHONY_RADIO_ACCESS 464 iOpportunisticNetworkService.setEnable(false, pkgForDebug); 465 iOpportunisticNetworkService.isEnabled(pkgForDebug); 466 iOpportunisticNetworkService.updateAvailableNetworks(availableNetworkInfos, null, 467 pkgForDebug); 468 } catch (Exception e) { 469 fail("Not expect exception " + e.getMessage()); 470 } 471 472 // Replace field to set SDK version of vendor partition to Android V 473 int vendorApiLevel = Build.VERSION_CODES.VANILLA_ICE_CREAM; 474 replaceInstance(OpportunisticNetworkService.class, "mVendorApiLevel", 475 mOpportunisticNetworkService, vendorApiLevel); 476 477 // FEATURE_TELEPHONY_DATA is not defined, expect UnsupportedOperationException. 478 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_DATA)) 479 .thenReturn(false); 480 481 assertThrows(UnsupportedOperationException.class, 482 () -> iOpportunisticNetworkService.setPreferredDataSubscriptionId( 483 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false, null, pkgForDebug)); 484 assertThrows(UnsupportedOperationException.class, 485 () -> iOpportunisticNetworkService.getPreferredDataSubscriptionId( 486 pkgForDebug, pkgForFeature)); 487 488 // FEATURE_TELEPHONY_DATA is not defined, expect UnsupportedOperationException. 489 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)) 490 .thenReturn(false); 491 assertThrows(UnsupportedOperationException.class, 492 () -> iOpportunisticNetworkService.setEnable(false, pkgForDebug)); 493 assertThrows(UnsupportedOperationException.class, 494 () -> iOpportunisticNetworkService.isEnabled(pkgForDebug)); 495 assertThrows(UnsupportedOperationException.class, 496 () -> iOpportunisticNetworkService.updateAvailableNetworks( 497 availableNetworkInfos, null, pkgForDebug)); 498 } 499 replaceInstance(final Class c, final String instanceName, final Object obj, final Object newValue)500 private void replaceInstance(final Class c, final String instanceName, final Object obj, 501 final Object newValue) throws Exception { 502 Field field = c.getDeclaredField(instanceName); 503 field.setAccessible(true); 504 field.set(obj, newValue); 505 } 506 getIOns()507 private IOns getIOns() { 508 return IOns.Stub.asInterface( 509 TelephonyFrameworkInitializer 510 .getTelephonyServiceManager() 511 .getOpportunisticNetworkServiceRegisterer() 512 .get()); 513 } 514 waitForMs(long ms)515 public static void waitForMs(long ms) { 516 try { 517 Thread.sleep(ms); 518 } catch (InterruptedException e) { 519 Log.d(TAG, "InterruptedException while waiting: " + e); 520 } 521 } 522 } 523