怎样从C++代码直接訪问android framework层的WifiService

时间:2023-03-09 05:03:33
怎样从C++代码直接訪问android framework层的WifiService

说究竟,Java层的service就是就C++层的binder的封装。所以从原理上来讲通过C++代码直接訪问android framework层的service是全然可能的,这篇文章以訪问WifiService为例,解说怎样去实现这个功能。

费话少说。直接上代码:

WifiTest.cpp

#include <sys/types.h>
#include <unistd.h>
#include <grp.h> #include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h> #include <utils/String16.h>
//#include <utils/Vector.h>
#include <utils/List.h>
#include <utils/PropertyMap.h> using namespace android; #define WIFI_SERVICE "wifi"
const String16 WIFI_DESCRIPTOR("android.net.wifi.IWifiManager"); class ScanResult
{ private:
ScanResult& operator=(const ScanResult& o); public:
ScanResult(const ScanResult& o):
mSsid(o.mSsid),mBssid(o.mBssid),mCaps(o.mCaps),mLevel(o.mLevel),mFrequency(o.mFrequency),mTimestamp(o.mTimestamp)
{
} ScanResult(String8 ssid,String16 bssid,String16 caps,int level,int freq,int64_t timeStamp):
mSsid(ssid),mBssid(bssid),mCaps(caps),mLevel(level),mFrequency(freq),mTimestamp(timeStamp)
{
}
void dump()
{
char temp[130];
int size;
memset(temp,0,sizeof(temp));
printf("ssid %s \n",mSsid.string()); size = mBssid.size();
if(size > sizeof(temp)/2 - 1)
{
size = sizeof(temp)/2 - 1;
}
utf16_to_utf8(mBssid.string(), size, temp);
printf("Bssid %s \n",temp); size = mCaps.size();
if(size > sizeof(temp)/2 - 1)
{
size = sizeof(temp)/2 - 1;
}
utf16_to_utf8(mCaps.string(), size, temp);
printf("ssid %s \n",temp); printf("level %d \n",mLevel);
printf("freq %d \n",mFrequency);
printf("freq %ld \n",mTimestamp);
}
private:
String8 mSsid;
String16 mBssid;
String16 mCaps;
int mLevel;
int mFrequency;
int64_t mTimestamp;
}; class IWifiService: public android::IInterface {
public:
DECLARE_META_INTERFACE(WifiService) virtual void startScan(int forceActive) = 0;
virtual int getScanResults(List<ScanResult> &list) = 0;
virtual bool setWifiEnabled(bool enable) = 0;
}; class BpWifiService: public android::BpInterface<IWifiService>
{
enum
{
FIRST_CALL_TRANSACTION = 1,
TRANSACTION_getConfiguredNetworks = (android::IBinder::FIRST_CALL_TRANSACTION + 0),
TRANSACTION_addOrUpdateNetwork = (android::IBinder::FIRST_CALL_TRANSACTION + 1),
TRANSACTION_removeNetwork = (android::IBinder::FIRST_CALL_TRANSACTION + 2),
TRANSACTION_enableNetwork = (android::IBinder::FIRST_CALL_TRANSACTION + 3),
TRANSACTION_disableNetwork = (android::IBinder::FIRST_CALL_TRANSACTION + 4),
TRANSACTION_pingSupplicant = (android::IBinder::FIRST_CALL_TRANSACTION + 5),
TRANSACTION_startScan = (android::IBinder::FIRST_CALL_TRANSACTION + 6),
TRANSACTION_getScanResults = (android::IBinder::FIRST_CALL_TRANSACTION + 7),
TRANSACTION_disconnect = (android::IBinder::FIRST_CALL_TRANSACTION + 8),
TRANSACTION_reconnect = (android::IBinder::FIRST_CALL_TRANSACTION + 9),
TRANSACTION_reassociate = (android::IBinder::FIRST_CALL_TRANSACTION + 10),
TRANSACTION_getConnectionInfo = (android::IBinder::FIRST_CALL_TRANSACTION + 11),
TRANSACTION_setWifiEnabled = (android::IBinder::FIRST_CALL_TRANSACTION + 12),
TRANSACTION_getWifiEnabledState = (android::IBinder::FIRST_CALL_TRANSACTION + 13),
TRANSACTION_setCountryCode = (android::IBinder::FIRST_CALL_TRANSACTION + 14),
TRANSACTION_setFrequencyBand = (android::IBinder::FIRST_CALL_TRANSACTION + 15),
TRANSACTION_getFrequencyBand = (android::IBinder::FIRST_CALL_TRANSACTION + 16),
TRANSACTION_isDualBandSupported = (android::IBinder::FIRST_CALL_TRANSACTION + 17),
TRANSACTION_saveConfiguration = (android::IBinder::FIRST_CALL_TRANSACTION + 18),
TRANSACTION_getDhcpInfo = (android::IBinder::FIRST_CALL_TRANSACTION + 19),
TRANSACTION_acquireWifiLock = (android::IBinder::FIRST_CALL_TRANSACTION + 20),
TRANSACTION_updateWifiLockWorkSource = (android::IBinder::FIRST_CALL_TRANSACTION + 21),
TRANSACTION_releaseWifiLock = (android::IBinder::FIRST_CALL_TRANSACTION + 22),
TRANSACTION_initializeMulticastFiltering = (android::IBinder::FIRST_CALL_TRANSACTION + 23),
TRANSACTION_isMulticastEnabled = (android::IBinder::FIRST_CALL_TRANSACTION + 24),
TRANSACTION_acquireMulticastLock = (android::IBinder::FIRST_CALL_TRANSACTION + 25),
TRANSACTION_releaseMulticastLock = (android::IBinder::FIRST_CALL_TRANSACTION + 26),
TRANSACTION_setWifiApEnabled = (android::IBinder::FIRST_CALL_TRANSACTION + 27),
TRANSACTION_getWifiApEnabledState = (android::IBinder::FIRST_CALL_TRANSACTION + 28),
TRANSACTION_getWifiApConfiguration = (android::IBinder::FIRST_CALL_TRANSACTION + 29),
TRANSACTION_setWifiApConfiguration = (android::IBinder::FIRST_CALL_TRANSACTION + 30),
TRANSACTION_startWifi = (android::IBinder::FIRST_CALL_TRANSACTION + 31),
TRANSACTION_stopWifi = (android::IBinder::FIRST_CALL_TRANSACTION + 32),
TRANSACTION_addToBlacklist = (android::IBinder::FIRST_CALL_TRANSACTION + 33),
TRANSACTION_clearBlacklist = (android::IBinder::FIRST_CALL_TRANSACTION + 34),
TRANSACTION_getWifiServiceMessenger = (android::IBinder::FIRST_CALL_TRANSACTION + 35),
TRANSACTION_getWifiStateMachineMessenger = (android::IBinder::FIRST_CALL_TRANSACTION + 36),
TRANSACTION_getConfigFile = (android::IBinder::FIRST_CALL_TRANSACTION + 37),
TRANSACTION_captivePortalCheckComplete = (android::IBinder::FIRST_CALL_TRANSACTION + 38),
};
public:
BpWifiService(const android::sp<android::IBinder>& impl): android::BpInterface<IWifiService>(impl)
{
} void startScan(int forceActive)
{
android::Parcel data, reply;
data.writeInterfaceToken(WIFI_DESCRIPTOR);
if (forceActive)
{
data.writeInt32(1);
}
else
{
data.writeInt32(0);
}
remote()->transact(TRANSACTION_startScan, data, &reply, 0);
} virtual int getScanResults(List<ScanResult> &list)
{
Parcel data, reply;
data.writeInterfaceToken(WIFI_DESCRIPTOR);
remote()->transact(TRANSACTION_getScanResults, data, &reply, 0);
if (0 != reply.readExceptionCode())
{
return 0;
}
int count = reply.readInt32();
for (int i=0;i<count;i++)
{
String8 ssid;
int res = reply.readInt32();
if (res != 0)
{
reply.readInt32();
reply.readInt32();
int length = reply.readInt32();
ssid = String8((const char*)reply.readInplace(length),length);
} // utf16_to_utf8(const char16_t* src, size_t src_len, char* dst); String16 BSSID = reply.readString16();
String16 caps = reply.readString16();
int level = reply.readInt32();
int frequency = reply.readInt32();
int64_t timestamp = reply.readInt64();
ScanResult result(ssid,BSSID,caps,level,frequency,timestamp);
list.push_back(result);
}
return count;
} bool setWifiEnabled(bool enable)
{
Parcel data, reply;
data.writeInterfaceToken(WIFI_DESCRIPTOR); if(enable)
data.writeInt32(1);
else
data.writeInt32(0);
remote()->transact(TRANSACTION_setWifiEnabled, data,&reply,0);
reply.readExceptionCode();
return 0!=reply.readInt32();
} }; IMPLEMENT_META_INTERFACE(WifiService, WIFI_DESCRIPTOR) int main(int argc, char *argv[])
{ android::sp<android::IServiceManager> sm = android::defaultServiceManager();
android::sp<android::IBinder> binder;
android::sp<IWifiService> wifi; binder = sm->getService(android::String16(WIFI_SERVICE)); if (binder == 0)
{
return 1;
} wifi = android::interface_cast<IWifiService>(binder); wifi->setWifiEnabled(true);
printf("+++++scan start");
wifi->startScan(1); for(int i=0;i<10;i++)
{
usleep(1*1000*1000);
List<ScanResult> list;
wifi->getScanResults(list);
if(list.size() > 0)
{
for(List<ScanResult>::iterator it = list.begin();it != list.end();++it)
{
(*it).dump();
}
break;
}
} return(0);
}

主要的思路非常easy:

先通过:

android::defaultServiceManager()->getService(android::String16(WIFI_SERVICE));

获取binder接口。再通过Parcel读与binder,详细的实现能够參考IWifiManager.java的代码。

编译后执行以上的代码能够得到类似下面的输出:

ssid wifitest

Bssid b8:55:10:84:13:57

ssid [WPA-PSK-CCMP][WPA2-PSK-CCMP][WPS][ESS]

level -55

freq 2447

time stamp 1073922473

ssid test

Bssid 08:bd:43:c3:a9:96

ssid [WPA2-PSK-CCMP][WPS][ESS]

level -66

freq 2462

time stamp 1073922473

完整代码下载:

http://download.****.net/detail/i2cbus/7613361