1. 程式人生 > >簡單說Binder(1)

簡單說Binder(1)

Binder算是Android中比較難懂的一部分內容了,但是非常的重要,要想研究Framework層無論如何也繞不開Binder。網上也有很多講解Binder的文章,有的很深入涉及到底層C層面,理解起來難度較大,要完全理解還需要Linux驅動的知識,看了還也是似懂非懂,我認為也不需要理解那麼深入。寫這篇部落格主要是我從最學習理解Binder的過程的角度出發,也來談談Binder。

Binder是什麼

Binder是android中用於程序間通訊IPC的重要機制,ActivityManagerService、WinderManagerService等系統服務的背後都是Binder。

Binder架構包括伺服器介面、Binder驅動、客戶端介面三個模組。

Binder服務端:一個Binder服務端實際上就是Binder類的物件,該物件一旦建立,內部則會啟動一個隱藏執行緒,會接收Binder驅動傳送的訊息,收到訊息後,會執行Binder物件中的onTransact()函式,並按照該函式的引數執行不同的伺服器端程式碼。onTransact函式的引數是客戶端呼叫transact函式的輸入。

Binder驅動:任意一個服務端Binder物件被建立時,同時會在Binder驅動中建立一個mRemote物件,該物件也是一個Binder類。客戶端訪問遠端服務端都是通過該mRemote物件。

客戶端:獲取遠端服務在Binder驅動中對應的mRemote引用,然後呼叫它的transact方法即可向服務端傳送訊息。


這幅圖展現了Binder框架的大致構成,至於裡面有一些內容需要看完這篇部落格才能看懂。

需要注意的一個問題既然客戶端要通過mRemote引用呼叫它的transact方法向服務端傳送訊息,那麼客戶端獲取遠端服務在Binder中的mRemote引用?

客戶端獲取遠端服務在Binder中的mRemote引用有兩種方式:系統服務和自定義的服務端程式不一樣,對於系統服務使用Binder就可以實現服務端,而我們自定義的服務必須藉助Service來編寫。

》》系統服務是在系統啟動的時候在SystemServer程序的init2函式中啟動ServerThread執行緒,在這個執行緒中啟動了各種服務,並且通過呼叫ServerManager.addService(String name, IBinder service)將其加入儲存起來。

ServerManager就相當於DNS伺服器,在查詢某個服務時通過呼叫ServerManager.getService(String name)函式就可以獲得遠端服務的Binder,至於它的具體細節可以檢視Android啟動相關的原始碼。

》》自定義的服務必須通過Service來實現。

通過bind函式繫結一個遠端服務

public boolean bindService(Intent service, ServiceConnection conn, int flags)

其中第二個引數是一個回撥介面,onServiceConnected的引數service即為遠端服務在Binder驅動中的binder引用。

public interface ServiceConnection {
    public void onServiceConnected(ComponentName name, IBinder service);
    public void onServiceDisconnected(ComponentName name);
}

使用Binder進行IPC通訊

實現如下效果:Activity‘中有一個按鈕,點選該按鈕,將abc和def三個字母拼接起來,拼接的函式在另一個程序中。

客戶端

public class MainActivity extends Activity {
	private boolean isBound;
	private Button btn_add;
	private IBinder mRemote = null;
	private ServiceConnection serviceConn = new ServiceConnection() {  
		@Override  
		public void onServiceConnected(ComponentName name, IBinder service) {
			mRemote = service;
		}
        @Override  
        public void onServiceDisconnected(ComponentName name) {
        }
    };
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		bind();
        btn_add = (Button)findViewById(R.id.btn_add);
        btn_add.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				String result = null;
				try {
					result = strcat("abc", "def");
				} catch (RemoteException e) {
					Toast.makeText(MainActivity.this, "error", 0).show();
					e.printStackTrace();
				}
				Toast.makeText(MainActivity.this, result, 0).show();
			}
		});
	}
	
	private void bind() {
		Intent intent = new Intent(MainActivity.this, ComputeService.class);  
		isBound = bindService(intent, serviceConn, Context.BIND_AUTO_CREATE);
	}
	
	private void unbind() {
		if (isBound) {
			MainActivity.this.unbindService(serviceConn);
			isBound = false;
		}
    }
	
	private String strcat(String x, String y) throws RemoteException {
		android.os.Parcel _data = android.os.Parcel.obtain();
		android.os.Parcel _reply = android.os.Parcel.obtain();
		String _result;
		try {
			_data.writeString(x);
			_data.writeString(y);
			mRemote.transact(1, _data, _reply, 0);
			_result = _reply.readString();
		} finally {
			_reply.recycle();
			_data.recycle();
		}
		return _result;
	}

	@Override
	protected void onDestroy() {
		unbind();
		super.onDestroy();
	}
}

