前面我们说到,我们在这里举的例子包含了一个Server端和一个Client端实现,其中, Server端就是通过前面一个构造函数来创建一个匿名共享内存文件,接着,Client端过Binder进程间通信机制来向Server请求这个匿名共享内存的文件描述符,有了这个文件描述符之后,就可以通过后面一个构造函数来共享这个内存文件了。

        因为涉及到Binder进程间通信,我们首先定义好Binder进程间通信接口。Binder进程间通信机制的相关介绍,请参考前面一篇文章,这里就不详细介绍了,直接进入主题。

        首先在源代码工程的packages/experimental目录下创建一个应用程序工程目录Ashmem。关于如何获得Android源代码工程,请参考一文;关于如何在Android源代码工程中创建应用程序工程,请参考一文。这里,工程名称就是Ashmem了,它定义了一个路径为shy.luo.ashmem的package,这个例子的源代码主要就是实现在这里了。下面,将会逐一介绍这个package里面的文件。

        这里要用到的Binder进程间通信接口定义在src/shy/luo/ashmem/IMemoryService.java文件中:

 

[java]
  1. package shy.luo.ashmem;  
  2.   
  3. import android.util.Log;  
  4. import android.os.IInterface;  
  5. import android.os.Binder;  
  6. import android.os.IBinder;  
  7. import android.os.Parcel;  
  8. import android.os.ParcelFileDescriptor;  
  9. import android.os.RemoteException;  
  10.   
  11. public interface IMemoryService extends IInterface {  
  12.     public static abstract class Stub extends Binder implements IMemoryService {  
  13.         private static final String DESCRIPTOR = "shy.luo.ashmem.IMemoryService";  
  14.   
  15.         public Stub() {  
  16.             attachInterface(this, DESCRIPTOR);  
  17.         }  
  18.   
  19.         public static IMemoryService asInterface(IBinder obj) {  
  20.             if (obj == null) {  
  21.                 return null;  
  22.             }  
  23.   
  24.             IInterface iin = (IInterface)obj.queryLocalInterface(DESCRIPTOR);  
  25.             if (iin != null && iin instanceof IMemoryService) {  
  26.                 return (IMemoryService)iin;  
  27.             }  
  28.   
  29.             return new IMemoryService.Stub.Proxy(obj);  
  30.         }  
  31.   
  32.         public IBinder asBinder() {  
  33.             return this;  
  34.         }  
  35.   
  36.         @Override   
  37.         public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws android.os.RemoteException {  
  38.             switch (code) {  
  39.             case INTERFACE_TRANSACTION: {  
  40.                 reply.writeString(DESCRIPTOR);  
  41.                 return true;  
  42.             }  
  43.             case TRANSACTION_getFileDescriptor: {  
  44.                 data.enforceInterface(DESCRIPTOR);  
  45.                   
  46.                 ParcelFileDescriptor result = this.getFileDescriptor();  
  47.                   
  48.                 reply.writeNoException();  
  49.                   
  50.                 if (result != null) {  
  51.                     reply.writeInt(1);  
  52.                     result.writeToParcel(reply, 0);  
  53.                 } else {  
  54.                     reply.writeInt(0);  
  55.                 }  
  56.   
  57.                 return true;  
  58.             }  
  59.             case TRANSACTION_setValue: {  
  60.                 data.enforceInterface(DESCRIPTOR);  
  61.                   
  62.                 int val = data.readInt();  
  63.                 setValue(val);  
  64.                   
  65.                 reply.writeNoException();  
  66.                   
  67.                 return true;  
  68.             }  
  69.             }  
  70.   
  71.             return super.onTransact(code, data, reply, flags);  
  72.         }  
  73.   
  74.         private static class Proxy implements IMemoryService {  
  75.             private IBinder mRemote;  
  76.   
  77.             Proxy(IBinder remote) {  
  78.                 mRemote = remote;  
  79.             }  
  80.   
  81.             public IBinder asBinder() {  
  82.                 return mRemote;  
  83.             }  
  84.   
  85.             public String getInterfaceDescriptor() {  
  86.                 return DESCRIPTOR;  
  87.             }  
  88.   
  89.             public ParcelFileDescriptor getFileDescriptor() throws RemoteException {  
  90.                 Parcel data = Parcel.obtain();  
  91.                 Parcel reply = Parcel.obtain();  
  92.   
  93.                 ParcelFileDescriptor result;  
  94.       
  95.                 try {  
  96.                     data.writeInterfaceToken(DESCRIPTOR);  
  97.   
  98.                     mRemote.transact(Stub.TRANSACTION_getFileDescriptor, data, reply, 0);  
  99.           
  100.                     reply.readException();  
  101.                     if (0 != reply.readInt()) {  
  102.                         result = ParcelFileDescriptor.CREATOR.createFromParcel(reply);  
  103.                     } else {  
  104.                         result = null;  
  105.                     }  
  106.                 } finally {  
  107.                     reply.recycle();  
  108.                     data.recycle();  
  109.                 }  
  110.       
  111.                 return result;  
  112.             }  
  113.   
  114.             public void setValue(int val) throws RemoteException {  
  115.                 Parcel data = Parcel.obtain();  
  116.                 Parcel reply = Parcel.obtain();  
  117.   
  118.                 try {  
  119.                     data.writeInterfaceToken(DESCRIPTOR);  
  120.                     data.writeInt(val);  
  121.   
  122.                     mRemote.transact(Stub.TRANSACTION_setValue, data, reply, 0);  
  123.                       
  124.                     reply.readException();  
  125.                 } finally {  
  126.                     reply.recycle();  
  127.                     data.recycle();  
  128.                 }  
  129.             }  
  130.         }  
  131.   
  132.         static final int TRANSACTION_getFileDescriptor = IBinder.FIRST_CALL_TRANSACTION + 0;  
  133.         static final int TRANSACTION_setValue = IBinder.FIRST_CALL_TRANSACTION + 1;  
  134.   
  135.     }  
  136.   
  137.     public ParcelFileDescriptor getFileDescriptor() throws RemoteException;  
  138.     public void setValue(int val) throws RemoteException;  
  139. }  
[java]
  1. package shy.luo.ashmem;  
  2.   
  3. import android.util.Log;  
  4. import android.os.IInterface;  
  5. import android.os.Binder;  
  6. import android.os.IBinder;  
  7. import android.os.Parcel;  
  8. import android.os.ParcelFileDescriptor;  
  9. import android.os.RemoteException;  
  10.   
  11. public interface IMemoryService extends IInterface {  
  12.     public static abstract class Stub extends Binder implements IMemoryService {  
  13.         private static final String DESCRIPTOR = "shy.luo.ashmem.IMemoryService";  
  14.   
  15.         public Stub() {  
  16.             attachInterface(this, DESCRIPTOR);  
  17.         }  
  18.   
  19.         public static IMemoryService asInterface(IBinder obj) {  
  20.             if (obj == null) {  
  21.                 return null;  
  22.             }  
  23.   
  24.             IInterface iin = (IInterface)obj.queryLocalInterface(DESCRIPTOR);  
  25.             if (iin != null && iin instanceof IMemoryService) {  
  26.                 return (IMemoryService)iin;  
  27.             }  
  28.   
  29.             return new IMemoryService.Stub.Proxy(obj);  
  30.         }  
  31.   
  32.         public IBinder asBinder() {  
  33.             return this;  
  34.         }  
  35.   
  36.         @Override   
  37.         public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws android.os.RemoteException {  
  38.             switch (code) {  
  39.             case INTERFACE_TRANSACTION: {  
  40.                 reply.writeString(DESCRIPTOR);  
  41.                 return true;  
  42.             }  
  43.             case TRANSACTION_getFileDescriptor: {  
  44.                 data.enforceInterface(DESCRIPTOR);  
  45.                   
  46.                 ParcelFileDescriptor result = this.getFileDescriptor();  
  47.                   
  48.                 reply.writeNoException();  
  49.                   
  50.                 if (result != null) {  
  51.                     reply.writeInt(1);  
  52.                     result.writeToParcel(reply, 0);  
  53.                 } else {  
  54.                     reply.writeInt(0);  
  55.                 }  
  56.   
  57.                 return true;  
  58.             }  
  59.             case TRANSACTION_setValue: {  
  60.                 data.enforceInterface(DESCRIPTOR);  
  61.                   
  62.                 int val = data.readInt();  
  63.                 setValue(val);  
  64.                   
  65.                 reply.writeNoException();  
  66.                   
  67.                 return true;  
  68.             }  
  69.             }  
  70.   
  71.             return super.onTransact(code, data, reply, flags);  
  72.         }  
  73.   
  74.         private static class Proxy implements IMemoryService {  
  75.             private IBinder mRemote;  
  76.   
  77.             Proxy(IBinder remote) {  
  78.                 mRemote = remote;  
  79.             }  
  80.   
  81.             public IBinder asBinder() {  
  82.                 return mRemote;  
  83.             }  
  84.   
  85.             public String getInterfaceDescriptor() {  
  86.                 return DESCRIPTOR;  
  87.             }  
  88.   
  89.             public ParcelFileDescriptor getFileDescriptor() throws RemoteException {  
  90.                 Parcel data = Parcel.obtain();  
  91.                 Parcel reply = Parcel.obtain();  
  92.   
  93.                 ParcelFileDescriptor result;  
  94.       
  95.                 try {  
  96.                     data.writeInterfaceToken(DESCRIPTOR);  
  97.   
  98.                     mRemote.transact(Stub.TRANSACTION_getFileDescriptor, data, reply, 0);  
  99.           
  100.                     reply.readException();  
  101.                     if (0 != reply.readInt()) {  
  102.                         result = ParcelFileDescriptor.CREATOR.createFromParcel(reply);  
  103.                     } else {  
  104.                         result = null;  
  105.                     }  
  106.                 } finally {  
  107.                     reply.recycle();  
  108.                     data.recycle();  
  109.                 }  
  110.       
  111.                 return result;  
  112.             }  
  113.   
  114.             public void setValue(int val) throws RemoteException {  
  115.                 Parcel data = Parcel.obtain();  
  116.                 Parcel reply = Parcel.obtain();  
  117.   
  118.                 try {  
  119.                     data.writeInterfaceToken(DESCRIPTOR);  
  120.                     data.writeInt(val);  
  121.   
  122.                     mRemote.transact(Stub.TRANSACTION_setValue, data, reply, 0);  
  123.                       
  124.                     reply.readException();  
  125.                 } finally {  
  126.                     reply.recycle();  
  127.                     data.recycle();  
  128.                 }  
  129.             }  
  130.         }  
  131.   
  132.         static final int TRANSACTION_getFileDescriptor = IBinder.FIRST_CALL_TRANSACTION + 0;  
  133.         static final int TRANSACTION_setValue = IBinder.FIRST_CALL_TRANSACTION + 1;  
  134.   
  135.     }  
  136.   
  137.     public ParcelFileDescriptor getFileDescriptor() throws RemoteException;  
  138.     public void setValue(int val) throws RemoteException;  
  139. }  
package shy.luo.ashmem;import android.util.Log;import android.os.IInterface;import android.os.Binder;import android.os.IBinder;import android.os.Parcel;import android.os.ParcelFileDescriptor;import android.os.RemoteException;public interface IMemoryService extends IInterface {	public static abstract class Stub extends Binder implements IMemoryService {		private static final String DESCRIPTOR = "shy.luo.ashmem.IMemoryService";		public Stub() {			attachInterface(this, DESCRIPTOR);		}		public static IMemoryService asInterface(IBinder obj) {			if (obj == null) {				return null;			}			IInterface iin = (IInterface)obj.queryLocalInterface(DESCRIPTOR);			if (iin != null && iin instanceof IMemoryService) {				return (IMemoryService)iin;			}			return new IMemoryService.Stub.Proxy(obj);		}		public IBinder asBinder() {			return this;		}		@Override 		public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws android.os.RemoteException {			switch (code) {			case INTERFACE_TRANSACTION: {				reply.writeString(DESCRIPTOR);				return true;			}			case TRANSACTION_getFileDescriptor: {				data.enforceInterface(DESCRIPTOR);								ParcelFileDescriptor result = this.getFileDescriptor();								reply.writeNoException();								if (result != null) {					reply.writeInt(1);					result.writeToParcel(reply, 0);				} else {					reply.writeInt(0);				}				return true;			}			case TRANSACTION_setValue: {				data.enforceInterface(DESCRIPTOR);								int val = data.readInt();				setValue(val);								reply.writeNoException();								return true;			}			}			return super.onTransact(code, data, reply, flags);		}		private static class Proxy implements IMemoryService {			private IBinder mRemote;			Proxy(IBinder remote) {				mRemote = remote;			}			public IBinder asBinder() {				return mRemote;			}			public String getInterfaceDescriptor() {				return DESCRIPTOR;			}			public ParcelFileDescriptor getFileDescriptor() throws RemoteException {				Parcel data = Parcel.obtain();				Parcel reply = Parcel.obtain();				ParcelFileDescriptor result;					try {					data.writeInterfaceToken(DESCRIPTOR);					mRemote.transact(Stub.TRANSACTION_getFileDescriptor, data, reply, 0);							reply.readException();					if (0 != reply.readInt()) {						result = ParcelFileDescriptor.CREATOR.createFromParcel(reply);					} else {						result = null;					}				} finally {					reply.recycle();					data.recycle();				}					return result;			}			public void setValue(int val) throws RemoteException {				Parcel data = Parcel.obtain();				Parcel reply = Parcel.obtain();				try {					data.writeInterfaceToken(DESCRIPTOR);					data.writeInt(val);					mRemote.transact(Stub.TRANSACTION_setValue, data, reply, 0);										reply.readException();				} finally {					reply.recycle();					data.recycle();				}			}		}		static final int TRANSACTION_getFileDescriptor = IBinder.FIRST_CALL_TRANSACTION + 0;		static final int TRANSACTION_setValue = IBinder.FIRST_CALL_TRANSACTION + 1;	}	public ParcelFileDescriptor getFileDescriptor() throws RemoteException;	public void setValue(int val) throws RemoteException;}

        这里主要是定义了IMemoryService接口,它里面有两个调用接口:

 

 

[java]
  1. public ParcelFileDescriptor getFileDescriptor() throws RemoteException;  
  2. public void setValue(int val) throws RemoteException;  
[java]
  1. public ParcelFileDescriptor getFileDescriptor() throws RemoteException;  
  2. public void setValue(int val) throws RemoteException;  
public ParcelFileDescriptor getFileDescriptor() throws RemoteException;	public void setValue(int val) throws RemoteException;

        同时,还分别定义了用于Server端实现的IMemoryService.Stub基类和用于Client端使用的代理IMemoryService.Stub.Proxy类。关于Binder进程间通信机制在应用程序框架层的Java接口定义,请参考前面一文。