当前位置: 首页> 科技> 能源 > b站免费版_商标转让平台商标_网络营销策划案_淘宝代运营

b站免费版_商标转让平台商标_网络营销策划案_淘宝代运营

时间:2025/7/11 9:53:11来源:https://blog.csdn.net/yang_0323/article/details/143705978 浏览次数:0次
b站免费版_商标转让平台商标_网络营销策划案_淘宝代运营

xref: /packages/apps/Settings/src/com/android/settings/wifi/WifiSettings.java

/** Called when the state of Wifi has changed. */
@Override
public void onWifiStateChanged(int state) {if (mIsRestricted) {return;}final int wifiState = mWifiManager.getWifiState();switch (wifiState) {case WifiManager.WIFI_STATE_ENABLED:updateAccessPointPreferences();break;case WifiManager.WIFI_STATE_ENABLING:removeConnectedAccessPointPreference();removeAccessPointPreference();addMessagePreference(R.string.wifi_starting);setProgressBarVisible(true);break;case WifiManager.WIFI_STATE_DISABLING:removeConnectedAccessPointPreference();removeAccessPointPreference();addMessagePreference(R.string.wifi_stopping);break;case WifiManager.WIFI_STATE_DISABLED:setOffMessage();setAdditionalSettingsSummaries();setProgressBarVisible(false);break;}
}.........................................................................................private void updateAccessPointPreferences() {// in case state has changedif (!mWifiManager.isWifiEnabled()) {return;}// AccessPoints are sorted by the WifiTrackerfinal List<AccessPoint> accessPoints = mWifiTracker.getAccessPoints();if (isVerboseLoggingEnabled()) {Log.i(TAG, "updateAccessPoints called for: " + accessPoints);}boolean hasAvailableAccessPoints = false;mStatusMessagePreference.setVisible(false);mConnectedAccessPointPreferenceCategory.setVisible(true);mAccessPointsPreferenceCategory.setVisible(true);cacheRemoveAllPrefs(mAccessPointsPreferenceCategory);int index =configureConnectedAccessPointPreferenceCategory(accessPoints) ? 1 : 0;int numAccessPoints = accessPoints.size();for (; index < numAccessPoints; index++) {AccessPoint accessPoint = accessPoints.get(index);// Ignore access points that are out of range.if (accessPoint.isReachable()) {String key = accessPoint.getKey();hasAvailableAccessPoints = true;LongPressAccessPointPreference pref =(LongPressAccessPointPreference) getCachedPreference(key);if (pref != null) {pref.setOrder(index);continue;}LongPressAccessPointPreference preference =createLongPressAccessPointPreference(accessPoint);preference.setKey(key);preference.setOrder(index);if (mOpenSsid != null && mOpenSsid.equals(accessPoint.getSsidStr())&& (accessPoint.getSecurity() != AccessPoint.SECURITY_NONE &&accessPoint.getSecurity() != AccessPoint.SECURITY_OWE &&accessPoint.getSecurity() != AccessPoint.SECURITY_OWE_TRANSITION)) {if (!accessPoint.isSaved() || isDisabledByWrongPassword(accessPoint)) {onPreferenceTreeClick(preference);mOpenSsid = null;}}mAccessPointsPreferenceCategory.addPreference(preference);accessPoint.setListener(WifiSettings.this);preference.refresh();}}removeCachedPrefs(mAccessPointsPreferenceCategory);mAddWifiNetworkPreference.setOrder(index);mAccessPointsPreferenceCategory.addPreference(mAddWifiNetworkPreference);setAdditionalSettingsSummaries();if (!hasAvailableAccessPoints) {setProgressBarVisible(true);Preference pref = new Preference(getPrefContext());pref.setSelectable(false);pref.setSummary(R.string.wifi_empty_list_wifi_on);pref.setOrder(index++);pref.setKey(PREF_KEY_EMPTY_WIFI_LIST);mAccessPointsPreferenceCategory.addPreference(pref);} else {// Continuing showing progress bar for an additional delay to overlap with animationgetView().postDelayed(mHideProgressBarRunnable, 1700 /* delay millis */);}
}

        在onWifiStateChanged方法里面处理wifi的开关,当我们打开wifi按钮的时候会走WifiManager.WIFI_STATE_ENABLED分支,调用updateAccessPointPreferences方法完成wifi的添加。accessPoints是通过WifiTracker的getAccessPoints获得的。

xref: /frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java

