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分钟内只能发起一次扫描
上一篇 Android扫码器串口通讯
下一篇 Gradle 设置 Nexus 用户名密码
目录
文章列表
1 IntelliJ IDEA快速生成单元测试类
IntelliJ IDEA快速生成单元测试类
2
Android获取签名文件或apk的MD5及SHA1
Android获取签名文件或apk的MD5及SHA1
3
腾讯企业邮箱配置图文教程
腾讯企业邮箱配置图文教程
4
React Native学习之ReactJS组件通信
React Native学习之ReactJS组件通信
5
MySQL怎么修改锁记录超时等待时间
MySQL怎么修改锁记录超时等待时间
最新评论
一位WordPress评论者
一位WordPress评论者
2月12日
您好,这是一条评论。若需要审核、编辑或删除评论,请访问仪表盘的评论界面。评论者头像来自 Gravatar。