Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

Fixed bug 1606 - SDL does not implement SDL_GetPowerInfo() for Android.

Philipp Wiesemann 2012-09-22 05:26:11 PDT

currently SDL (HG) does not implement the power management functionality of
SDL_GetPowerInfo() for Android.

I attached a patch which tries to implement this functionality (JNI only, API
5). It supports plugged state and battery percent return values but not
remaining seconds (which are not available on Android).
  • Loading branch information
slouken committed Sep 23, 2012
1 parent b83fea4 commit 7839db2816abd9a154da373d7923f11e986a7c82
Showing with 102 additions and 1 deletion.
  1. +1 −0 Android.mk
  2. +4 −1 include/SDL_config_android.h
  3. +90 −0 src/core/android/SDL_android.cpp
  4. +3 −0 src/core/android/SDL_android.h
  5. +4 −0 src/power/SDL_power.c
@@ -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) \
@@ -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 */
@@ -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, "<init>", "(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)
{
@@ -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 <jni.h>
static void Android_JNI_ThreadDestroyed(void*);
@@ -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

0 comments on commit 7839db2

Please sign in to comment.