/*
 * Copyright 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 com.android.server.wifi;

import static android.net.wifi.WifiManager.EXTRA_SCAN_AVAILABLE;
import static android.net.wifi.WifiManager.WIFI_SCAN_AVAILABLE;
import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;

import android.content.Context;
import android.content.Intent;
import android.os.UserHandle;
import android.os.test.TestLooper;
import android.support.test.filters.SmallTest;

import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.List;

/**
 * Unit tests for {@link ScanOnlyModeManager}.
 */
@SmallTest
public class ScanOnlyModeManagerTest {
    private static final String TAG = "ScanOnlyModeManagerTest";
    private static final String TEST_INTERFACE_NAME = "testif0";
    private static final String OTHER_INTERFACE_NAME = "notTestIf";

    TestLooper mLooper;

    ScanOnlyModeManager mScanOnlyModeManager;

    @Mock Context mContext;
    @Mock WifiMetrics mWifiMetrics;
    @Mock WifiNative mWifiNative;
    @Mock ScanOnlyModeManager.Listener mListener;
    @Mock WifiMonitor mWifiMonitor;
    @Mock ScanRequestProxy mScanRequestProxy;
    @Mock WakeupController mWakeupController;
    @Mock SarManager mSarManager;

    final ArgumentCaptor<WifiNative.InterfaceCallback> mInterfaceCallbackCaptor =
            ArgumentCaptor.forClass(WifiNative.InterfaceCallback.class);

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mLooper = new TestLooper();

