/*
 * Copyright (C) 2018 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 android.carrierapi.cts;

import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;

import static org.junit.Assert.fail;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.os.Parcel;
import android.os.Process;
import android.os.UserHandle;
import android.telephony.AccessNetworkConstants;
import android.telephony.CellInfo;
import android.telephony.CellInfoGsm;
import android.telephony.CellInfoLte;
import android.telephony.CellInfoWcdma;
import android.telephony.NetworkScan;
import android.telephony.NetworkScanRequest;
import android.telephony.RadioAccessSpecifier;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyScanManager;
import android.util.Log;

import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Unit tests for {@link TelephonyManager}'s network scan APIs.
 *
 * <p>Test using `atest CtsCarrierApiTestCases:NetworkScanApiTest` or `make cts -j64 && cts-tradefed
 * run cts -m CtsCarrierApiTestCases --test android.carrierapi.cts.NetworkScanApiTest`
 */
@RunWith(AndroidJUnit4.class)
public class NetworkScanApiTest extends BaseCarrierApiTest {
    private static final String TAG = "NetworkScanApiTest";

    private TelephonyManager mTelephonyManager;
    private int mNetworkScanStatus;
    private static final int EVENT_NETWORK_SCAN_START = 100;
    private static final int EVENT_NETWORK_SCAN_RENOUNCE_START = 101;
    private static final int EVENT_NETWORK_SCAN_RESULTS = 200;
    private static final int EVENT_NETWORK_SCAN_RESTRICTED_RESULTS = 201;
    private static final int EVENT_NETWORK_SCAN_ERROR = 300;
    private static final int EVENT_NETWORK_SCAN_COMPLETED = 400;
    private static final int EVENT_SCAN_DENIED = 500;
    private List<CellInfo> mScanResults = null;
    private NetworkScanHandlerThread mTestHandlerThread;
    private Handler mHandler;
    private NetworkScan mNetworkScan;
    private NetworkScanRequest mNetworkScanRequest;
    private NetworkScanCallbackImpl mNetworkScanCallback;
    private static final int LOCATION_SETTING_CHANGE_WAIT_MS = 1000;
    private static final int MAX_CELLINFO_WAIT_MILLIS = 5000; // 5 seconds
    private static final int SCAN_SEARCH_TIME_SECONDS = 60;
    // Wait one second longer than the max scan search time to give the test time to receive the
    // results.
    private static final int MAX_INIT_WAIT_MS = (SCAN_SEARCH_TIME_SECONDS + 1) * 1000;
    private Object mLock = new Object();
    private boolean mReady;
    private int mErrorCode;
    /* All the following constants are used to construct NetworkScanRequest*/
    private static final int SCAN_TYPE = NetworkScanRequest.SCAN_TYPE_ONE_SHOT;
    private static final boolean INCREMENTAL_RESULTS = true;
    private static final int SEARCH_PERIODICITY_SEC = 5;
    private static final int MAX_SEARCH_TIME_SEC = 300;
    private static final int INCREMENTAL_RESULTS_PERIODICITY_SEC = 3;
    private static final ArrayList<String> MCC_MNC = new ArrayList<>();
    private static final RadioAccessSpecifier[] RADIO_ACCESS_SPECIFIERS = {
        new RadioAccessSpecifier(
                AccessNetworkConstants.AccessNetworkType.GERAN,
                null /* bands */,
                null /* channels */),
        new RadioAccessSpecifier(
                AccessNetworkConstants.AccessNetworkType.EUTRAN,
                null /* bands */,
                null /* channels */),
        new RadioAccessSpecifier(
                AccessNetworkConstants.AccessNetworkType.UTRAN,
                null /* bands */,
                null /* channels */)
    };

    // Needed because NETWORK_SCAN_PERMISSION is a systemapi
    public static final String NETWORK_SCAN_PERMISSION = "android.permission.NETWORK_SCAN";

