(五十七)Android O WiFi的扫描流程梳理续——梳理java与c++之间的aidl-cpp通信

前言:之前在(五十) Android O WiFi的扫描流程梳理 中梳理到wificond,就是找不到wificond对应的具体实现类,本文在现有发现上继续梳理,服务端是由cpp实现的,这种aidl实现方式被Google成为aidl-cpp


1.问题

在梳理WiFi 扫描流程的时候遇到如下方法,然后找不到对应服务端的实现类,现在专门梳理下找到的线索。


mWificond = mWifiInjector.makeWificond();

     public IWificond makeWificond() {
    // We depend on being able to refresh our binder in WifiStateMachine, so don't cache it.
    IBinder binder = ServiceManager.getService(WIFICOND_SERVICE_NAME);
    return IWificond.Stub.asInterface(binder);
    }
clientInterface = mWificond.createClientInterface()
mWificondScanner = mClientInterface.getWifiScannerImpl();
最终会调用mWificondScanner的scan方法来进行WiFi搜索。

具体相关代码存放路径:

aidl存放路径:

./system/connectivity/wificond/aidl/android/net/wifi/IWifiScannerImpl.aidl

./system/connectivity/wificond/aidl/android/net/wifi/IWificond.aidl

aidl对应的.h文件存放路径:


aidl对应的.cpp文件存放路径:

扫描二维码关注公众号,回复: 1956316 查看本文章


/out/target/product/xxxxxx/obj/STATIC_LIBRARIES/libwificond_ipc_intermediates/aidl-generated/src/aidl/android/net/wifi/IWificond.cpp


另外./system/connectivity/wificond对应的模块为wificond

可以通过“make wificond”编译出如下的执行文件,在system/bin下



2. 梳理下aidl的实现

参考https://www.jianshu.com/p/5f2ae92291af 或者 https://android.googlesource.com/platform/system/tools/aidl/+/brillo-m10-dev/docs/aidl-cpp.md

是有aidl-cpp这回事的,可以完成java和C++之间的IPC通信。


2.1 IWificond.aidl

./system/connectivity/wificond/aidl/android/net/wifi/IWificond.aidl

package android.net.wifi;


import android.net.wifi.IApInterface;
import android.net.wifi.IClientInterface;
import android.net.wifi.IInterfaceEventCallback;


// Service interface that exposes primitives for controlling the WiFi
// subsystems of a device.
interface IWificond {


    // Create a network interface suitable for use as an AP.
    @nullable IApInterface createApInterface();


    // Create a network interface suitable for use as a WiFi client.
    @nullable IClientInterface createClientInterface();


    // Tear down all existing interfaces.  This should enable clients to create
    // future interfaces immediately after this method returns.
    void tearDownInterfaces();


    // @return list of the currently configured IClientInterface instances.
    List<IBinder> GetClientInterfaces();


    // @return list of the currently configured IApInterface instances.
    List<IBinder> GetApInterfaces();


    // Register a callback to receive interface status updates.
    //
    // Multiple callbacks can be registered simultaneously.
    // Duplicate registrations of the same callback will be ignored.
    //
    // @param callback object to add to the set of registered callbacks.
    oneway void RegisterCallback(IInterfaceEventCallback callback);


    // Remove a callback from the set of registered callbacks.
    //
    // This must be the same instance as previously registered.
    // Requests to remove unknown callbacks will be ignored.
    //
    // @param callback object to remove from the set of registered callbacks.
    oneway void UnregisterCallback(IInterfaceEventCallback callback);
}


2.2 IWificond.h

/out/target/product/xxxxx/obj/STATIC_LIBRARIES/libwificond_ipc_intermediates/aidl-generated/include/android/net/wifi/IWificond.h

#ifndef AIDL_GENERATED_ANDROID_NET_WIFI_I_WIFICOND_H_
#define AIDL_GENERATED_ANDROID_NET_WIFI_I_WIFICOND_H_

