如何从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);
}

基本的思路很简单:

先通过:

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.csdn.net/detail/i2cbus/7613361

如何从C++代码直接访问android framework层的WifiService

时间: 2024-10-30 08:05:28

如何从C++代码直接访问android framework层的WifiService的相关文章

怎样从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/IPCThreadSt

android framework层 学习笔记(一)

大体结构 最近在研究android framework层的开发.  先来一张frame work的源码结构图 1  api 文件夹  不清楚用途,该目录下只有一个current.txt 内容看上去像代码,先放一放 2  cmds 文件夹,顾名思义是android 所支持的 command (命令) 最明显就是里面第一个文件夹就是am ,对应着android中的am 命令. 其他的命令里面有C语言写的也有java+C的. 3    core  文件夹这个文件夹下面有四个文件 java jni re

Android Framework层Power键关机流程(一,Power长按键操作处理)

一:Android处理Power按键长按操作 在Framework层中,Android4.x对Power键(KeyEvent.KEYCODE_POWER)的操作,我们从PhoneWindowManager开始分析,在分析前我这里打印了该方法的堆栈调用信息.大家可以参考一下. public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) { ...... android.uti

Android framework层JNI的使用浅析

尊重原创:http://blog.csdn.net/yuanzeyao/article/details/42418977 JNI技术对于多java开发的朋友相信并不陌生,即(java native interface),本地调用接口,主要功能有以下两点: 1.java层调用C/C++层代码 2.C/C++层调用java层代码 可能有些人会觉得jni技术破坏了Java语言的跨平台性,有这种想法可能是因为你对java理解得还不够深,如果你看看jdk源码,你会发现在jdk里面大量使用了jni技术,而且

译android framework层的资源文件

1.将资源放入 frameworks/base/core/res/res/ 中的相应目录,假设要添加的资源是 drawable 类型,文件名为 test(后缀可能为xml或者png等等),则将文件放入 frameworks/base/core/res/res/drawable*/ 下. 2.仿照已有的同类型系统资源修改 framework/base/core/res/res/values/public.xml,public.xml中有两种类型的资源描述,一种是<java-symbol/>系统私

android framework层 学习笔记(二)

 /framework/cmds   部分 这部分主要是命令的实现部分. android 本身是支持一部分linux命令的,并且再次基础上android又添加了一些他自身独有的命令,而这些命令正在存放在/framework/cmds文件夹下面的. 先来看第一个例子: am am 命令,我没能在源码中找到解释am具体的作用的描述文档,我只能根据源码来自己形容他,这个是一个用于开启组件的命令,包括activity 还有 service . ok,我的描述结束,接下来看源码: public class

Android Framework层Power键关机流程(二,关机流程)

二,关机流程 从前一篇博文我们知道,当用户长按Power键时会弹出(关机.重新启动,飞行模式等选项)对话框,我们点击关机,则会弹出关机确认对话框.那么从选项对话框到关机确认对话框又是一个什么流程呢.以下我们在简单分析一下: showGlobalActionsDialog()-->showDialog()-->handleShow()-->createDialog()-->onPress()-->shutdown() PhoneWindowManager.java void s

如何从python代码中直接访问Android的Service

在Kivy中,通过pyjnius扩展可以间接调用Java代码,而pyjnius利用的是Java的反射机制.但是在Python对象和Java对象中转来转去总让人感觉到十分别扭.好在android提供了binder这个进程间通信的功能,Java中的Service也是基于Binder的C++代码封装来实现进程间通信的,这也为从Python代码中绕开pyjnius直接访问Java代码提供了可能,既然Java的Service是基于C++的封装来实现的,也同样可以在Python中封装同样的C++代码,这篇文

Kivy A to Z -- 如何从python代码中直接访问Android的Service

在Kivy中,通过pyjnius扩展可以间接调用Java代码,而pyjnius利用的是Java的反射机制.但是在Python对象和Java对象中转来转去总让人感觉到十分别扭.好在android提供了binder这个进程间通信的功能,Java中的Service也是基于Binder的C++代码封装来实现进程间通信的,这也为从Python代码中绕开pyjnius直接访问Java代码提供了可能,既然Java的Service是基于C++的封装来实现的,也同样可以在Python中封装同样的C++代码,这篇文