Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d76e65be authored by Sundeep Ghuman's avatar Sundeep Ghuman
Browse files

Create and implement a CacheListener inside WifiNetworkScoreCache.

Bug: 33041117
Test: Unit tests
Change-Id: Ic07522062f79223079b84c49210fcfc0217ecd38
parent e2d85815
Loading
Loading
Loading
Loading
+91 −11
Original line number Diff line number Diff line
@@ -17,13 +17,19 @@
package android.net.wifi;

import android.Manifest.permission;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.Context;
import android.os.Handler;
import android.net.INetworkScoreCache;
import android.net.NetworkKey;
import android.net.ScoredNetwork;
import android.util.Log;

import com.android.internal.util.Preconditions;
import com.android.internal.annotations.GuardedBy;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.HashMap;
@@ -43,22 +49,41 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub {
    // We treat the lowest possible score as though there were no score, effectively allowing the
    // scorer to provide an RSSI threshold below which a network should not be used.
    public static final int INVALID_NETWORK_SCORE = Byte.MIN_VALUE;

    // See {@link #CacheListener}.
    @Nullable
    @GuardedBy("mCacheLock")
    private CacheListener mListener;

    private final Context mContext;
    private final Object mCacheLock = new Object();

    // The key is of the form "<ssid>"<bssid>
    // TODO: What about SSIDs that can't be encoded as UTF-8?
    private final Map<String, ScoredNetwork> mNetworkCache;


    public WifiNetworkScoreCache(Context context) {
        mContext = context;
        this(context, null /* listener */);
    }

    /**
     * Instantiates a WifiNetworkScoreCache.
     *
     * @param context Application context
     * @param listener CacheListener for cache updates
     */
    public WifiNetworkScoreCache(Context context, @Nullable CacheListener listener) {
        mContext = context.getApplicationContext();
        mListener = listener;
        mNetworkCache = new HashMap<String, ScoredNetwork>();
    }

    @Override public final void updateScores(List<ScoredNetwork> networks) {
      if (networks == null) {
        if (networks == null || networks.isEmpty()) {
           return;
        }
       Log.e(TAG, "updateScores list size=" + networks.size());
        Log.d(TAG, "updateScores list size=" + networks.size());

        synchronized(mNetworkCache) {
            for (ScoredNetwork network : networks) {
@@ -67,6 +92,12 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub {
                mNetworkCache.put(networkKey, network);
            }
        }

        synchronized (mCacheLock) {
            if (mListener != null) {
                mListener.post(networks);
            }
        }
    }

    @Override public final void clearScores() {
@@ -193,4 +224,53 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub {
        }
    }

    /** Registers a CacheListener instance, replacing the previous listener if it existed. */
    public void registerListener(CacheListener listener) {
        synchronized (mCacheLock) {
            mListener = listener;
        }
    }

    /** Removes the registered CacheListener. */
    public void unregisterListener() {
        synchronized (mCacheLock) {
            mListener = null;
        }
    }

    /** Listener for updates to the cache inside WifiNetworkScoreCache. */
    public abstract static class CacheListener {

        private Handler mHandler;

        /**
         * Constructor for CacheListener.
         *
         * @param handler the Handler on which to invoke the {@link #networkCacheUpdated} method.
         *          This cannot be null.
         */
        public CacheListener(@NonNull Handler handler) {
            Preconditions.checkNotNull(handler);
            mHandler = handler;
        }

        /** Invokes the {@link #networkCacheUpdated(List<ScoredNetwork>)} method on the handler. */
        void post(List<ScoredNetwork> updatedNetworks) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    networkCacheUpdated(updatedNetworks);
                }
            });
        }

        /**
         * Invoked whenever the cache is updated.
         *
         * <p>Clearing the cache does not invoke this method.
         *
         * @param updatedNetworks the networks that were updated
         */
        public abstract void networkCacheUpdated(List<ScoredNetwork> updatedNetworks);
    }
}
+160 −112
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
package android.net.wifi;

import static org.junit.Assert.*;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.Context;
@@ -24,6 +26,9 @@ import android.net.NetworkKey;
import android.net.RssiCurve;
import android.net.ScoredNetwork;
import android.net.WifiKey;
import android.net.wifi.WifiNetworkScoreCache.CacheListener;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;

@@ -33,17 +38,21 @@ import org.junit.Rule;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;


/** Unit tests for {@link WifiNetworkScoreCache}. */
@RunWith(AndroidJUnit4.class)
@SmallTest
public class WifiNetworkScoreCacheTest {

  @Mock public Context mockContext; // isn't used, can be null
  @Mock private RssiCurve mockRssiCurve;

    public static final String SSID = "ssid";
    public static final String FORMATTED_SSID = "\"" + SSID + "\"";
    public static final String BSSID = "AA:AA:AA:AA:AA:AA";
@@ -52,6 +61,15 @@ public class WifiNetworkScoreCacheTest {

    public static final ScanResult VALID_SCAN_RESULT = buildScanResult(SSID, BSSID);

    @Mock private Context mockApplicationContext;
    @Mock private Context mockContext; // isn't used, can be null
    @Mock private RssiCurve mockRssiCurve;


    private CacheListener mCacheListener;
    private CountDownLatch mLatch;
    private Handler mHandler;
    private List<ScoredNetwork> mUpdatedNetworksCaptor;
    private ScoredNetwork mValidScoredNetwork;
    private WifiNetworkScoreCache mScoreCache =
                new WifiNetworkScoreCache(mockContext);
@@ -80,9 +98,24 @@ public class WifiNetworkScoreCacheTest {
    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);

        when(mockContext.getApplicationContext()).thenReturn(mockApplicationContext);

        mValidScoredNetwork = buildScoredNetwork(VALID_KEY, mockRssiCurve);
        mScoreCache = new WifiNetworkScoreCache(mockContext);
        initializeCacheWithValidScoredNetwork();

        HandlerThread thread = new HandlerThread("WifiNetworkScoreCacheTest Handler Thread");
        thread.start();
        mHandler = new Handler(thread.getLooper());
        mLatch = new CountDownLatch(1);
        mCacheListener = new CacheListener(mHandler) {
            @Override
            public void networkCacheUpdated(List<ScoredNetwork> updatedNetworks) {
                mUpdatedNetworksCaptor = updatedNetworks;
                mLatch.countDown();
            }
        };
    }


@@ -148,9 +181,24 @@ public class WifiNetworkScoreCacheTest {
    @Test
    public void getMeteredHintShouldReturnTrue() {
        ScoredNetwork network =
        new ScoredNetwork(new NetworkKey(VALID_KEY), mockRssiCurve, true /* metered Hint */);
                new ScoredNetwork(
                    new NetworkKey(VALID_KEY), mockRssiCurve, true /* metered Hint */);
        mScoreCache.updateScores(ImmutableList.of(network));

        assertTrue(mScoreCache.getMeteredHint(VALID_SCAN_RESULT));
    }

    @Test
    public void updateScoresShouldInvokeCacheListener_networkCacheUpdated() {
        mScoreCache = new WifiNetworkScoreCache(mockContext, mCacheListener);
        initializeCacheWithValidScoredNetwork();

        try {
            mLatch.await(1, TimeUnit.SECONDS); // wait for listener to be executed
        } catch (InterruptedException e) {
            fail("Interrupted Exception while waiting for listener to be invoked.");
        }
        assertEquals("One network should be updated", 1, mUpdatedNetworksCaptor.size());
        assertEquals(mValidScoredNetwork, mUpdatedNetworksCaptor.get(0));
    }
}