@AnyThread
public List<AccessPoint> getAccessPoints() {synchronized (mLock) {return new ArrayList<>(mInternalAccessPoints);}
}

        这一部分是打开wifi按钮的时候主动获取accessPoints,接下来我们分析accessPoints是如果从系统底层推送的。

xref: /frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java

private final BroadcastReceiver mReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (action.equals(Intent.ACTION_USER_REMOVED)) {int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);mClientModeImpl.removeUserConfigs(userHandle);} else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,BluetoothAdapter.STATE_DISCONNECTED);mClientModeImpl.sendBluetoothAdapterStateChange(state);} else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {boolean emergencyMode = intent.getBooleanExtra("phoneinECMState", false);mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, emergencyMode ? 1 : 0, 0);} else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED)) {boolean inCall = intent.getBooleanExtra(PhoneConstants.PHONE_IN_EMERGENCY_CALL, false);mWifiController.sendMessage(CMD_EMERGENCY_CALL_STATE_CHANGED, inCall ? 1 : 0, 0);} else if (action.equals(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)) {handleIdleModeChanged();}}
};..................................................................................................void handleIdleModeChanged() {boolean doScan = false;synchronized (this) {boolean idle = mPowerManager.isDeviceIdleMode();if (mInIdleMode != idle) {mInIdleMode = idle;if (!idle) {if (mScanPending) {mScanPending = false;doScan = true;}}}}if (doScan) {// Someone requested a scan while we were idle; do a full scan now.// A security check of the caller's identity was made when the request arrived via// Binder. Now we'll pass the current process's identity to startScan().startScan(mContext.getOpPackageName());}
}..................................................................................................@Override
public boolean startScan(String packageName) {if (enforceChangePermission(packageName) != MODE_ALLOWED) {return false;}int callingUid = Binder.getCallingUid();long ident = Binder.clearCallingIdentity();mLog.info("startScan uid=%").c(callingUid).flush();synchronized (this) {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 false;}}try {mWifiPermissionsUtil.enforceCanAccessScanResults(packageName, callingUid);Mutable<Boolean> scanSuccess = new Mutable<>();boolean runWithScissorsSuccess = mWifiInjector.getClientModeImplHandler().runWithScissors(() -> {scanSuccess.value = mScanRequestProxy.startScan(callingUid, packageName);}, RUN_WITH_SCISSORS_TIMEOUT_MILLIS);if (!runWithScissorsSuccess) {Log.e(TAG, "Failed to post runnable to start scan");sendFailedScanBroadcast();return false;}if (!scanSuccess.value) {Log.e(TAG, "Failed to start scan");return false;}} catch (SecurityException e) {Slog.e(TAG, "Permission violation - startScan not allowed for"+ " uid=" + callingUid + ", packageName=" + packageName + ", reason=" + e);return false;} finally {Binder.restoreCallingIdentity(ident);}return true;
}

        注册广播,当收到ACTION_DEVICE_IDLE_MODE_CHANGED广播通知时就开始扫描。在startScan方法里会调用ScanRequestProxy类的startScan方法开启扫描。

xref: /frameworks/opt/net/wifi/service/java/com/android/server/wifi/ScanRequestProxy.java

public boolean startScan(int callingUid, String packageName) {if (!retrieveWifiScannerIfNecessary()) {Log.e(TAG, "Failed to retrieve wifiscanner");sendScanResultFailureBroadcastToPackage(packageName);return false;}boolean fromSettingsOrSetupWizard =mWifiPermissionsUtil.checkNetworkSettingsPermission(callingUid)|| mWifiPermissionsUtil.checkNetworkSetupWizardPermission(callingUid);// 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;}// Create a worksource using the caller's UID.WorkSource workSource = new WorkSource(callingUid, packageName);// Create the scan settings.WifiScanner.ScanSettings settings = new WifiScanner.ScanSettings();// Scan requests from apps with network settings will be of high accuracy type.if (fromSettingsOrSetupWizard) {settings.type = WifiScanner.TYPE_HIGH_ACCURACY;}// always do full scanssettings.band = WifiScanner.WIFI_BAND_BOTH_WITH_DFS;settings.reportEvents = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN| WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT;if (mScanningForHiddenNetworksEnabled) {// retrieve the list of hidden network SSIDs to scan for, if enabled.List<WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworkList =mWifiConfigManager.retrieveHiddenNetworkList();settings.hiddenNetworks = hiddenNetworkList.toArray(new WifiScanner.ScanSettings.HiddenNetwork[hiddenNetworkList.size()]);}mWifiScanner.startScan(settings, new ScanRequestProxyScanListener(), workSource);return true;
}

        mWifiScanner.startScan(settings, new ScanRequestProxyScanListener(), workSource)调用WifiScanner类的startScan方法扫描,同时设置扫描回调监听,当扫描结束后通过监听回调。

        我先分析如何扫描,然后再分析ScanRequestProxyScanListener扫描监听回调。

