HttpClientNetworkStateHandler extends HttpClientDecorator implements NetworkStateHelper.Listener { @Override public synchronized ServiceCall callAsync(String url, String method, Map<String, String> headers, CallTemplate callTemplate, ServiceCallback serviceCallback) { Call call = new Call(mDecoratedApi, url, method, headers, callTemplate, serviceCallback); if (mNetworkStateHelper.isNetworkConnected()) { call.run(); } else { mCalls.add(call); AppCenterLog.debug(LOG_TAG, "Call triggered with no network connectivity, waiting network to become available..."); } return call; } HttpClientNetworkStateHandler(HttpClient decoratedApi, NetworkStateHelper networkStateHelper); @Override synchronized ServiceCall callAsync(String url, String method, Map<String, String> headers, CallTemplate callTemplate, ServiceCallback serviceCallback); @Override synchronized void close(); @Override void reopen(); @Override synchronized void onNetworkStateUpdated(boolean connected);  }
@Test(timeout=3000) public void changeNetworkConnectionDuringCallWithoutDeadlock() throws Exception { TestUtils.setInternalState(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.LOLLIPOP); Context context = mock(Context.class); ConnectivityManager connectivityManager = mock(ConnectivityManager.class); when(context.getApplicationContext()).thenReturn(context); when(context.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(connectivityManager); HttpClient httpClient = mock(HttpClient.class); final CountDownLatch latch = new CountDownLatch(1); final NetworkStateHelper networkStateHelper = spy(new NetworkStateHelper(context)); when(networkStateHelper.isNetworkConnected()).thenAnswer(new Answer<Boolean>() { @Override public Boolean answer(InvocationOnMock invocation) throws Throwable { latch.await(); return (Boolean)invocation.callRealMethod(); } }); networkStateHelper.addListener(new NetworkStateHelper.Listener() { @Override public void onNetworkStateUpdated(boolean connected) { latch.countDown(); try { Thread.sleep(100); } catch (InterruptedException ignored) { } } }); final HttpClientNetworkStateHandler decorator = new HttpClientNetworkStateHandler(httpClient, networkStateHelper); Thread thread = new Thread(new Runnable() { @Override public void run() { String url = "http: decorator.callAsync(url, METHOD_GET, null, null, null); } }); thread.start(); Thread.sleep(100); ArgumentCaptor<ConnectivityManager.NetworkCallback> callback = ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class); verify(connectivityManager).registerNetworkCallback(any(NetworkRequest.class), callback.capture()); callback.getValue().onAvailable(mock(Network.class)); thread.interrupt(); TestUtils.setInternalState(Build.VERSION.class, "SDK_INT", 0); }