    @Before
    public void setUp() throws Exception {
        mTelephonyManager = getContext().getSystemService(TelephonyManager.class);
        String selfPackageName = getContext().getPackageName();
        InstrumentationRegistry.getInstrumentation()
                .getUiAutomation()
                .grantRuntimePermission(selfPackageName, ACCESS_FINE_LOCATION);
        InstrumentationRegistry.getInstrumentation()
                .getUiAutomation()
                .grantRuntimePermission(selfPackageName, ACCESS_BACKGROUND_LOCATION);
        mTestHandlerThread = new NetworkScanHandlerThread(TAG);
        mTestHandlerThread.start();
    }

    @After
    public void tearDown() throws Exception {
        if (!werePreconditionsSatisfied()) return;

        // Revoking runtime permissions makes ActivityManager kill our process, so we don't do it,
        // as the test harness will eventually uninstall this APK after testing completes anyway, so
        // we aren't really leaking anything long-term.
        mTestHandlerThread.quit();
    }

    private void waitUntilReady() {
        synchronized (mLock) {
            try {
                mLock.wait(MAX_INIT_WAIT_MS);
            } catch (InterruptedException ie) {
            }

            assertWithMessage("NetworkScanApiTest failed to initialize").that(mReady).isTrue();
        }
    }

    private void setReady(boolean ready) {
        synchronized (mLock) {
            mReady = ready;
            mLock.notifyAll();
        }
    }

    private class NetworkScanHandlerThread extends HandlerThread {

        public NetworkScanHandlerThread(String name) {
            super(name);
        }

        @Override
        public void onLooperPrepared() {
            /* create a custom handler for the Handler Thread */
            mHandler =
                    new Handler(mTestHandlerThread.getLooper()) {
                        @Override
                        public void handleMessage(Message msg) {
                            switch (msg.what) {
                                case EVENT_NETWORK_SCAN_START: {
                                    Log.d(TAG, "request network scan");
                                    boolean useShellIdentity = (Boolean) msg.obj;
                                    if (useShellIdentity) {
                                        InstrumentationRegistry.getInstrumentation()
                                                .getUiAutomation()
                                                .adoptShellPermissionIdentity();
                                    }
                                    try {
                                        mNetworkScan =
                                                mTelephonyManager.requestNetworkScan(
                                                        mNetworkScanRequest,
                                                        AsyncTask.SERIAL_EXECUTOR,
                                                        mNetworkScanCallback);
                                        if (mNetworkScan == null) {
                                            mNetworkScanStatus = EVENT_SCAN_DENIED;
                                            setReady(true);
                                        }
                                    } catch (SecurityException e) {
                                        mNetworkScanStatus = EVENT_SCAN_DENIED;
                                        setReady(true);
                                    } finally {
                                        if (useShellIdentity) {
                                            InstrumentationRegistry.getInstrumentation()
                                                    .getUiAutomation()
                                                    .dropShellPermissionIdentity();
                                        }
                                    }
                                    break;
                                }
                                case EVENT_NETWORK_SCAN_RENOUNCE_START: {
                                    Log.d(TAG, "request network scan with renounce");
                                    boolean useShellIdentity = (Boolean) msg.obj;
                                    if (useShellIdentity) {
                                        InstrumentationRegistry.getInstrumentation()
                                                .getUiAutomation()
                                                .adoptShellPermissionIdentity();
                                    }
                                    try {
                                        mNetworkScan = mTelephonyManager.requestNetworkScan(
                                                TelephonyManager.INCLUDE_LOCATION_DATA_NONE,
                                                mNetworkScanRequest,
                                                AsyncTask.SERIAL_EXECUTOR,
                                                mNetworkScanCallback);
                                        if (mNetworkScan == null) {
                                            mNetworkScanStatus = EVENT_SCAN_DENIED;
                                            setReady(true);
                                        }
                                    } catch (SecurityException e) {
                                        mNetworkScanStatus = EVENT_SCAN_DENIED;
                                        setReady(true);
                                    } finally {
                                        if (useShellIdentity) {
                                            InstrumentationRegistry.getInstrumentation()
                                                    .getUiAutomation()
                                                    .dropShellPermissionIdentity();
                                        }
                                    }
                                    break;
                                }
                                default:
                                    Log.d(TAG, "Unknown Event " + msg.what);
                            }
                        }
                    };
        }
    }

