如何从Python代码中直接访问Android的Service(2)

正如代码中所示,这里对C++的IBinder和Parcel两个对象进行了封装,而Java的Service的底层实现也正是对这两个类进行封装的结果,具体的可以看

frameworks\base\core\jni\Android_util_Binder.cpp

的代码,

再来看下如何在Python中使用这些代码,这里用cython来封装这些C接口:

binder.pyx


cdef extern from "utils/Unicode.h": 

ctypedef short char16_t 

ctypedef unsigned int uint32_t 

cdef extern from "Python.h": 

ctypedef short Py_UNICODE 

ctypedef size_t Py_ssize_t 

object PyString_FromStringAndSize(const char *v, Py_ssize_t len) 

int PyString_AsStringAndSize(object obj, char **buffer, Py_ssize_t *length) 

object PyUnicode_FromUnicode(const Py_UNICODE *u, Py_ssize_t size) 

Py_UNICODE* PyUnicode_AS_UNICODE(object) 

Py_ssize_t PyUnicode_GetSize(object) 

void Py_INCREF(object) 

void Py_DECREF(object) 

cdef extern from "binder_wrap.h": 

ctypedef int (*vector_visitor)(const char16_t* str16,int length,void *data) 

int binder_listServices(vector_visitor visitor,void *data) 

ctypedef int (*fnOnTransact)(uint32_t code,const void *data,void *reply,uint32_t flags,void *userData) 

int server_create(const char *name,const char *descriptor,fnOnTransact onTrans,void *data) 

void* binder_getbinder(const char *name) 

int binder_releasebinder(void* binder) 

int binder_getInterfaceDescriptor(void *binder,char16_t *descriptor,int size) 

int binder_transact(void* binder,int code,const void *data,void* reply,int flags) 

void* parcel_new() 

int parcel_destroy(void* parcel) 

int parcel_writeInterfaceToken(void* parcel,const char *interface) 

int parcel_writeInt32(void *parcel,int val) 

int parcel_writeCString(void *parcel,const char* str) 

int parcel_writeString16(void *parcel,const char16_t* str, size_t len) 

int parcel_readInt32(void *parcel) 

int parcel_readInt64(void *parcel) 

int parcel_readString16(void *parcel,char16_t* str, size_t len) 

int parcel_readExceptionCode(void *parcel) 

int parcel_readInplace(void *parcel,void* data, int len) 

int parcel_dataAvail(void *parcel) 

cdef int visitor(const char16_t* str16,int length,void *data): 

arr = <object>data 

o = PyUnicode_FromUnicode(<Py_UNICODE*>str16,length) 

arr.append(o) 

def listServices(): 

arr = [] 

Py_INCREF(arr) 

binder_listServices(visitor,<void *>arr) 

Py_DECREF(arr) 

return arr 

cdef class Binder: 

cdef void *ptr 

def __cinit__(self,char *name): #, sp[IBinder] service): 

self.ptr = binder_getbinder(name) 

def __dealloc__(self): 

binder_releasebinder(self.ptr) 

def getInterfaceDescriptor(self): 

cdef char16_t descriptor[256] 

cdef int ret 

ret = binder_getInterfaceDescriptor(self.ptr,descriptor,sizeof(descriptor)) 

if not ret: 

return None 

return PyUnicode_FromUnicode(<Py_UNICODE*>descriptor,ret) 

def transact(self,int code,data,reply,int flags): 

cdef int dataPtr = data.getNativePtr() 

cdef int replyPtr = reply.getNativePtr() 

binder_transact(self.ptr,code,<void *>dataPtr,<void*>replyPtr,flags) 

return reply 

cdef class Parcel: 

cdef void *ptr 

cdef int nativePtr 

def __cinit__(self,unsigned int nativePtr=0): #, sp[IBinder] service): 

self.nativePtr = nativePtr 

if not nativePtr: 

self.ptr = parcel_new() 

else: 

self.ptr = <void *>nativePtr 

def __dealloc__(self): 

if not self.nativePtr: 

