/* * WiFiAnalyzer * Copyright (C) 2019 VREM Software Development <[email protected]> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> */ package com.vrem.wifianalyzer.wifi.scanner; import android.net.wifi.ScanResult; import android.net.wifi.WifiInfo; import com.vrem.wifianalyzer.MainContext; import org.apache.commons.collections4.Closure; import org.apache.commons.collections4.IterableUtils; import org.apache.commons.lang3.builder.CompareToBuilder; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Deque; import java.util.List; import androidx.annotation.NonNull; class Cache { private static final int ADJUST = 10; private final Deque<List<ScanResult>> cachedScanResults = new ArrayDeque<>(); private WifiInfo cachedWifiInfo = null; @NonNull List<CacheResult> getScanResults() { ScanResult current = null; int levelTotal = 0; int count = 0; List<CacheResult> results = new ArrayList<>(); for (ScanResult scanResult : combineCache()) { if (current != null && !scanResult.BSSID.equals(current.BSSID)) { CacheResult cacheResult = getCacheResult(current, levelTotal, count); results.add(cacheResult); count = 0; levelTotal = 0; } current = scanResult; count++; levelTotal += scanResult.level; } if (current != null) { results.add(getCacheResult(current, levelTotal, count)); } return results; } WifiInfo getWifiInfo() { return cachedWifiInfo; } @NonNull private CacheResult getCacheResult(@NonNull ScanResult current, int level, int count) { CacheResult cacheResult; if (isSizeAvailable()) { cacheResult = new CacheResult(current, level / count); } else { cacheResult = new CacheResult(current, (level - ADJUST) / count); } return cacheResult; } @NonNull private List<ScanResult> combineCache() { List<ScanResult> scanResults = new ArrayList<>(); IterableUtils.forEach(cachedScanResults, new CacheClosure(scanResults)); Collections.sort(scanResults, new ScanResultComparator()); return scanResults; } void add(@NonNull List<ScanResult> scanResults, WifiInfo wifiInfo) { int cacheSize = getCacheSize(); while (cachedScanResults.size() >= cacheSize) { cachedScanResults.pollLast(); } cachedScanResults.addFirst(scanResults); cachedWifiInfo = wifiInfo; } @NonNull List<ScanResult> getFirst() { return cachedScanResults.getFirst(); } @NonNull List<ScanResult> getLast() { return cachedScanResults.getLast(); } int getCacheSize() { if (isSizeAvailable()) { int scanSpeed = MainContext.INSTANCE.getSettings().getScanSpeed(); if (scanSpeed < 2) { return 4; } if (scanSpeed < 5) { return 3; } if (scanSpeed < 10) { return 2; } } return 1; } private boolean isSizeAvailable() { try { return MainContext.INSTANCE.getConfiguration().isSizeAvailable(); } catch (Exception e) { return false; } } private static class ScanResultComparator implements Comparator<ScanResult> { @Override public int compare(ScanResult lhs, ScanResult rhs) { return new CompareToBuilder() .append(lhs.BSSID, rhs.BSSID) .append(lhs.level, rhs.level) .toComparison(); } } private class CacheClosure implements Closure<List<ScanResult>> { private final List<ScanResult> scanResults; private CacheClosure(@NonNull List<ScanResult> scanResults) { this.scanResults = scanResults; } @Override public void execute(List<ScanResult> cachedScanResults) { scanResults.addAll(cachedScanResults); } } }