    private class NetworkScanCallbackImpl extends TelephonyScanManager.NetworkScanCallback {
        @Override
        public void onResults(List<CellInfo> results) {
            Log.d(TAG, "onResults: " + results.toString());
            mNetworkScanStatus = EVENT_NETWORK_SCAN_RESULTS;
            mScanResults = results;
        }

        @Override
        public void onComplete() {
            Log.d(TAG, "onComplete");
            mNetworkScanStatus = EVENT_NETWORK_SCAN_COMPLETED;
            setReady(true);
        }

        @Override
        public void onError(int error) {
            Log.d(TAG, "onError: " + String.valueOf(error));
            mNetworkScanStatus = EVENT_NETWORK_SCAN_ERROR;
            mErrorCode = error;
            setReady(true);
        }
    }

    private class CellInfoResultsCallback extends TelephonyManager.CellInfoCallback {
        public List<CellInfo> cellInfo;

        @Override
        public synchronized void onCellInfo(List<CellInfo> cellInfo) {
            this.cellInfo = cellInfo;
            notifyAll();
        }

        public synchronized void wait(int millis) throws InterruptedException {
            if (cellInfo == null) {
                super.wait(millis);
            }
        }
    }

    private List<RadioAccessSpecifier> getRadioAccessSpecifier(List<CellInfo> allCellInfo) {
        List<RadioAccessSpecifier> radioAccessSpecifier = new ArrayList<>();
        List<Integer> lteChannels = new ArrayList<>();
        List<Integer> wcdmaChannels = new ArrayList<>();
        List<Integer> gsmChannels = new ArrayList<>();
        for (int i = 0; i < allCellInfo.size(); i++) {
            CellInfo cellInfo = allCellInfo.get(i);
            if (cellInfo instanceof CellInfoLte) {
                lteChannels.add(((CellInfoLte) cellInfo).getCellIdentity().getEarfcn());
            } else if (cellInfo instanceof CellInfoWcdma) {
                wcdmaChannels.add(((CellInfoWcdma) cellInfo).getCellIdentity().getUarfcn());
            } else if (cellInfo instanceof CellInfoGsm) {
                gsmChannels.add(((CellInfoGsm) cellInfo).getCellIdentity().getArfcn());
            }
        }
        if (!lteChannels.isEmpty()) {
            Log.d(TAG, "lte channels" + lteChannels.toString());
            int ranLte = AccessNetworkConstants.AccessNetworkType.EUTRAN;
            radioAccessSpecifier.add(
                    new RadioAccessSpecifier(
                            ranLte,
                            null /* bands */,
                            lteChannels.stream().mapToInt(i -> i).toArray()));
        }
        if (!wcdmaChannels.isEmpty()) {
            Log.d(TAG, "wcdma channels" + wcdmaChannels.toString());
            int ranWcdma = AccessNetworkConstants.AccessNetworkType.UTRAN;
            radioAccessSpecifier.add(
                    new RadioAccessSpecifier(
                            ranWcdma,
                            null /* bands */,
                            wcdmaChannels.stream().mapToInt(i -> i).toArray()));
        }
        if (!gsmChannels.isEmpty()) {
            Log.d(TAG, "gsm channels" + gsmChannels.toString());
            int ranGsm = AccessNetworkConstants.AccessNetworkType.GERAN;
            radioAccessSpecifier.add(
                    new RadioAccessSpecifier(
                            ranGsm,
                            null /* bands */,
                            gsmChannels.stream().mapToInt(i -> i).toArray()));
        }
        return radioAccessSpecifier;
    }