parcel_destroy(self.ptr) 

def getNativePtr(self): 

return <int>self.ptr 

def writeInterfaceToken(self,const char *interface): 

return parcel_writeInterfaceToken(<void *>self.ptr,interface) 

def writeInt(self,int val): 

self.writeInt32(val) 

def writeInt32(self,int val): 

return parcel_writeInt32(<void *>self.ptr,val) 

def writeCString(self,const char* cstr): 

return parcel_writeCString(<void *>self.ptr,cstr) 

def writeString16(self,ustr): 

cdef char16_t *un 

cdef int size 

if isinstance(ustr,unicode): 

un = <char16_t*>PyUnicode_AS_UNICODE(ustr) 

size = PyUnicode_GetSize(ustr) 

return parcel_writeString16(<void *>self.ptr,un,size) 

def readInt32(self): 

return parcel_readInt32(self.ptr) 

def readInt(self): 

return self.readInt32() 

def readInt64(self): 

return parcel_readInt64(self.ptr) 

def readExceptionCode(self): 

return parcel_readExceptionCode(self.ptr) 

def readString16(self): 

cdef char16_t str16[256] 

cdef int ret 

ret = parcel_readString16(self.ptr,str16,sizeof(str16)) 

if not ret: 

return None 

return PyUnicode_FromUnicode(<Py_UNICODE*>str16,ret) 

def readByteArray(self): 

return self.createByteArray() 

def createByteArray(self): 

length = self.readInt() 

print 'createByteArray:',length 

return self.readInplace(length) 

#    int parcel_readInplace(void *parcel,void* data, size_t len) 

def readInplace(self,length): 

cdef char arr[512] 

ret = parcel_readInplace(self.ptr,arr,length) 

if ret == length: 

return PyString_FromStringAndSize(arr,length) 

else: 

return None 

#    int parcel_dataAvail(void *parcel) 

def dataAvail(self): 

return parcel_dataAvail(self.ptr) 

def createTypedArrayList(self,creator): 

N = self.readInt() 

if N <= 0: 

return None 

arr = [] 

for i in range(N): 

if self.readInt() == 0: 

continue 

else: 

result = creator.createFromParcel(self) 

arr.append(result) 

return arr 

@classmethod 

def obtain(cls): 

return Parcel() 

@classmethod 

def recycle(cls): 

pass

好,再来看看如何来实现访问WifiService的功能:

WifiService.py


from binder import Binder,Parcel 

WIFI_SERVICE = "wifi"; 

DESCRIPTOR = "android.net.wifi.IWifiManager"; 

FIRST_CALL_TRANSACTION = 1 

TRANSACTION_getConfiguredNetworks = (FIRST_CALL_TRANSACTION + 0); 

TRANSACTION_addOrUpdateNetwork = (FIRST_CALL_TRANSACTION + 1); 

TRANSACTION_removeNetwork = (FIRST_CALL_TRANSACTION + 2); 

TRANSACTION_enableNetwork = (FIRST_CALL_TRANSACTION + 3); 

TRANSACTION_disableNetwork = (FIRST_CALL_TRANSACTION + 4); 

TRANSACTION_pingSupplicant = (FIRST_CALL_TRANSACTION + 5); 

TRANSACTION_startScan = (FIRST_CALL_TRANSACTION + 6); 

TRANSACTION_getScanResults = (FIRST_CALL_TRANSACTION + 7); 

TRANSACTION_disconnect = (FIRST_CALL_TRANSACTION + 8); 

TRANSACTION_reconnect = (FIRST_CALL_TRANSACTION + 9); 

TRANSACTION_reassociate = (FIRST_CALL_TRANSACTION + 10); 

TRANSACTION_getConnectionInfo = (FIRST_CALL_TRANSACTION + 11); 

TRANSACTION_setWifiEnabled = (FIRST_CALL_TRANSACTION + 12); 

TRANSACTION_getWifiEnabledState = (FIRST_CALL_TRANSACTION + 13); 

TRANSACTION_setCountryCode = (FIRST_CALL_TRANSACTION + 14); 

