/** * Adds bandwidth to the current filtered latency counter. Sends a broadcast to all {@link * ConnectionClassStateChangeListener} if the counter moves from one bucket to another (i.e. poor * bandwidth -> moderate bandwidth). */ public synchronized void addBandwidth(long bytes, long timeInMs) { // Ignore garbage values. if (timeInMs == 0 || (bytes) * 1.0 / (timeInMs) * BYTES_TO_BITS < BANDWIDTH_LOWER_BOUND) { return; } double bandwidth = (bytes) * 1.0 / (timeInMs) * BYTES_TO_BITS; mDownloadBandwidth.addMeasurement(bandwidth); if (mInitiateStateChange) { mSampleCounter += 1; if (getCurrentBandwidthQuality() != mNextBandwidthConnectionQuality.get()) { mInitiateStateChange = false; mSampleCounter = 1; } if (mSampleCounter >= DEFAULT_SAMPLES_TO_QUALITY_CHANGE && significantlyOutsideCurrentBand()) { mInitiateStateChange = false; mSampleCounter = 1; mCurrentBandwidthConnectionQuality.set(mNextBandwidthConnectionQuality.get()); notifyListeners(); } return; } if (mCurrentBandwidthConnectionQuality.get() != getCurrentBandwidthQuality()) { mInitiateStateChange = true; mNextBandwidthConnectionQuality = new AtomicReference<ConnectionQuality>(getCurrentBandwidthQuality()); } }
private boolean significantlyOutsideCurrentBand() { if (mDownloadBandwidth == null) { // Make Infer happy. It wouldn't make any sense to call this while mDownloadBandwidth is null. return false; } ConnectionQuality currentQuality = mCurrentBandwidthConnectionQuality.get(); double bottomOfBand; double topOfBand; switch (currentQuality) { case POOR: bottomOfBand = 0; topOfBand = DEFAULT_POOR_BANDWIDTH; break; case MODERATE: bottomOfBand = DEFAULT_POOR_BANDWIDTH; topOfBand = DEFAULT_MODERATE_BANDWIDTH; break; case GOOD: bottomOfBand = DEFAULT_MODERATE_BANDWIDTH; topOfBand = DEFAULT_GOOD_BANDWIDTH; break; case EXCELLENT: bottomOfBand = DEFAULT_GOOD_BANDWIDTH; topOfBand = Float.MAX_VALUE; break; default: // If current quality is UNKNOWN, then changing is always valid. return true; } double average = mDownloadBandwidth.getAverage(); if (average > topOfBand) { if (average > topOfBand * HYSTERESIS_TOP_MULTIPLIER) { return true; } } else if (average < bottomOfBand * HYSTERESIS_BOTTOM_MULTIPLIER) { return true; } return false; }
/** * Accessor method for the current bandwidth average. * * @return The current bandwidth average, or -1 if no average has been recorded. */ public synchronized double getDownloadKBitsPerSecond() { return mDownloadBandwidth == null ? -1.0 : mDownloadBandwidth.getAverage(); }
/** * Get the ConnectionQuality that the moving bandwidth average currently represents. * * @return A ConnectionQuality representing the device's bandwidth at this exact moment. */ public synchronized ConnectionQuality getCurrentBandwidthQuality() { if (mDownloadBandwidth == null) { return ConnectionQuality.UNKNOWN; } return mapBandwidthQuality(mDownloadBandwidth.getAverage()); }
/** Resets the bandwidth average for this instance of the bandwidth manager. */ public void reset() { if (mDownloadBandwidth != null) { mDownloadBandwidth.reset(); } mCurrentBandwidthConnectionQuality.set(ConnectionQuality.UNKNOWN); }