xref: /frameworks/base/wifi/java/android/net/wifi/WifiScanner.java        

@RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public void startScan(ScanSettings settings, ScanListener listener, WorkSource workSource) {Preconditions.checkNotNull(listener, "listener cannot be null");int key = addListener(listener);if (key == INVALID_KEY) return;validateChannel();Bundle scanParams = new Bundle();scanParams.putParcelable(SCAN_PARAMS_SCAN_SETTINGS_KEY, settings);scanParams.putParcelable(SCAN_PARAMS_WORK_SOURCE_KEY, workSource);scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());mAsyncChannel.sendMessage(CMD_START_SINGLE_SCAN, 0, key, scanParams);
}

        通过AsyncChannel发送message(CMD_START_SINGLE_SCAN),最终在WifiScanningServiceImpl.java里面处理

xref: /frameworks/opt/net/wifi/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java

class WifiSingleScanStateMachine extends StateMachine implements WifiNative.ScanEventHandler {/*** Maximum age of results that we return from our cache via* {@link WifiScanner#getScanResults()}.* This is currently set to 3 minutes to restore parity with the wpa_supplicant's scan* result cache expiration policy. (See b/62253332 for details)*/@VisibleForTestingpublic static final int CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS = 180 * 1000;private final DefaultState mDefaultState = new DefaultState();private final DriverStartedState mDriverStartedState = new DriverStartedState();private final IdleState  mIdleState  = new IdleState();private final ScanningState  mScanningState  = new ScanningState();private WifiNative.ScanSettings mActiveScanSettings = null;private RequestList<ScanSettings> mActiveScans = new RequestList<>();private RequestList<ScanSettings> mPendingScans = new RequestList<>();// Scan results cached from the last full single scan request.private final List<ScanResult> mCachedScanResults = new ArrayList<>();WifiSingleScanStateMachine(Looper looper) {super("WifiSingleScanStateMachine", looper);setLogRecSize(128);setLogOnlyTransitions(false);// CHECKSTYLE:OFF IndentationCheckaddState(mDefaultState);addState(mDriverStartedState, mDefaultState);addState(mIdleState, mDriverStartedState);addState(mScanningState, mDriverStartedState);// CHECKSTYLE:ON IndentationChecksetInitialState(mDefaultState);}...................................................................................../*** State representing when the driver is running. This state is not meant to be transitioned* directly, but is instead intended as a parent state of ScanningState and IdleState* to hold common functionality and handle cleaning up scans when the driver is shut down.*/class DriverStartedState extends State {.....................................................................................................@Overridepublic boolean processMessage(Message msg) {ClientInfo ci = mClients.get(msg.replyTo);switch (msg.what) {case CMD_DRIVER_LOADED:// Ignore if we're already in driver loaded state.return HANDLED;case WifiScanner.CMD_START_SINGLE_SCAN: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)) {mWifiMetrics.incrementOneshotScanCount();if (scanSettings.band == WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY|| scanSettings.band == WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS|| scanSettings.band == WifiScanner.WIFI_BAND_BOTH_WITH_DFS) {mWifiMetrics.incrementOneshotScanWithDfsCount();}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;}}}..........................................................................................................void tryToStartNewScan() {if (mPendingScans.size() == 0) { // no pending requestsreturn;}mChannelHelper.updateChannels();// TODO move merging logic to a schedulerWifiNative.ScanSettings settings = new WifiNative.ScanSettings();settings.num_buckets = 1;WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings();bucketSettings.bucket = 0;bucketSettings.period_ms = 0;bucketSettings.report_events = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN;ChannelCollection channels = mChannelHelper.createChannelCollection();List<WifiNative.HiddenNetwork> hiddenNetworkList = new ArrayList<>();for (RequestInfo<ScanSettings> entry : mPendingScans) {settings.scanType =mergeScanTypes(settings.scanType, getNativeScanType(entry.settings.type));channels.addChannels(entry.settings);if (entry.settings.hiddenNetworks != null) {for (int i = 0; i < entry.settings.hiddenNetworks.length; i++) {WifiNative.HiddenNetwork hiddenNetwork = new WifiNative.HiddenNetwork();hiddenNetwork.ssid = entry.settings.hiddenNetworks[i].ssid;hiddenNetworkList.add(hiddenNetwork);}}if ((entry.settings.reportEvents & WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT)!= 0) {bucketSettings.report_events |= WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT;}}if (hiddenNetworkList.size() > 0) {settings.hiddenNetworks = new WifiNative.HiddenNetwork[hiddenNetworkList.size()];int numHiddenNetworks = 0;for (WifiNative.HiddenNetwork hiddenNetwork : hiddenNetworkList) {settings.hiddenNetworks[numHiddenNetworks++] = hiddenNetwork;}}channels.fillBucketSettings(bucketSettings, Integer.MAX_VALUE);settings.buckets = new WifiNative.BucketSettings[] {bucketSettings};if (mScannerImpl.startSingleScan(settings, this)) {// store the active scan settingsmActiveScanSettings = settings;// swap pending and active scan requestsRequestList<ScanSettings> tmp = mActiveScans;mActiveScans = mPendingScans;mPendingScans = tmp;// make sure that the pending list is clearmPendingScans.clear();transitionTo(mScanningState);} else {mWifiMetrics.incrementScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_UNKNOWN, mPendingScans.size());// notify and cancel failed scanssendOpFailedToAllAndClear(mPendingScans, WifiScanner.REASON_UNSPECIFIED,"Failed to start single scan");}}
}

        在tryToStartNewScan方法里面会调用用WifiScannerImpl类的startSingleScan方法。WifiScannerImpl是个抽象类,具体实现方法是在WificondScannerImpl.java类中。