TRANSACTION_setFrequencyBand = (FIRST_CALL_TRANSACTION + 15); 

TRANSACTION_getFrequencyBand = (FIRST_CALL_TRANSACTION + 16); 

TRANSACTION_isDualBandSupported = (FIRST_CALL_TRANSACTION + 17); 

TRANSACTION_saveConfiguration = (FIRST_CALL_TRANSACTION + 18); 

TRANSACTION_getDhcpInfo = (FIRST_CALL_TRANSACTION + 19); 

TRANSACTION_acquireWifiLock = (FIRST_CALL_TRANSACTION + 20); 

TRANSACTION_updateWifiLockWorkSource = (FIRST_CALL_TRANSACTION + 21); 

TRANSACTION_releaseWifiLock = (FIRST_CALL_TRANSACTION + 22); 

TRANSACTION_initializeMulticastFiltering = (FIRST_CALL_TRANSACTION + 23); 

TRANSACTION_isMulticastEnabled = (FIRST_CALL_TRANSACTION + 24); 

TRANSACTION_acquireMulticastLock = (FIRST_CALL_TRANSACTION + 25); 

TRANSACTION_releaseMulticastLock = (FIRST_CALL_TRANSACTION + 26); 

TRANSACTION_setWifiApEnabled = (FIRST_CALL_TRANSACTION + 27); 

TRANSACTION_getWifiApEnabledState = (FIRST_CALL_TRANSACTION + 28); 

TRANSACTION_getWifiApConfiguration = (FIRST_CALL_TRANSACTION + 29); 

TRANSACTION_setWifiApConfiguration = (FIRST_CALL_TRANSACTION + 30); 

TRANSACTION_startWifi = (FIRST_CALL_TRANSACTION + 31); 

TRANSACTION_stopWifi = (FIRST_CALL_TRANSACTION + 32); 

TRANSACTION_addToBlacklist = (FIRST_CALL_TRANSACTION + 33); 

TRANSACTION_clearBlacklist = (FIRST_CALL_TRANSACTION + 34); 

TRANSACTION_getWifiServiceMessenger = (FIRST_CALL_TRANSACTION + 35); 

TRANSACTION_getWifiStateMachineMessenger = (FIRST_CALL_TRANSACTION + 36); 

TRANSACTION_getConfigFile = (FIRST_CALL_TRANSACTION + 37); 

TRANSACTION_captivePortalCheckComplete = (FIRST_CALL_TRANSACTION + 38); 

mRemote = Binder(WIFI_SERVICE) 

def transact(TRANSACTION): 

_data = Parcel() 

_reply = Parcel() 

_data.writeInterfaceToken(DESCRIPTOR) 

mRemote.transact(TRANSACTION, _data, _reply, 0) 

_reply.readExceptionCode() 

return _reply.readInt32() 

def getConfiguredNetworks(): 

pass 

def addOrUpdateNetwork(): 

pass 

def removeNetwork(): 

pass 

def enableNetwork(netId,disableOthers): 

_data = Parcel() 

_reply = Parcel() 

_data.writeInterfaceToken(DESCRIPTOR) 

_data.writeInt32(netId) 

if disableOthers: 

_data.writeInt32(1) 

else: 

_data.writeInt32(0) 

mRemote.transact(TRANSACTION_enableNetwork, _data, _reply, 0) 

_reply.readExceptionCode() 

return _reply.readInt32() != 0 

def disableNetwork(netId): 

_data = Parcel() 

_reply = Parcel() 

_data.writeInterfaceToken(DESCRIPTOR) 

_data.writeInt32(netId) 

mRemote.transact(TRANSACTION_disableNetwork, _data, _reply, 0) 

_reply.readExceptionCode() 

return _reply.readInt32() != 0 

def pingSupplicant(): 

_data = Parcel() 

_reply = Parcel() 

_data.writeInterfaceToken(DESCRIPTOR) 

mRemote.transact(TRANSACTION_pingSupplicant, _data, _reply, 0) 

