1 /* 2 * Copyright (C) 2018 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 android.carrierapi.cts; 17 18 import android.content.Context; 19 import android.content.pm.PackageManager; 20 import android.os.Handler; 21 import android.os.HandlerThread; 22 import android.os.Message; 23 import android.os.Parcel; 24 import android.support.test.InstrumentationRegistry; 25 import android.support.test.runner.AndroidJUnit4; 26 import android.telephony.CellInfo; 27 import android.telephony.CellInfoGsm; 28 import android.telephony.CellInfoLte; 29 import android.telephony.CellInfoWcdma; 30 import android.telephony.NetworkScan; 31 import android.telephony.NetworkScanRequest; 32 import android.telephony.RadioAccessSpecifier; 33 import android.telephony.AccessNetworkConstants; 34 import android.telephony.TelephonyManager; 35 import android.telephony.TelephonyScanManager; 36 import android.util.Log; 37 38 import org.junit.After; 39 import org.junit.Before; 40 import org.junit.Test; 41 import org.junit.runner.RunWith; 42 43 import java.util.ArrayList; 44 import java.util.Arrays; 45 import java.util.List; 46 47 import static org.junit.Assert.assertFalse; 48 import static org.junit.Assert.assertNotSame; 49 import static org.junit.Assert.assertNull; 50 import static org.junit.Assert.assertTrue; 51 import static org.junit.Assert.assertEquals; 52 import static org.junit.Assert.fail; 53 54 /** 55 * Build, install and run the tests by running the commands below: 56 * make cts -j64 57 * cts-tradefed run cts -m CtsCarrierApiTestCases --test android.carrierapi.cts.NetworkScanApiTest 58 */ 59 @RunWith(AndroidJUnit4.class) 60 public class NetworkScanApiTest { 61 private TelephonyManager mTelephonyManager; 62 private PackageManager mPackageManager; 63 private static final String TAG = "NetworkScanApiTest"; 64 private int mNetworkScanStatus; 65 private static final int EVENT_NETWORK_SCAN_START = 100; 66 private static final int EVENT_NETWORK_SCAN_RESULTS = 200; 67 private static final int EVENT_NETWORK_SCAN_ERROR = 300; 68 private static final int EVENT_NETWORK_SCAN_COMPLETED = 400; 69 private List<CellInfo> mScanResults = null; 70 private NetworkScanHandlerThread mTestHandlerThread; 71 private Handler mHandler; 72 private NetworkScan mNetworkScan; 73 private NetworkScanRequest mNetworkScanRequest; 74 private NetworkScanCallbackImpl mNetworkScanCallback; 75 private static final int MAX_INIT_WAIT_MS = 60000; // 60 seconds 76 private Object mLock = new Object(); 77 private boolean mReady; 78 private int mErrorCode; 79 /* All the following constants are used to construct NetworkScanRequest*/ 80 private static final int SCAN_TYPE = NetworkScanRequest.SCAN_TYPE_ONE_SHOT; 81 private static final boolean INCREMENTAL_RESULTS = true; 82 private static final int SEARCH_PERIODICITY_SEC = 5; 83 private static final int MAX_SEARCH_TIME_SEC = 300; 84 private static final int INCREMENTAL_RESULTS_PERIODICITY_SEC = 3; 85 private static final ArrayList<String> MCC_MNC = new ArrayList<>(); 86 private static final RadioAccessSpecifier[] RADIO_ACCESS_SPECIFIERS = { 87 new RadioAccessSpecifier( 88 AccessNetworkConstants.AccessNetworkType.GERAN, 89 null /* bands */, 90 null /* channels */), 91 new RadioAccessSpecifier( 92 AccessNetworkConstants.AccessNetworkType.EUTRAN, 93 null /* bands */, 94 null /* channels */), 95 new RadioAccessSpecifier( 96 AccessNetworkConstants.AccessNetworkType.UTRAN, 97 null /* bands */, 98 null /* channels */) 99 }; 100 101 @Before 102 public void setUp() throws Exception { 103 mTelephonyManager = (TelephonyManager) 104 InstrumentationRegistry.getContext().getSystemService(Context.TELEPHONY_SERVICE); 105 mPackageManager = InstrumentationRegistry.getContext().getPackageManager(); 106 mTestHandlerThread = new NetworkScanHandlerThread(TAG); 107 mTestHandlerThread.start(); 108 } 109 110 @After 111 public void tearDown() throws Exception { 112 mTestHandlerThread.quit(); 113 } 114 115 private void waitUntilReady() { 116 synchronized (mLock) { 117 try { 118 mLock.wait(MAX_INIT_WAIT_MS); 119 } catch (InterruptedException ie) { 120 } 121 122 if (!mReady) { 123 fail("NetworkScanApiTest failed to initialize"); 124 } 125 } 126 } 127 128 private void setReady(boolean ready) { 129 synchronized (mLock) { 130 mReady = ready; 131 mLock.notifyAll(); 132 } 133 } 134 135 private class NetworkScanHandlerThread extends HandlerThread { 136 137 public NetworkScanHandlerThread(String name) { 138 super(name); 139 } 140 141 @Override 142 public void onLooperPrepared() { 143 /* create a custom handler for the Handler Thread */ 144 mHandler = new Handler(mTestHandlerThread.getLooper()) { 145 @Override 146 public void handleMessage(Message msg) { 147 switch (msg.what) { 148 case EVENT_NETWORK_SCAN_START: 149 Log.d(TAG, "request network scan"); 150 mNetworkScan = mTelephonyManager.requestNetworkScan( 151 mNetworkScanRequest, mNetworkScanCallback); 152 break; 153 default: 154 Log.d(TAG, "Unknown Event " + msg.what); 155 } 156 } 157 }; 158 } 159 } 160 161 private class NetworkScanCallbackImpl extends TelephonyScanManager.NetworkScanCallback { 162 @Override 163 public void onResults(List<CellInfo> results) { 164 Log.d(TAG, "onResults: " + results.toString()); 165 mNetworkScanStatus = EVENT_NETWORK_SCAN_RESULTS; 166 mScanResults = results; 167 } 168 169 @Override 170 public void onComplete() { 171 Log.d(TAG, "onComplete"); 172 mNetworkScanStatus = EVENT_NETWORK_SCAN_COMPLETED; 173 setReady(true); 174 } 175 176 @Override 177 public void onError(int error) { 178 Log.d(TAG, "onError: " + String.valueOf(error)); 179 mNetworkScanStatus = EVENT_NETWORK_SCAN_ERROR; 180 mErrorCode = error; 181 Log.d(TAG, "Stop the network scan"); 182 mNetworkScan.stopScan(); 183 setReady(true); 184 } 185 } 186 187 private RadioAccessSpecifier getRadioAccessSpecifier(CellInfo cellInfo) { 188 RadioAccessSpecifier ras; 189 if (cellInfo instanceof CellInfoLte) { 190 int ranLte = AccessNetworkConstants.AccessNetworkType.EUTRAN; 191 int[] lteChannels = {((CellInfoLte) cellInfo).getCellIdentity().getEarfcn()}; 192 ras = new RadioAccessSpecifier(ranLte, null /* bands */, lteChannels); 193 } else if (cellInfo instanceof CellInfoWcdma) { 194 int ranLte = AccessNetworkConstants.AccessNetworkType.UTRAN; 195 int[] wcdmaChannels = {((CellInfoWcdma) cellInfo).getCellIdentity().getUarfcn()}; 196 ras = new RadioAccessSpecifier(ranLte, null /* bands */, wcdmaChannels); 197 } else if (cellInfo instanceof CellInfoGsm) { 198 int ranGsm = AccessNetworkConstants.AccessNetworkType.GERAN; 199 int[] gsmChannels = {((CellInfoGsm) cellInfo).getCellIdentity().getArfcn()}; 200 ras = new RadioAccessSpecifier(ranGsm, null /* bands */, gsmChannels); 201 } else { 202 ras = null; 203 } 204 return ras; 205 } 206 207 /** 208 * Tests that the device properly requests a network scan. 209 */ 210 @Test 211 public void testRequestNetworkScan() throws InterruptedException { 212 if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) { 213 // Checks whether the cellular stack should be running on this device. 214 Log.e(TAG, "No cellular support, the test will be skipped."); 215 return; 216 } 217 if (!mTelephonyManager.hasCarrierPrivileges()) { 218 fail("This test requires a SIM card with carrier privilege rule on it."); 219 } 220 221 // Make sure that there should be at least one entry. 222 List<CellInfo> allCellInfo = mTelephonyManager.getAllCellInfo(); 223 if (allCellInfo == null) { 224 fail("TelephonyManager.getAllCellInfo() returned NULL!"); 225 } 226 if (allCellInfo.size() == 0) { 227 fail("TelephonyManager.getAllCellInfo() returned zero-length list!"); 228 } 229 230 // Construct a NetworkScanRequest 231 List<RadioAccessSpecifier> radioAccessSpecifier = new ArrayList<>(); 232 for (int i = 0; i < allCellInfo.size(); i++) { 233 RadioAccessSpecifier ras = getRadioAccessSpecifier(allCellInfo.get(i)); 234 if (ras != null) { 235 radioAccessSpecifier.add(ras); 236 } 237 } 238 if (radioAccessSpecifier.size() == 0) { 239 RadioAccessSpecifier gsm = new RadioAccessSpecifier( 240 AccessNetworkConstants.AccessNetworkType.GERAN, 241 null /* bands */, 242 null /* channels */); 243 RadioAccessSpecifier lte = new RadioAccessSpecifier( 244 AccessNetworkConstants.AccessNetworkType.EUTRAN, 245 null /* bands */, 246 null /* channels */); 247 RadioAccessSpecifier wcdma = new RadioAccessSpecifier( 248 AccessNetworkConstants.AccessNetworkType.UTRAN, 249 null /* bands */, 250 null /* channels */); 251 radioAccessSpecifier.add(gsm); 252 radioAccessSpecifier.add(lte); 253 radioAccessSpecifier.add(wcdma); 254 } 255 RadioAccessSpecifier[] radioAccessSpecifierArray = 256 new RadioAccessSpecifier[radioAccessSpecifier.size()]; 257 mNetworkScanRequest = new NetworkScanRequest( 258 NetworkScanRequest.SCAN_TYPE_ONE_SHOT /* scan type */, 259 radioAccessSpecifier.toArray(radioAccessSpecifierArray), 260 5 /* search periodicity */, 261 60 /* max search time */, 262 true /*enable incremental results*/, 263 5 /* incremental results periodicity */, 264 null /* List of PLMN ids (MCC-MNC) */); 265 266 mNetworkScanCallback = new NetworkScanCallbackImpl(); 267 Message startNetworkScan = mHandler.obtainMessage(EVENT_NETWORK_SCAN_START); 268 setReady(false); 269 startNetworkScan.sendToTarget(); 270 waitUntilReady(); 271 272 Log.d(TAG, "mNetworkScanStatus: " + mNetworkScanStatus); 273 assertTrue("The final scan status is not ScanCompleted or ScanError with an error " 274 + "code ERROR_MODEM_UNAVAILABLE or ERROR_UNSUPPORTED", 275 isScanStatusValid()); 276 } 277 278 private boolean isScanStatusValid() { 279 // TODO(b/72162885): test the size of ScanResults is not zero after the blocking bug fixed. 280 if ((mNetworkScanStatus == EVENT_NETWORK_SCAN_COMPLETED) && (mScanResults != null)) { 281 // Scan complete. 282 return true; 283 } 284 if ((mNetworkScanStatus == EVENT_NETWORK_SCAN_ERROR) 285 && ((mErrorCode == NetworkScan.ERROR_MODEM_UNAVAILABLE) 286 || (mErrorCode == NetworkScan.ERROR_UNSUPPORTED))) { 287 // Scan error but the error type is allowed. 288 return true; 289 } 290 return false; 291 } 292 293 private ArrayList<String> getPlmns() { 294 ArrayList<String> mccMncs = new ArrayList<>(); 295 mccMncs.add("310260"); 296 mccMncs.add("310120"); 297 return mccMncs; 298 } 299 300 /** 301 * To test its constructor and getters. 302 */ 303 @Test 304 public void testNetworkScanRequest_ConstructorAndGetters(){ 305 NetworkScanRequest networkScanRequest = new NetworkScanRequest( 306 SCAN_TYPE, 307 RADIO_ACCESS_SPECIFIERS, 308 SEARCH_PERIODICITY_SEC, 309 MAX_SEARCH_TIME_SEC, 310 INCREMENTAL_RESULTS, 311 INCREMENTAL_RESULTS_PERIODICITY_SEC, 312 getPlmns()); 313 314 assertEquals("getScanType() returns wrong value", 315 SCAN_TYPE, networkScanRequest.getScanType()); 316 assertEquals("getSpecifiers() returns wrong value", 317 RADIO_ACCESS_SPECIFIERS, networkScanRequest.getSpecifiers()); 318 assertEquals("getSearchPeriodicity() returns wrong value", 319 SEARCH_PERIODICITY_SEC, networkScanRequest.getSearchPeriodicity()); 320 assertEquals("getMaxSearchTime() returns wrong value", 321 MAX_SEARCH_TIME_SEC, networkScanRequest.getMaxSearchTime()); 322 assertEquals("getIncrementalResults() returns wrong value", 323 INCREMENTAL_RESULTS, networkScanRequest.getIncrementalResults()); 324 assertEquals("getIncrementalResultsPeriodicity() returns wrong value", 325 INCREMENTAL_RESULTS_PERIODICITY_SEC, 326 networkScanRequest.getIncrementalResultsPeriodicity()); 327 assertEquals("getPlmns() returns wrong value", getPlmns(), networkScanRequest.getPlmns()); 328 assertEquals("describeContents() returns wrong value", 329 0, networkScanRequest.describeContents()); 330 } 331 332 /** 333 * To test its hashCode method. 334 */ 335 @Test 336 public void testNetworkScanRequestParcel_Hashcode() { 337 NetworkScanRequest networkScanRequest1 = new NetworkScanRequest( 338 SCAN_TYPE, 339 RADIO_ACCESS_SPECIFIERS, 340 SEARCH_PERIODICITY_SEC, 341 MAX_SEARCH_TIME_SEC, 342 INCREMENTAL_RESULTS, 343 INCREMENTAL_RESULTS_PERIODICITY_SEC, 344 getPlmns()); 345 346 NetworkScanRequest networkScanRequest2 = new NetworkScanRequest( 347 SCAN_TYPE, 348 RADIO_ACCESS_SPECIFIERS, 349 SEARCH_PERIODICITY_SEC, 350 MAX_SEARCH_TIME_SEC, 351 INCREMENTAL_RESULTS, 352 INCREMENTAL_RESULTS_PERIODICITY_SEC, 353 getPlmns()); 354 355 NetworkScanRequest networkScanRequest3 = new NetworkScanRequest( 356 SCAN_TYPE, 357 null, 358 SEARCH_PERIODICITY_SEC, 359 MAX_SEARCH_TIME_SEC, 360 false, 361 0, 362 getPlmns()); 363 364 assertEquals("hashCode() returns different hash code for same objects", 365 networkScanRequest1.hashCode(), networkScanRequest2.hashCode()); 366 assertNotSame("hashCode() returns same hash code for different objects", 367 networkScanRequest1.hashCode(), networkScanRequest3.hashCode()); 368 } 369 370 /** 371 * To test its comparision method. 372 */ 373 @Test 374 public void testNetworkScanRequestParcel_Equals() { 375 NetworkScanRequest networkScanRequest1 = new NetworkScanRequest( 376 SCAN_TYPE, 377 RADIO_ACCESS_SPECIFIERS, 378 SEARCH_PERIODICITY_SEC, 379 MAX_SEARCH_TIME_SEC, 380 INCREMENTAL_RESULTS, 381 INCREMENTAL_RESULTS_PERIODICITY_SEC, 382 getPlmns()); 383 384 NetworkScanRequest networkScanRequest2 = new NetworkScanRequest( 385 SCAN_TYPE, 386 RADIO_ACCESS_SPECIFIERS, 387 SEARCH_PERIODICITY_SEC, 388 MAX_SEARCH_TIME_SEC, 389 INCREMENTAL_RESULTS, 390 INCREMENTAL_RESULTS_PERIODICITY_SEC, 391 getPlmns()); 392 393 assertTrue(networkScanRequest1.equals(networkScanRequest2)); 394 395 networkScanRequest2 = new NetworkScanRequest( 396 SCAN_TYPE, 397 RADIO_ACCESS_SPECIFIERS, 398 SEARCH_PERIODICITY_SEC, 399 MAX_SEARCH_TIME_SEC, 400 INCREMENTAL_RESULTS, 401 INCREMENTAL_RESULTS_PERIODICITY_SEC, 402 null /* List of PLMN ids (MCC-MNC) */); 403 assertFalse(networkScanRequest1.equals(networkScanRequest2)); 404 } 405 406 /** 407 * To test its writeToParcel and createFromParcel methods. 408 */ 409 @Test 410 public void testNetworkScanRequestParcel_Parcel() { 411 NetworkScanRequest networkScanRequest = new NetworkScanRequest( 412 SCAN_TYPE, 413 null /* Radio Access Specifier */, 414 SEARCH_PERIODICITY_SEC, 415 MAX_SEARCH_TIME_SEC, 416 INCREMENTAL_RESULTS, 417 INCREMENTAL_RESULTS_PERIODICITY_SEC, 418 getPlmns()); 419 420 Parcel p = Parcel.obtain(); 421 networkScanRequest.writeToParcel(p, 0); 422 p.setDataPosition(0); 423 NetworkScanRequest newnsr = NetworkScanRequest.CREATOR.createFromParcel(p); 424 assertTrue(networkScanRequest.equals(newnsr)); 425 426 } 427 } 428