#include <android/net/wifi/IApInterface.h>
#include <android/net/wifi/IClientInterface.h>
#include <android/net/wifi/IInterfaceEventCallback.h>
#include <binder/IBinder.h>
#include <binder/IInterface.h>
#include <binder/Status.h>
#include <utils/StrongPointer.h>
#include <vector>

namespace android {

namespace net {

namespace wifi {

class IWificond : public ::android::IInterface {
public:
DECLARE_META_INTERFACE(Wificond)
virtual ::android::binder::Status createApInterface(::android::sp<::android::net::wifi::IApInterface>* _aidl_return) = 0;
virtual ::android::binder::Status createClientInterface(::android::sp<::android::net::wifi::IClientInterface>* _aidl_return) = 0;
virtual ::android::binder::Status tearDownInterfaces() = 0;
virtual ::android::binder::Status GetClientInterfaces(::std::vector<::android::sp<::android::IBinder>>* _aidl_return) = 0;
virtual ::android::binder::Status GetApInterfaces(::std::vector<::android::sp<::android::IBinder>>* _aidl_return) = 0;
virtual ::android::binder::Status RegisterCallback(const ::android::sp<::android::net::wifi::IInterfaceEventCallback>& callback) = 0;
virtual ::android::binder::Status UnregisterCallback(const ::android::sp<::android::net::wifi::IInterfaceEventCallback>& callback) = 0;
enum Call {
  CREATEAPINTERFACE = ::android::IBinder::FIRST_CALL_TRANSACTION + 0,
  CREATECLIENTINTERFACE = ::android::IBinder::FIRST_CALL_TRANSACTION + 1,
  TEARDOWNINTERFACES = ::android::IBinder::FIRST_CALL_TRANSACTION + 2,
  GETCLIENTINTERFACES = ::android::IBinder::FIRST_CALL_TRANSACTION + 3,
  GETAPINTERFACES = ::android::IBinder::FIRST_CALL_TRANSACTION + 4,
  REGISTERCALLBACK = ::android::IBinder::FIRST_CALL_TRANSACTION + 5,
  UNREGISTERCALLBACK = ::android::IBinder::FIRST_CALL_TRANSACTION + 6,
};
};  // class IWificond

}  // namespace wifi

}  // namespace net

}  // namespace android

#endif  // AIDL_GENERATED_ANDROID_NET_WIFI_I_WIFICOND_H_


2.3 IWificond.cpp

/out/target/product/xxxxxx/obj/STATIC_LIBRARIES/libwificond_ipc_intermediates/aidl-generated/src/aidl/android/net/wifi/IWificond.cpp

#include <android/net/wifi/IWificond.h>
#include <android/net/wifi/BpWificond.h>

namespace android {

namespace net {

namespace wifi {

IMPLEMENT_META_INTERFACE(Wificond, "android.net.wifi.IWificond")

}  // namespace wifi

}  // namespace net

}  // namespace android
#include <android/net/wifi/BpWificond.h>
#include <binder/Parcel.h>

