Android O WiFi对应用前后台扫描的限制

流程梳理

  • ScanRequestProxy

    // Check and throttle scan request unless,
    // a) App has either NETWORK_SETTINGS or NETWORK_SETUP_WIZARD permission.
    // b) Throttling has been disabled by user.
    if (!fromSettingsOrSetupWizard && mThrottleEnabledSettingObserver.isEnabled()
        && shouldScanRequestBeThrottledForApp(callingUid, packageName)) {
        Log.i(TAG, "Scan request from " + packageName + " throttled");
        sendScanResultFailureBroadcastToPackage(packageName);
        return false;
    }
}

/**
 * Checks if the scan request from the app (specified by callingUid & packageName) needs
 * to be throttled.
 */
private boolean shouldScanRequestBeThrottledForApp(int callingUid, String packageName) {
    boolean isThrottled;
    if (isRequestFromBackground(callingUid, packageName)) {
        isThrottled = shouldScanRequestBeThrottledForBackgroundApp();
        if (isThrottled) {
            if (mVerboseLoggingEnabled) {
                Log.v(TAG, "Background scan app request [" + callingUid + ", "
                        + packageName + "]");
            }
            mWifiMetrics.incrementExternalBackgroundAppOneshotScanRequestsThrottledCount();
        }
    } else {
        isThrottled = shouldScanRequestBeThrottledForForegroundApp(callingUid, packageName);
        if (isThrottled) {
            if (mVerboseLoggingEnabled) {
                Log.v(TAG, "Foreground scan app request [" + callingUid + ", "
                        + packageName + "]");
            }
            mWifiMetrics.incrementExternalForegroundAppOneshotScanRequestsThrottledCount();
        }
    }
    mWifiMetrics.incrementExternalAppOneshotScanRequestsCount();
    return isThrottled;
}

后台扫描限制

/**
 * Checks if the scan request from a background app needs to be throttled.
 */
private boolean shouldScanRequestBeThrottledForBackgroundApp() {
    long lastScanMs = mLastScanTimestampForBgApps;
    long elapsedRealtime = mClock.getElapsedSinceBootMillis();
    if (lastScanMs != 0
            && (elapsedRealtime - lastScanMs) < SCAN_REQUEST_THROTTLE_INTERVAL_BG_APPS_MS) {
        return true;
    }
    // Proceed with the scan request and record the time.
    mLastScanTimestampForBgApps = elapsedRealtime;
    return false;
}

public static final int SCAN_REQUEST_THROTTLE_INTERVAL_BG_APPS_MS = 30 * 60 * 1000;

也就是说所有后台应用30min内只能发起一次扫描

前台扫描限制

/**
 * Checks if the scan request from the app (specified by packageName) needs
 * to be throttled.
 * The throttle limit allows a max of {@link #SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS}
 * in {@link #SCAN_REQUEST_THROTTLE_TIME_WINDOW_FG_APPS_MS} window.
 */
private boolean shouldScanRequestBeThrottledForForegroundApp(
        int callingUid, String packageName) {
    LinkedList<Long> scanRequestTimestamps =
            getOrCreateScanRequestTimestampsForForegroundApp(callingUid, packageName);
    long currentTimeMillis = mClock.getElapsedSinceBootMillis();
    // First evict old entries from the list.
    trimPastScanRequestTimesForForegroundApp(scanRequestTimestamps, currentTimeMillis);
    if (scanRequestTimestamps.size() >= SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS) {
        return true;
    }
    // Proceed with the scan request and record the time.
    scanRequestTimestamps.addLast(currentTimeMillis);
    return false;
}

@VisibleForTesting
public static final int SCAN_REQUEST_THROTTLE_TIME_WINDOW_FG_APPS_MS = 120 * 1000;
@VisibleForTesting
public static final int SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS = 4;

private void trimPastScanRequestTimesForForegroundApp(
        List<Long> scanRequestTimestamps, long currentTimeMillis) {
    Iterator<Long> timestampsIter = scanRequestTimestamps.iterator();
    while (timestampsIter.hasNext()) {
        Long scanRequestTimeMillis = timestampsIter.next();
        if ((currentTimeMillis - scanRequestTimeMillis)
                > SCAN_REQUEST_THROTTLE_TIME_WINDOW_FG_APPS_MS) {
            timestampsIter.remove();
        } else {
            // This list is sorted by timestamps, so we can skip any more checks
            break;
        }
    }
}

也就是说每个应用2分钟内只能发起四次扫描

总结

 * d) Throttle scan requests from non-setting apps:
 *  a) Each foreground app can request a max of
 *   {@link #SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS} scan every
 *   {@link #SCAN_REQUEST_THROTTLE_TIME_WINDOW_FG_APPS_MS}.
 *  b) Background apps combined can request 1 scan every
 *   {@link #SCAN_REQUEST_THROTTLE_INTERVAL_BG_APPS_MS}.

ScanRequestProxy的注释讲的很清楚

  • 每个前台应用2分钟内只能发起四次扫描
  • 所有的后台应用加起来30分钟内只能发起一次扫描

版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/03/29/restrictions-of-android-o-wifi-on-application-front-end-and-back-end-scanning/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
海报
Android O WiFi对应用前后台扫描的限制
流程梳理 ScanRequestProxy // Check and throttle scan request unless, // a) App has either NETWORK_SETTINGS or NETWORK_SETUP_WIZARD permis……
<<上一篇
下一篇>>
文章目录
关闭
目 录