Fixed bug 1606 - SDL does not implement SDL_GetPowerInfo() for Android.
authorSam Lantinga <slouken@libsdl.org>
Sun, 23 Sep 2012 01:37:44 -0700
changeset 644864a6297a8b93
parent 6447 33f87072db4d
child 6449 fa00544b1374
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).
Android.mk
include/SDL_config_android.h
src/core/android/SDL_android.cpp
src/core/android/SDL_android.h
src/power/SDL_power.c
     1.1 --- a/Android.mk	Thu Sep 20 22:40:23 2012 -0700
     1.2 +++ b/Android.mk	Sun Sep 23 01:37:44 2012 -0700
     1.3 @@ -30,6 +30,7 @@
     1.4  	$(wildcard $(LOCAL_PATH)/src/joystick/android/*.c) \
     1.5  	$(wildcard $(LOCAL_PATH)/src/loadso/dlopen/*.c) \
     1.6  	$(wildcard $(LOCAL_PATH)/src/power/*.c) \
     1.7 +	$(wildcard $(LOCAL_PATH)/src/power/android/*.c) \
     1.8  	$(wildcard $(LOCAL_PATH)/src/render/*.c) \
     1.9  	$(wildcard $(LOCAL_PATH)/src/render/*/*.c) \
    1.10  	$(wildcard $(LOCAL_PATH)/src/stdlib/*.c) \
     2.1 --- a/include/SDL_config_android.h	Thu Sep 20 22:40:23 2012 -0700
     2.2 +++ b/include/SDL_config_android.h	Sun Sep 23 01:37:44 2012 -0700
     2.3 @@ -130,4 +130,7 @@
     2.4  #define SDL_VIDEO_RENDER_OGL_ES	1
     2.5  #define SDL_VIDEO_RENDER_OGL_ES2	1
     2.6  
     2.7 -#endif /* _SDL_config_minimal_h */
     2.8 +/* Enable system power support */
     2.9 +#define SDL_POWER_ANDROID 1
    2.10 +
    2.11 +#endif /* _SDL_config_android_h */
     3.1 --- a/src/core/android/SDL_android.cpp	Thu Sep 20 22:40:23 2012 -0700
     3.2 +++ b/src/core/android/SDL_android.cpp	Sun Sep 23 01:37:44 2012 -0700
     3.3 @@ -735,6 +735,96 @@
     3.4      return Android_JNI_FileClose(ctx, true);
     3.5  }
     3.6  
     3.7 +// returns 0 on success or -1 on error (others undefined then)
     3.8 +// returns truthy or falsy value in plugged, charged and battery
     3.9 +// returns the value in seconds and percent or -1 if not available
    3.10 +extern "C" int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seconds, int* percent)
    3.11 +{
    3.12 +    LocalReferenceHolder refs;
    3.13 +    JNIEnv* env = Android_JNI_GetEnv();
    3.14 +    if (!refs.init(env)) {
    3.15 +        return -1;
    3.16 +    }
    3.17 +
    3.18 +    jmethodID mid;
    3.19 +
    3.20 +    mid = env->GetStaticMethodID(mActivityClass, "getContext", "()Landroid/content/Context;");
    3.21 +    jobject context = env->CallStaticObjectMethod(mActivityClass, mid);
    3.22 +
    3.23 +    jstring action = env->NewStringUTF("android.intent.action.BATTERY_CHANGED");
    3.24 +
    3.25 +    jclass cls = env->FindClass("android/content/IntentFilter");
    3.26 +
    3.27 +    mid = env->GetMethodID(cls, "<init>", "(Ljava/lang/String;)V");
    3.28 +    jobject filter = env->NewObject(cls, mid, action);
    3.29 +
    3.30 +    env->DeleteLocalRef(action);
    3.31 +
    3.32 +    mid = env->GetMethodID(mActivityClass, "registerReceiver", "(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;");
    3.33 +    jobject intent = env->CallObjectMethod(context, mid, NULL, filter);
    3.34 +
    3.35 +    env->DeleteLocalRef(filter);
    3.36 +
    3.37 +    cls = env->GetObjectClass(intent);
    3.38 +
    3.39 +    jstring iname;
    3.40 +    jmethodID imid = env->GetMethodID(cls, "getIntExtra", "(Ljava/lang/String;I)I");
    3.41 +
    3.42 +#define GET_INT_EXTRA(var, key) \
    3.43 +    iname = env->NewStringUTF(key); \
    3.44 +    int var = env->CallIntMethod(intent, imid, iname, -1); \
    3.45 +    env->DeleteLocalRef(iname);
    3.46 +
    3.47 +    jstring bname;
    3.48 +    jmethodID bmid = env->GetMethodID(cls, "getBooleanExtra", "(Ljava/lang/String;Z)Z");
    3.49 +
    3.50 +#define GET_BOOL_EXTRA(var, key) \
    3.51 +    bname = env->NewStringUTF(key); \
    3.52 +    int var = env->CallBooleanMethod(intent, bmid, bname, JNI_FALSE); \
    3.53 +    env->DeleteLocalRef(bname);
    3.54 +
    3.55 +    if (plugged) {
    3.56 +        GET_INT_EXTRA(plug, "plugged") // == BatteryManager.EXTRA_PLUGGED (API 5)
    3.57 +        if (plug == -1) {
    3.58 +            return -1;
    3.59 +        }
    3.60 +        // 1 == BatteryManager.BATTERY_PLUGGED_AC
    3.61 +        // 2 == BatteryManager.BATTERY_PLUGGED_USB
    3.62 +        *plugged = (0 < plug) ? 1 : 0;
    3.63 +    }
    3.64 +
    3.65 +    if (charged) {
    3.66 +        GET_INT_EXTRA(status, "status") // == BatteryManager.EXTRA_STATUS (API 5)
    3.67 +        if (status == -1) {
    3.68 +            return -1;
    3.69 +        }
    3.70 +        // 5 == BatteryManager.BATTERY_STATUS_FULL
    3.71 +        *charged = (status == 5) ? 1 : 0;
    3.72 +    }
    3.73 +
    3.74 +    if (battery) {
    3.75 +        GET_BOOL_EXTRA(present, "present") // == BatteryManager.EXTRA_PRESENT (API 5)
    3.76 +        *battery = present ? 1 : 0;
    3.77 +    }
    3.78 +
    3.79 +    if (seconds) {
    3.80 +        *seconds = -1; // not possible
    3.81 +    }
    3.82 +
    3.83 +    if (percent) {
    3.84 +        GET_INT_EXTRA(level, "level") // == BatteryManager.EXTRA_LEVEL (API 5)
    3.85 +        GET_INT_EXTRA(scale, "scale") // == BatteryManager.EXTRA_SCALE (API 5)
    3.86 +        if ((level == -1) || (scale == -1)) {
    3.87 +            return -1;
    3.88 +        }
    3.89 +        *percent = level * 100 / scale;
    3.90 +    }
    3.91 +
    3.92 +    env->DeleteLocalRef(intent);
    3.93 +
    3.94 +    return 0;
    3.95 +}
    3.96 +
    3.97  // sends message to be handled on the UI event dispatch thread
    3.98  extern "C" int Android_JNI_SendMessage(int command, int param)
    3.99  {
     4.1 --- a/src/core/android/SDL_android.h	Thu Sep 20 22:40:23 2012 -0700
     4.2 +++ b/src/core/android/SDL_android.h	Sun Sep 23 01:37:44 2012 -0700
     4.3 @@ -47,6 +47,9 @@
     4.4  size_t Android_JNI_FileWrite(SDL_RWops* ctx, const void* buffer, size_t size, size_t num);
     4.5  int Android_JNI_FileClose(SDL_RWops* ctx);
     4.6  
     4.7 +/* Power support */
     4.8 +int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seconds, int* percent);
     4.9 +
    4.10  // Threads
    4.11  #include <jni.h>
    4.12  static void Android_JNI_ThreadDestroyed(void*);
     5.1 --- a/src/power/SDL_power.c	Thu Sep 20 22:40:23 2012 -0700
     5.2 +++ b/src/power/SDL_power.c	Sun Sep 23 01:37:44 2012 -0700
     5.3 @@ -36,6 +36,7 @@
     5.4  SDL_bool SDL_GetPowerInfo_BeOS(SDL_PowerState *, int *, int *);
     5.5  SDL_bool SDL_GetPowerInfo_NintendoDS(SDL_PowerState *, int *, int *);
     5.6  SDL_bool SDL_GetPowerInfo_UIKit(SDL_PowerState *, int *, int *);
     5.7 +SDL_bool SDL_GetPowerInfo_Android(SDL_PowerState *, int *, int *);
     5.8  
     5.9  #ifndef SDL_POWER_DISABLED
    5.10  #ifdef SDL_POWER_HARDWIRED
    5.11 @@ -73,6 +74,9 @@
    5.12  #ifdef SDL_POWER_BEOS           /* handles BeOS, Zeta, with euc.jp apm driver. */
    5.13      SDL_GetPowerInfo_BeOS,
    5.14  #endif
    5.15 +#ifdef SDL_POWER_ANDROID        /* handles Android. */
    5.16 +    SDL_GetPowerInfo_Android,
    5.17 +#endif
    5.18  #ifdef SDL_POWER_HARDWIRED
    5.19      SDL_GetPowerInfo_Hardwired,
    5.20  #endif