亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android binder 匿名服務(wù)實(shí)現(xiàn)雙向通信的解決方案

 更新時(shí)間:2024年04月27日 09:37:50   作者:Kbattery  
這篇文章主要介紹了Android binder 匿名服務(wù)實(shí)現(xiàn)雙向通信的解決方案,當(dāng)然,這種方案是可行的,只是需要client和server都向servicemanager注冊(cè)一個(gè)服務(wù),實(shí)現(xiàn)起來有點(diǎn)麻煩,不太建議這么做,需要的朋友可以參考下

在binder 用戶空間通信模型中,涉及client,server和servicemanager進(jìn)程。一般來說,都是server注冊(cè)服務(wù)到servicemanager中,client從servicemanager中獲取服務(wù),然后由client發(fā)起,使用服務(wù)中的方法。server都是被動(dòng)的接收client發(fā)起的請(qǐng)求。那如果server想主動(dòng)的發(fā)起請(qǐng)求調(diào)用client中的方法,應(yīng)該怎么做呢?
實(shí)現(xiàn)上面的需求,首先可以想到的是,client也向servicemanager注冊(cè)一個(gè)服務(wù),server中從servicemanager獲取服務(wù),這樣client就變成了服務(wù)端,server就變成了客戶端,不就可以實(shí)現(xiàn)嗎?
當(dāng)然,這種方案是可行的,只是需要client和server都向servicemanager注冊(cè)一個(gè)服務(wù),實(shí)現(xiàn)起來有點(diǎn)麻煩,不太建議這么做。完全可以使用匿名服務(wù)來實(shí)現(xiàn)雙向通信的需求
1,背景知識(shí)
在注冊(cè)服務(wù)時(shí),通過調(diào)用Parcel的writeStrongBinder,會(huì)構(gòu)造一個(gè)flat_binder_obj結(jié)構(gòu)體,其中的type為BINDER_TYPE_BINDER,binder驅(qū)動(dòng)對(duì)于type是BINDER_TYPE_BINDER,則會(huì)生成一個(gè)binder_node,并為servicemanager創(chuàng)建binder_ref,而且還會(huì)將這個(gè)flat_binder_obj的type改為BINDER_TYPE_HANDLE,將binder_ref中的desc存入flat_binder_obj的handle,傳給servicemanager,在servicemanager中記錄其信息。這個(gè)過程就是binder實(shí)名服務(wù)的注冊(cè)過程。

2,匿名服務(wù)是什么?
binder_node代表一個(gè)服務(wù)的實(shí)體。了解了上面的背景知識(shí)后知道writeStrongBinder會(huì)導(dǎo)致在驅(qū)動(dòng)中創(chuàng)建一個(gè)binder_node,那么我們可不可以直接在client和server通信的過程中,調(diào)用writeStrongBinder,而不需要通過添加服務(wù)在servicemanager中記錄這個(gè)服務(wù)的信息呢?答案是可以的,這就是匿名服務(wù)。匿名服務(wù)需要依賴于server已經(jīng)注冊(cè)好的實(shí)名服務(wù)

3,匿名服務(wù)在系統(tǒng)源碼中的使用
應(yīng)用進(jìn)程和wms進(jìn)行通信,通常是借助于一個(gè)IWindowSession對(duì)象。我們來看一下其構(gòu)造過程