遠端服務端

public class ComputeService extends Service {
	
	private IBinder binder = new Binder(){
		protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
			if (code == 1) {
				String _arg0;
				_arg0 = data.readString();
				String _arg1;
				_arg1 = data.readString();
				String _result = this.strcat(_arg0, _arg1);
				reply.writeString(_result);
				return true;
			}
			return super.onTransact(code, data, reply, flags);
		};
		
		public String strcat(String x, String y){
			return x + y;
		}
	};
	
	@Override
	public IBinder onBind(Intent arg0) {
		return binder;
	}
}

將該service配置在一個新的程序中

<service android:name = "org.qhyuan.binder.ComputeService"
    android:process=":remote"/>

點選按鈕如圖所示彈出提示


接下來分析上面的程式碼:

客戶端通過bindService啟動遠端服務。最終會由系統回撥傳入的ServiceConnection介面,因此可以在onServiceConnected函式中獲得該遠端服務所對應的Binder驅動中的引用,接下來想要和遠端服務端通訊只需呼叫該mRemote的transact方法即可。

public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException;

code標識要執行的動作,其實就是指呼叫服務端的哪個函式。

data是對輸入引數的打包

reply是對返回值的打包

writeString<--->readString  客戶端打包一個Parcel物件,在服務端讀取該Parcel物件中打包的資料,客戶端的寫入和服務端的讀取時對應的。

這裡存在的問題要統一客戶端寫入和服務端讀取的順序,當然對於一個程式設計師來說,保證這一點是很簡單的。

接下來呼叫mRemote的transact方法會陷入核心態,也就是說剩下的都是由系統完成的,binder驅動會掛起當前執行緒,將引數包裹發給服務端程式,在服務端的onTransact(code, data, reply, flags)函式裡面讀取出包裝的資料進行處理(資料處理的過程也就是根據code執行指定的服務函式),然後把執行的結果放入客戶端提供的reply包裹中,然後服務端向Binder驅動傳送一個notify訊息,喚醒客戶端執行緒,繼續執行使得客戶端執行緒從Binder驅動返回到客戶端程式碼區,再次回到使用者態。

使用AIDL

我們也看到了上面使用Binder進行IPC通訊的時候程式碼比較繁瑣,尤其是客戶端給服務端傳送訊息的打包過程中要保證順序的一致性。當然android也給我們提供了一個比較好的方式,那就是使用android提供的aidl工具。

AIDL(Android Interface Definition Language),編譯器通過*.aidl檔案的描述資訊生成符合通訊協議的Java程式碼,我們不需要自己寫這些繁雜的程式碼,使用非常方便。只需要建立一個xxx.aidl檔案,這時在gen目錄下就會生成對應的java檔案

package org.qhyuan.aidl;
interface ICompute {
	String strcat (String x,String y);
}
這樣使用aidl來實現上面的功能就可以很簡單了。於是客戶端程式碼
public class MainActivity extends Activity {
	private ICompute compute = null;
	private boolean isBound;
	private Button btn_add;
	private ServiceConnection serviceConn = new ServiceConnection() {  
		@Override  
		public void onServiceConnected(ComponentName name, IBinder service) {
			compute = ICompute.Stub.asInterface(service);
		}
        @Override  
        public void onServiceDisconnected(ComponentName name) {
        }
    };
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		bind();
        btn_add = (Button)findViewById(R.id.btn_add);
        btn_add.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				String result = null;
				try {
					result = compute.strcat("abc", "def");
				} catch (RemoteException e) {
					Toast.makeText(MainActivity.this, "error", 0).show();
					e.printStackTrace();
				}
				Toast.makeText(MainActivity.this, result, 0).show();
			}
		});
	}
	
	private void bind() {
		Intent intent = new Intent(MainActivity.this, ComputeService.class);  
		isBound = bindService(intent, serviceConn, Context.BIND_AUTO_CREATE);
	}
	
	private void unbind() {
		if (isBound) {
			MainActivity.this.unbindService(serviceConn);
			isBound = false;
		}
    }

	@Override
	protected void onDestroy() {
		unbind();
		super.onDestroy();
	}
}
服務端程式碼
public class ComputeService extends Service {
	
	private IBinder binder = new ICompute.Stub() {
		@Override
		public String strcat(String x, String y) throws RemoteException {
			return x+y;
		}
	};
	
	@Override
	public IBinder onBind(Intent arg0) {
		return binder;
	}
}
其他的都不需要改變,是不是簡單了很多?封裝了底層的細節,使得程式寫起來很優美。之前手動寫的transact函式和重寫的onTransact函式也不見蹤影了。

接下來分析上面的程式碼,看看aidl檔案到底做了什麼,能使得我們編寫程式簡化很多。

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: E:\\EclipseProject\\Binder\\src\\org\\qhyuan\\aidl\\ICompute.aidl
 */
package org.qhyuan.aidl;

public interface ICompute extends android.os.IInterface {
	/** Local-side IPC implementation stub class. */
	public static abstract class Stub extends android.os.Binder implements
			org.qhyuan.aidl.ICompute {
		private static final java.lang.String DESCRIPTOR = "org.qhyuan.aidl.ICompute";

		/** Construct the stub at attach it to the interface. */
		public Stub() {
			this.attachInterface(this, DESCRIPTOR);
		}

		/**
		 * Cast an IBinder object into an org.qhyuan.aidl.ICompute interface,
		 * generating a proxy if needed.
		 */
		public static org.qhyuan.aidl.ICompute asInterface(
				android.os.IBinder obj) {
			if ((obj == null)) {
				return null;
			}
			android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
			if (((iin != null) && (iin instanceof org.qhyuan.aidl.ICompute))) {
				return ((org.qhyuan.aidl.ICompute) iin);
			}
			return new org.qhyuan.aidl.ICompute.Stub.Proxy(obj);
		}

		@Override
		public android.os.IBinder asBinder() {
			return this;
		}

		@Override
		public boolean onTransact(int code, android.os.Parcel data,
				android.os.Parcel reply, int flags)
				throws android.os.RemoteException {
			switch (code) {
			case INTERFACE_TRANSACTION: {
				reply.writeString(DESCRIPTOR);
				return true;
			}
			case TRANSACTION_strcat: {
				data.enforceInterface(DESCRIPTOR);
				java.lang.String _arg0;
				_arg0 = data.readString();
				java.lang.String _arg1;
				_arg1 = data.readString();
				java.lang.String _result = this.strcat(_arg0, _arg1);
				reply.writeNoException();
				reply.writeString(_result);
				return true;
			}
			}
			return super.onTransact(code, data, reply, flags);
		}

		private static class Proxy implements org.qhyuan.aidl.ICompute {
			private android.os.IBinder mRemote;

			Proxy(android.os.IBinder remote) {
				mRemote = remote;
			}

			@Override
			public android.os.IBinder asBinder() {
				return mRemote;
			}

			public java.lang.String getInterfaceDescriptor() {
				return DESCRIPTOR;
			}

			@Override
			public java.lang.String strcat(java.lang.String x,
					java.lang.String y) throws android.os.RemoteException {
				android.os.Parcel _data = android.os.Parcel.obtain();
				android.os.Parcel _reply = android.os.Parcel.obtain();
				java.lang.String _result;
				try {
					_data.writeInterfaceToken(DESCRIPTOR);
					_data.writeString(x);
					_data.writeString(y);
					mRemote.transact(Stub.TRANSACTION_strcat, _data, _reply, 0);
					_reply.readException();
					_result = _reply.readString();
				} finally {
					_reply.recycle();
					_data.recycle();
				}
				return _result;
			}
		}

		static final int TRANSACTION_strcat = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
	}