    /** Tests that the device properly requests a network scan. */
    @Test
    public void testRequestNetworkScan() {
        boolean isLocationSwitchOn = getAndSetLocationSwitch(true);
        try {
            mNetworkScanRequest = buildNetworkScanRequest(true);
            mNetworkScanCallback = new NetworkScanCallbackImpl();
            Message startNetworkScan = mHandler.obtainMessage(EVENT_NETWORK_SCAN_START, false);
            setReady(false);
            startNetworkScan.sendToTarget();
            waitUntilReady();

            Log.d(TAG, "mNetworkScanStatus: " + mNetworkScanStatus);
            assertWithMessage(
                            "The final scan status is "
                                    + mNetworkScanStatus
                                    + " with error code "
                                    + mErrorCode
                                    + ", not ScanCompleted"
                                    + " or ScanError with an error code ERROR_MODEM_UNAVAILABLE or"
                                    + " ERROR_UNSUPPORTED")
                    .that(isScanStatusValid())
                    .isTrue();
        } finally {
            getAndSetLocationSwitch(isLocationSwitchOn);
        }
    }

    /** Tests that the device properly requests a network scan. */
    @Test
    public void testRequestNetworkScanWithRenounce() {
        boolean isLocationSwitchOn = getAndSetLocationSwitch(true);
        try {
            mNetworkScanRequest = buildNetworkScanRequest(true);
            mNetworkScanCallback = new NetworkScanCallbackImpl();
            Message startNetworkScan = mHandler.obtainMessage(EVENT_NETWORK_SCAN_RENOUNCE_START,
                    false);
            setReady(false);
            startNetworkScan.sendToTarget();
            waitUntilReady();

            Log.d(TAG, "mNetworkScanStatus: " + mNetworkScanStatus);
            assertWithMessage(
                    "The final scan status is "
                            + mNetworkScanStatus
                            + " with error code "
                            + mErrorCode
                            + ", not ScanCompleted"
                            + " or ScanError with an error code ERROR_MODEM_UNAVAILABLE or"
                            + " ERROR_UNSUPPORTED")
                    .that(mNetworkScanStatus)
                    .isEqualTo(EVENT_SCAN_DENIED);
        } finally {
            getAndSetLocationSwitch(isLocationSwitchOn);
        }
    }

    @Test
    public void testRequestNetworkScanLocationOffPass() {
        requestNetworkScanLocationOffHelper(false, true);
    }

    @Test
    public void testRequestNetworkScanLocationOffFail() {
        requestNetworkScanLocationOffHelper(true, true);
    }

    public void requestNetworkScanLocationOffHelper(
            boolean includeBandsAndChannels, boolean useSpecialScanPermission) {
        mNetworkScanRequest = buildNetworkScanRequest(includeBandsAndChannels);

        boolean isLocationSwitchOn = getAndSetLocationSwitch(false);
        try {
            mNetworkScanCallback = new NetworkScanCallbackImpl();
            Message startNetworkScan =
                    mHandler.obtainMessage(EVENT_NETWORK_SCAN_START, useSpecialScanPermission);
            setReady(false);
            startNetworkScan.sendToTarget();
            waitUntilReady();
            if (includeBandsAndChannels) {
                // If we included the bands when location is off, expect a security error and
                // nothing else.
                assertThat(mNetworkScanStatus).isEqualTo(EVENT_SCAN_DENIED);
                return;
            }

            Log.d(TAG, "mNetworkScanStatus: " + mNetworkScanStatus);
            assertWithMessage(
                            "The final scan status is "
                                    + mNetworkScanStatus
                                    + " with error code "
                                    + mErrorCode
                                    + ", not ScanCompleted"
                                    + " or ScanError with an error code ERROR_MODEM_UNAVAILABLE or"
                                    + " ERROR_UNSUPPORTED")
                    .that(isScanStatusValid())
                    .isTrue();
        } finally {
            getAndSetLocationSwitch(isLocationSwitchOn);
        }
    }

