在上文中我们实现了利用Service来设计HAL,但是根据Android的框架,一般应用程序都不直接和Service打交到,中间需要经过一个Manager层。

我们在这里也按照Android的框架,进一步优化HAL的设计。结构如下:

HAL stub <-> JNI 库 <-> JAVA Service <-> Manager <-> JAVA 应用程序。

由于LedManager和LedService属于两个进程,他们之间的通信需要通过AIDL来实现,下面是ILedService.aidl

 
  
  1. package mokoid.hardware; 
  2.  
  3. interface ILedService 
  4.     boolean setOn(int led); 
  5.     boolean setOff(int led); 

在这个文件中定义了LedService提供给LedManager的接口,经过aidl工具会被编译成ILedService.java文件。

我们再看看LedManager是如何实现的: 

 
  
  1. public class LedManager 
  2.     private static final String TAG = "LedManager"
  3.     private ILedService mLedService; 
  4.  
  5.     public LedManager() { 
  6.      
  7.         mLedService = ILedService.Stub.asInterface( 
  8.                              ServiceManager.getService("led")); 
  9.  
  10.     if (mLedService != null) { 
  11.             Log.i(TAG, "The LedManager object is ready."); 
  12.     } 
  13.     } 
  14.  
  15.     public boolean LedOn(int n) { 
  16.         boolean result = false
  17.  
  18.         try { 
  19.             result = mLedService.setOn(n); 
  20.         } catch (RemoteException e) { 
  21.             Log.e(TAG, "RemoteException in LedManager.LedOn:", e); 
  22.         } 
  23.         return result; 
  24.     } 
  25.  
  26.     public boolean LedOff(int n) { 
  27.         boolean result = false
  28.  
  29.         try { 
  30.             result = mLedService.setOff(n); 
  31.         } catch (RemoteException e) { 
  32.             Log.e(TAG, "RemoteException in LedManager.LedOff:", e); 
  33.         } 
  34.         return result; 
  35.     } 

这里需要注意的是mLedService = ILedService.Stub.asInterface(nager.getService("led")); 通过这个函数可以得到LedService的实例,从而调用它的方法。

而对于LedService我们需要作一个小小的改变,如下:

 
  
  1. public final class LedService extends ILedService.Stub { 
  2.  
  3.     static { 
  4.         System.load("/system/lib/libmokoid_runtime.so"); 
  5.     } 
  6.  
  7.     public LedService() { 
  8.         Log.i("LedService""Go to get LED Stub..."); 
  9.     _init(); 
  10.     } 
  11.  
  12.     /* 
  13.      * Mokoid LED native methods. 
  14.      */ 
  15.     public boolean setOn(int led) { 
  16.         Log.i("MokoidPlatform""LED On"); 
  17.     return _set_on(led); 
  18.     } 
  19.  
  20.     public boolean setOff(int led) { 
  21.         Log.i("MokoidPlatform""LED Off"); 
  22.     return _set_off(led); 
  23.     } 
  24.  
  25.     private static native boolean _init(); 
  26.     private static native boolean _set_on(int led); 
  27.     private static native boolean _set_off(int led); 

该LedService需要继承自ILedService.Stub从而实现AIDL接口与LedManager通信。

最后我们看看应用程序,在应用程序中,我们实现了一个service(注意和上面的service的区别)和一个activity,在service中start了LedService, 而在activity中通过LedManager来使用LedService中提供的接口。

我们首先来看看service的实现:

 
  
  1. public class LedSystemServer extends Service { 
  2.  
  3.     @Override 
  4.     public IBinder onBind(Intent intent) { 
  5.         return null
  6.     } 
  7.  
  8.     public void onStart(Intent intent, int startId) { 
  9.         Log.i("LedSystemServer""Start LedService..."); 
  10.  
  11.     /* Please also see SystemServer.java for your interests. */ 
  12.     LedService ls = new LedService(); 
  13.  
  14.         try { 
  15.             ServiceManager.addService("led", ls); 
  16.         } catch (RuntimeException e) { 
  17.             Log.e("LedSystemServer""Start LedService failed."); 
  18.         } 
  19.     } 

这里需要注意的是ServiceManager.addService("led", ls); 通过它可以启动恰面创建的LedService。

我们再看看Activity的实现:

 
  
  1. public class LedTest extends Activity implements View.OnClickListener { 
  2.     private LedManager mLedManager = null
  3.  
  4.     @Override 
  5.     public void onCreate(Bundle savedInstanceState) { 
  6.         super.onCreate(savedInstanceState); 
  7.  
  8.         // Start LedService in a seperated process. 
  9.         startService(new Intent("com.mokoid.systemserver")); 
  10.  
  11.         Button btn = new Button(this); 
  12.         btn.setText("Click to turn LED 1 On"); 
  13.         btn.setOnClickListener(this); 
  14.  
  15.         setContentView(btn); 
  16.     } 
  17.  
  18.     public void onClick(View v) { 
  19.  
  20.         // Get LedManager. 
  21.         if (mLedManager == null) { 
  22.         Log.i("LedTest""Creat a new LedManager object."); 
  23.         mLedManager = new LedManager(); 
  24.         } 
  25.  
  26.         if (mLedManager != null) { 
  27.         Log.i("LedTest""Got LedManager object."); 
  28.     } 
  29.  
  30.         /** Call methods in LedService via proxy object  
  31.          * which is provided by LedManager.  
  32.          */ 
  33.         mLedManager.LedOn(1); 
  34.  
  35.         TextView tv = new TextView(this); 
  36.         tv.setText("LED 1 is On."); 
  37.         setContentView(tv); 
  38.     } 

当这个activity创建的时候,会通过intent开启上面定义的LedSystemServer,该LedSystemServer会开启前面定义的LedService,当点击button的时候,会new一个LedManager,该LedManager会通过ServiceManager.addService("led", ls)得到LedService的实例,并且提供LedService中的接口给这个activity使用,从而在该activity中实现对Led的控制。