android hal 测试代码,Android HAL实例解析(二)
(3)service(属于Framework层)文件:frameworks/base/service/java/com/mokoid/server/LedService.javapackagecom.mokoid.server;importandroid.util.Config;importandroid.util.Log;importandroid.content.Context;imp...
(3)service(属于Framework层)
文件:frameworks/base/service/java/com/mokoid/server/LedService.java
package com.mokoid.server;
import android.util.Config;
import android.util.Log;
import android.content.Context;
import android.os.Binder;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.IBinder;
import mokoid.hardware.ILedService;
publicfinalclassLedService extends ILedService.Stub {
//对于这种直接模式不需要进程通讯,所以可以不加extends ILedService.Stub,此处加上主要是为了后面的第二种模式.
static{
System.load("/system/lib/libmokoid_runtime.so");//加载jni的动态库
}
publicLedService() {
Log.i("LedService","Go to get LED Stub...");
_init();
}
/*
* Mokoid LED native methods.
*/
publicboolean setOn(intled) {
Log.i("MokoidPlatform","LED On");
return_set_on(led);
}
publicboolean setOff(intled) {
Log.i("MokoidPlatform","LED Off");
return_set_off(led);
}
privatestaticnative boolean _init();//声明jni库可以提供的方法
privatestaticnative boolean _set_on(intled);
privatestaticnative boolean _set_off(intled);
}
(4)APP测试程序(属于APP层)
文件:apps/LedClient/src/com/mokoid/LedClient/LedClient.java
package com.mokoid.LedClient;
import com.mokoid.server.LedService;// 导入Framework层的LedService
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
publicclassLedClient extends Activity {
@Override
publicvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Call an API on the library.
LedService ls = newLedService();//实例化LedService
ls.setOn(1); //通过LedService提供的方法,控制底层硬件
ls.setOff(2);
TextView tv = newTextView(this);
tv.setText("LED 1 is on. LED 2 is off.");
setContentView(tv);
}
}
5、第二种方法:经过Manager调用service
HAL、JNI两层和第一种方法一样,所以后面只分析其他的层次。
(1)Manager(属于Framework层)
APP通过这个Manager和service通讯。
文件:mokoid-read-only /frameworks/base/core/java/mokoid/hardware/LedManager.java
package mokoid.hardware;
import android.content.Context;
import android.os.Binder;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.Handler;
import android.os.Message;
import android.os.ServiceManager;
import android.util.Log;
import mokoid.hardware.ILedService;
/*
* Class that lets you access the Mokoid LedService.
*/
publicclassLedManager
{
privatestaticfinal String TAG ="LedManager";
privateILedService mLedService;
publicLedManager() {
mLedService = ILedService.Stub.asInterface(ServiceManager.getService("led"));
/*
*这一步是关键,利用ServiceManager获取到LedService,从而调用它提供的方法。这要求LedService必
*须已经添加到了ServiceManager中,这个过程将在App中的一个service进程中完成。
*/
if(mLedService !=null) {
Log.i(TAG, "The LedManager object is ready.");
}
}
publicboolean LedOn(intn) {
boolean result = false;
try{
result = mLedService.setOn(n);
} catch(RemoteException e) {
Log.e(TAG, "RemoteException in LedManager.LedOn:", e);
}
returnresult;
}
publicboolean LedOff(intn) {
boolean result = false;
try{
result = mLedService.setOff(n);
} catch(RemoteException e) {
Log.e(TAG, "RemoteException in LedManager.LedOff:", e);
}
returnresult;
}
}
因为LedService和LedManager在不同的进程,所以要考虑到进程通讯的问题。Manager通过增加一个aidl文件来描述通讯接口。
文件:mokoid-read-only/frameworks/base/core/java/mokoid/hardware/ILedService.aidl
package mokoid.hardware;
interfaceILedService
{
boolean setOn(intled);
boolean setOff(intled);
}
//系统的aidl工具会将ILedService.aidl文件ILedService.java文件,实现了ILedService
(2)SystemServer(属于APP层)
文件:mokoid-read-only/apps/LedTest/src/com/mokoid/LedTest/LedSystemServer.java
package com.mokoid.LedTest;
import com.mokoid.server.LedService;
import android.os.IBinder;
import android.os.ServiceManager;
import android.util.Log;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
publicclassLedSystemServer extends Service {
//注意这里的Service是APP中的概念,代表一个后台进程。注意区别和Framework中的service的概念。
@Override
publicIBinder onBind(Intent intent) {
returnnull;
publicvoidonStart(Intent intent,intstartId) {
Log.i("LedSystemServer","Start LedService...");
/* Please also see SystemServer.java for your interests. */
LedService ls = newLedService();
try{
ServiceManager.addService("led", ls);//将LedService添加到ServiceManager中
} catch(RuntimeException e) {
Log.e("LedSystemServer","Start LedService failed.");
}
}
}
(3)APP测试程序(属于APP层)
文件:mokoid-read-only/apps/LedTest/src/com/mokoid/LedTest/LedTest.java
package com.mokoid.LedTest;
import mokoid.hardware.LedManager;
import com.mokoid.server.LedService;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Button;
import android.content.Intent;
import android.view.View;
publicclassLedTest extends Activity implements View.OnClickListener {
privateLedManager mLedManager =null;
@Override
publicvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Start LedService in a seperated process.
startService(newIntent("com.mokoid.systemserver"));//开启后台进程
Button btn = newButton(this);
btn.setText("Click to turn LED 1 On");
btn.setOnClickListener(this);
setContentView(btn);
}
publicvoidonClick(View v) {
// Get LedManager.
if(mLedManager ==null) {
Log.i("LedTest","Creat a new LedManager object.");
mLedManager = newLedManager();//实例化Framework层中的Manager
}
if(mLedManager !=null) {
Log.i("LedTest","Got LedManager object.");
}
/** Call methods in LedService via proxy object
* which is provided by LedManager.
*/
mLedManager.LedOn(1);
TextView tv = newTextView(this);
tv.setText("LED 1 is On.");
setContentView(tv);
}
}
五、实验中需要注意的问题
将下载后的源码放到你的android源码目录下,然后编译系统。本实验用的android版本为2.1。实验的过程中大致出现过以下几个问题:
1、目标系统中没有生成LedClient.apk或LedTest.apk应用程序
编译完成后,没有在目标系统的system/app/目录下找到LedClient.apk或LedTest应用程序。只有通过单独编译LedClient或LedTest才能在目标目录中生成。方法如下:
#mmmmokoid-read-only/apps/LedTest/
检查原因后发现mokoid-read-only/apps/LedTest/Android.mk
LOCAL_MODULES_TAGS :=user
而我们的s5pc100系统在配置时tapas时选择的是eng,所以没有装载到目标系统
所以修改LedTest和LedClient的Android.mk
LOCAL_MODULES_TAGS :=usereng
再次编译即可自动装载到目标系统/system/app/目录下。
2、启动后没有图标,找不到应用程序
目标系统启动后找不到两个应用程序的图标。仔细阅读logcat输出的信息发现:
E/PackageManager( 2717): Package com.mokoid.LedClient requires unavailable shared library com.mokoid.server; failing!
原因是找不到 com.mokoid.server。检查mokoid-read-only/frameworks/base/Android.mk发现系统将LedManager和LedService编译成 mokoid.jar库文件。为了让应用程序可以访问到这个库,需要通过com.mokoid.server.xml 来设定其对应关系。解决方法:拷贝com.mokoid.server.xml到目标系统的system/etc/permissions/目录下
此时两个应用的程序的图标都正常出现了。
3、提示找不到JNI_OnLoad
按照以前的实验加入下列代码:
staticintregisterMethods(JNIEnv* env) {
staticconstchar*constkClassName ="com/mokoid/server/LedService";
jclass clazz;
/* look up the class */
clazz = env->FindClass(kClassName);
if(clazz == NULL) {
LOGE("Can't find class %s\n", kClassName);
return-1;
}
/* register all the methods */
if(env->RegisterNatives(clazz, gMethods,
sizeof(gMethods) /sizeof(gMethods[0])) != JNI_OK)
{
LOGE("Failed registering methods for %s\n", kClassName);
return-1;
}
/* fill out the rest of the ID cache */
return0;
}
/*
* This is called by the VM when the shared library is first loaded.
*/
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env = NULL;
jint result = -1;
LOGI("JNI_OnLoad LED");
if(vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
LOGE("ERROR: GetEnv failed\n");
gotofail;
}
assert(env != NULL);
if(registerMethods(env) != 0) {
LOGE("ERROR: PlatformLibrary native registration failed\n");
gotofail;
}
/* success -- return valid version number */
result = JNI_VERSION_1_4;
fail:
returnresult;
}
4、需要针对你的目标平台修改HAL的Makefile
修改mokoid-read-only/hardware/modules/led/Android.mk
LOCAL_MODULE := led.default
5、在eclipse中编译不了LedSystemServer.java
原因是程序中要用到ServiceManager.addService,这需要系统权限。
解决方法可以把应用程序放入Android源码中编译,并确保以下两点:
(1)在应用程序的AndroidManifest.xml中的manifest节点中加入android:sharedUserId="android.uid.system"这个属性。
(2)修改Android加入LOCAL_CERTIFICATE := platform.
当然:mokoid工程源码中已经做了这些。
更多推荐
所有评论(0)