_reply.readExceptionCode() 

return _reply.readInt32() != 0 

def startScan(forceActive): 

_data = Parcel() 

_reply = Parcel() 

ret = 0 

try: 

_data.writeInterfaceToken(DESCRIPTOR) 

if forceActive: 

_data.writeInt(1) 

else: 

_data.writeInt(0) 

mRemote.transact(TRANSACTION_startScan, _data, _reply, 0) 

ret = _reply.readExceptionCode() 

finally: 

_reply.recycle() 

_data.recycle() 

return ret == 0 

class ScanResult: 

def __init__(self,ssid,bssid,caps,level,frequency,timestamp): 

self.ssid = ssid 

self.bssid = bssid 

self.caps = caps 

self.level = level 

self.frequency = frequency 

self.timestamp = timestamp 

@classmethod 

def createFromParcel(cls,reply): 

has_ssid = reply.readInt32() 

ssid = None 

if has_ssid: 

ssid_lengt = reply.readInt() 

ssid = reply.readByteArray() 

BSSID = reply.readString16() 

caps = reply.readString16() 

level = reply.readInt() 

frequency = reply.readInt() 

timestamp = reply.readInt64() 

print 'BSSID:',BSSID     

print 'caps:',caps 

print 'level:',level 

print 'frequency:',frequency 

print 'timestamp:',timestamp 

return ScanResult(ssid,BSSID,caps,level,frequency,timestamp) 

def getScanResults(): 

_data = Parcel.obtain() 

_reply = Parcel.obtain() 

_result = None 

try: 

_data.writeInterfaceToken(DESCRIPTOR) 

mRemote.transact(TRANSACTION_getScanResults, _data, _reply, 0) 

if 0 != _reply.readExceptionCode(): 

return None 

_result = _reply.createTypedArrayList(ScanResult) 

finally: 

_reply.recycle() 

_data.recycle() 

return _result 

def disconnect(): 

return transact(TRANSACTION_disconnect) != 0 

def reconnect(): 

return transact(TRANSACTION_reconnect) != 0 

def reassociate(): 

return transact(TRANSACTION_reassociate) != 0 

"""

class WifiInfo:

def __init__():

pass

@classmethod

def createFromParcel(cls,r):

info = WifiInfo();

info.networkId  = r.readInt32()

info.rssi = r.readInt32()

info.linkSpeed = r.readInt32()

if r.readByte() == 1:

info.setInetAddress(InetAddress.getByAddress(in.createByteArray()))

if r.readInt() == 1:

info.mWifiSsid = WifiSsid.CREATOR.createFromParcel(r)

info.mBSSID = r.readString16()

info.mMacAddress = r.readString16()

info.mMeteredHint = r.readInt32() != 0

""" 

def getConnectionInfo(): 

pass 

def setWifiEnabled(enable): 

_data = Parcel() 

_reply = Parcel() 

_data.writeInterfaceToken(DESCRIPTOR) 

if enable: 

_data.writeInt32(1) 

else: 

_data.writeInt32(0) 

mRemote.transact(TRANSACTION_setWifiEnabled, _data,_reply,0) 

_reply.readExceptionCode() 

_result = (0!=_reply.readInt32()) 

return _result; 

def getWifiEnabledState(): 

return transact(TRANSACTION_getWifiEnabledState) 

def setCountryCode(country,persist): 

_data = Parcel() 

_reply = Parcel() 

_data.writeInterfaceToken(DESCRIPTOR) 

if isinstance(country,str): 

country = unicode(contry) 

_data.writeString16(country) 

if persist: 

_data.writeInt32(1) 

else: 

_data.writeInt32(0) 

mRemote.transact(TRANSACTION_setCountryCode, _data,_reply,0) 

_reply.readExceptionCode() 

_result = (0!=_reply.readInt32()) 

return _result; 

def setFrequencyBand(band, persist): 

_data = Parcel() 

_reply = Parcel() 

_data.writeInterfaceToken(DESCRIPTOR) 

if isinstance(country,str): 

country = unicode(contry) 