xref: /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;}synchronized (mSettingsLock) {if (mLastScanSettings != null) {Log.w(TAG, "A single scan is already running");return false;}ChannelCollection allFreqs = mChannelHelper.createChannelCollection();boolean reportFullResults = false;for (int i = 0; i < settings.num_buckets; ++i) {WifiNative.BucketSettings bucketSettings = settings.buckets[i];if ((bucketSettings.report_events& WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) != 0) {reportFullResults = true;}allFreqs.addChannels(bucketSettings);}List<String> hiddenNetworkSSIDSet = new ArrayList<>();if (settings.hiddenNetworks != null) {int numHiddenNetworks =Math.min(settings.hiddenNetworks.length, MAX_HIDDEN_NETWORK_IDS_PER_SCAN);for (int i = 0; i < numHiddenNetworks; i++) {hiddenNetworkSSIDSet.add(settings.hiddenNetworks[i].ssid);}}mLastScanSettings = new LastScanSettings(mClock.getElapsedSinceBootMillis(),reportFullResults, allFreqs, eventHandler);boolean success = false;Set<Integer> freqs;if (!allFreqs.isEmpty()) {freqs = allFreqs.getScanFreqs();success = mWifiNative.scan(mIfaceName, settings.scanType, freqs, hiddenNetworkSSIDSet);if (!success) {Log.e(TAG, "Failed to start scan, freqs=" + freqs);}} else {// There is a scan request but no available channels could be scanned for.// We regard it as a scan failure in this case.Log.e(TAG, "Failed to start scan because there is no available channel to scan");}if (success) {if (DBG) {Log.d(TAG, "Starting wifi scan for freqs=" + freqs);}mScanTimeoutListener = new AlarmManager.OnAlarmListener() {@Override public void onAlarm() {handleScanTimeout();}};mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,mClock.getElapsedSinceBootMillis() + SCAN_TIMEOUT_MS,TIMEOUT_ALARM_TAG, mScanTimeoutListener, mEventHandler);} else {// indicate scan failure asyncmEventHandler.post(new Runnable() {@Override public void run() {reportScanFailure();}});}return true;}
}

        在startSingleScan方法里面会调用WifiNative里面的scan方法(mWifiNative.scan)。

xref: /frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java

public boolean scan(@NonNull String ifaceName, int scanType, Set<Integer> freqs,List<String> hiddenNetworkSSIDs) {return mWificondControl.scan(ifaceName, scanType, freqs, hiddenNetworkSSIDs);
}

        调用WificondControl类的scan方法

xref: /frameworks/opt/net/wifi/service/java/com/android/server/wifi/WificondControl.java
 

public boolean scan(@NonNull String ifaceName,int scanType,Set<Integer> freqs,List<String> hiddenNetworkSSIDs) {IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);if (scannerImpl == null) {Log.e(TAG, "No valid wificond scanner interface handler");return false;}SingleScanSettings settings = new SingleScanSettings();try {settings.scanType = getScanType(scanType);} catch (IllegalArgumentException e) {Log.e(TAG, "Invalid scan type ", e);return false;}settings.channelSettings  = new ArrayList<>();settings.hiddenNetworks  = new ArrayList<>();if (freqs != null) {for (Integer freq : freqs) {ChannelSettings channel = new ChannelSettings();channel.frequency = freq;settings.channelSettings.add(channel);}}if (hiddenNetworkSSIDs != null) {for (String ssid : hiddenNetworkSSIDs) {HiddenNetwork network = new HiddenNetwork();try {network.ssid = NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(ssid));} catch (IllegalArgumentException e) {Log.e(TAG, "Illegal argument " + ssid, e);continue;}// settings.hiddenNetworks is expected to be very small, so this shouldn't cause// any performance issues.if (!settings.hiddenNetworks.contains(network)) {settings.hiddenNetworks.add(network);}}}try {return scannerImpl.scan(settings);} catch (RemoteException e1) {Log.e(TAG, "Failed to request scan due to remote exception");}return false;
}

        调用scanner_impl.cpp中的scan方法

xref: /system/connectivity/wificond/scanning/scanner_impl.cpp

Status ScannerImpl::scan(const SingleScanSettings& scan_settings,bool* out_success) {if (!CheckIsValid()) {*out_success = false;return Status::ok();}if (scan_started_) {LOG(WARNING) << "Scan already started";}// Only request MAC address randomization when station is not associated.bool request_random_mac =wiphy_features_.supports_random_mac_oneshot_scan &&!client_interface_->IsAssociated();int scan_type = scan_settings.scan_type_;if (!IsScanTypeSupported(scan_settings.scan_type_, wiphy_features_)) {LOG(DEBUG) << "Ignoring scan type because device does not support it";scan_type = SCAN_TYPE_DEFAULT;}// Initialize it with an empty ssid for a wild card scan.vector<vector<uint8_t>> ssids = {{}};vector<vector<uint8_t>> skipped_scan_ssids;for (auto& network : scan_settings.hidden_networks_) {if (ssids.size() + 1 > scan_capabilities_.max_num_scan_ssids) {skipped_scan_ssids.emplace_back(network.ssid_);continue;}ssids.push_back(network.ssid_);}LogSsidList(skipped_scan_ssids, "Skip scan ssid for single scan");vector<uint32_t> freqs;for (auto& channel : scan_settings.channel_settings_) {freqs.push_back(channel.frequency_);}int error_code = 0;if (!scan_utils_->Scan(interface_index_, request_random_mac, scan_type,ssids, freqs, &error_code)) {CHECK(error_code != ENODEV) << "Driver is in a bad state, restarting wificond";*out_success = false;return Status::ok();}scan_started_ = true;*out_success = true;return Status::ok();
}Status ScannerImpl::startPnoScan(const PnoSettings& pno_settings,bool* out_success) {pno_settings_ = pno_settings;pno_scan_results_from_offload_ = false;LOG(VERBOSE) << "startPnoScan";if (offload_scan_supported_ && StartPnoScanOffload(pno_settings)) {// scanning over offload succeeded*out_success = true;} else {*out_success = StartPnoScanDefault(pno_settings);}return Status::ok();
}

        调用scan_utils.app的Scan方法

xref: /system/connectivity/wificond/scanning/scan_utils.cpp

bool ScanUtils::Scan(uint32_t interface_index,bool request_random_mac,int scan_type,const vector<vector<uint8_t>>& ssids,const vector<uint32_t>& freqs,int* error_code) {NL80211Packet trigger_scan(netlink_manager_->GetFamilyId(),NL80211_CMD_TRIGGER_SCAN,netlink_manager_->GetSequenceNumber(),getpid());// If we do not use NLM_F_ACK, we only receive a unicast repsonse// when there is an error. If everything is good, scan results notification// will only be sent through multicast.// If NLM_F_ACK is set, there will always be an unicast repsonse, either an// ERROR or an ACK message. The handler will always be called and removed by// NetlinkManager.trigger_scan.AddFlag(NLM_F_ACK);NL80211Attr<uint32_t> if_index_attr(NL80211_ATTR_IFINDEX, interface_index);NL80211NestedAttr ssids_attr(NL80211_ATTR_SCAN_SSIDS);for (size_t i = 0; i < ssids.size(); i++) {ssids_attr.AddAttribute(NL80211Attr<vector<uint8_t>>(i, ssids[i]));}NL80211NestedAttr freqs_attr(NL80211_ATTR_SCAN_FREQUENCIES);for (size_t i = 0; i < freqs.size(); i++) {freqs_attr.AddAttribute(NL80211Attr<uint32_t>(i, freqs[i]));}trigger_scan.AddAttribute(if_index_attr);trigger_scan.AddAttribute(ssids_attr);// An absence of NL80211_ATTR_SCAN_FREQUENCIES attribue informs kernel to// scan all supported frequencies.if (!freqs.empty()) {trigger_scan.AddAttribute(freqs_attr);}uint32_t scan_flags = 0;if (request_random_mac) {scan_flags |= NL80211_SCAN_FLAG_RANDOM_ADDR;}switch (scan_type) {case IWifiScannerImpl::SCAN_TYPE_LOW_SPAN:scan_flags |= NL80211_SCAN_FLAG_LOW_SPAN;break;case IWifiScannerImpl::SCAN_TYPE_LOW_POWER:scan_flags |= NL80211_SCAN_FLAG_LOW_POWER;break;case IWifiScannerImpl::SCAN_TYPE_HIGH_ACCURACY:scan_flags |= NL80211_SCAN_FLAG_HIGH_ACCURACY;break;case IWifiScannerImpl::SCAN_TYPE_DEFAULT:break;default:CHECK(0) << "Invalid scan type received: " << scan_type;}if (scan_flags) {trigger_scan.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_SCAN_FLAGS,scan_flags));}// We are receiving an ERROR/ACK message instead of the actual// scan results here, so it is OK to expect a timely response because// kernel is supposed to send the ERROR/ACK back before the scan starts.vector<unique_ptr<const NL80211Packet>> response;if (!netlink_manager_->SendMessageAndGetAckOrError(trigger_scan,error_code)) {// Logging is done inside |SendMessageAndGetAckOrError|.return false;}if (*error_code != 0) {LOG(ERROR) << "NL80211_CMD_TRIGGER_SCAN failed: " << strerror(*error_code);return false;}return true;
}

        通过trigger_scan方法将数据发送给内核开启wifi扫描。接下来我们分析ScanRequestProxyScanListener扫描监听回调。

xref: /frameworks/opt/net/wifi/service/java/com/android/server/wifi/ScanRequestProxy.java

private class GlobalScanListener implements WifiScanner.ScanListener {@Overridepublic void onSuccess() {// Ignore. These will be processed from the scan request listener.}@Overridepublic void onFailure(int reason, String description) {// Ignore. These will be processed from the scan request listener.}@Overridepublic void onResults(WifiScanner.ScanData[] scanDatas) {if (mVerboseLoggingEnabled) {Log.d(TAG, "Scan results received");}// For single scans, the array size should always be 1.if (scanDatas.length != 1) {Log.wtf(TAG, "Found more than 1 batch of scan results, Failing...");sendScanResultBroadcast(false);return;}WifiScanner.ScanData scanData = scanDatas[0];ScanResult[] scanResults = scanData.getResults();if (mVerboseLoggingEnabled) {Log.d(TAG, "Received " + scanResults.length + " scan results");}// Only process full band scan results.if (scanData.getBandScanned() == WifiScanner.WIFI_BAND_BOTH_WITH_DFS) {// Store the last scan results & send out the scan completion broadcast.mLastScanResults.clear();mLastScanResults.addAll(Arrays.asList(scanResults));sendScanResultBroadcast(true);}}@Overridepublic void onFullResult(ScanResult fullScanResult) {// Ignore for single scans.}@Overridepublic void onPeriodChanged(int periodInMs) {// Ignore for single scans.}
};// Common scan listener for scan requests initiated by this class.
private class ScanRequestProxyScanListener implements WifiScanner.ScanListener {@Overridepublic void onSuccess() {// Scan request succeeded, wait for results to report to external clients.if (mVerboseLoggingEnabled) {Log.d(TAG, "Scan request succeeded");}}@Overridepublic void onFailure(int reason, String description) {Log.e(TAG, "Scan failure received. reason: " + reason + ",description: " + description);sendScanResultBroadcast(false);}@Overridepublic void onResults(WifiScanner.ScanData[] scanDatas) {// Ignore. These will be processed from the global listener.}@Overridepublic void onFullResult(ScanResult fullScanResult) {// Ignore for single scans.}@Overridepublic void onPeriodChanged(int periodInMs) {// Ignore for single scans.}
};.................................................................................../*** Helper method to send the scan request status broadcast.*/
private void sendScanResultBroadcast(boolean scanSucceeded) {Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);intent.putExtra(WifiManager.EXTRA_RESULTS_UPDATED, scanSucceeded);mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
}

        在ScanRequestProxyScanListener的onResults方法里面有一行这样的注释(Ignore. These will be processed from the global listener.),这个方法已经丢弃了,我们看GlobalScanListener的onResults方法,onResult是底层完成扫描后的上报,把扫描结果添加到mLastScanResult中。调用sendScanResultBroadcast方法发送广播SCAN_RESULTS_AVAILABLE_ACTION通知WifiTracker获取扫描结果。

xref: /frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java

final BroadcastReceiver mReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {updateWifiState(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,WifiManager.WIFI_STATE_UNKNOWN));} else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action)) {mStaleScanResults = false;mLastScanSucceeded =intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, true);fetchScansAndConfigsAndUpdateAccessPoints();} else if (WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION.equals(action)|| WifiManager.LINK_CONFIGURATION_CHANGED_ACTION.equals(action)) {fetchScansAndConfigsAndUpdateAccessPoints();} else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {// TODO(sghuman): Refactor these methods so they cannot result in duplicate// onAccessPointsChanged updates being called from this intent.NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);updateNetworkInfo(info);fetchScansAndConfigsAndUpdateAccessPoints();} else if (WifiManager.RSSI_CHANGED_ACTION.equals(action)) {NetworkInfo info =mConnectivityManager.getNetworkInfo(mWifiManager.getCurrentNetwork());updateNetworkInfo(info);}}
};........................................................................................private void fetchScansAndConfigsAndUpdateAccessPoints() {List<ScanResult> newScanResults = mWifiManager.getScanResults();// Filter all unsupported networks from the scan result listfinal List<ScanResult> filteredScanResults =filterScanResultsByCapabilities(newScanResults);if (isVerboseLoggingEnabled()) {Log.i(TAG, "Fetched scan results: " + filteredScanResults);}List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();updateAccessPoints(filteredScanResults, configs);
}

        在mReceiver中走SCAN_RESULTS_AVAILABLE_ACTION分支,调用fetchScansAndConfigsAndUpdateAccessPoints()方法。通过mWifiManager.getScanResults获取扫描数据。