    private NetworkScanRequest buildNetworkScanRequest(boolean includeBandsAndChannels) {
        // Make sure that there should be at least one entry.
        List<CellInfo> allCellInfo = getCellInfo();
        List<RadioAccessSpecifier> radioAccessSpecifier = new ArrayList<>();

        if (allCellInfo != null && allCellInfo.size() != 0) {
            // Construct a NetworkScanRequest
            radioAccessSpecifier = getRadioAccessSpecifier(allCellInfo);
            if (!includeBandsAndChannels) {
                radioAccessSpecifier =
                        radioAccessSpecifier.stream()
                                .map(
                                        spec ->
                                                new RadioAccessSpecifier(
                                                        spec.getRadioAccessNetwork(), null, null))
                                .collect(Collectors.toList());
            }
        }

        Log.d(TAG, "number of radioAccessSpecifier: " + radioAccessSpecifier.size());
        if (radioAccessSpecifier.isEmpty()) {
            // Put in some arbitrary bands and channels so that we trip the location check if needed
            int[] fakeBands =
                    includeBandsAndChannels
                            ? new int[] {AccessNetworkConstants.EutranBand.BAND_5}
                            : null;
            int[] fakeChannels = includeBandsAndChannels ? new int[] {2400} : null;

            RadioAccessSpecifier gsm =
                    new RadioAccessSpecifier(
                            AccessNetworkConstants.AccessNetworkType.GERAN,
                            null /* bands */,
                            null /* channels */);
            RadioAccessSpecifier lte =
                    new RadioAccessSpecifier(
                            AccessNetworkConstants.AccessNetworkType.EUTRAN,
                            fakeBands /* bands */,
                            fakeChannels /* channels */);
            RadioAccessSpecifier wcdma =
                    new RadioAccessSpecifier(
                            AccessNetworkConstants.AccessNetworkType.UTRAN,
                            null /* bands */,
                            null /* channels */);
            radioAccessSpecifier.add(gsm);
            radioAccessSpecifier.add(lte);
            radioAccessSpecifier.add(wcdma);
        }
        RadioAccessSpecifier[] radioAccessSpecifierArray =
                new RadioAccessSpecifier[radioAccessSpecifier.size()];
        return new NetworkScanRequest(
                NetworkScanRequest.SCAN_TYPE_ONE_SHOT /* scan type */,
                radioAccessSpecifier.toArray(radioAccessSpecifierArray),
                5 /* search periodicity */,
                SCAN_SEARCH_TIME_SECONDS /* max search time */,
                true /*enable incremental results*/,
                5 /* incremental results periodicity */,
                null /* List of PLMN ids (MCC-MNC) */);
    }

    private List<CellInfo> getCellInfo() {
        CellInfoResultsCallback resultsCallback = new CellInfoResultsCallback();
        mTelephonyManager.requestCellInfoUpdate(r -> r.run(), resultsCallback);
        try {
            resultsCallback.wait(MAX_CELLINFO_WAIT_MILLIS);
        } catch (InterruptedException ex) {
            fail("CellInfoCallback was interrupted: " + ex);
        }
        return resultsCallback.cellInfo;
    }

    @Test
    public void testNetworkScanPermission() {
        PackageManager pm = getContext().getPackageManager();

        List<Integer> specialUids =
                Arrays.asList(Process.SYSTEM_UID, Process.PHONE_UID, Process.SHELL_UID);

        List<PackageInfo> holding =
                pm.getPackagesHoldingPermissions(
                        new String[] {NETWORK_SCAN_PERMISSION},
                        PackageManager.MATCH_DISABLED_COMPONENTS);

        List<Integer> nonSpecialPackages =
                holding.stream()
                        .map(
                                pi -> {
                                    try {
                                        return pm.getPackageUid(pi.packageName, 0);
                                    } catch (PackageManager.NameNotFoundException e) {
                                        return Process.INVALID_UID;
                                    }
                                })
                        .filter(uid -> !specialUids.contains(UserHandle.getAppId(uid)))
                        .collect(Collectors.toList());

        assertWithMessage(
                        "Only one app on the device is allowed to hold the NETWORK_SCAN"
                                + " permission.")
                .that(nonSpecialPackages.size())
                .isAtMost(1);
    }

