2013年8月5日星期一

Using Android NDK and Java testing Linux driver

 

the Android emulator and testing on Ubuntu Linux driver

 

Third, using the AndroidNDK < / span> test Linux drive

 

in the Android system the user is a Linux driver APK main program. Therefore, Linux drivers after finishing procedures for testing must be used in order to explain APK Linux driver can be used normally. Because the one used on the Android virtual machine executable program written in C language test Linux drivers, so it is easy to think of Android NDK can be used to test the Linux driver,

 

also use the Android NDK C / C + + to write programs, so you can use on a C-language code, of course, have to add some AndroidNDK specific code. Linux driver in use AndroidNDK testing needs to be done before the following two things.

 

1. because Linux driver module will not change with the Android system startup and loading, it is necessary to execute the script file build.sh install word_count drive.

 

2. should not use the default way to start the Android emulator, but to use our own compilation of the Linux kernel boot Android emulator, start the emulator command is as follows:

 

# emulator-avd myavd-kernel / root / kernel / goldfish / arch / arm / boot / zImage

 

For convenience, the reader can book with CD-ROM with Ubuntu Linux in a virtual environment directly execute the following command to start the Android emulator asynchronous. Which emulator.sh file / root / drivers directory.

 

# sh emulator.sh &

 

examples in this section has been included in the CD with the book and virtual environments, the path is as follows:

 

CD with the book: / sources/ch06/word_count/word_count_ndk

 

virtual environment: / root/drivers/ch06/word_count/word_count_ndk

 

word_count_ndk code works in part by WordCountNDKTestMain.java and ndk_test_word_count.c files. Engineering structures shown in Figure 6-17.

 

 

ndk_test_word_count.c word_count driver used to access the file. The file contains two functions for Java access were used to read / dev / wordcount device file of the word count and to / dev / wordcount device file writes the string. Here take a look at the complete code ndk_test_word_count.c file.

 
  
    #include <string.h>   