xref: /frameworks/base/wifi/java/android/net/wifi/WifiManager.java

public List<ScanResult> getScanResults() {try {return mService.getScanResults(mContext.getOpPackageName());} catch (RemoteException e) {throw e.rethrowFromSystemServer();}
}

        mService的具体实现类是WifiServiceImpl.java。所有我们直接去看WifiServiceImpl.java类里面的getScanResults方法

xref: /frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java

       

@Override
public List<ScanResult> getScanResults(String callingPackage) {enforceAccessPermission();int uid = Binder.getCallingUid();long ident = Binder.clearCallingIdentity();if (mVerboseLoggingEnabled) {mLog.info("getScanResults uid=%").c(uid).flush();}try {mWifiPermissionsUtil.enforceCanAccessScanResults(callingPackage, uid);final List<ScanResult> scanResults = new ArrayList<>();boolean success = mWifiInjector.getClientModeImplHandler().runWithScissors(() -> {scanResults.addAll(mScanRequestProxy.getScanResults());}, RUN_WITH_SCISSORS_TIMEOUT_MILLIS);if (!success) {Log.e(TAG, "Failed to post runnable to fetch scan results");return new ArrayList<ScanResult>();}return scanResults;} catch (SecurityException e) {Slog.e(TAG, "Permission violation - getScanResults not allowed for uid="+ uid + ", packageName=" + callingPackage + ", reason=" + e);return new ArrayList<ScanResult>();} finally {Binder.restoreCallingIdentity(ident);}
}

        通过mScanRequestProxy.getScanResults()我们又回到了ScanRequestProxy.java里面。

