Merge "[ManualNetworkSelect] Improve error handling"

This commit is contained in:
Bonian Chen
2019-09-24 10:05:23 +00:00
committed by Android (Google) Code Review
2 changed files with 248 additions and 1 deletions

View File

@@ -37,6 +37,7 @@ import com.google.common.util.concurrent.SettableFuture;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
@@ -177,6 +178,9 @@ public class NetworkScanHelper {
@Override
public void onFailure(Throwable t) {
if (t instanceof CancellationException) {
return;
}
int errCode = Integer.parseInt(t.getMessage());
onError(errCode);
}
@@ -184,10 +188,16 @@ public class NetworkScanHelper {
mExecutor.execute(new NetworkScanSyncTask(
mTelephonyManager, (SettableFuture) mNetworkScanFuture));
} else if (type == NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS) {
if (mNetworkScanRequester != null) {
return;
}
mNetworkScanRequester = mTelephonyManager.requestNetworkScan(
NETWORK_SCAN_REQUEST,
mExecutor,
mInternalNetworkScanCallback);
if (mNetworkScanRequester == null) {
onError(NetworkScan.ERROR_RADIO_INTERFACE_ERROR);
}
}
}
@@ -199,7 +209,7 @@ public class NetworkScanHelper {
public void stopNetworkQuery() {
if (mNetworkScanRequester != null) {
mNetworkScanRequester.stopScan();
mNetworkScanFuture = null;
mNetworkScanRequester = null;
}
if (mNetworkScanFuture != null) {

View File

@@ -0,0 +1,237 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.network.telephony;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.telephony.CellInfo;
import android.telephony.NetworkScan;
import android.telephony.NetworkScanRequest;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyScanManager;
import com.android.internal.telephony.CellNetworkScanResult;
import com.android.internal.telephony.OperatorInfo;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.robolectric.RobolectricTestRunner;
@RunWith(RobolectricTestRunner.class)
public class NetworkScanHelperTest {
@Mock
private TelephonyManager mTelephonyManager;
@Mock
private CellNetworkScanResult mCellNetworkScanResult;
@Mock
private NetworkScanHelper.NetworkScanCallback mNetworkScanCallback;
private static final long THREAD_EXECUTION_TIMEOUT_MS = 3000L;
private ExecutorService mNetworkScanExecutor;
private NetworkScanHelper mNetworkScanHelper;
private static final int SCAN_ID = 1234;
private static final int SUB_ID = 1;
private NetworkScan mNetworkScan;
private OperatorInfo mOperatorInfo;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mNetworkScanExecutor = Executors.newFixedThreadPool(1);
mNetworkScanHelper = new NetworkScanHelper(mTelephonyManager,
mNetworkScanCallback, mNetworkScanExecutor);
mNetworkScan = spy(new NetworkScan(SCAN_ID, SUB_ID));
mOperatorInfo = new OperatorInfo("Testing", "Test", "12345", "unknown");
}
@Test
public void startNetworkScan_scanOnceAndSuccess_completionWithResult() {
ArrayList<OperatorInfo> expectedResult = new ArrayList<OperatorInfo>();
expectedResult.add(mOperatorInfo);
when(mTelephonyManager.getAvailableNetworks()).thenReturn(mCellNetworkScanResult);
when(mCellNetworkScanResult.getStatus()).thenReturn(
CellNetworkScanResult.STATUS_SUCCESS);
when(mCellNetworkScanResult.getOperators()).thenReturn(expectedResult);
ArgumentCaptor<List<CellInfo>> argument = ArgumentCaptor.forClass(List.class);
startNetworkScan_waitForAll(true);
verify(mNetworkScanCallback, times(1)).onResults(argument.capture());
List<CellInfo> actualResult = argument.getValue();
assertThat(actualResult.size()).isEqualTo(expectedResult.size());
verify(mNetworkScanCallback, times(1)).onComplete();
}
@Test
public void startNetworkScan_scanOnceAndFail_failureWithErrorCode() {
when(mTelephonyManager.getAvailableNetworks()).thenReturn(mCellNetworkScanResult);
when(mCellNetworkScanResult.getStatus()).thenReturn(
CellNetworkScanResult.STATUS_RADIO_GENERIC_FAILURE);
startNetworkScan_waitForAll(true);
verify(mNetworkScanCallback, times(1)).onError(anyInt());
}
@Test
public void startNetworkScan_scanOnceAndAbort_withoutCrash() {
when(mCellNetworkScanResult.getStatus()).thenReturn(
CellNetworkScanResult.STATUS_RADIO_GENERIC_FAILURE);
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Thread.sleep(THREAD_EXECUTION_TIMEOUT_MS);
return mCellNetworkScanResult;
}
}).when(mTelephonyManager).getAvailableNetworks();
startNetworkScan_waitForAll(false);
verify(mNetworkScanCallback, times(0)).onError(anyInt());
}
@Test
public void startNetworkScan_incrementalAndSuccess_completionWithResult() {
ArrayList<CellInfo> expectedResult = new ArrayList<CellInfo>();
expectedResult.add(CellInfoUtil.convertOperatorInfoToCellInfo(mOperatorInfo));
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
TelephonyScanManager.NetworkScanCallback callback =
(TelephonyScanManager.NetworkScanCallback)
(invocation.getArguments()[2]);
callback.onResults(expectedResult);
callback.onComplete();
return mNetworkScan;
}
}).when(mTelephonyManager).requestNetworkScan(
any(NetworkScanRequest.class), any(Executor.class),
any(TelephonyScanManager.NetworkScanCallback.class));
ArgumentCaptor<List<CellInfo>> argument = ArgumentCaptor.forClass(List.class);
startNetworkScan_incremental(true);
verify(mNetworkScanCallback, times(1)).onResults(argument.capture());
List<CellInfo> actualResult = argument.getValue();
assertThat(actualResult.size()).isEqualTo(expectedResult.size());
verify(mNetworkScanCallback, times(1)).onComplete();
}
@Test
public void startNetworkScan_incrementalAndImmediateFailure_failureWithErrorCode() {
doReturn(null).when(mTelephonyManager).requestNetworkScan(
any(NetworkScanRequest.class), any(Executor.class),
any(TelephonyScanManager.NetworkScanCallback.class));
startNetworkScan_incremental(true);
verify(mNetworkScanCallback, times(1)).onError(anyInt());
}
@Test
public void startNetworkScan_incrementalAndFailure_failureWithErrorCode() {
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
TelephonyScanManager.NetworkScanCallback callback =
(TelephonyScanManager.NetworkScanCallback)
(invocation.getArguments()[2]);
callback.onError(CellNetworkScanResult.STATUS_RADIO_GENERIC_FAILURE);
return mNetworkScan;
}
}).when(mTelephonyManager).requestNetworkScan(
any(NetworkScanRequest.class), any(Executor.class),
any(TelephonyScanManager.NetworkScanCallback.class));
startNetworkScan_incremental(true);
verify(mNetworkScanCallback, times(1)).onError(anyInt());
}
@Test
public void startNetworkScan_incrementalAndAbort_doStop() {
doReturn(mNetworkScan).when(mTelephonyManager).requestNetworkScan(
any(NetworkScanRequest.class), any(Executor.class),
any(TelephonyScanManager.NetworkScanCallback.class));
startNetworkScan_incremental(false);
verify(mNetworkScan, times(1)).stopScan();
}
private void startNetworkScan_waitForAll(boolean waitForCompletion) {
mNetworkScanHelper.startNetworkScan(
NetworkScanHelper.NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS);
if (!waitForCompletion) {
mNetworkScanHelper.stopNetworkQuery();
}
mNetworkScanExecutor.shutdown();
boolean executorTerminate = false;
try {
executorTerminate = mNetworkScanExecutor.awaitTermination(
THREAD_EXECUTION_TIMEOUT_MS, TimeUnit.MILLISECONDS);
} catch (Exception ex) {
}
assertThat(executorTerminate).isEqualTo(waitForCompletion);
}
private void startNetworkScan_incremental(boolean waitForCompletion) {
mNetworkScanHelper.startNetworkScan(
NetworkScanHelper.NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS);
if (!waitForCompletion) {
mNetworkScanHelper.stopNetworkQuery();
}
}
}