c文件:hardware/libhardware_legacy/power/power.ccss
以其中set_screen_state(int)函數爲例html
其Android.mk中添加:
LOCAL_MODULE:= libpower 編譯成lib
LOCAL_SRC_FILES += power.c
javahardware/libhardware_legacy/power/power.candroid
1: int2: set_screen_state(int on)3: {
4: QEMU_FALLBACK(set_screen_state(on));
5:
6: LOGI("*** set_screen_state %d", on);7:
8: initialize_fds();
9:
10: //LOGI("go_to_sleep eventTime=%lld now=%lld g_error=%s\n", eventTime,11: // systemTime(), strerror(g_error));12:
13: if (g_error)14: goto failure;15:
16: char buf[32];17: int len;18: if(on)19: len = snprintf(buf, sizeof(buf), "%s", on_state);20: else21: len = snprintf(buf, sizeof(buf), "%s", off_state);22:
23: buf[sizeof(buf) - 1] = '\0';24: len = write(g_fds[REQUEST_STATE], buf, len);
25: if(len < 0) {26: failure:
27: LOGE("Failed setting last user activity: g_error=%d\n", g_error);28: }
29: return 0;30: }
其頭文件power.h中:c++
1: #if__cplusplus
2: extern "C" { //注13: #endif4: enum {5: PARTIAL_WAKE_LOCK = 1, // the cpu stays on, but the screen is off6: FULL_WAKE_LOCK = 2 // the screen is also on7: };
8:
9: // while you have a lock held, the device will stay on at least at the10: // level you request.11: int acquire_wake_lock(int lock, const char* id);12: int release_wake_lock(const char* id);13:
14: // true if you want the screen on, false if you want it off15: int set_screen_state(int on);16:
17: // set how long to stay awake after the last user activity in seconds18: int set_last_user_activity_timeout(int64_t delay);19:
20:
21: #if __cplusplus22: } // extern "C"23: #endif
注1:數組
注1:extern表示其餘的類已經定義了這段代碼裏面的內容,這裏只是作聲明。
"C」表示的一種編譯和鏈接規約,這裏爲下一步c++調用其作準備.
好比void foo(int,int);該函數被C編譯器編譯後在庫中的名字爲_foo,
而C++編譯器則會產生像_foo_int_int之類的名字用來支持函數重載和類型安全鏈接。
因爲編譯後的名字不一樣,C++程序不能直接調用C函數。
所以C++提供了一個C鏈接交換指定符號extern「C」來解決這個問題而不是一種語言。
C表示這段代碼能夠是符合C語言的編譯和鏈接規約的任何語言,如Fortran、assembler等。安全
一個CPP文件調用之,則需添加其頭文件,好比frameworks/base/core/jni/android_os_Power.cpp.函數
1: #include "JNIHelp.h"2: #include "jni.h"3: #include "android_runtime/AndroidRuntime.h"4: #include <hardware_legacy/power.h>
5: namespace android{6: ....
7:
8: //定義函數:9: static int setScreenState(JNIEnv *env, jobject clazz, jboolean on)10: {
11: return set_screen_state(on);//以此實現cpp到c的調用12: }
13:
14: static JNINativeMethod method_table[] = {//此處實現java對cpp的調用轉化 注215: { "acquireWakeLock", "(ILjava/lang/String;)V", (void*)acquireWakeLock },16: { "releaseWakeLock", "(Ljava/lang/String;)V", (void*)releaseWakeLock },17: { "setLastUserActivityTimeout", "(J)I", (void*)setLastUserActivityTimeout },18: { "setScreenState", "(Z)I", (void*)setScreenState },19: { "shutdown", "()V", (void*)android_os_Power_shutdown },20: { "rebootNative", "(Ljava/lang/String;)V", (void*)android_os_Power_reboot },21: };
22: int register_android_os_Power(JNIEnv *env) //此處註冊jni23: { //向VM(即AndroidRuntime)登記 gMethods[]表格所含的本地函數24: return AndroidRuntime::registerNativeMethods(25: env, "android/os/Power",26: method_table, NELEM(method_table));
27: }
28: };
注2:typedef struct {
const char* name; //Java中函數的名字
const char* signature; //用字符串是描述了函數的參數和返回值
void* fnPtr; //函數指針,指向C函數
} JNINativeMethod;
其中比較難以理解的是第二個參數,例如
"()V"
"(II)V"
"(Ljava/lang/String;Ljava/lang/String;)V"
實際上這些字符是與函數的參數類型一一對應的。
"()" 中的字符表示參數,後面的則表明返回值。例如"()V" 就表示void Func();
"(II)V" 表示 void Func(int, int);
具體的每個字符的對應關係以下
字符 Java類型 C類型
V void void
Z jboolean boolean
I jint int
J jlong long
D jdouble double
F jfloat float
B jbyte byte
C jchar char
S jshort short
數組則以"["開始,用兩個字符表示
[I jintArray int[]
[F jfloatArray float[]
[B jbyteArray byte[]
[C jcharArray char[]
[S jshortArray short[]
[D jdoubleArray double[]
[J jlongArray long[]
[Z jbooleanArray boolean[]
上面的都是基本類型。若是Java函數的參數是class,則以"L"開頭,以";"結尾中間是用"/" 隔開的包及類名。而其對應的C函數名的參數則爲jobject. 一個例外是String類,其對應的類爲jstring
Ljava/lang/String; String jstring
Ljava/net/Socket; Socket jobject
若是JAVA函數位於一個嵌入類,則用$做爲類名間的分隔符。
例如 "(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z"ui
frameworks/base/core/java/android/os/Power.java //此處路徑跟cpp中註冊jni處的路徑是一致的.待細研究是否有關係spa
1: package android.os;
2: public class Power3: {
4: ...
5: public static native int setScreenState(boolean on); //被native修飾的表示調用了非java語言的本地方法6: ...
7: }
frameworks/base/services/java/com/android/server/PowerManagerService.java
import android.os.Power; public class PowerManagerService extends IPowerManager.Stub implements LocalPowerManager, Watchdog.Monitor { ... int err = Power.setScreenState(on); ... }