        mScanOnlyModeManager = createScanOnlyModeManager();
        mLooper.dispatchAll();
    }

    private ScanOnlyModeManager createScanOnlyModeManager() {
        return new ScanOnlyModeManager(mContext, mLooper.getLooper(), mWifiNative, mListener,
                mWifiMetrics, mScanRequestProxy, mWakeupController, mSarManager);
    }

    private void startScanOnlyModeAndVerifyEnabled() throws Exception {
        when(mWifiNative.setupInterfaceForClientMode(anyBoolean(), any())).thenReturn(
                TEST_INTERFACE_NAME);
        mScanOnlyModeManager.start();
        mLooper.dispatchAll();

        verify(mWifiNative).setupInterfaceForClientMode(eq(true),
                mInterfaceCallbackCaptor.capture());

        // now mark the interface as up
        mInterfaceCallbackCaptor.getValue().onUp(TEST_INTERFACE_NAME);
        mLooper.dispatchAll();

        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
        verify(mContext, times(2)).sendStickyBroadcastAsUser(intentCaptor.capture(),
                eq(UserHandle.ALL));
        List<Intent> intents = intentCaptor.getAllValues();

        checkWifiScanStateChangedBroadcast(intents.get(0), WIFI_STATE_DISABLED);
        checkWifiScanStateChangedBroadcast(intents.get(1), WIFI_STATE_ENABLED);
        checkWifiStateChangeListenerUpdate(WIFI_STATE_ENABLED);
        verify(mScanRequestProxy, atLeastOnce()).clearScanResults();
        verify(mScanRequestProxy, atLeastOnce()).enableScanningForHiddenNetworks(false);
        verify(mSarManager).setScanOnlyWifiState(eq(WIFI_STATE_ENABLED));
    }

    private void checkWifiScanStateChangedBroadcast(Intent intent, int expectedCurrentState) {
        String action = intent.getAction();
        assertEquals(WIFI_SCAN_AVAILABLE, action);
        int currentState = intent.getIntExtra(EXTRA_SCAN_AVAILABLE, WIFI_STATE_UNKNOWN);
        assertEquals(expectedCurrentState, currentState);
    }

    private void checkWifiStateChangeListenerUpdate(int expectedCurrentState) {
        verify(mListener).onStateChanged(eq(expectedCurrentState));
    }

    /**
     * ScanMode start sets up an interface in ClientMode for scanning.
     */
    @Test
    public void scanModeStartAndVerifyEnabled() throws Exception {
        startScanOnlyModeAndVerifyEnabled();
    }

    /**
     * ScanMode start does not indicate scanning is available when the interface name is empty.
     */
    @Test
    public void scanModeStartDoesNotSendScanningActiveWhenClientInterfaceNameIsEmpty()
            throws Exception {
        when(mWifiNative.setupInterfaceForClientMode(anyBoolean(), any())).thenReturn("");
        mScanOnlyModeManager.start();
        mLooper.dispatchAll();

        verify(mContext, never()).sendStickyBroadcastAsUser(any(), eq(UserHandle.ALL));
        checkWifiStateChangeListenerUpdate(WIFI_STATE_UNKNOWN);
    }

    /**
     * Calling ScanOnlyModeManager.start twice does not crash or restart scan mode.
     */
    @Test
    public void scanOnlyModeStartCalledTwice() throws Exception {
        startScanOnlyModeAndVerifyEnabled();
        reset(mWifiNative, mContext);
        mScanOnlyModeManager.start();
        mLooper.dispatchAll();
        verifyNoMoreInteractions(mWifiNative, mContext);
    }

    /**
     * ScanMode stop properly cleans up state
     */
    @Test
    public void scanModeStopCleansUpState() throws Exception {
        startScanOnlyModeAndVerifyEnabled();
        reset(mContext, mListener);
        mScanOnlyModeManager.stop();
        mLooper.dispatchAll();
        verify(mWifiNative).teardownInterface(TEST_INTERFACE_NAME);
        verify(mContext, never()).sendStickyBroadcastAsUser(any(), eq(UserHandle.ALL));
        verify(mSarManager).setScanOnlyWifiState(eq(WIFI_STATE_DISABLED));
        verifyNoMoreInteractions(mListener);
    }

    /**
     * ScanMode properly stops when underlying interface is destroyed.
     */
    @Test
    public void scanModeStopsOnInterfaceDestroyed() throws Exception {
        startScanOnlyModeAndVerifyEnabled();
        reset(mContext);
        mInterfaceCallbackCaptor.getValue().onDestroyed(TEST_INTERFACE_NAME);
        mLooper.dispatchAll();
        verify(mContext, never()).sendStickyBroadcastAsUser(any(), eq(UserHandle.ALL));
    }

    /**
     * Calling stop when ScanMode is not started should not send scan state updates
     */
    @Test
    public void scanModeStopWhenNotStartedDoesNotUpdateScanStateUpdates() throws Exception {
        startScanOnlyModeAndVerifyEnabled();
        mScanOnlyModeManager.stop();
        mLooper.dispatchAll();
        reset(mContext, mListener);

        // now call stop again
        mScanOnlyModeManager.stop();
        mLooper.dispatchAll();
        verify(mContext, never()).sendStickyBroadcastAsUser(any(), any());
        verify(mListener, never()).onStateChanged(anyInt());
    }

    /**
     * Triggering interface down when ScanOnlyMode is active properly exits the active state and
     * reports an error.
     */
    @Test
    public void scanModeStartedStopsWhenInterfaceDown() throws Exception {
        startScanOnlyModeAndVerifyEnabled();
        reset(mContext);
        mInterfaceCallbackCaptor.getValue().onDown(TEST_INTERFACE_NAME);
        mLooper.dispatchAll();
        verify(mContext, never()).sendStickyBroadcastAsUser(any(), eq(UserHandle.ALL));
        checkWifiStateChangeListenerUpdate(WIFI_STATE_UNKNOWN);
        verify(mScanRequestProxy).clearScanResults();
    }

    /**
     * Triggering an interface down for a different interface will not exit scan mode.
     */
    @Test
    public void scanModeStartedDoesNotStopOnDownForDifferentIface() throws Exception {
        startScanOnlyModeAndVerifyEnabled();
        reset(mContext, mListener, mScanRequestProxy);
        mInterfaceCallbackCaptor.getValue().onDown(OTHER_INTERFACE_NAME);

        mLooper.dispatchAll();

        verifyNoMoreInteractions(mContext, mListener);

        verify(mScanRequestProxy, never()).clearScanResults();
    }

    /**
     * Verify that onDestroyed after scan mode is stopped doesn't trigger a callback.
     */
    @Test
    public void noCallbackOnInterfaceDestroyedWhenAlreadyStopped() throws Exception {
        startScanOnlyModeAndVerifyEnabled();

        reset(mListener);

        mScanOnlyModeManager.stop();
        mLooper.dispatchAll();

        // now trigger interface destroyed and make sure callback doesn't get called
        mInterfaceCallbackCaptor.getValue().onDestroyed(TEST_INTERFACE_NAME);
        mLooper.dispatchAll();

        verifyNoMoreInteractions(mListener);
    }

    /**
     * Entering StartedState starts the WakeupController.
     */
    @Test
    public void scanModeEnterStartsWakeupController() throws Exception {
        startScanOnlyModeAndVerifyEnabled();

        verify(mWakeupController).start();
    }

    /**
     * Exiting StartedState stops the WakeupController.
     */
    @Test
    public void scanModeExitStopsWakeupController() throws Exception {
        startScanOnlyModeAndVerifyEnabled();

        mScanOnlyModeManager.stop();
        mLooper.dispatchAll();

        InOrder inOrder = inOrder(mWakeupController, mWifiNative, mListener);

        inOrder.verify(mWakeupController).start();
        inOrder.verify(mWakeupController).stop();
        inOrder.verify(mWifiNative).teardownInterface(eq(TEST_INTERFACE_NAME));
    }
}