#include <jni.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
// JNI函数:readWordCountFromDev
// 用于从/dev/wordcount设备文件读取单词数
jint Java_mobile_android_word_count_ndk_WordCountNDKTestMain_readWordCountFromDev(
JNIEnv* env, jobject thiz)
{

int dev; // open函数打开/dev/wordcount设备文件后返回的句柄,打开失败返回-1
jint wordcount = 0; // 单词数
unsigned char buf[4]; // 以4个字节形式存储的单词数

// 以只读方式打开/dev/wordcount设备文件
dev = open("/dev/wordcount", O_RDONLY);

// 从dev/wordcount设备文件中读取单词数
read(dev, buf, 4);

int n = 0; // 存储单词数的int类型变量

// 将由4个字节表示的单词数转换成int类型的值
n = ((int) buf[0]) << 24 | ((int) buf[1]) << 16 | ((int) buf[2]) << 8 | ((int) buf[3]);
// 将int类型的单词数转换成jint类型的单词数
wordcount = (jint) n;
// 关闭/dev/wordcount设备文件
close(dev);
// 返回单词数
return wordcount;
}
// 将jstring类型的值转换成char *类型的值
char* jstring_to_pchar(JNIEnv* env, jstring str)
{
char* pstr = NULL;
// 下面的代码会调用Java中的String.getBytes方法获取字符串的字节数

// 获取java.lang.String类
jclass clsstring = (*env)->FindClass(env, "java/lang/String");
// 将字符串"utf-8"转换成jstring类型的值
jstring strencode = (*env)->NewStringUTF(env, "utf-8");
// 获取java.lang.String.getBytes方法
jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes", "(Ljava/lang/String;)[B");
// 调用String.getBytes方法将str变量的值转换成jbytearray类型的值
jbyteArray byteArray = (jbyteArray)( (*env)->CallObjectMethod(env, str, mid, strencode));
// 获取字节长度
jsize size = (*env)->GetArrayLength(env, byteArray);
// 将jbytearray类型的值转换成jbyte*类型的值
jbyte* pbyte = (*env)->GetByteArrayElements(env, byteArray, JNI_FALSE);
if (size > 0)
{
// 为char*类型变量pstr分配空间
pstr = (char*) malloc(size);
// 将pbyte变量中的值复制到pstr变量中
memcpy(pstr, pbyte, size);
}
// 返回转换后的值
return pstr;
}
// JNI函数:writeStringToDev
// 用于向/dev/wordcount设备文件写入字符串
void Java_mobile_android_word_count_ndk_WordCountNDKTestMain_writeStringToDev(
JNIEnv* env, jobject thiz, jstring str)
{

int dev; // open函数打开/dev/wordcount设备文件后返回的句柄,打开失败返回-1
// 以只写方式打开/dev/wordcount设备文件
dev = open("/dev/wordcount", O_WRONLY);
// 将jstring类型字符串转换成char* 类型的值
char* pstr = jstring_to_pchar(env, str);
if (pstr != NULL)
{
// 向/dev/wordcount设备文件写入字符串
write(dev,pstr, strlen(pstr));
}
// 关闭/dev/wordcount设备文件
close(dev);
}
 
 

write the above code has a focus is jstring_to_pchar function. The function can be jstring types of data into a data type char *. The basic idea is to convert the Java method calls String.getBytes, get a string corresponding byte array (jbyteArray). Write function is needed because of type char * data, so you must also jbyteArray types of data into a data type char *. Approach is to first convert the data type jbyteArray jbyte types of data, and then call memcpy function jbyte types of data replication to use malloc function allocates a char * pointer space. In jstring_to_pchar function has the following line of code.

 

jmethodID mid = (* env) -> GetMethodID (env, clsstring, "getBytes", "(Ljava / lang / String ;) [B"];

 

see getMethodID method the value of the last parameter is "(Ljava / lang / String ;) [B", may be Android NDK beginners will feel confused, thought it was wrong the. In fact, this is the JNI (Android NDK JNI program actually is to follow the rules of procedure) for method parameters and return type description. In order to facilitate the procedure described JNI Java data types, the use of a simple type capital letters, as shown in Table 6-1.

 

 

Apart shown in Table 6-1 Java simple types, there are some data types require corresponding JNI code. Table 6-2 shows the data type descriptor in JNI.

 

 

from the type of data shown in Table 6-2 control relationship is very easy to think that in this case "(Ljava / lang / String ;) [B" what it meant. jstring_to_pchar function call is as follows getBytes method overloads.

 

public byte [] getBytes (String charsetName) throwsUnsupportedEncodingException

 

in JNI to call Java methods need to specify the method parameters and return value data types. In JNI format is as follows:

 

"(parameter type) return value type"

 

getBytes method parameter type is String, described in Table 6-2, String type descriptor is in JNI " Ljava / lang / String; ". getBytes method's return value type is byte []. This involves an array notation. In JNI array using the left bracket ([] that followed the type of elements in the array in each dimension requires the use of a "[". Byte [] is a one-dimensional array of bytes, so the use of "[B" represents. If the byte [] [] [], you should use "[[[B" means that if the Java method does not return any value (return type is void), is denoted by V as void mymethod (int value) parameters and return value type can be expressed as "(I) V".

 

Android NDK program also requires a Android.mk file, the code is as follows:

 
  
    LOCAL_PATH := $(call my-dir)   

include $(CLEAR_VARS)

LOCAL_MODULE := ndk_test_word_count
LOCAL_SRC_FILES := ndk_test_word_count.c

include $(BUILD_SHARED_LIBRARY)
 
 

 

in writing Java code before calling JNI functions, look at the example of the interface, shown in Figure 6-18.

 

 

readers need to run on a PC build.sh script file to install word_count drive. Then click "From the / dev / wordcount number of words read" button, the button beneath the output current / dev / wordcount device file in the statistics of the number of words. Readers can also in the input box to enter a space-separated string, and then click "to / dev / wordcount writing the string" button, then click the "from / dev / wordcount number of words read 'button, you will the statistics of the number of words contained in a string, the effect shown in Figure 6-19.

 

following look at this example, the Java section (WordCountNDKTestMain.java) the complete code.

 
  
    package mobile.android.word.count.ndk;   

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class WordCountNDKTestMain extends Activity
{
private TextView tvWordCount;
private EditText etString;

@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tvWordCount = (TextView) findViewById(R.id.textview_wordcount);
etString = (EditText) findViewById(R.id.edittext_string);
}
// "从/dev/wordcount读取单词数"按钮的执行代码
public void onClick_ReadWordCountFromDev(View view)
{
// 显示单词数
tvWordCount.setText("单词数:" + String.valueOf(readWordCountFromDev()));
}
// "向/dev/wordcount写入字符串"按钮的执行代码
public void onClick_WriteStringToDev(View view)
{
// 向/dev/wordcount设备文件写入字符串
writeStringToDev(etString.getText().toString());
Toast.makeText(this, "已向/dev/wordcount写入字符串", Toast.LENGTH_LONG).show();
}

// native方法
public native int readWordCountFromDev();
public native void writeStringToDev(String str);
static
{
System.loadLibrary("ndk_test_word_count");
}
}
 
 

 