    private boolean getAndSetLocationSwitch(boolean enabled) {
        CountDownLatch locationChangeLatch = new CountDownLatch(1);
        BroadcastReceiver locationModeChangeReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (LocationManager.MODE_CHANGED_ACTION.equals(intent.getAction())
                        && intent.getBooleanExtra(LocationManager.EXTRA_LOCATION_ENABLED, !enabled)
                        == enabled) {
                    locationChangeLatch.countDown();
                }
            }
        };

        InstrumentationRegistry.getInstrumentation().getUiAutomation()
                .adoptShellPermissionIdentity();
        try {
            Context context = InstrumentationRegistry.getContext();
            LocationManager lm = context.getSystemService(
                    LocationManager.class);
            boolean oldLocationOn = lm.isLocationEnabledForUser(
                    UserHandle.of(UserHandle.myUserId()));

            if (enabled != oldLocationOn) {
                context.registerReceiver(locationModeChangeReceiver,
                        new IntentFilter(LocationManager.MODE_CHANGED_ACTION));
                lm.setLocationEnabledForUser(enabled, UserHandle.of(UserHandle.myUserId()));
                try {
                    assertThat(locationChangeLatch.await(LOCATION_SETTING_CHANGE_WAIT_MS,
                            TimeUnit.MILLISECONDS)).isTrue();
                } catch (InterruptedException e) {
                    Log.w(NetworkScanApiTest.class.getSimpleName(),
                            "Interrupted while waiting for location settings change. Test results"
                                    + " may not be accurate.");
                } finally {
                    context.unregisterReceiver(locationModeChangeReceiver);
                }
            }
            return oldLocationOn;
        } finally {
            InstrumentationRegistry.getInstrumentation().getUiAutomation()
                    .dropShellPermissionIdentity();
        }
    }

    private boolean isScanStatusValid() {
        // TODO(b/72162885): test the size of ScanResults is not zero after the blocking bug fixed.
        if ((mNetworkScanStatus == EVENT_NETWORK_SCAN_COMPLETED) && (mScanResults != null)) {
            // Scan complete.
            return true;
        }
        if ((mNetworkScanStatus == EVENT_NETWORK_SCAN_ERROR)
                && ((mErrorCode == NetworkScan.ERROR_MODEM_UNAVAILABLE)
                        || (mErrorCode == NetworkScan.ERROR_UNSUPPORTED))) {
            // Scan error but the error type is allowed.
            return true;
        }
        return false;
    }

    private ArrayList<String> getPlmns() {
        ArrayList<String> mccMncs = new ArrayList<>();
        mccMncs.add("310260");
        mccMncs.add("310120");
        return mccMncs;
    }

    /** To test its constructor and getters. */
    @Test
    public void testNetworkScanRequest_constructorAndGetters() {
        NetworkScanRequest networkScanRequest =
                new NetworkScanRequest(
                        SCAN_TYPE,
                        RADIO_ACCESS_SPECIFIERS,
                        SEARCH_PERIODICITY_SEC,
                        MAX_SEARCH_TIME_SEC,
                        INCREMENTAL_RESULTS,
                        INCREMENTAL_RESULTS_PERIODICITY_SEC,
                        getPlmns());

        assertWithMessage("getScanType() returns wrong value")
                .that(networkScanRequest.getScanType())
                .isEqualTo(SCAN_TYPE);
        assertWithMessage("getSpecifiers() returns wrong value")
                .that(networkScanRequest.getSpecifiers())
                .isEqualTo(RADIO_ACCESS_SPECIFIERS);
        assertWithMessage("getSearchPeriodicity() returns wrong value")
                .that(networkScanRequest.getSearchPeriodicity())
                .isEqualTo(SEARCH_PERIODICITY_SEC);
        assertWithMessage("getMaxSearchTime() returns wrong value")
                .that(networkScanRequest.getMaxSearchTime())
                .isEqualTo(MAX_SEARCH_TIME_SEC);
        assertWithMessage("getIncrementalResults() returns wrong value")
                .that(networkScanRequest.getIncrementalResults())
                .isEqualTo(INCREMENTAL_RESULTS);
        assertWithMessage("getIncrementalResultsPeriodicity() returns wrong value")
                .that(networkScanRequest.getIncrementalResultsPeriodicity())
                .isEqualTo(INCREMENTAL_RESULTS_PERIODICITY_SEC);
        assertWithMessage("getPlmns() returns wrong value")
                .that(networkScanRequest.getPlmns())
                .isEqualTo(getPlmns());
        assertWithMessage("describeContents() returns wrong value")
                .that(networkScanRequest.describeContents())
                .isEqualTo(0);
    }

    /** To test its hashCode method. */
    @Test
    public void testNetworkScanRequestParcel_hashCode() {
        NetworkScanRequest networkScanRequest1 =
                new NetworkScanRequest(
                        SCAN_TYPE,
                        RADIO_ACCESS_SPECIFIERS,
                        SEARCH_PERIODICITY_SEC,
                        MAX_SEARCH_TIME_SEC,
                        INCREMENTAL_RESULTS,
                        INCREMENTAL_RESULTS_PERIODICITY_SEC,
                        getPlmns());

        NetworkScanRequest networkScanRequest2 =
                new NetworkScanRequest(
                        SCAN_TYPE,
                        RADIO_ACCESS_SPECIFIERS,
                        SEARCH_PERIODICITY_SEC,
                        MAX_SEARCH_TIME_SEC,
                        INCREMENTAL_RESULTS,
                        INCREMENTAL_RESULTS_PERIODICITY_SEC,
                        getPlmns());

        NetworkScanRequest networkScanRequest3 =
                new NetworkScanRequest(
                        SCAN_TYPE,
                        null,
                        SEARCH_PERIODICITY_SEC,
                        MAX_SEARCH_TIME_SEC,
                        false,
                        0,
                        getPlmns());

        assertWithMessage("hashCode() returns different hash code for same objects")
                .that(networkScanRequest1.hashCode())
                .isEqualTo(networkScanRequest2.hashCode());
        assertWithMessage("hashCode() returns same hash code for different objects")
                .that(networkScanRequest1.hashCode())
                .isNotEqualTo(networkScanRequest3.hashCode());
    }

    /** To test its comparison method. */
    @Test
    public void testNetworkScanRequestParcel_equals() {
        NetworkScanRequest networkScanRequest1 =
                new NetworkScanRequest(
                        SCAN_TYPE,
                        RADIO_ACCESS_SPECIFIERS,
                        SEARCH_PERIODICITY_SEC,
                        MAX_SEARCH_TIME_SEC,
                        INCREMENTAL_RESULTS,
                        INCREMENTAL_RESULTS_PERIODICITY_SEC,
                        getPlmns());

        NetworkScanRequest networkScanRequest2 =
                new NetworkScanRequest(
                        SCAN_TYPE,
                        RADIO_ACCESS_SPECIFIERS,
                        SEARCH_PERIODICITY_SEC,
                        MAX_SEARCH_TIME_SEC,
                        INCREMENTAL_RESULTS,
                        INCREMENTAL_RESULTS_PERIODICITY_SEC,
                        getPlmns());

        assertThat(networkScanRequest1).isEqualTo(networkScanRequest2);

        networkScanRequest2 =
                new NetworkScanRequest(
                        SCAN_TYPE,
                        RADIO_ACCESS_SPECIFIERS,
                        SEARCH_PERIODICITY_SEC,
                        MAX_SEARCH_TIME_SEC,
                        INCREMENTAL_RESULTS,
                        INCREMENTAL_RESULTS_PERIODICITY_SEC,
                        null /* List of PLMN ids (MCC-MNC) */);
        assertThat(networkScanRequest1).isNotEqualTo(networkScanRequest2);
    }

    /** To test its writeToParcel and createFromParcel methods. */
    @Test
    public void testNetworkScanRequestParcel_parcel() {
        NetworkScanRequest networkScanRequest =
                new NetworkScanRequest(
                        SCAN_TYPE,
                        null /* Radio Access Specifier */,
                        SEARCH_PERIODICITY_SEC,
                        MAX_SEARCH_TIME_SEC,
                        INCREMENTAL_RESULTS,
                        INCREMENTAL_RESULTS_PERIODICITY_SEC,
                        getPlmns());

        Parcel p = Parcel.obtain();
        networkScanRequest.writeToParcel(p, 0);
        p.setDataPosition(0);
        NetworkScanRequest newnsr = NetworkScanRequest.CREATOR.createFromParcel(p);
        assertThat(networkScanRequest).isEqualTo(newnsr);
    }
}