xref: /frameworks/opt/net/wifi/service/java/com/android/server/wifi/ScanRequestProxy.java

public List<ScanResult> getScanResults() {return mLastScanResults;
}

        mLastScanResults就是我们之前在onResults方法里面遇到过的,就是之前广播接收到的扫描结果,mLastScanResults.addAll(Arrays.asList(scanResults))。

xref: /frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java   

private void fetchScansAndConfigsAndUpdateAccessPoints() {List<ScanResult> newScanResults = mWifiManager.getScanResults();// Filter all unsupported networks from the scan result listfinal List<ScanResult> filteredScanResults =filterScanResultsByCapabilities(newScanResults);if (isVerboseLoggingEnabled()) {Log.i(TAG, "Fetched scan results: " + filteredScanResults);}List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();updateAccessPoints(filteredScanResults, configs);
}...........................................................................................private void updateAccessPoints(final List<ScanResult> newScanResults,List<WifiConfiguration> configs) {// Map configs and scan results necessary to make AccessPointsfinal Map<String, WifiConfiguration> configsByKey = new ArrayMap(configs.size());if (configs != null) {for (WifiConfiguration config : configs) {configsByKey.put(AccessPoint.getKey(config), config);}}WifiConfiguration connectionConfig = null;if (mLastInfo != null) {connectionConfig = getWifiConfigurationForNetworkId(mLastInfo.getNetworkId(), configs);}// Rather than dropping and reacquiring the lock multiple times in this method, we lock// once for efficiency of lock acquisition time and readabilitysynchronized (mLock) {ArrayMap<String, List<ScanResult>> scanResultsByApKey =updateScanResultCache(newScanResults);// Swap the current access points into a cached list for maintaining AP listenersList<AccessPoint> cachedAccessPoints;cachedAccessPoints = new ArrayList<>(mInternalAccessPoints);ArrayList<AccessPoint> accessPoints = new ArrayList<>();final List<NetworkKey> scoresToRequest = new ArrayList<>();for (Map.Entry<String, List<ScanResult>> entry : scanResultsByApKey.entrySet()) {for (ScanResult result : entry.getValue()) {NetworkKey key = NetworkKey.createFromScanResult(result);if (key != null && !mRequestedScores.contains(key)) {scoresToRequest.add(key);}}AccessPoint accessPoint =getCachedOrCreate(entry.getValue(), cachedAccessPoints);// Update the matching config if there is one, to populate saved network infoaccessPoint.update(configsByKey.get(entry.getKey()));accessPoints.add(accessPoint);}List<ScanResult> cachedScanResults = new ArrayList<>(mScanResultCache.values());// Add a unique Passpoint AccessPoint for each Passpoint profile's FQDN.accessPoints.addAll(updatePasspointAccessPoints(mWifiManager.getAllMatchingWifiConfigs(cachedScanResults), cachedAccessPoints));// Add OSU Provider AccessPointsaccessPoints.addAll(updateOsuAccessPoints(mWifiManager.getMatchingOsuProviders(cachedScanResults), cachedAccessPoints));if (mLastInfo != null && mLastNetworkInfo != null) {for (AccessPoint ap : accessPoints) {ap.update(connectionConfig, mLastInfo, mLastNetworkInfo);}}// If there were no scan results, create an AP for the currently connected network (if// it exists).if (accessPoints.isEmpty() && connectionConfig != null) {AccessPoint activeAp = new AccessPoint(mContext, connectionConfig);activeAp.update(connectionConfig, mLastInfo, mLastNetworkInfo);accessPoints.add(activeAp);scoresToRequest.add(NetworkKey.createFromWifiInfo(mLastInfo));}requestScoresForNetworkKeys(scoresToRequest);for (AccessPoint ap : accessPoints) {ap.update(mScoreCache, mNetworkScoringUiEnabled, mMaxSpeedLabelScoreCacheAge);}// Pre-sort accessPoints to speed preference insertionCollections.sort(accessPoints);// Log accesspoints that are being removedif (DBG()) {Log.d(TAG,"------ Dumping AccessPoints that were not seen on this scan ------");for (AccessPoint prevAccessPoint : mInternalAccessPoints) {String prevTitle = prevAccessPoint.getTitle();boolean found = false;for (AccessPoint newAccessPoint : accessPoints) {if (newAccessPoint.getTitle() != null && newAccessPoint.getTitle().equals(prevTitle)) {found = true;break;}}if (!found)Log.d(TAG, "Did not find " + prevTitle + " in this scan");}Log.d(TAG,"---- Done dumping AccessPoints that were not seen on this scan ----");}mInternalAccessPoints.clear();mInternalAccessPoints.addAll(accessPoints);}conditionallyNotifyListeners();
}

        再回到WifiTracker.java类里面的fetchScansAndConfigsAndUpdateAccessPoints方法。通过fetchScansAndConfigsAndUpdateAccessPoints拿到的扫描结果其实就是mLastScanResults。捋清楚这个流程很重要。接下来调用updateAccessPoints方法,将扫描结果添加到mInternalAccessPoints中。

关键字:b站免费版_商标转让平台商标_网络营销策划案_淘宝代运营

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: