diff --git a/Android.mk b/Android.mk index 4bfa7ee21..a344a5294 100755 --- a/Android.mk +++ b/Android.mk @@ -30,6 +30,7 @@ LOCAL_SRC_FILES := \ $(wildcard $(LOCAL_PATH)/src/joystick/android/*.c) \ $(wildcard $(LOCAL_PATH)/src/loadso/dlopen/*.c) \ $(wildcard $(LOCAL_PATH)/src/power/*.c) \ + $(wildcard $(LOCAL_PATH)/src/power/android/*.c) \ $(wildcard $(LOCAL_PATH)/src/render/*.c) \ $(wildcard $(LOCAL_PATH)/src/render/*/*.c) \ $(wildcard $(LOCAL_PATH)/src/stdlib/*.c) \ diff --git a/include/SDL_config_android.h b/include/SDL_config_android.h index efd40b400..eeddcdab3 100644 --- a/include/SDL_config_android.h +++ b/include/SDL_config_android.h @@ -130,4 +130,7 @@ #define SDL_VIDEO_RENDER_OGL_ES 1 #define SDL_VIDEO_RENDER_OGL_ES2 1 -#endif /* _SDL_config_minimal_h */ +/* Enable system power support */ +#define SDL_POWER_ANDROID 1 + +#endif /* _SDL_config_android_h */ diff --git a/src/core/android/SDL_android.cpp b/src/core/android/SDL_android.cpp index 1fe3e40a9..e5b574d0c 100755 --- a/src/core/android/SDL_android.cpp +++ b/src/core/android/SDL_android.cpp @@ -735,6 +735,96 @@ extern "C" int Android_JNI_FileClose(SDL_RWops* ctx) return Android_JNI_FileClose(ctx, true); } +// returns 0 on success or -1 on error (others undefined then) +// returns truthy or falsy value in plugged, charged and battery +// returns the value in seconds and percent or -1 if not available +extern "C" int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seconds, int* percent) +{ + LocalReferenceHolder refs; + JNIEnv* env = Android_JNI_GetEnv(); + if (!refs.init(env)) { + return -1; + } + + jmethodID mid; + + mid = env->GetStaticMethodID(mActivityClass, "getContext", "()Landroid/content/Context;"); + jobject context = env->CallStaticObjectMethod(mActivityClass, mid); + + jstring action = env->NewStringUTF("android.intent.action.BATTERY_CHANGED"); + + jclass cls = env->FindClass("android/content/IntentFilter"); + + mid = env->GetMethodID(cls, "", "(Ljava/lang/String;)V"); + jobject filter = env->NewObject(cls, mid, action); + + env->DeleteLocalRef(action); + + mid = env->GetMethodID(mActivityClass, "registerReceiver", "(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;"); + jobject intent = env->CallObjectMethod(context, mid, NULL, filter); + + env->DeleteLocalRef(filter); + + cls = env->GetObjectClass(intent); + + jstring iname; + jmethodID imid = env->GetMethodID(cls, "getIntExtra", "(Ljava/lang/String;I)I"); + +#define GET_INT_EXTRA(var, key) \ + iname = env->NewStringUTF(key); \ + int var = env->CallIntMethod(intent, imid, iname, -1); \ + env->DeleteLocalRef(iname); + + jstring bname; + jmethodID bmid = env->GetMethodID(cls, "getBooleanExtra", "(Ljava/lang/String;Z)Z"); + +#define GET_BOOL_EXTRA(var, key) \ + bname = env->NewStringUTF(key); \ + int var = env->CallBooleanMethod(intent, bmid, bname, JNI_FALSE); \ + env->DeleteLocalRef(bname); + + if (plugged) { + GET_INT_EXTRA(plug, "plugged") // == BatteryManager.EXTRA_PLUGGED (API 5) + if (plug == -1) { + return -1; + } + // 1 == BatteryManager.BATTERY_PLUGGED_AC + // 2 == BatteryManager.BATTERY_PLUGGED_USB + *plugged = (0 < plug) ? 1 : 0; + } + + if (charged) { + GET_INT_EXTRA(status, "status") // == BatteryManager.EXTRA_STATUS (API 5) + if (status == -1) { + return -1; + } + // 5 == BatteryManager.BATTERY_STATUS_FULL + *charged = (status == 5) ? 1 : 0; + } + + if (battery) { + GET_BOOL_EXTRA(present, "present") // == BatteryManager.EXTRA_PRESENT (API 5) + *battery = present ? 1 : 0; + } + + if (seconds) { + *seconds = -1; // not possible + } + + if (percent) { + GET_INT_EXTRA(level, "level") // == BatteryManager.EXTRA_LEVEL (API 5) + GET_INT_EXTRA(scale, "scale") // == BatteryManager.EXTRA_SCALE (API 5) + if ((level == -1) || (scale == -1)) { + return -1; + } + *percent = level * 100 / scale; + } + + env->DeleteLocalRef(intent); + + return 0; +} + // sends message to be handled on the UI event dispatch thread extern "C" int Android_JNI_SendMessage(int command, int param) { diff --git a/src/core/android/SDL_android.h b/src/core/android/SDL_android.h index cd9a85052..6d0939359 100755 --- a/src/core/android/SDL_android.h +++ b/src/core/android/SDL_android.h @@ -47,6 +47,9 @@ size_t Android_JNI_FileRead(SDL_RWops* ctx, void* buffer, size_t size, size_t ma size_t Android_JNI_FileWrite(SDL_RWops* ctx, const void* buffer, size_t size, size_t num); int Android_JNI_FileClose(SDL_RWops* ctx); +/* Power support */ +int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seconds, int* percent); + // Threads #include static void Android_JNI_ThreadDestroyed(void*); diff --git a/src/power/SDL_power.c b/src/power/SDL_power.c index 9c6d62b47..ce7725c7c 100755 --- a/src/power/SDL_power.c +++ b/src/power/SDL_power.c @@ -36,6 +36,7 @@ SDL_bool SDL_GetPowerInfo_MacOSX(SDL_PowerState *, int *, int *); SDL_bool SDL_GetPowerInfo_BeOS(SDL_PowerState *, int *, int *); SDL_bool SDL_GetPowerInfo_NintendoDS(SDL_PowerState *, int *, int *); SDL_bool SDL_GetPowerInfo_UIKit(SDL_PowerState *, int *, int *); +SDL_bool SDL_GetPowerInfo_Android(SDL_PowerState *, int *, int *); #ifndef SDL_POWER_DISABLED #ifdef SDL_POWER_HARDWIRED @@ -73,6 +74,9 @@ static SDL_GetPowerInfo_Impl implementations[] = { #ifdef SDL_POWER_BEOS /* handles BeOS, Zeta, with euc.jp apm driver. */ SDL_GetPowerInfo_BeOS, #endif +#ifdef SDL_POWER_ANDROID /* handles Android. */ + SDL_GetPowerInfo_Android, +#endif #ifdef SDL_POWER_HARDWIRED SDL_GetPowerInfo_Hardwired, #endif