WordCountNDKTestMain.java the code simply calls the JNI functions to manipulate / dev / wordcount file. Other codes are regular Android application-level code. If the reader is not familiar with this part, you can see the author's book "Android Developer Definitive Guide."

 

four, using Java code directly operate the device file to test Linux driver

 If you have root privileges

Android, Java code can be used directly manipulate / dev / wordcount device file (without root privileges, Linux driver module is not installed). This section describes how to use Java code to test the Linux driver (test program does not use a line C / C + + code). Examples in this section of the path is as follows:

 

CD with the book: / sources/ch06/word_count/word_count_java

 

virtual environment: / root/drivers/ch06/word_count/word_count_java

 

word_count_java project is only one source code file WordCountJavaTestMain.java. The document reads as follows:

 
  
    package mobile.android.word.count.java;   

import java.io.FileInputStream;
import java.io.FileOutputStream;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class WordCountJavaTestMain extends Activity
{
private TextView tvWordCount;
private EditText etString;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tvWordCount = (TextView) findViewById(R.id.textview_wordcount);
etString = (EditText) findViewById(R.id.edittext_string);
}
// "从/dev/wordcount读取单词数"按钮的执行代码
public void onClick_ReadWordCountFromDev(View view)
{
// 显示单词数
tvWordCount.setText("单词数:" + String.valueOf(readWordCountFromDev()));
}
// "向/dev/wordcount写入字符串"按钮的执行代码
public void onClick_WriteStringToDev(View view)
{
// 向/dev/wordcount设备文件写入字符串
writeStringToDev(etString.getText().toString());
Toast.makeText(this, "已向/dev/wordcount写入字符串", Toast.LENGTH_LONG).show();
}
// 下面是用Java实现的操作/dev/wordcount设备文件的代码

// 读取/dev/wordcount设备文件中的单词数
private int readWordCountFromDev()
{
int n = 0;
byte[] buffer = new byte[4];
try
{
// 打开/dev/wordcount设备文件
FileInputStream fis = new FileInputStream("/dev/wordcount");
// 从设备文件中读取4个字节
fis.read(buffer);
// 将4个字节转换成int类型的值
n = ((int) buffer[0]) << 24 | ((int) buffer[1]) << 16
| ((int) buffer[2]) << 8 | ((int) buffer[3]);
fis.close();
}
catch (Exception e)
{
}
return n;
}
// 向/dev/wordcount设备文件中写入字符串
private void writeStringToDev(String str)
{
try
{
// 打开/dev/wordcount设备文件
FileOutputStream fos = new FileOutputStream("/dev/wordcount");
// 写入字符串
fos.write(str.getBytes("iso-8859-1"));
fos.close();
}
catch (Exception e)
{
}
}
}
 
 

effect of running this example and use a method similar to the example above. Readers can run the CD with the book or virtual environments on one of the examples and comparative examples.

 


This excerpt from "Android Deep Exploration (Volume 1): HAL and Driver Development " , the next few articles will elaborate on how to develop the ARM architecture Linux driver, and were using the android program, NDK, executable test Linux driven. In ubuntu Linux, Android emulator and S3C6410 development board (you can buy OK6410-A development board, need to brush Android)

没有评论:

发表评论