android 8 wifi wifi 扫描过程
查看一下android wifi扫描的过程。
packages\apps\Settings\src\com\android\settings\wifi\WifiSettings.java
public void onStart() {
super.onStart();
// On/off switch is hidden for Setup Wizard (returns null)
mWifiEnabler = createWifiEnabler();
mWifiTracker.startTracking();
if (mIsRestricted) {
restrictUi();
return;
}
onWifiStateChanged(mWifiManager.getWifiState());
}
frameworks\base\packages\SettingsLib\src\com\android\settingslib\wifi\WifiTracker.java
public void startTracking() {
synchronized (mLock) {
registerScoreCache();
// 是否显示wifi评分的UI
mNetworkScoringUiEnabled =
Settings.Global.getInt(
mContext.getContentResolver(),
Settings.Global.NETWORK_SCORING_UI_ENABLED, 0) == 1;
// 是否显示wifi速度
mMaxSpeedLabelScoreCacheAge =
Settings.Global.getLong(
mContext.getContentResolver(),
Settings.Global.SPEED_LABEL_CACHE_EVICTION_AGE_MILLIS,
DEFAULT_MAX_CACHED_SCORE_AGE_MILLIS);
resumeScanning();
if (!mRegistered) {
mContext.registerReceiver(mReceiver, mFilter);
// NetworkCallback objects cannot be reused. http://b/20701525 .
mNetworkCallback = new WifiTrackerNetworkCallback();
mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback);
mRegistered = true;
}
}
}
扫描服务
public void resumeScanning() {
if (mScanner == null) {
mScanner = new Scanner();
}
mWorkHandler.sendEmptyMessage(WorkHandler.MSG_RESUME);
if (mWifiManager.isWifiEnabled()) {
mScanner.resume(); // 发送扫描消息
}
}
//
class Scanner extends Handler {
static final int MSG_SCAN = 0;
private int mRetry = 0;
void resume() {
if (!hasMessages(MSG_SCAN)) {
sendEmptyMessage(MSG_SCAN);
}
}
void forceScan() {
removeMessages(MSG_SCAN);
sendEmptyMessage(MSG_SCAN);
}
void pause() {
mRetry = 0;
removeMessages(MSG_SCAN);
}
@VisibleForTesting
boolean isScanning() {
return hasMessages(MSG_SCAN);
}
@Override
public void handleMessage(Message message) {
if (message.what != MSG_SCAN) return;
if (mWifiManager.startScan()) { // 启动扫描
mRetry = 0;
} else if (++mRetry >= 3) {
mRetry = 0;
if (mContext != null) {
Toast.makeText(mContext, R.string.wifi_fail_to_scan, Toast.LENGTH_LONG).show();
}
return;
}
// 扫描界面扫描间隔。
sendEmptyMessageDelayed(MSG_SCAN, WIFI_RESCAN_INTERVAL_MS);
}
}
frameworks\base\wifi\java\android\net\wifi\WifiManager.java
/**
* Request a scan for access points. Returns immediately. The availability
* of the results is made known later by means of an asynchronous event sent
* on completion of the scan.
* @return {@code true} if the operation succeeded, i.e., the scan was initiated
*/
public boolean startScan() {
return startScan(null);
}
/** @hide */
@SystemApi
@RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
public boolean startScan(WorkSource workSource) {
try {
String packageName = mContext.getOpPackageName();
mService.startScan(null, workSource, packageName);
return true;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
frameworks\opt\net\wifi\service\java\com\android\server\wifi\WifiServiceImpl.java
/**
* see {@link android.net.wifi.WifiManager#startScan}
* and {@link android.net.wifi.WifiManager#startCustomizedScan}
*
* @param settings If null, use default parameter, i.e. full scan.
* @param workSource If null, all blame is given to the calling uid.
* @param packageName Package name of the app that requests wifi scan.
*/
@Override
public void startScan(ScanSettings settings, WorkSource workSource, String packageName) {
enforceChangePermission();
mLog.info("startScan uid=%").c(Binder.getCallingUid()).flush();
// Check and throttle background apps for wifi scan.
if (isRequestFromBackground(packageName)) {
long lastScanMs = mLastScanTimestamps.getOrDefault(packageName, 0L);
long elapsedRealtime = mClock.getElapsedSinceBootMillis();
if (lastScanMs != 0 && (elapsedRealtime - lastScanMs) < mBackgroundThrottleInterval) {
sendFailedScanBroadcast();
return;
}
// Proceed with the scan request and record the time.
mLastScanTimestamps.put(packageName, elapsedRealtime);
}
synchronized (this) {
if (mWifiScanner == null) {
mWifiScanner = mWifiInjector.getWifiScanner();
}
if (mInIdleMode) {
// Need to send an immediate scan result broadcast in case the
// caller is waiting for a result ..
// TODO: investigate if the logic to cancel scans when idle can move to
// WifiScanningServiceImpl. This will 1 - clean up WifiServiceImpl and 2 -
// avoid plumbing an awkward path to report a cancelled/failed scan. This will
// be sent directly until b/31398592 is fixed.
sendFailedScanBroadcast();
mScanPending = true;
return;
}
}
if (settings != null) {
settings = new ScanSettings(settings);
if (!settings.isValid()) {
Slog.e(TAG, "invalid scan setting");
return;
}
}
if (workSource != null) {
enforceWorkSourcePermission();
// WifiManager currently doesn't use names, so need to clear names out of the
// supplied WorkSource to allow future WorkSource combining.
workSource.clearNames();
}
if (workSource == null && Binder.getCallingUid() >= 0) {
workSource = new WorkSource(Binder.getCallingUid());
}
mWifiStateMachine.startScan(Binder.getCallingUid(), scanRequestCounter++,
settings, workSource);
}
class SupplicantStartedState extends State {
case CMD_START_SCAN:
// TODO: remove scan request path (b/31445200)
handleScanRequest(message);
break;
private void handleScanRequest(Message message) {
ScanSettings settings = null;
WorkSource workSource = null;
// unbundle parameters
Bundle bundle = (Bundle) message.obj;
if (bundle != null) {
settings = bundle.getParcelable(CUSTOMIZED_SCAN_SETTING);
workSource = bundle.getParcelable(CUSTOMIZED_SCAN_WORKSOURCE);
}
Set<Integer> freqs = null;
if (settings != null && settings.channelSet != null) {
freqs = new HashSet<>();
for (WifiChannel channel : settings.channelSet) {
freqs.add(channel.freqMHz);
}
}
// Retrieve the list of hidden network SSIDs to scan for.
List<WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworks =
mWifiConfigManager.retrieveHiddenNetworkList();
// call wifi native to start the scan
if (startScanNative(freqs, hiddenNetworks, workSource)) {
// a full scan covers everything, clearing scan request buffer
if (freqs == null)
mBufferedScanMsg.clear();
messageHandlingStatus = MESSAGE_HANDLING_STATUS_OK;
return;
}
// if reach here, scan request is rejected
if (!mIsScanOngoing) {
// if rejection is NOT due to ongoing scan (e.g. bad scan parameters),
// discard this request and pop up the next one
if (mBufferedScanMsg.size() > 0) {
sendMessage(mBufferedScanMsg.remove());
}
messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD;
} else if (!mIsFullScanOngoing) {
// if rejection is due to an ongoing scan, and the ongoing one is NOT a full scan,
// buffer the scan request to make sure specified channels will be scanned eventually
if (freqs == null)
mBufferedScanMsg.clear();
if (mBufferedScanMsg.size() < SCAN_REQUEST_BUFFER_MAX_SIZE) {
Message msg = obtainMessage(CMD_START_SCAN,
message.arg1, message.arg2, bundle);
mBufferedScanMsg.add(msg);
} else {
// if too many requests in buffer, combine them into a single full scan
bundle = new Bundle();
bundle.putParcelable(CUSTOMIZED_SCAN_SETTING, null);
bundle.putParcelable(CUSTOMIZED_SCAN_WORKSOURCE, workSource);
Message msg = obtainMessage(CMD_START_SCAN, message.arg1, message.arg2, bundle);
mBufferedScanMsg.clear();
mBufferedScanMsg.add(msg);
}
messageHandlingStatus = MESSAGE_HANDLING_STATUS_LOOPED;
} else {
// mIsScanOngoing and mIsFullScanOngoing
messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL;
}
}
private boolean startScanNative(final Set<Integer> freqs,
List<WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworkList,
WorkSource workSource) {
WifiScanner.ScanSettings settings = new WifiScanner.ScanSettings();
if (freqs == null) {
settings.band = WifiScanner.WIFI_BAND_BOTH_WITH_DFS;
} else {
settings.band = WifiScanner.WIFI_BAND_UNSPECIFIED;
int index = 0;
settings.channels = new WifiScanner.ChannelSpec[freqs.size()];
for (Integer freq : freqs) {
settings.channels[index++] = new WifiScanner.ChannelSpec(freq);
}
}
settings.reportEvents = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN
| WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT;
settings.hiddenNetworks =
hiddenNetworkList.toArray(
new WifiScanner.ScanSettings.HiddenNetwork[hiddenNetworkList.size()]);
WifiScanner.ScanListener nativeScanListener = new WifiScanner.ScanListener() {
// ignore all events since WifiStateMachine is registered for the supplicant events
@Override
public void onSuccess() {
}
@Override
public void onFailure(int reason, String description) {
mIsScanOngoing = false;
mIsFullScanOngoing = false;
}
@Override
public void onResults(WifiScanner.ScanData[] results) {
}
@Override
public void onFullResult(ScanResult fullScanResult) {
}
@Override
public void onPeriodChanged(int periodInMs) {
}
};
mWifiScanner.startScan(settings, nativeScanListener, workSource);
mIsScanOngoing = true;
mIsFullScanOngoing = (freqs == null);
lastScanFreqs = freqs;
return true;
}
frameworks\opt\net\wifi\service\java\com\android\server\wifi\scanner\WifiScanningServiceImpl.java
class DriverStartedState extends State {
@Override
public void exit() {
// clear scan results when scan mode is not active
mCachedScanResults.clear();
mWifiMetrics.incrementScanReturnEntry(
WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED,
mPendingScans.size());
sendOpFailedToAllAndClear(mPendingScans, WifiScanner.REASON_UNSPECIFIED,
"Scan was interrupted");
}
@Override
public boolean processMessage(Message msg) {
ClientInfo ci = mClients.get(msg.replyTo);
switch (msg.what) {
case WifiScanner.CMD_START_SINGLE_SCAN:
mWifiMetrics.incrementOneshotScanCount();
int handler = msg.arg2;
Bundle scanParams = (Bundle) msg.obj;
if (scanParams == null) {
logCallback("singleScanInvalidRequest", ci, handler, "null params");
replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, "params null");
return HANDLED;
}
scanParams.setDefusable(true);
ScanSettings scanSettings =
scanParams.getParcelable(WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY);
WorkSource workSource =
scanParams.getParcelable(WifiScanner.SCAN_PARAMS_WORK_SOURCE_KEY);
if (validateScanRequest(ci, handler, scanSettings, workSource)) {
logScanRequest("addSingleScanRequest", ci, handler, workSource,
scanSettings, null);
replySucceeded(msg);
// If there is an active scan that will fulfill the scan request then
// mark this request as an active scan, otherwise mark it pending.
// If were not currently scanning then try to start a scan. Otherwise
// this scan will be scheduled when transitioning back to IdleState
// after finishing the current scan.
if (getCurrentState() == mScanningState) {
if (activeScanSatisfies(scanSettings)) {
mActiveScans.addRequest(ci, handler, workSource, scanSettings);
} else {
mPendingScans.addRequest(ci, handler, workSource, scanSettings);
}
} else {
mPendingScans.addRequest(ci, handler, workSource, scanSettings);
tryToStartNewScan();
}
} else {
logCallback("singleScanInvalidRequest", ci, handler, "bad request");
replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, "bad request");
mWifiMetrics.incrementScanReturnEntry(
WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION, 1);
}
return HANDLED;
case WifiScanner.CMD_STOP_SINGLE_SCAN:
removeSingleScanRequest(ci, msg.arg2);
return HANDLED;
default:
return NOT_HANDLED;
}
}
}
frameworks\opt\net\wifi\service\java\com\android\server\wifi\scanner\WificondScannerImpl.java
public boolean startSingleScan(WifiNative.ScanSettings settings,
WifiNative.ScanEventHandler eventHandler) {
if (eventHandler == null || settings == null) {
Log.w(TAG, "Invalid arguments for startSingleScan: settings=" + settings
+ ",eventHandler=" + eventHandler);
return false;
}
if (mPendingSingleScanSettings != null
|| (mLastScanSettings != null && mLastScanSettings.singleScanActive)) {
Log.w(TAG, "A single scan is already running");
return false;
}
synchronized (mSettingsLock) {
mPendingSingleScanSettings = settings;
mPendingSingleScanEventHandler = eventHandler;
processPendingScans();
return true;
}
}
android 8 wifi wifi 扫描过程的更多相关文章
- Android Wifi 主动扫描 被动扫描
介绍主动扫描,被动扫描以及连接的wifi的扫描过程 参考文档 <802.11无线网络权威指南> <80_Y0513_1_QCA_WCN36X0_SOFTWARE_ARCHITECTU ...
- Android 中的WiFi剖析
Android的WiFi 我们通常看到WiFi的守护进程wpa_supplicant在我们的ps的进程列表中,这个就是我们的wifi守护进程.wpa_supplicant在external/wpa_s ...
- 马上搞定Android平台的Wi-Fi Direct开发
导语 移动互联网时代,很多用户趋向于将大量的资料保存在移动设备上.但在给用户带来便利的同时引发了一个新的问题——保存在移动设备上的资料该怎样共享出去?到了思考时间,普通青年这样想:折腾什么劲啊,直接用 ...
- Android 开发 创建WiFi、WiFi热点 ---开发集合
WIFI 权限 <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> < ...
- android开发之 Wifi的四个类
android开发之 Wifi的四个类 在Android中对Wifi操作,android本身提供了一些实用的包,在android.net.wifi包以下.简介一下: 大致能够分为四个基本的类ScanR ...
- WiFi无线连接过程中有哪几个主要步骤?
WiFi无线连接过程中有哪几个主要步骤?[1]在使用WIFI功能时,经常性的操作是打开手机上的WiFi设备,搜索到心目中的热点,输入密码,联网成功,成功上网.这个看似简单的过程,背后却是隐藏着大量的无 ...
- android学习-仿Wifi模块实现
最近研究android内核-系统关键服务的启动解析,然而我也不知道研究wifi的作用,就当兴趣去做吧(其实是作业-_-) 系统原生WiFI功能大概有:启动WiFI服务,扫描WiFi信息(这个好像已经被 ...
- Android中的WiFi P2P
Android中的WiFi P2P可以同意一定范围内的设备通过Wifi直接互连而不必通过热点或互联网. 使用WiFi P2P须要Android API Level >= 14才干够,并且不要忘记 ...
- Android掌控WiFi不完全指南
前言 如果想要对针对WiFi的攻击进行监测,就需要定期获取WiFi的运行状态,例如WiFi的SSID,WiFi强度,是否开放,加密方式等信息,在Android中通过WiFiManager来实现 WiF ...
- S3c6410 平台 Android系统的Wi-Fi调试记录
硬件平台:S3c6410 操作系统:Android 网卡芯片:GH381(SDIO接口 sdio8688) 1.SDIO驱动 因为是SDIO接口,所以请先保证mmc驱动(代码在“kernel\driv ...
随机推荐
- 使用Maven对JAVA程序打包-带主类、带依赖【转】
很多时候,我们需要对编写的程序进行打包,这个时候,我们可以借助一些项目构建工具,如maven, sbt, ant等,这里我使用的是maven. 打包成可执行有主类的jar包(jar包中无依赖) 以下是 ...
- LeetCode: Search a 2D Matrix 解题报告
Search a 2D Matrix Write an efficient algorithm that searches for a value in an m x n matrix. This m ...
- LeetCode: Minimum Depth of Binary Tree 解题报告
Minimum Depth of Binary Tree Given a binary tree, find its minimum depth. The minimum depth is the n ...
- Excel工作记录表制作
前言:我们一天中的工作可能特别忙.事情特别多,这时候你就要像CPU一样去调度.去执行任务,但总要有个地方记录你的执行情况,这就需要我们自己去记录和管理了,下面是使用excel的简单管理记录方式,下图是 ...
- 加快Terminal的打开加载速度
加快Terminal的打开加载速度html, body {overflow-x: initial !important;}.CodeMirror { height: auto; } .CodeMirr ...
- css部分样式资料
1. css字体 Lato,"Helvetica Neue","Segoe UI",Helvetica,Arial,sans-serif
- CentOS7安装MySQL5.7常见问题
下载与安装 亲测有效: https://www.linuxidc.com/Linux/2016-09/135288.htm 设置MySQL服务开机自启动 注意,CentOS6和7有一点不同:CentO ...
- Linux下LDAP统一认证解决方案
Linux下LDAP统一认证解决方案 --http://www.cangfengzhe.com/wangluoanquan/3.html 转自:http://www.cnblogs.com/MYSQL ...
- 如何在CentOS 6.5上升级PHP
CentOS 6.5上默认安装PHP 5.3.因为后台网站无法正确运行在PHP 5.3上,所以计划将PHP升级到开发平台一样的版本PHP 5.5.为了方便,我们采用YUM的方式升级PHP 工具/原料 ...
- Extjs4.x TreeGrid Dirty 更新数据,dirty标记不会自动清除的bug
如上图所示,当修改某个属性值,成功提交后,dirty的小三角不会自动清除,这个是官方treegrid的一个bug,目前尚未解决. bug:http://www.sencha.com/forum/sho ...