namespace android {

namespace net {

namespace wifi {

BpWificond::BpWificond(const ::android::sp<::android::IBinder>& _aidl_impl)
    : BpInterface<IWificond>(_aidl_impl){
}

::android::binder::Status BpWificond::createApInterface(::android::sp<::android::net::wifi::IApInterface>* _aidl_return) {
::android::Parcel _aidl_data;
::android::Parcel _aidl_reply;
::android::status_t _aidl_ret_status = ::android::OK;
::android::binder::Status _aidl_status;
_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_ret_status = remote()->transact(IWificond::CREATEAPINTERFACE, _aidl_data, &_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
if (!_aidl_status.isOk()) {
return _aidl_status;
}
_aidl_ret_status = _aidl_reply.readNullableStrongBinder(_aidl_return);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_error:
_aidl_status.setFromStatusT(_aidl_ret_status);
return _aidl_status;
}

::android::binder::Status BpWificond::createClientInterface(::android::sp<::android::net::wifi::IClientInterface>* _aidl_return) {
::android::Parcel _aidl_data;
::android::Parcel _aidl_reply;
::android::status_t _aidl_ret_status = ::android::OK;
::android::binder::Status _aidl_status;
_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_ret_status = remote()->transact(IWificond::CREATECLIENTINTERFACE, _aidl_data, &_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
if (!_aidl_status.isOk()) {
return _aidl_status;
}
_aidl_ret_status = _aidl_reply.readNullableStrongBinder(_aidl_return);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_error:
_aidl_status.setFromStatusT(_aidl_ret_status);
return _aidl_status;
}

::android::binder::Status BpWificond::tearDownInterfaces() {
::android::Parcel _aidl_data;
::android::Parcel _aidl_reply;
::android::status_t _aidl_ret_status = ::android::OK;
::android::binder::Status _aidl_status;
_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_ret_status = remote()->transact(IWificond::TEARDOWNINTERFACES, _aidl_data, &_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
if (!_aidl_status.isOk()) {
return _aidl_status;
}
_aidl_error:
_aidl_status.setFromStatusT(_aidl_ret_status);
return _aidl_status;
}

::android::binder::Status BpWificond::GetClientInterfaces(::std::vector<::android::sp<::android::IBinder>>* _aidl_return) {
::android::Parcel _aidl_data;
::android::Parcel _aidl_reply;
::android::status_t _aidl_ret_status = ::android::OK;
::android::binder::Status _aidl_status;
_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_ret_status = remote()->transact(IWificond::GETCLIENTINTERFACES, _aidl_data, &_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
if (!_aidl_status.isOk()) {
return _aidl_status;
}
_aidl_ret_status = _aidl_reply.readStrongBinderVector(_aidl_return);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_error:
_aidl_status.setFromStatusT(_aidl_ret_status);
return _aidl_status;
}

::android::binder::Status BpWificond::GetApInterfaces(::std::vector<::android::sp<::android::IBinder>>* _aidl_return) {
::android::Parcel _aidl_data;
::android::Parcel _aidl_reply;
::android::status_t _aidl_ret_status = ::android::OK;
::android::binder::Status _aidl_status;
_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_ret_status = remote()->transact(IWificond::GETAPINTERFACES, _aidl_data, &_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
if (!_aidl_status.isOk()) {
return _aidl_status;
}
_aidl_ret_status = _aidl_reply.readStrongBinderVector(_aidl_return);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_error:
_aidl_status.setFromStatusT(_aidl_ret_status);
return _aidl_status;
}

::android::binder::Status BpWificond::RegisterCallback(const ::android::sp<::android::net::wifi::IInterfaceEventCallback>& callback) {
::android::Parcel _aidl_data;
::android::Parcel _aidl_reply;
::android::status_t _aidl_ret_status = ::android::OK;
::android::binder::Status _aidl_status;
_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_ret_status = _aidl_data.writeStrongBinder(::android::net::wifi::IInterfaceEventCallback::asBinder(callback));
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_ret_status = remote()->transact(IWificond::REGISTERCALLBACK, _aidl_data, &_aidl_reply, ::android::IBinder::FLAG_ONEWAY);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_error:
_aidl_status.setFromStatusT(_aidl_ret_status);
return _aidl_status;
}

::android::binder::Status BpWificond::UnregisterCallback(const ::android::sp<::android::net::wifi::IInterfaceEventCallback>& callback) {
::android::Parcel _aidl_data;
::android::Parcel _aidl_reply;
::android::status_t _aidl_ret_status = ::android::OK;
::android::binder::Status _aidl_status;
_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_ret_status = _aidl_data.writeStrongBinder(::android::net::wifi::IInterfaceEventCallback::asBinder(callback));
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_ret_status = remote()->transact(IWificond::UNREGISTERCALLBACK, _aidl_data, &_aidl_reply, ::android::IBinder::FLAG_ONEWAY);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_error:
_aidl_status.setFromStatusT(_aidl_ret_status);
return _aidl_status;
}

}  // namespace wifi

}  // namespace net

}  // namespace android
#include <android/net/wifi/BnWificond.h>
#include <binder/Parcel.h>

namespace android {

namespace net {

namespace wifi {

::android::status_t BnWificond::onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) {
::android::status_t _aidl_ret_status = ::android::OK;
switch (_aidl_code) {
case Call::CREATEAPINTERFACE:
{
::android::sp<::android::net::wifi::IApInterface> _aidl_return;
if (!(_aidl_data.checkInterface(this))) {
_aidl_ret_status = ::android::BAD_TYPE;
break;
}
::android::binder::Status _aidl_status(createApInterface(&_aidl_return));
_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
if (!_aidl_status.isOk()) {
break;
}
_aidl_ret_status = _aidl_reply->writeStrongBinder(::android::net::wifi::IApInterface::asBinder(_aidl_return));
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
}
break;
case Call::CREATECLIENTINTERFACE:
{
::android::sp<::android::net::wifi::IClientInterface> _aidl_return;
if (!(_aidl_data.checkInterface(this))) {
_aidl_ret_status = ::android::BAD_TYPE;
break;
}
::android::binder::Status _aidl_status(createClientInterface(&_aidl_return));
_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
if (!_aidl_status.isOk()) {
break;
}
_aidl_ret_status = _aidl_reply->writeStrongBinder(::android::net::wifi::IClientInterface::asBinder(_aidl_return));
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
}
break;
case Call::TEARDOWNINTERFACES:
{
if (!(_aidl_data.checkInterface(this))) {
_aidl_ret_status = ::android::BAD_TYPE;
break;
}
::android::binder::Status _aidl_status(tearDownInterfaces());
_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
if (!_aidl_status.isOk()) {
break;
}
}
break;
case Call::GETCLIENTINTERFACES:
{
::std::vector<::android::sp<::android::IBinder>> _aidl_return;
if (!(_aidl_data.checkInterface(this))) {
_aidl_ret_status = ::android::BAD_TYPE;
break;
}
::android::binder::Status _aidl_status(GetClientInterfaces(&_aidl_return));
_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
if (!_aidl_status.isOk()) {
break;
}
_aidl_ret_status = _aidl_reply->writeStrongBinderVector(_aidl_return);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
}
break;
case Call::GETAPINTERFACES:
{
::std::vector<::android::sp<::android::IBinder>> _aidl_return;
if (!(_aidl_data.checkInterface(this))) {
_aidl_ret_status = ::android::BAD_TYPE;
break;
}
::android::binder::Status _aidl_status(GetApInterfaces(&_aidl_return));
_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
if (!_aidl_status.isOk()) {
break;
}
_aidl_ret_status = _aidl_reply->writeStrongBinderVector(_aidl_return);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
}
break;
case Call::REGISTERCALLBACK:
{
::android::sp<::android::net::wifi::IInterfaceEventCallback> in_callback;
if (!(_aidl_data.checkInterface(this))) {
_aidl_ret_status = ::android::BAD_TYPE;
break;
}
_aidl_ret_status = _aidl_data.readStrongBinder(&in_callback);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
::android::binder::Status _aidl_status(RegisterCallback(in_callback));
}
break;
case Call::UNREGISTERCALLBACK:
{
::android::sp<::android::net::wifi::IInterfaceEventCallback> in_callback;
if (!(_aidl_data.checkInterface(this))) {
_aidl_ret_status = ::android::BAD_TYPE;
break;
}
_aidl_ret_status = _aidl_data.readStrongBinder(&in_callback);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
::android::binder::Status _aidl_status(UnregisterCallback(in_callback));
}
break;
default:
{
_aidl_ret_status = ::android::BBinder::onTransact(_aidl_code, _aidl_data, _aidl_reply, _aidl_flags);
}
break;
}
if (_aidl_ret_status == ::android::UNEXPECTED_NULL) {
_aidl_ret_status = ::android::binder::Status::fromExceptionCode(::android::binder::Status::EX_NULL_POINTER).writeToParcel(_aidl_reply);
}
return _aidl_ret_status;
}

}  // namespace wifi

}  // namespace net

}  // namespace android

前面三个类比于java中的aidl和自动生成的实现类,c++多了.h和.cpp,对应于.java。


2.4 wificond.te

./system/sepolicy/public/wificond.te

# wificond
type wificond, domain;
type wificond_exec, exec_type, file_type;

binder_use(wificond)
binder_call(wificond, system_server)

add_service(wificond, wificond_service)

set_prop(wificond, wifi_prop)
set_prop(wificond, ctl_default_prop)

# create sockets to set interfaces up and down
allow wificond self:udp_socket create_socket_perms;
# setting interface state up/down is a privileged ioctl
allowxperm wificond self:udp_socket ioctl { SIOCSIFFLAGS };
allow wificond self:capability { net_admin net_raw };
# allow wificond to speak to nl80211 in the kernel
allow wificond self:netlink_socket create_socket_perms_no_ioctl;
# newer kernels (e.g. 4.4 but not 4.1) have a new class for sockets
allow wificond self:netlink_generic_socket create_socket_perms_no_ioctl;

r_dir_file(wificond, proc_net)

# wificond writes out configuration files for wpa_supplicant/hostapd.
# wificond also reads pid files out of this directory
allow wificond wifi_data_file:dir rw_dir_perms;
allow wificond wifi_data_file:file create_file_perms;

# allow wificond to check permission for dumping logs
allow wificond permission_service:service_manager find;

# dumpstate support
allow wificond dumpstate:fd use;
allow wificond dumpstate:fifo_file write;

这边看起来是添加wificond服务。


2.5 BnWificond.h

#ifndef AIDL_GENERATED_ANDROID_NET_WIFI_BN_WIFICOND_H_
#define AIDL_GENERATED_ANDROID_NET_WIFI_BN_WIFICOND_H_

#include <binder/IInterface.h>
#include <android/net/wifi/IWificond.h>

namespace android {

namespace net {

namespace wifi {

class BnWificond : public ::android::BnInterface<IWificond> {
public:
::android::status_t onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags = 0) override;
};  // class BnWificond

}  // namespace wifi

}  // namespace net

}  // namespace android

#endif  // AIDL_GENERATED_ANDROID_NET_WIFI_BN_WIFICOND_H_

暂且认为 BnWificond.h继承了IWificond.h,c++这块需要很好地补习一下。这里不是很懂,C++当时就学了个入门,都好多年没碰了。


2.6 server.h and server.cpp

那么如下server.h很满足服务端的条件。

/system/connectivity/wificond/server.h

#include "android/net/wifi/BnWificond.h"
#include "android/net/wifi/IApInterface.h"
#include "android/net/wifi/IClientInterface.h"
#include "android/net/wifi/IInterfaceEventCallback.h"

#include "wificond/ap_interface_impl.h"
#include "wificond/client_interface_impl.h"

namespace android {
namespace wificond {

class NL80211Packet;
class NetlinkUtils;
class ScanUtils;

struct InterfaceInfo;

class Server : public android::net::wifi::BnWificond {
 public:
  Server(std::unique_ptr<wifi_system::InterfaceTool> if_tool,
         std::unique_ptr<wifi_system::SupplicantManager> supplicant_man,
         std::unique_ptr<wifi_system::HostapdManager> hostapd_man,
         NetlinkUtils* netlink_utils,
         ScanUtils* scan_utils);
  ~Server() override = default;