	public java.lang.String strcat(java.lang.String x, java.lang.String y)
			throws android.os.RemoteException;
}
為了看起來方便,這裡存在幾個類及每個類中的屬性和方法大致簡化如下。
interface ICompute extends IInterface
{
	strcat();

	static abstract class Stub extends Binder implements ICompute {
		static final int TRANSACTION_strcat;
		static final String DESCRIPTOR;
		static asInterface();
		asBinder();
		onTransact();

		static class Proxy implements ICompute {
			IBinder binder;
			asBinder();
			getInterfaceDescriptor();
			strcat();
		}
	}
}
首先要明白AIDL的主要設計思想。產生的這個類的思想是抽象出了一個介面,接口裡麵包含我們想實現的strcat方法,於是服務端的Binder來實現這個介面,其實就是這裡的Stub類。然後客戶端在獲得了服務端在Binder驅動中的Binder引用mRemote後,通過該引用給遠端服務端傳送訊息,這是包含在Proxy類的strcat函式中。由於有aidl工具生成的程式碼所以包裹中的打包資料的順序都是一致的。

ICompute類中的strcat函式不需要實現,僅僅是提供介面而已,具體的在Stub的子類類和Proxy類中實現。

在Stub子類中具體實現,一般是在服務端程式中的。

在Proxy類中的strcat函式包括對引數的打包和通過Binder驅動中的mRemote呼叫transact函式向服務端傳送包裹,再從reply包裹中讀取出返回值返回。

》》TRANSACTION_strcat:是對函式的編號,由於這裡只有一個函式stract,所以只有這一個整型值。

》》DESCRIPTOR:每個Stub類有一個描述符,與它實現的介面有關。

》》onTransact:收到Binder驅動發來的包裹,進行解包,這裡面呼叫了this.strcat(_arg0, _arg1);是非常重要的,實際上是在伺服器端實現的類的strcat函式。

》》asInterface:是最重要的一個函式,這是一個靜態方法,是用在客戶端將一個IBinder物件轉化為它實現的介面。

如果能根據DESCRIPTION通過queryLocalInterface查詢到的值,就直接返回該值,(如果不是因為是static的,是不是返回this就可以了?)這對應的情況是client和服務端在同一個程序中,返回的就是服務端的Binder,接下來的呼叫就是直接用服務端的Binder呼叫服務端的程式,不存在IPC。否則就將該IBinder(其實是BinderProxy型別了)包裝成一個新的類Proxy類,接下來呼叫Proxy的stract方法實質上是用的Binder驅動中的遠端Binder的引用mRemote來呼叫的,是IPC。這裡,Proxy顧名思義是代理的意思,本地呼叫就直接返回ICompute介面實際上是當前伺服器端的Binder,否則就返回一個代理類,該代理類實現了ICompute,裡面封裝的是Binder驅動中的mRemote引用,這樣保證接下來的操作是一致的。

一句話就是說asInterface函式的存在將本地呼叫和程序間呼叫綜合在一起了。看到這裡有沒有覺得三個類組織的非常巧妙程式碼很優美呢。

另,上面三個類如果寫成三個類而不是寫成巢狀類的形式會好理解很多。並且和最開始手工寫的Binder本質上是一致的。

程式碼中出現的如下幾個打包的資料可以認為是增加安全性和處理一些其他的問題,沒有也是可以可以的。writeInterfaceToken<--->enforceInterface 客戶端封裝一個String標識,在服務端收到後對比確保該Binder驅動確實是想訪問我。類似的還有writeException<--->readException。

再此基礎上去看系統中一些XXXManager程式碼,就會容易很多,裡面使用Binder的部分都類似於AIDL產生的那些程式碼,本質上就是上面講的Binder進行IPC通訊,下面舉例子說明原始碼中使用Binder的地方。

系統服務中的Binder分析

下面以ServiceManager和ActivityManagerService為例來分析。

ServiceManager:

