Binder探索の適用(上)

7567 ワード

本明細書では、クライアントActivity、サービス側リモートサービス、aidl、およびJavaインタフェースファイルを含むdemoコードを主に羅列し、クライアントおよびサービス側アプリケーションbinderインタラクションプロセスを記述する.
このコードの例を簡単に説明します.BookManagerServiceというリモート・サービスがあります.Bookオブジェクトを保存するためのlistを持ち、listのgetメソッドとaddメソッドを外部に提供します.クライアントActivityは、サービスをバインドし、そのインタフェースにアクセスします.
  • クライアントActivityは、onCreate時にBookManagerServiceをバインドし、接続に成功するとIBookManagerオブジェクトを生成し、BookManagerServiceの外部インタフェースにアクセスできます.
  • BookManagerServiceにはremoteが設定されており、別のプロセスで実行されるリモート・サービスであり、onCreate時にリストに2行のデータをロードした後、onBindメソッドでserviceBinderオブジェクトを返します.

  • まずaidlファイルです.
    //IBookManager.aidl
    interface IBookManager {
         List getBookList();
         void addBook(in Book book);
    }
    //Book.aidl
    parcelable Book;
    
    

    次にクライアントActivity:
        private IBookManager mRemoteBookManager;
        private ServiceConnection mConnection = new ServiceConnection() {
            public void onServiceConnected(ComponentName className, IBinder service) {
                IBookManager bookManager = IBookManager.Stub.asInterface(service);
                mRemoteBookManager = bookManager;
                try {
                   //mRemoteBookManager.asBinder().linkToDeath(mDeathRecipient, 0);
                    List list = bookManager.getBookList();
                    Book newBook = new Book(3, "Android ");
                    bookManager.addBook(newBook);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_book_manager);
            Intent intent = new Intent(this, BookManagerService.class);
            bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
        }

    最後に、サービス側BookManagerService:
        private CopyOnWriteArrayList mBookList = new CopyOnWriteArrayList();
        private Binder mBinder = new serviceBinder();
        @Override
        public IBinder onBind(Intent arg0) {
            return mBinder;
        }
        @Override
        public boolean onUnbind(Intent intent) {
            return super.onUnbind(intent);
        }
        @Override
        public void onCreate() {
            super.onCreate();
            mBookList.add(new Book(1, "Android"));
            mBookList.add(new Book(2, "Ios"));
        }
    
        public class serviceBinder extends IBookManager.Stub{
            @Override
            public void addBook(Book book) throws RemoteException {
                mBookList.add(book);
            }@Override
            public List getBookList() throws RemoteException {
                return mBookList;
            }
        }

    プログラムは異なるプロセスで1つのサービスをバインドするもので、最初に実行される大まかなプロセスは次のとおりです.
  • クライアントActivityプロセスは、AMSがシステムサービスプロセスで実行されるため、BookManagerServiceサービスをバインドする要求をAMSに送信する(これもbinder要求である).
  • AMSルーチンチェックは、まずBookManagerServiceが登録されているか、どのアプリが登録されているか(これらの情報はappインストール時にmanifestを解析して取得されたもの)をチェックし、次にBookManagerServiceを起動するプロセスが存在するかをチェックします.BookManagerServiceはremoteを設定しているため、この時点でプロセスは存在しません.そこで、まずService情報を保存し、リクエストをバインドした後、新しいプロセスを作成します.
  • 新しいプロセスが開始されると、AMSに準備が完了したことを通知し、AMSは先ほど保存したサービス情報を新しいプロセスに送信してサービス(oncreateなど)を開始し、サービスが開始された後にAMSに通知します.
  • AMSは、バインドされた要求をBookManagerServiceに再送信し、BookManagerServiceはonbindを呼び出し、AMSにbinderオブジェクトを返します.
  • AMSはbinderオブジェクトをクライアントActivity(onServiceConnected呼び出し)
  • に返す.
    これらのプロセスはandroidによってブロックされています.アプリケーションでは、クライアントActivityのonServiceConnectedが返すBinderProxyオブジェクトと、サービス側BookManagerServiceのonBindが返すBinderオブジェクトの2つのオブジェクトに注目する必要があります.しかし、アプリケーションではStubとProxyが見られ、StubはBinderを継承し、ProxyはBidnerProxyのパッケージクラスであり、BinderProxyもBidnerもIBinderインタフェースを実現し、IBinderで受信することができる.
  • IBookManagerインタフェースはgetBookListとaddBookメソッドを定義し、Iinterfaceインタフェースも継承し、asBinderメソッドが複数あり、次のStubとProxyはIBookManagerインタフェースを実現しています.
  • StubクラスはBidnerクラスだけでなくIBookManagerインタフェースも継承し、サービス側BookManagerServiceのserviceBinderはStubクラスを継承し、getBookListとaddBookメソッド(asBinderインタフェースはStubクラスで実現)を実現し、serviceBinderのオブジェクトmBinderはAMSに戻される.
  • クライアントActivityのonServiceConnectedは、IBookManagerを介してBinderProxyに戻ります.Stub.asInterfaceメソッドはProxyオブジェクトにパッケージされており、Proxy実装のgetBookListメソッドとaddBookメソッドを呼び出すことができ、ProxyはasBinderインタフェースも実装している.

  • IBookManagerインタフェース:
    public interface IBookManager extends IInterface {
    
        static final String DESCRIPTOR = "com.example.testbinder.IBookManager";
        static final int TRANSACTION_getBookList = (IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_addBook = (IBinder.FIRST_CALL_TRANSACTION + 1);
    
           public List getBookList()throws RemoteException;
           public void addBook(Book book)throws RemoteException;
    }

    Stubクラス:
    public static abstract class Stub extends Binder implements IBookManager {
    	public Stub() {
    		this.attachInterface(this, DESCRIPTOR);
    	}
    	public static IBookManager asInterface(IBinder obj) {
    		if ((obj == null)) {
    			return null;
    		}
    		android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
    		if (((iin != null) && (iin instanceof IBookManager))) {
    			return ((IBookManager) iin);
    		}
    		return new IBookManager.Stub.Proxy(obj);
    	}
    	@Override
    	public android.os.IBinder asBinder() {
    		return this;
    	}
    	@Override
    	public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
    		switch (code) {
    		case INTERFACE_TRANSACTION: {
    			reply.writeString(DESCRIPTOR);
    			return true;
    		}
    		case TRANSACTION_getBookList: {
    			data.enforceInterface(DESCRIPTOR);
    			List _result = this.getBookList();
    			reply.writeNoException();
    			reply.writeTypedList(_result);
    			return true;
    		}
    		case TRANSACTION_addBook: {
    			data.enforceInterface(DESCRIPTOR);
    			Book _arg0;
    			if ((0 != data.readInt())) {
    				_arg0 = Book.CREATOR.createFromParcel(data);
    			} else {
    				_arg0 = null;
    			}
    			this.addBook(_arg0);
    			reply.writeNoException();
    			return true;
    		}
    		return super.onTransact(code, data, reply, flags);
    	}
           @Override
        public List getBookList() throws RemoteException {
            //          
                   return null;
        }
    
        @Override
        public void addBook(Book book) throws RemoteException {
            //      
           }   
     }

    Proxyクラス:
    private static class Proxy implements IBookManager {
    	private IBinder mRemote;
    	Proxy(IBinder remote) {
    		mRemote = remote;
    	}
    	@Override
    	public IBinder asBinder() {
    		return mRemote;
    	}
    	public String getInterfaceDescriptor() {
    		return DESCRIPTOR;
    	}
    	@Override
    	public List getBookList()throws RemoteException {
    		Parcel _data = Parcel.obtain();
    		Parcel _reply = Parcel.obtain();
    		List _result;
    		try {
    			_data.writeInterfaceToken(DESCRIPTOR);
    			mRemote.transact(Stub.TRANSACTION_getBookList, _data,_reply, 0);
    			_reply.readException();
    			_result = _reply.createTypedArrayList(Book.CREATOR);
    		} finally {
    			_reply.recycle();
    			_data.recycle();
    		}
    		return _result;
    	}
    	@Override
    	public void addBook(Book book)throws RemoteException {
    		Parcel _data = Parcel.obtain();
    		Parcel _reply = Parcel.obtain();
    		try {
    			_data.writeInterfaceToken(DESCRIPTOR);
    			if ((book != null)) {
    				_data.writeInt(1);
    				book.writeToParcel(_data, 0);
    			} else {
    				_data.writeInt(0);
    			}
    			mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
    			_reply.readException();
    		} finally {
    			_reply.recycle();
    			_data.recycle();
    		}
    	}
    }	    
    

           
    次の文章ではbinder通信プロセスについて説明する.