Test the Linux driver on the android simulator and ubuntu.
Iii. UseAndroidndkTestLinuxDriver
In Android, the main user of the Linux driver is APK.Program. Therefore, you must use the APK program to test the Linux driver. Since the Linux driver was tested using an executable program written in C language on the android virtual machine in the previous section, it is easy to think that android ndk can be used to test the Linux driver,
Because Android ndk also uses C/C ++ to write programs, you can use the C language in the previous sectionCodeOf course, some androidndk-specific code must be added. Before using androidndk to test the Linux driver, you need to do the following two things.
1. Because the Linux driver module is not loaded with the Android system, you must run the build. Sh script file to install the word_count driver.
2. the android simulator cannot be started by default, but the android simulator should be started using the Linux kernel compiled by ourselves. The command for starting the simulator is as follows:
# Emulator-AVD myavd-kernel/root/kernel/goldfish/ARCH/ARM/boot/zimage
For convenience, you can also run the following command in the Ubuntu Linux virtual environment that comes with the CD-Rom to start the android simulator asynchronously. The emulator. Sh file is in the/root/DRIVERS directory.
# Sh emulator. Sh &
The example in this section is already included in the CD and virtual environment. The path is as follows:
CD:<CD root directory>/sources/ch06/word_count/word_count_ndk
Virtual Environment:/Root/Drivers/ch06/word_count/word_count_ndk
The code of the word_count_ndk project consists of the wordcountndktestmain. Java and ndk_test_word_count.c files. The project structure is 6-17.
The ndk_test_word_count.c file is used to access the word_count driver. This file contains two functions for Java access, which are used to read the number of words in the/dev/wordcount device file and to write strings to the/dev/wordcount device file. Next, let's take a look at the complete code of the 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 function: readwordcountfromdev // used to read the number of words from the/dev/wordcount device file. jint counts (jnienv * ENV, jobject thiz) {int dev; // The OPEN function opens the handle returned by the/dev/wordcount device file. If the file fails to be opened,-1 jint wordcount is returned. = 0; // Number of words unsigned char Buf [4]; // Number of words stored in 4 bytes // open the/dev/wordcount Device File Dev = open ("/dev/wordcount", o_rdonly) in read-only mode ); // read the number of words from the dev/wordcount Device File Read (Dev, Buf, 4); int n = 0; // int type variable for storing the number of words // convert the number of words represented by four bytes to the int type value n = (INT) BUF [0]) <24 | (INT) BUF [1]) <16 | (INT) BUF [2]) <8 | (INT) BUF [3]); // convert the int type word count to the jint type word count wordcount = (jint) N; // close/dev/wordcount device file close (Dev); // return a ticket Return wordcount;} // convert a value of the jstring type to a char * type value of the char * jstring_to_pchar (jnienv * ENV, jstring Str) {char * pstr = NULL; // The following code calls string in Java. getbytes method to get the number of bytes of a string // get Java. lang. string class jclass clsstring = (* env)-> findclass (ENV, "Java/lang/string "); // convert the string "UTF-8" to the jstring type value jstring strencode = (* env)-> newstringutf (ENV, "UTF-8"); // obtain Java. lang. string. getbytes method jmethodid mid = (* env)-> getmet Hodid (ENV, clsstring, "getbytes", "(ljava/lang/string;) [B"); // call string. the getbytes method converts the STR variable value to the jbytearray type value jbytearray bytearray = (jbytearray) (* env)-> callobjectmethod (ENV, STR, mid, strencode )); // get the byte length jsize size = (* env)-> getarraylength (ENV, bytearray ); // convert the value of the jbytearray type to the value of the jbyte * type jbyte * pbyte = (* env)-> getbytearrayelements (ENV, bytearray, jni_false); If (size> 0) {// For the char * type variable pstr Space pstr = (char *) malloc (size); // copy the value in the pbyte variable to memcpy (pstr, pbyte, size) in the pstr variable );} // return the converted value return pstr;} // JNI function: writestringtodev // used to write the string void encode (jnienv * ENV, jobject thiz, jstring Str) {int dev; // handle returned after the/dev/wordcount device file is opened by the open function, -1 // open the/dev/wordcount Device File Dev = open ("/dev/wordcount", O_wronly); // convert a jstring to a char * type value char * pstr = jstring_to_pchar (ENV, STR); If (pstr! = NULL) {// write (Dev, pstr, strlen (pstr) to the/dev/wordcount device file ));} // close/dev/wordcount device file close (Dev );}
The preceding Code focuses on the jstring_to_pchar function. This function can convert data of the jstring type to char * type. The basic idea of conversion is to call the Java method string. getbytes to obtain the byte array (jbytearray) corresponding to the string ). Since the write function requires data of the char * type, you must convert the data of the jbytearray type to the data of the char * type. The method is to convert the data of the jbytearray type to the data of the jbyte type, and then call the memcpy function to copy the data of the jbyte type to the char * pointer space allocated using the malloc function. The jstring_to_pchar function contains the following code.
Jmethodid mid = (* env)-> getmethodid (ENV, clsstring, "getbytes", "(ljava/lang/string;) [B"];
The value of the last parameter of the getmethodid method is "(ljava/lang/string;) [B". This may be confusing for beginners of Android ndk and I thought it was wrong. In fact, this is the description of method parameters and return types in JNI (the android ndk program is actually a program that follows the JNI rules. To facilitate the description of Java Data Types in the JNI program, a simple type is represented by an uppercase/lowercase letter, as shown in Table 6-1.
In addition to the Java simple type shown in Table 6-1, some data types need to be matched in the JNI code. Table 6-2 is the descriptor of these data types in JNI.
From the data type comparison relationship shown in Table 6-2, it is easy to think of the meaning of "(ljava/lang/string;) [B" in this example. The jstring_to_pchar function calls the following overload form of the getbytes method.
Public byte [] getbytes (string charsetname) throwsunsupportedencodingexception
To call a Java method in JNI, you must specify the Data Type of the method parameters and returned values. The format in JNI is as follows:
"(Parameter type) Return Value Type"
The parameter type of the getbytes method is string. According to the description in Table 6-2, the JNI descriptor in the string type is"Ljava/lang/string;". The Return Value Type of the getbytes method is byte []. An array representation is involved here. In JNI, the array is represented by [], followed by the element type in the array. Each dimension requires a "[". Byte [] is a one-dimensional byte array, so it is represented by "[B. If it is byte [] [] [], use "[[B. If the Java method does not return any value (the return value type is void), it is represented by V. For example, the void mymethod (INT value) parameter and return value type can be expressed as "(I) V ".
The android ndk program also needs an 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)
Before writing Java code to call the JNI function, let's take a look at the interface of this example, as shown in 6-18.
You must first run the build. Sh script file on the PC to install the word_count driver. Then, click the "read word count from/dev/wordcount" button to output the total number of words in the current/dev/wordcount device file. You can also enter a string separated by spaces in the input box, and then click "Write string to/dev/wordcount, click the "read word count from/dev/wordcount" button to calculate the number of words contained in the string. The result is 6-19.
The following describes the complete Java code (wordcountndktestmain. Java) in this example.
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);} // Execution Code of the "read word count from/dev/wordcount" button public void onclick_readwordcountfromdev (view) {// display the number of words tvwordcount. settext ("Number of words:" + String. valueof (readwordcountfromdev ();} // Execution Code of the "Write string to/dev/wordcount" button public void onclick_writestringtodev (view) {// write the writestringtodev (etstring. gettext (). tostring (); toast. maketext (this, "a string has been written to/dev/wordcount", toast. length_long ). show () ;}// native method public native int readwordcountfromdev (); Public native void writestringtodev (string Str); static {system. loadlibrary ("ndk_test_word_count ");}}
The code in wordcountndktestmain. Java simply calls the JNI function to operate the/dev/wordcount file. Other codes are common android application-level codes. If you are not familiar with this part, you can refer to the author's Android development authoritative guide.
4. Use Java code to directly operate the device file to test the Linux driver
If android has the root permission, you can directly use the Java code to operate on the/dev/wordcount device file (without the root permission, the Linux driver module cannot be installed ). This section describes how to use Java code to test the Linux Driver (the test program does not use a line of C/C ++ code ). The path of this example is as follows:
CD:<CD root directory>/sources/ch06/word_count/word_count_java
Virtual Environment:/Root/Drivers/ch06/word_count/word_count_java
There is only one word_count_java ProjectSource codeFile wordcountjavatestmain. java. The content of this file is 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);} // Execution Code of the "read word count from/dev/wordcount" button public void onclick_readwordcountfromdev (view) {// display the number of words tvwordcount. settext ("Number of words:" + String. valueof (readwordcountfromdev ();} // Execution Code of the "Write string to/dev/wordcount" button public void onclick_writestringtodev (view) {// write the writestringtodev (etstring. gettext (). tostring (); toast. maketext (this, "a string has been written to/dev/wordcount", toast. length_long ). show () ;}/// the code of the Operation/dev/wordcount Device File implemented in Java // read the number of words in the/dev/wordcount device file private int readwordcountfromdev () {int n = 0; byte [] buffer = new byte [4]; try {// open the/dev/wordcount Device File fileinputstream FD = new fileinputstream ("/dev/wordcount"); // read the 4-byte FCM from the device file. read (buffer); // converts four bytes to an int value (n = (INT) buffer [0]) <24 | (INT) buffer [1]) <16 | (INT) buffer [2]) <8 | (INT) buffer [3. close () ;} catch (exception e) {} return n ;}// write the private void writestringtodev (string Str) string to the/dev/wordcount Device File) {try {// open the/dev/wordcount Device File fileoutputstream Fos = new fileoutputstream ("/dev/wordcount"); // write the string FOS. write (Str. getbytes ("iso-8859-1"); FOS. close () ;}catch (exception e ){}}}
The Running Effect and usage of this example are similar to those in the previous example. You can run the CD or virtual environment examples to compare them with the previous example.
This article is excerptedAndroid Deep Exploration (Volume 1): Hal and driver development,
Next several articlesArticleWe will explain in detail how to develop the Linux driver of the ARM architecture, and test the Linux driver by using the android program, ndk, and executable files. In ubuntu
Linux, Android simulator and cloud6410 Development Board (you can buy OK6410-A Development Board, need to brush Android)