IBinder

I will use call IAudioFlinger::setMode API as a sample scenario to show how the Android IPC
system works. AudioFlinger is a service in the media_server program
Service Manager Run
service_manager provide service manager service to other process. It must be started before any
other service gets running.
int main(int argc, char **argv)
{
struct binder_state *bs;
void *svcmgr = BINDER_SERVICE_MANAGER;
bs = binder_open(128*1024);
if (binder_become_context_manager(bs)) {
LOGE("cannot become context manager (%s)/n", strerror(errno));
return -1;
}
svcmgr_handle = svcmgr;
binder_loop(bs, svcmgr_handler);
return 0;
}
It first open “/dev/binder” driver and then call BINDER_SET_CONTEXT_MGR ioctl to let
binder kernel driver know it acts as a manager. Then it enters into a loop to wait for any data from
other process.
void binder_loop(struct binder_state *bs, binder_handler func)
{
int res;
struct binder_write_read bwr;
unsigned readbuf[32];
bwr.write_size = 0;
bwr.write_consumed = 0;
bwr.write_buffer = 0;
readbuf[0] = BC_ENTER_LOOPER;
binder_write(bs, readbuf, sizeof(unsigned));
for (;;) {
bwr.read_size = sizeof(readbuf);
bwr.read_consumed = 0;
bwr.read_buffer = (unsigned) readbuf;
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
if (res < 0) {
LOGE("binder_loop: ioctl failed (%s)/n", strerror(errno));
break;
}
res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func);
if (res == 0) {
LOGE("binder_loop: unexpected reply?!/n");
break;
}
if (res < 0) {
LOGE("binder_loop: io error %d %s/n", res, strerror(errno));
break;
}
}
}
Pay attention to BINDER_SERVICE_MANAGER.
/* the one magic object */
#define BINDER_SERVICE_MANAGER ((void*) 0)
BINDER_SERVICE_MANAGER is the registered handle for service_manager. The other process
must use this handle to talk with service_manager.
Get IServiceManager
To get an IServiceManager instance the only method is to call defaultServiceManager
implemented in IServiceManager.cpp.
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
if (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
}
}
return gDefaultServiceManager;
}
gDefaultServiceManager is defined in libutil, so any program or library which included libutil will
have this symbol, it’s unique in one process. The first time gDefaultServiceManager is NULL, so
it will first get a ProcessState instance through ProcessState::self(). One process has only one
ProcessState instance. ProcessState will open “/dev/binder” driver for IPCThreadState use.
ProcessState::ProcessState()
: mDriverFD(open_driver())
Now we have an instance of ProcessState, let’s look at the getContextObject.
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
{
if (supportsProcesses()) {
return getStrongProxyForHandle(0);
} else {
return getContextObject(String16("default"), caller);
}
}
The board support binder driver, so we will get into getStrongProxyForHandle. (Handle 0 is
reserved for service manager, which will be explained later.)
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
// We need to create a new BpBinder if there isn't currently one, OR we
// are unable to acquire a weak reference on this current one. See comment
// in getWeakProxyForHandle() for more info about this.
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
b = new BpBinder(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
// This little bit of nastyness is to allow us to add a primary
// reference to the remote proxy when this team doesn't have one
// but another team is sending the handle to us.
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
The first time b will be NULL, so the code will new an BpBinder instance. BpBinder is a base
proxy class for remote binder object.
BpBinder::BpBinder(int32_t handle)
: mHandle(handle)
, mAlive(1)
, mObitsSent(0)
, mObituaries(NULL)
{
LOGV("Creating BpBinder %p handle %d/n", this, mHandle);
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
IPCThreadState::self()->incWeakHandle(handle);
}
IPCThreadState::incWeakHandle will add a BC_INCREFS command in output buffer.
void IPCThreadState::incWeakHandle(int32_t handle)
{
LOG_REMOTEREFS("IPCThreadState::incWeakHandle(%d)/n", handle);
mOut.writeInt32(BC_INCREFS);
mOut.writeInt32(handle);
}
Now getContextObject returns a BpBinder instance, it will be interface_cast to IServiceManager.
interface_cast is defined in IInterface.h. It will be extended as:
inline sp<IServiceManager> interface_cast(const sp<IBinder>& obj)
{
return IServiceManager::asInterface(obj);
}
Now let’s take a look at definition of IServiceManager.
class IServiceManager : public IInterface
{
public:
DECLARE_META_INTERFACE(ServiceManager);
/**
* Retrieve an existing service, blocking for a few seconds
* if it doesn't yet exist.
*/
virtual sp<IBinder> getService( const String16& name) const = 0;
/**
* Retrieve an existing service, non-blocking.
*/
virtual sp<IBinder> checkService( const String16& name) const = 0;
/**
* Register a service.
*/
virtual status_t addService( const String16& name,
const sp<IBinder>& service) = 0;
/**
* Return list of all existing services.
*/
virtual Vector<String16> listServices() = 0;
enum {
GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
CHECK_SERVICE_TRANSACTION,
ADD_SERVICE_TRANSACTION,
LIST_SERVICES_TRANSACTION,
};
};
DECLARE_META_INTERFACE macro is defined as follows in IInterface.h. And it will be
extended to the following code:
static const String16 descriptor;
static sp<IServiceManager> asInterface(const sp<IBinder>& obj);
virtual String16 getInterfaceDescriptor() const;
As you can see, DECLARE_META_INTERFACE macro declares two functions which are
implemented by IMPLEMENT_META_INTERFACE macro in IServiceManager.cpp.
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
The code will be extended like this.
const String16 IServiceManager::descriptor(NAME);
String16 IServiceManager::getInterfaceDescriptor() const {
return IServiceManager::descriptor;
}
sp<IServiceManager> IServiceManager::asInterface(const sp<IBinder>& obj)
{
sp<IServiceManager> intr;
if (obj != NULL) {
intr = static_cast<IServiceManager*>(
obj->queryLocalInterface(
IServiceManager::descriptor).get());
if (intr == NULL) {
intr = new BpServiceManager(obj);
}
}
return intr;
}
So IServiceManager::asInterface will finally new a BpServiceManager instance and return it to
user. BpServiceManager works as a proxy for remote BnServiceManager. Any operation on
IServiceManager now actually is to call the corresponding virtual functions in BpServiceManager.
Summary:
This section gives out details in how to get a proxy object for remote object.
Assume you want to implement your own service IFunnyTest, you must do the following:

发布了52 篇原创文章 · 获赞 2 · 访问量 6万+
展开阅读全文

通过Handler实现Service和Activity的数据交互,与onbind返回Binder对象冲突,我该如何解决?

07-10

在做service和activity通讯,需要服务能够控制活动的运行,同时能够实时进行数据传输 我通过Handler实现Service和Activity的数据交互,但尴尬的是onBind已经用于传递BleBind的一个实例了,没办法return messenger.getBinder(); ``` package com.example.bluserver; import android.app.Service; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.content.Context; import android.content.Intent; import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.util.Log; import android.widget.TextView; import android.widget.Toast; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.UUID; public class bluService extends Service { public static final int MSG = 123; private static final String TAG = "BleService"; private BluetoothAdapter mBA; private Context mContext; private final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");//这是蓝牙透传的uuid // 这里本身即是服务端也是客户端,需要如下类 private BluetoothSocket mSocket; private BluetoothDevice mOldDevice; private BluetoothDevice mCurDevice; // 输出流_客户端需要往服务端输出 private OutputStream os; private Messenger mActivityMessenger; private BleBinder bleBinder=new BleBinder(); @Override public IBinder onBind(Intent intent) { Messenger messenger=new Messenger(handler); //return messenger.getBinder();//Handler实现Service和Activity的数据交互 return bleBinder;//返回BleBinder实例供活动调用 } class BleBinder extends Binder{//以下是以供调用的公共方法 //开始读取传感器数据 public void startread(){ { new Thread(new Runnable() { @Override public void run() { try { Log.d(TAG,"开始运行run()函数"); InputStream is = mSocket.getInputStream(); Log.d(TAG,"已获取输入流"); while (true) { synchronized (this) { //Log.d(TAG,"已获取锁"); //Thread.sleep(50); byte[] tt = new byte[is.available()]; if (tt.length > 0) { is.read(tt, 0, tt.length); Message msg = new Message(); msg.obj = new String(tt, "GBK"); //大概在这里要获取整个字符串,字符串以回车分割,如此才能准确识别 Log.e(TAG, "客户端:" + msg.obj); showToast("客户端:" + msg.obj); mActivityMessenger.send(msg); //handler.sendMessage(msg); } } } } catch (Exception e) { e.printStackTrace(); } } }).start(); } } public void stopread(){}//停止读取传感器数据 /** * 弹出Toast窗口 * * @param message */ private void showToast(String message) { if (mContext != null) { Toast.makeText(mContext, message, Toast.LENGTH_LONG).show(); } else { Log.e(TAG, "message:" + message); } } /** * 主动连接蓝牙 * * @param device */ public void connectDevice(BluetoothDevice device) { // 判断是否在搜索,如果在搜索,就取消搜索 if (mBA.isDiscovering()) { mBA.cancelDiscovery(); } try { // 获得远程设备 Log.e(TAG, "开始检索"); if (mCurDevice == null || mCurDevice != mOldDevice) { mCurDevice = mBA.getRemoteDevice(device.getAddress()); Log.e(TAG, device.getAddress()); mOldDevice = mCurDevice; Log.e(TAG, "device:" + mCurDevice); mSocket = mCurDevice.createRfcommSocketToServiceRecord(MY_UUID); // 连接 mSocket.connect(); // 获得输出流 os = mSocket.getOutputStream(); Log.e(TAG, "获取输入流"); startread(); Log.e(TAG, "开启读线程"); //intent流转byte数组 // byte[] input=ByteToInputStream.input2byte(mSocket.getInputStream()); // Intent intent=new Intent(); // intent.putExtra("inputstream",input); // mContext.startActivity(intent); } // 如果成功获得输出流 Log.e(TAG, "3"); } catch (IOException e) { e.printStackTrace(); } } /** * 判断是否打开蓝牙 * * @return */ public boolean isEnabled() { if (mBA.isEnabled()) { return true; } return false; } /** * 传输数据 * * @param message */ public void write(String message) { try { if (os != null) { os.write(message.getBytes("GBK")); } Log.e(TAG, "write:" + message); } catch (IOException e) { e.printStackTrace(); } } public BluetoothDevice getCurDevice() { return mCurDevice; } } public bluService() { mBA = BluetoothAdapter.getDefaultAdapter(); } private Handler handler = new Handler() { public void handleMessage(Message msg) { //Toast.makeText(this,String.valueOf(msg.obj),Toast.LENGTH_LONG); //将在此处向主线程发送信息,用于更新界面(已废弃) //将在此处处理来自活动的消息,发送消息在线程内 // 参考代码 https://blog.csdn.net/CodeNoodles/article/details/51679532 switch (msg.what){ case MSG: mActivityMessenger = msg.replyTo; break; } Log.e(TAG, "服务端:" + msg.obj); super.handleMessage(msg); } }; @Override public void onDestroy() { Log.d(TAG,"服务已销毁"); super.onDestroy(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG,"服务已启动"); return super.onStartCommand(intent, flags, startId); } @Override public void onCreate() { super.onCreate(); Log.d(TAG,"服务已创建"); } } ``` 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览