前面已經提到過ServiceManager可以認為是DNS,用來查詢系統服務。儲存了已經開啟的系統服務。他有兩個主要的方法

public static IBinder getService(String name)
public static void addService(String name, IBinder service)

實際上ServerManager既是系統服務的管理者,同時也是一個系統服務。因此它肯定是基於Binder實現的。

接下來的分析中,時刻記得使用aidl工具生成那三個類:IXXX、IXXX.Stub和IXXX.Stub.Proxy,並做好對應。這樣看ServiceManager的相關的程式碼就容易多了。

1.與IXXX相對應的類就是IServiceManager類,封裝了遠端呼叫的幾個主要函式。

public interface IServiceManager extends IInterface
{
    public IBinder getService(String name) throws RemoteException;
    public IBinder checkService(String name) throws RemoteException;
    public void addService(String name, IBinder service, boolean allowIsolated)
                throws RemoteException;
    public String[] listServices() throws RemoteException;
    public void setPermissionController(IPermissionController controller)
            throws RemoteException;
    static final String descriptor = "android.os.IServiceManager";
    int GET_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION;
    int CHECK_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+1;
    int ADD_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+2;
    int LIST_SERVICES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+3;
    int CHECK_SERVICES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+4;
    int SET_PERMISSION_CONTROLLER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+5;
}
2.與IXXX.Stub對應的類就是ServiceManagerNative。
public abstract class ServiceManagerNative extends Binder implements IServiceManager{
    static public IServiceManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IServiceManager in = (IServiceManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }
        return new ServiceManagerProxy(obj);
    }
    
    public ServiceManagerNative() {
        attachInterface(this, descriptor);
    }
    
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags){
        try {
            switch (code) {
            case IServiceManager.GET_SERVICE_TRANSACTION: {
                data.enforceInterface(IServiceManager.descriptor);
                String name = data.readString();
                IBinder service = getService(name);
                reply.writeStrongBinder(service);
                return true;
            }
            case IServiceManager.ADD_SERVICE_TRANSACTION: {
                data.enforceInterface(IServiceManager.descriptor);
                String name = data.readString();
                IBinder service = data.readStrongBinder();
                boolean allowIsolated = data.readInt() != 0;
                addService(name, service, allowIsolated);
                return true;
            }
            // ...
        } catch (RemoteException e) {
        }
        
        return false;
    }
    public IBinder asBinder() {
        return this;
    }
}
3.與IXXX.Stub.Proxy對應的類ServiceManagerProxy
class ServiceManagerProxy implements IServiceManager {
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
    }
    
    public IBinder asBinder() {
        return mRemote;
    }
    
    public IBinder getService(String name) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
        IBinder binder = reply.readStrongBinder();
        reply.recycle();
        data.recycle();
        return binder;
    }
    public void addService(String name, IBinder service, boolean allowIsolated) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        data.writeStrongBinder(service);
        data.writeInt(allowIsolated ? 1 : 0);
        mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
        reply.recycle();
        data.recycle();
    }
    // ....
    private IBinder mRemote;
}

觀察上面的程式碼,實際上和使用adil生成的程式碼沒什麼兩樣。僅僅是類命名不一樣,將三個類分開寫了而已。

不用看原始碼也知道接下來該怎麼做了吧?!當然就是在服務端繼承ServiceManagerNative類實現裡面的相關方法就能實現服務端,然後在客戶端將遠端服務端所對應的的Binder封裝成IServiceManager iSm = ServiceManagerNative.asInterface(binder)即可,正常情況下確實是這樣的。實際上,在原始碼中找不到繼承自ServiceManagerNative類的遠端服務端類,比如說ServiceManagerService,根本就找不到這樣一個類。原因是SMS在native層被實現成一個獨立的程序,是在啟動後解析init.rc指令碼啟動服務的。native層的程式碼沒必要去研究,那麼這個遠端的Binder怎麼獲得呢?系統提供的函式BinderInternal.getContextObject()來獲得對應的Binder引用。還是ServiceManager比較特殊嘛,畢竟對於“DNS”來說不得一開機就啟動,還與其他“主機”有點差別,但是其他的系統服務就和上面我們想象的那樣是一樣的了。