  android::binder::Status RegisterCallback(
      const android::sp<android::net::wifi::IInterfaceEventCallback>&
          callback) override;
  android::binder::Status UnregisterCallback(
      const android::sp<android::net::wifi::IInterfaceEventCallback>&
          callback) override;

  android::binder::Status createApInterface(
      android::sp<android::net::wifi::IApInterface>*
          created_interface) override;

  android::binder::Status createClientInterface(
      android::sp<android::net::wifi::IClientInterface>*
          created_interface) override;

  android::binder::Status tearDownInterfaces() override;

  android::binder::Status GetClientInterfaces(
      std::vector<android::sp<android::IBinder>>* out_client_ifs) override;
...

对应的cpp文件

Status Server::createClientInterface(sp<IClientInterface>* created_interface) {
  InterfaceInfo interface;
  if (!SetupInterface(&interface)) {
    return Status::ok();  // Logging was done internally
  }

  unique_ptr<ClientInterfaceImpl> client_interface(new ClientInterfaceImpl(
      wiphy_index_,
      interface.name,
      interface.index,
      interface.mac_address,
      if_tool_.get(),
      supplicant_manager_.get(),
      netlink_utils_,
      scan_utils_));
  *created_interface = client_interface->GetBinder();
  client_interfaces_.push_back(std::move(client_interface));
  BroadcastClientInterfaceReady(client_interfaces_.back()->GetBinder());

  return Status::ok();
}

搜一下getWifiScannerImpl方法实现


这里看到只有client_interface_binder.cpp有对应实现

Status ClientInterfaceBinder::getWifiScannerImpl(
    sp<IWifiScannerImpl>* out_wifi_scanner_impl) {
  if (impl_ == nullptr) {
    *out_wifi_scanner_impl = nullptr;
    return Status::ok();
  }
  *out_wifi_scanner_impl = impl_->GetScanner();
  return Status::ok();
}

这边传入的参数还不知晓,只知道是IWifiScannerImpl的实现类,而impl_应该就是ClientInterfaceImpl。

而GetScanner方法:

./client_interface_impl.h:82:  const android::sp<ScannerImpl> GetScanner() { return scanner_; };

直接返回scanner_,所以看下ClientInterfaceImpl的scanner初始化为什么?


2.7 client_interface_impl.h and client_interface_impl.cpp


ClientInterfaceImpl::ClientInterfaceImpl(
    uint32_t wiphy_index,
    const std::string& interface_name,
    uint32_t interface_index,
    const std::vector<uint8_t>& interface_mac_addr,
    InterfaceTool* if_tool,
    SupplicantManager* supplicant_manager,
    NetlinkUtils* netlink_utils,
    ScanUtils* scan_utils)
    : wiphy_index_(wiphy_index),
      interface_name_(interface_name),
      interface_index_(interface_index),
      interface_mac_addr_(interface_mac_addr),
      if_tool_(if_tool),
      supplicant_manager_(supplicant_manager),
      netlink_utils_(netlink_utils),
      scan_utils_(scan_utils),
      offload_service_utils_(new OffloadServiceUtils()),
      mlme_event_handler_(new MlmeEventHandlerImpl(this)),
      binder_(new ClientInterfaceBinder(this)),
      is_associated_(false) {
  netlink_utils_->SubscribeMlmeEvent(
      interface_index_,
      mlme_event_handler_.get());
  if (!netlink_utils_->GetWiphyInfo(wiphy_index_,
                               &band_info_,
                               &scan_capabilities_,
                               &wiphy_features_)) {
    LOG(ERROR) << "Failed to get wiphy info from kernel";
  }
  LOG(INFO) << "create scanner for interface with index: "
            << (int)interface_index_;
  scanner_ = new ScannerImpl(wiphy_index,
                             interface_index_,
                             scan_capabilities_,
                             wiphy_features_,
                             this,
                             netlink_utils_,
                             scan_utils_,
                             offload_service_utils_);
}

ScannerImpl是IWifiScannerImpl的实现类(?)和Wificond应该是一样的。

namespace android {
namespace wificond {

class ClientInterfaceImpl;
class OffloadServiceUtils;
class ScanUtils;
class OffloadScanCallbackInterfaceImpl;
class OffloadScanManager;

class ScannerImpl : public android::net::wifi::BnWifiScannerImpl {

貌似流程对上了,继续看下ScannerImpl的构造方法

./scanning/scanner_impl.h:41:  ScannerImpl(uint32_t wiphy_index, uint32_t interface_index,
./scanning/scanner_impl.h:47:  ~ScannerImpl();
./scanning/scanner_impl.cpp:49:ScannerImpl::ScannerImpl(uint32_t wiphy_index, uint32_t interface_index,
./scanning/scanner_impl.cpp:89:ScannerImpl::~ScannerImpl() {}
namespace android {
namespace wificond {

ScannerImpl::ScannerImpl(uint32_t wiphy_index, uint32_t interface_index,
                         const ScanCapabilities& scan_capabilities,
                         const WiphyFeatures& wiphy_features,
                         ClientInterfaceImpl* client_interface,
                         NetlinkUtils* netlink_utils, ScanUtils* scan_utils,
                         weak_ptr<OffloadServiceUtils> offload_service_utils)
    : valid_(true),
      scan_started_(false),
      pno_scan_started_(false),
      offload_scan_supported_(false),
      pno_scan_running_over_offload_(false),
      pno_scan_results_from_offload_(false),
      wiphy_index_(wiphy_index),
      interface_index_(interface_index),
      scan_capabilities_(scan_capabilities),
      wiphy_features_(wiphy_features),
      client_interface_(client_interface),
      netlink_utils_(netlink_utils),
      scan_utils_(scan_utils),
      scan_event_handler_(nullptr) {
  // Subscribe one-shot scan result notification from kernel.
  LOG(INFO) << "subscribe scan result for interface with index: "
            << (int)interface_index_;
  scan_utils_->SubscribeScanResultNotification(
      interface_index_,
      std::bind(&ScannerImpl::OnScanResultsReady, this, _1, _2, _3, _4));
  // Subscribe scheduled scan result notification from kernel.
  scan_utils_->SubscribeSchedScanResultNotification(
      interface_index_,
      std::bind(&ScannerImpl::OnSchedScanResultsReady,
                this,
                _1, _2));
  std::shared_ptr<OffloadScanCallbackInterfaceImpl>
      offload_scan_callback_interface =
          offload_service_utils.lock()->GetOffloadScanCallbackInterface(this);
  offload_scan_manager_ = offload_service_utils.lock()->GetOffloadScanManager(
      offload_service_utils, offload_scan_callback_interface);
  offload_scan_supported_ = offload_service_utils.lock()->IsOffloadScanSupported();
}

看下这个类的scan方法

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();

  // 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, 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();
}

 这边会调用到scan_utils方法:




2.8 scan_utils.cpp

bool ScanUtils::Scan(uint32_t interface_index,
                     bool request_random_mac,
                     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);
  }


  if (request_random_mac) {
    trigger_scan.AddAttribute(
        NL80211Attr<uint32_t>(NL80211_ATTR_SCAN_FLAGS,
                              NL80211_SCAN_FLAG_RANDOM_ADDR));
  }
  // 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的命令,下面的逻辑只和命令下发有关,具体操作最终只看packet这个参数了。

搜了下

NetlinkManager: 接收来自kernel的3种UEVENT消息,并通过command listener转发给Java层的NetworkManagementService

什么鬼,我们是下发,可不是上报呀。。。这里先牵强附会的觉得是将命令下发到kernel吧=-=


2.9 netlink_manager.cpp

bool NetlinkManager::SendMessageAndGetAckOrError(const NL80211Packet& packet,
                                                 int* error_code) {
  unique_ptr<const NL80211Packet> response;
  if (!SendMessageAndGetSingleResponseOrError(packet, &response)) {
    return false;
  }
  uint16_t type = response->GetMessageType();
  if (type != NLMSG_ERROR) {
    LOG(ERROR) << "Receive unexpected message type :" << type;
    return false;
  }

  *error_code = response->GetErrorCode();
  return true;
}


bool NetlinkManager::SendMessageAndGetSingleResponseOrError(
    const NL80211Packet& packet,
    unique_ptr<const NL80211Packet>* response) {
  vector<unique_ptr<const NL80211Packet>> response_vec;
  if (!SendMessageAndGetResponses(packet, &response_vec)) {
    return false;
  }
  if (response_vec.size() != 1) {
    LOG(ERROR) << "Unexpected response size: " << response_vec.size();
    return false;
  }

  *response = std::move(response_vec[0]);
  return true;
}
bool NetlinkManager::SendMessageAndGetResponses(
    const NL80211Packet& packet,
    vector<unique_ptr<const NL80211Packet>>* response) {
  if (!SendMessageInternal(packet, sync_netlink_fd_.get())) {
    return false;
  }
  // Polling netlink socket, waiting for GetFamily reply.
  struct pollfd netlink_output;
  memset(&netlink_output, 0, sizeof(netlink_output));
  netlink_output.fd = sync_netlink_fd_.get();
  netlink_output.events = POLLIN;

  uint32_t sequence = packet.GetMessageSequence();

  int time_remaining = kMaximumNetlinkMessageWaitMilliSeconds;
  // Multipart messages may come with seperated datagrams, ending with a
  // NLMSG_DONE message.
  // ReceivePacketAndRunHandler() will remove the handler after receiving a
  // NLMSG_DONE message.
  message_handlers_[sequence] = std::bind(AppendPacket, response, _1);

  while (time_remaining > 0 &&
      message_handlers_.find(sequence) != message_handlers_.end()) {
    nsecs_t interval = systemTime(SYSTEM_TIME_MONOTONIC);
    int poll_return = poll(&netlink_output,
                           1,
                           time_remaining);

    if (poll_return == 0) {
      LOG(ERROR) << "Failed to poll netlink fd: time out ";
      message_handlers_.erase(sequence);
      return false;
    } else if (poll_return == -1) {
      LOG(ERROR) << "Failed to poll netlink fd: " << strerror(errno);
      message_handlers_.erase(sequence);
      return false;
    }
    ReceivePacketAndRunHandler(sync_netlink_fd_.get());
    interval = systemTime(SYSTEM_TIME_MONOTONIC) - interval;
    time_remaining -= static_cast<int>(ns2ms(interval));
  }
  if (time_remaining <= 0) {
    LOG(ERROR) << "Timeout waiting for netlink reply messages";
    message_handlers_.erase(sequence);
    return false;
  }
  return true;
}
bool NetlinkManager::SendMessageInternal(const NL80211Packet& packet, int fd) {
  const vector<uint8_t>& data = packet.GetConstData();
  ssize_t bytes_sent =
      TEMP_FAILURE_RETRY(send(fd, data.data(), data.size(), 0));
  if (bytes_sent == -1) {
    LOG(ERROR) << "Failed to send netlink message: " << strerror(errno);
    return false;
  }
  return true;
}

3. 总结

这次WiFi扫描的梳理艰难地到达了C++,这块具体怎么称呼也不清楚,梳理的地方回头看起来有不少牵强附会的地方,可以确定的是C++和java直接是可以通过aidl-cpp完成服务端和客户端交互的,WiFi的搜索命令也通过该机制下发到C++层继续实现。下阶段目标:重新复习下C++。。。


猜你喜欢

转载自blog.csdn.net/sinat_20059415/article/details/80945447