@UnsupportedAppUsage
    public static IWindowSession getWindowSession() {
        synchronized (WindowManagerGlobal.class) {
            if (sWindowSession == null) {
                try {
                    // Emulate the legacy behavior.  The global instance of InputMethodManager
                    // was instantiated here.
                    // TODO(b/116157766): Remove this hack after cleaning up @UnsupportedAppUsage
                    InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary();
                    IWindowManager windowManager = getWindowManagerService();//1
                    sWindowSession = windowManager.openSession( //2
                            new IWindowSessionCallback.Stub() {
                                @Override
                                public void onAnimatorScaleChanged(float scale) {
                                    ValueAnimator.setDurationScale(scale);
                                }
                            });
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
            return sWindowSession;
        }
    }

注釋1處獲取一個(gè)IWindowManager.Stub.Proxy對(duì)象,不在本分分析的重點(diǎn)。注釋2處通過調(diào)用openSession獲取一個(gè)IWindowSession對(duì)象。

@Override public android.view.IWindowSession openSession(android.view.IWindowSessionCallback callback, com.android.internal.view.IInputMethodClient client, com.android.internal.view.IInputContext inputContext) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
android.view.IWindowSession _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStrongBinder((((callback!=null))?(callback.asBinder()):(null)));
_data.writeStrongBinder((((client!=null))?(client.asBinder()):(null)));
_data.writeStrongBinder((((inputContext!=null))?(inputContext.asBinder()):(null)));
mRemote.transact(Stub.TRANSACTION_openSession, _data, _reply, 0);//1
_reply.readException();
_result = android.view.IWindowSession.Stub.asInterface(_reply.readStrongBinder());//2
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}

可以看出,注釋1處發(fā)起遠(yuǎn)程調(diào)用,然后注釋2處從_reply中取出數(shù)據(jù),轉(zhuǎn)化之后返回。那我們來看看服務(wù)端的處理

case TRANSACTION_openSession:
{
data.enforceInterface(DESCRIPTOR);
android.view.IWindowSessionCallback _arg0;
_arg0 = android.view.IWindowSessionCallback.Stub.asInterface(data.readStrongBinder());
com.android.internal.view.IInputMethodClient _arg1;
_arg1 = com.android.internal.view.IInputMethodClient.Stub.asInterface(data.readStrongBinder());
com.android.internal.view.IInputContext _arg2;
_arg2 = com.android.internal.view.IInputContext.Stub.asInterface(data.readStrongBinder());
android.view.IWindowSession _result = this.openSession(_arg0, _arg1, _arg2);
reply.writeNoException();
reply.writeStrongBinder((((_result!=null))?(_result.asBinder()):(null)));//1
return true;
}

注釋1處也是調(diào)用writeStrongBinder,直接寫給客戶端。結(jié)合前面的背景知識(shí),就知道這是一個(gè)binder匿名服務(wù)(并沒有先向servicemanager獲取)。匿名服務(wù)的實(shí)現(xiàn)也是通過writeStrongBinder來實(shí)現(xiàn)的,客戶端通過readStrongBinder來取出binder驅(qū)動(dòng)轉(zhuǎn)化過后的flat_binder_obj,取出handle并存入BpBinder中

4,匿名服務(wù)雙向通信實(shí)戰(zhàn)

在我們的日常開發(fā)中,通常有這樣的需求,服務(wù)端更新了某種狀態(tài)需要實(shí)時(shí)的通知給客戶端。那么我們就可以在客戶端通過writeStrongBinder創(chuàng)建一個(gè)binder匿名服務(wù)供服務(wù)端使用。

1,在客戶端和服務(wù)端新建一個(gè)用于服務(wù)端通知客戶端的aidl文件,如:ICallBack.aidl。注意包名需要一致

// ICallBack.aidl
package com.test.testserver;
// Declare any non-default types here with import statements
interface ICallBack {
    void onSucess(int code);
    void onError();
}

2,在客戶端和服務(wù)端本來的通信文件中(客戶端發(fā)起和服務(wù)端通信的aidl文件),新增接口

// ITestInterface.aidl
package com.test.testserver;
import com.test.testserver.ICallBack;
// Declare any non-default types here with import statements
interface ITestInterface {
    void registerCallBack(ICallBack callback);
}

3,客戶端調(diào)用 registerCallBack

binder.registerCallBack(new ICallBack.Stub() {
                    @Override
                    public void onSucess(int code) throws RemoteException {
                        Log.d("test", "onSucess code: "+code);
                    }
                    @Override
                    public void onError() throws RemoteException {
                        Log.d("test", "onError: ");
                    }
                });

4,服務(wù)端接收到之后,做自己的處理

@Override
    public void registerCallBack(ICallBack callback) throws RemoteException {
        this.callBack = callback;
    }

我這里只是將客戶端傳過來的ICallBack 賦值給自己的callBack 對(duì)象

5,服務(wù)端需要通知時(shí),調(diào)用ICallBack 中的方法

callBack.onError();
或者
callBack.onSucess(1);

最后我們來看看,內(nèi)部實(shí)現(xiàn)是不是通過writeStrongBinder和readStrongBinder來實(shí)現(xiàn)
客戶端發(fā)起調(diào)用:

@Override public void registerCallBack(com.test.testserver.ICallBack callback) throws android.os.RemoteException
      {
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        try {
          _data.writeInterfaceToken(DESCRIPTOR);
          _data.writeStrongBinder((((callback!=null))?(callback.asBinder()):(null)));//1
          boolean _status = mRemote.transact(Stub.TRANSACTION_registerCallBack, _data, _reply, 0);
          if (!_status && getDefaultImpl() != null) {
            getDefaultImpl().registerCallBack(callback);
            return;
          }
          _reply.readException();
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
      }

注釋1處可以看出是通過writeStrongBinder,構(gòu)建一個(gè)匿名服務(wù)
服務(wù)端:

case TRANSACTION_registerCallBack:
        {
          data.enforceInterface(descriptor);
          com.test.testserver.ICallBack _arg0;
          _arg0 = com.test.testserver.ICallBack.Stub.asInterface(data.readStrongBinder());//1
          this.registerCallBack(_arg0);
          reply.writeNoException();
          return true;
        }

注釋1處是通過readStrongBinder取出來并轉(zhuǎn)化為ICallBack.Stub.proxy對(duì)象,用于和客戶端通信

到此這篇關(guān)于Android binder 匿名服務(wù)實(shí)現(xiàn)雙向通信的文章就介紹到這了,更多相關(guān)Android binder 匿名服務(wù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論