這裡要說明一點,雖然SMS服務時在native層,獲取遠端服務卻並不一定非要在native層實現,使用Binder構架與是用什麼語言沒必然關係。

當然了,這裡的ServiceManagerNative確實沒什麼用,如果要說有用,就是他的靜態方法asInterface吧。但不知道為什麼android原始碼中還有這個類的存在,至少這樣讓我們隱約感覺Binder通訊的框架就是這樣的,提高了一致性。

接下來我們看ServiceManager類

public final class ServiceManager {
    private static final String TAG = "ServiceManager";
    private static IServiceManager sServiceManager;
    // 本地有快取
    private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();
    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }
        // Find the service manager
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
        return sServiceManager;
    }
    public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
            	// 其實是IPC呼叫,具體會呼叫
                return getIServiceManager().getService(name);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }
    public static void addService(String name, IBinder service) {
        try {
            getIServiceManager().addService(name, service, false);
        } catch (RemoteException e) {
            Log.e(TAG, "error in addService", e);
        }
    }
    // ...
}

ServiceManager類其實就是對遠端的SMS服務的Binder的封裝。使用ServiceManagerNative.asInterface(BinderInternal.getContextObject());將其轉化為sServiceManager介面,接下來使用該物件即可完成IPC呼叫。

舉個例子比如呼叫ServiceManager的getService方法,實際上會ServiceManagerProxy走到ServiceManagerProxy類的getService方法裡面去,然後就是向服務端發訊息。當然這些細節就不用考慮了,因為android的Binder機制封裝的就是這麼完美,你不用關注底層細節。

ActivityManager:

再看看ActivityManager中的Binder。

IActivityManager對應IXXX介面

ActivityManagerNative對應IXXX.Stub類,繼承自Binder類。

ActivityManagerProxy對應IXXX.Stub.Proxy類。

那麼AMS的服務端是那個類呢?沒錯,就是ActivityManagerService類,這個類繼承自ActivityManagerNative,實現了IActivityManager介面中的方法用來進行IPC。

那麼只要在客戶端得到了這個遠端服務端的Binder引用就可以進行IPC通訊了,事實確實是這樣的。舉個栗子,在ActivityThread的attach方法裡有下面兩行程式碼

IActivityManager mgr = ActivityManagerNative.getDefault();
mgr.attachApplication(mAppThread);

而getDefault方法程式碼如下

static public IActivityManager getDefault() {
    return gDefault.get();
}
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
        	// 這裡可以看到通過呼叫getService方法得到Binder
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

顯然,ActivityManagerNative.getDefault()就可以得到遠端的activity的服務AMS對應的Binder引用,並且呼叫asInterface將其轉化為IActivityManager,接下來呼叫介面中的函式即可和遠端的AMS通訊。一般來說,對於其他的Service一般就是通過ServiceManager來獲取對應的Binder。

當然,如果還想弄的更清楚點還需要知道這個系統服務是在哪裡啟動和將Binder新增到SystemServer中的

在SystemServerr程序的init2函式中啟動ServerThread執行緒,這個執行緒中啟動了很多系統服務,而每個系統服務都是一個執行緒。ServerThread的run方法大概有1000行,裡面啟動了系統服務,不同的服務有不同的啟動方法。

比如這裡的AMS是通過呼叫context = ActivityManagerService.main(factoryTest)實現的。main函式裡面啟動了AThread執行緒。

接下來又呼叫了ActivityManagerService.setSystemProcess();

public static void setSystemProcess() {
    ActivityManagerService m = mSelf;
    ServiceManager.addService("activity", m, true);
    ServiceManager.addService("meminfo", new MemBinder(m));
    ServiceManager.addService("gfxinfo", new GraphicsBinder(m));
    ServiceManager.addService("dbinfo", new DbBinder(m));
    // ....
   }

這裡的m是在AThread執行緒中new出來的ActivityManagerService例項。至此,就完成了服務的啟動和向ServiceManager中的新增。當然裡面有很多細節,這裡主要是跟蹤Binder通訊的過程。