_data.writeInt32(band) 

if persist: 

_data.writeInt32(1) 

else: 

_data.writeInt32(0) 

mRemote.transact(TRANSACTION_setFrequencyBand, _data,_reply,0) 

_reply.readExceptionCode() 

_result = (0!=_reply.readInt32()) 

return _result; 

def getFrequencyBand(): 

return transact(TRANSACTION_getFrequencyBand) 

def isDualBandSupported(): 

return transact(TRANSACTION_isDualBandSupported) != 0 

def saveConfiguration(): 

pass 

def get_readable_address(addr): 

return "%d:%d:%d:%d"%(addr&0xff,(addr>>8)&0xff,(addr>>16)&0xff,(addr>>24)&0xff) 

def getDhcpInfo(): 

_data = Parcel() 

_reply = Parcel() 

_data.writeInterfaceToken(DESCRIPTOR) 

mRemote.transact(TRANSACTION_getDhcpInfo, _data,_reply,0) 

_reply.readExceptionCode() 

if 0 == _reply.readInt32(): 

return None 

ipAddress = get_readable_address(reply.readInt32()); 

gateway = get_readable_address(reply.readInt32()); 

netmask = get_readable_address(reply.readInt32()); 

dns1 = get_readable_address(reply.readInt32()); 

dns2 = get_readable_address(reply.readInt32()); 

serverAddress = get_readable_address(reply.readInt32()); 

leaseDuration = get_readable_address(reply.readInt32()); 

info = (ipAddress,gateway,netmask,dns1,dns2,serverAddress,leaseDuration) 

print "ipAddress %s,\ngateway %s,\nnetmask %s,\ndns1 %s,\ndns2 %s,\nserverAddress %s,\nleaseDuration %s"%info 

return info 

def acquireWifiLock(): 

pass 

def updateWifiLockWorkSource(): 

pass 

def releaseWifiLock(): 

pass 

def initializeMulticastFiltering(): 

pass 

def isMulticastEnabled(): 

pass 

def acquireMulticastLock(): 

pass 

def releaseMulticastLock(): 

pass 

def setWifiApEnabled(wifiConfig,enable): 

_data = Parcel() 

_reply = Parcel() 

_data.writeInterfaceToken(DESCRIPTOR) 

if wifiConfig: 

_data.writeInt32(1) 

wifiConfig.writeToParcel(_data) 

else: 

_data.writeInt32(0) 

if enable: 

_data.writeInt32(1) 

else: 

_data.writeInt32(0) 

mRemote.transact(TRANSACTION_setWifiApEnabled, _data,_reply,0) 

_reply.readExceptionCode() 

def getWifiApEnabledState(): 

return transact(TRANSACTION_getWifiApEnabledState) 

def getWifiApConfiguration(): 

pass 

def setWifiApConfiguration(): 

pass 

def startWifi(): 

return transact(TRANSACTION_startWifi) 

def stopWifi(): 

return transact(TRANSACTION_stopWifi) 

def addToBlacklist(bssid): 

_data = Parcel() 

_reply = Parcel() 

_data.writeInterfaceToken(DESCRIPTOR) 

if isinstance(bssid,str): 

bssid = unicode(bssid) 

_data.writeString16(bssid) 

mRemote.transact(TRANSACTION_addToBlacklist, _data,_reply,0) 

_reply.readExceptionCode() 

def clearBlacklist(): 

return transact(TRANSACTION_clearBlacklist) 

def getWifiServiceMessenger(): 

pass 

def getWifiStateMachineMessenger(): 

pass 

def getConfigFile(): 

_data = Parcel() 

_reply = Parcel() 

_data.writeInterfaceToken(DESCRIPTOR) 

mRemote.transact(TRANSACTION_getConfigFile, _data,_reply,0) 

_reply.readExceptionCode() 

return _reply.readString16() 

def captivePortalCheckComplete(): 

return transact(TRANSACTION_captivePortalCheckComplete) != 0

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/5886a8e55bfd59716ea874ae9aef230a.html