diff options
Diffstat (limited to 'platform/android/power_android.cpp')
-rw-r--r-- | platform/android/power_android.cpp | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/platform/android/power_android.cpp b/platform/android/power_android.cpp new file mode 100644 index 0000000000..8cd5cb1397 --- /dev/null +++ b/platform/android/power_android.cpp @@ -0,0 +1,238 @@ +/*************************************************************************/ +/* power_android.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "core/error_macros.h" + +#include "power_android.h" + +static void LocalReferenceHolder_Cleanup(struct LocalReferenceHolder *refholder) { + if (refholder->m_env) { + JNIEnv* env = refholder->m_env; + (*env)->PopLocalFrame(env, NULL); + --s_active; + } +} + +static struct LocalReferenceHolder LocalReferenceHolder_Setup(const char *func) +{ + struct LocalReferenceHolder refholder; + refholder.m_env = NULL; + refholder.m_func = func; + return refholder; +} + +static bool LocalReferenceHolder_Init(struct LocalReferenceHolder *refholder, JNIEnv *env) +{ + const int capacity = 16; + if ((*env)->PushLocalFrame(env, capacity) < 0) { + return false; + } + ++s_active; + refholder->m_env = env; + return true; +} + + +static SDL_bool LocalReferenceHolder_IsActive(void) +{ + return s_active > 0; +} + +ANativeWindow* Android_JNI_GetNativeWindow(void) +{ + ANativeWindow* anw; + jobject s; + JNIEnv *env = Android_JNI_GetEnv(); + + s = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetNativeSurface); + anw = ANativeWindow_fromSurface(env, s); + (*env)->DeleteLocalRef(env, s); + + return anw; +} + + +/* + * CODE CHUNK IMPORTED FROM SDL 2.0 + * 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 + */ +int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seconds, int* percent) +{ + env = Android_JNI_GetEnv(); + refs = LocalReferenceHolder_Setup(__FUNCTION__); + + if (!LocalReferenceHolder_Init(&refs, env)) { + LocalReferenceHolder_Cleanup(&refs); + return -1; + } + mid = (*env)->GetStaticMethodID(env, mActivityClass, "getContext", "()Landroid/content/Context;"); + context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid); + action = (*env)->NewStringUTF(env, "android.intent.action.BATTERY_CHANGED"); + cls = (*env)->FindClass(env, "android/content/IntentFilter"); + mid = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/lang/String;)V"); + filter = (*env)->NewObject(env, cls, mid, action); + (*env)->DeleteLocalRef(env, action); + mid = (*env)->GetMethodID(env, mActivityClass, "registerReceiver", "(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;"); + intent = (*env)->CallObjectMethod(env, context, mid, NULL, filter); + (*env)->DeleteLocalRef(env, filter); + cls = (*env)->GetObjectClass(env, intent); + imid = (*env)->GetMethodID(env, cls, "getIntExtra", "(Ljava/lang/String;I)I"); + // Watch out for C89 scoping rules because of the macro +#define GET_INT_EXTRA(var, key) \ + int var; \ + iname = (*env)->NewStringUTF(env, key); \ + var = (*env)->CallIntMethod(env, intent, imid, iname, -1); \ + (*env)->DeleteLocalRef(env, iname); + bmid = (*env)->GetMethodID(env, cls, "getBooleanExtra", "(Ljava/lang/String;Z)Z"); + // Watch out for C89 scoping rules because of the macro +#define GET_BOOL_EXTRA(var, key) \ + int var; \ + bname = (*env)->NewStringUTF(env, key); \ + var = (*env)->CallBooleanMethod(env, intent, bmid, bname, JNI_FALSE); \ + (*env)->DeleteLocalRef(env, bname); + if (plugged) { + // Watch out for C89 scoping rules because of the macro + GET_INT_EXTRA(plug, "plugged") // == BatteryManager.EXTRA_PLUGGED (API 5) + if (plug == -1) { + LocalReferenceHolder_Cleanup(&refs); + return -1; + } + // 1 == BatteryManager.BATTERY_PLUGGED_AC + // 2 == BatteryManager.BATTERY_PLUGGED_USB + *plugged = (0 < plug) ? 1 : 0; + } + if (charged) { + // Watch out for C89 scoping rules because of the macro + GET_INT_EXTRA(status, "status") // == BatteryManager.EXTRA_STATUS (API 5) + if (status == -1) { + LocalReferenceHolder_Cleanup(&refs); + 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) { + int level; + int scale; + // Watch out for C89 scoping rules because of the macro + { + GET_INT_EXTRA(level_temp, "level") // == BatteryManager.EXTRA_LEVEL (API 5) + level = level_temp; + } + // Watch out for C89 scoping rules because of the macro + { + GET_INT_EXTRA(scale_temp, "scale") // == BatteryManager.EXTRA_SCALE (API 5) + scale = scale_temp; + } + if ((level == -1) || (scale == -1)) { + LocalReferenceHolder_Cleanup(&refs); + return -1; + } + *percent = level * 100 / scale; + } + (*env)->DeleteLocalRef(env, intent); + LocalReferenceHolder_Cleanup(&refs); + + return 0; +} + + +bool power_android::GetPowerInfo_Android() { + int battery; + int plugged; + int charged; + + if (Android_JNI_GetPowerInfo(&plugged, &charged, &battery, &this->nsecs_left, &this->percent_left) != -1) { + if (plugged) { + if (charged) { + this->power_state = POWERSTATE_CHARGED; + } else if (battery) { + this->power_state = POWERSTATE_CHARGING; + } else { + this->power_state = POWERSTATE_NO_BATTERY; + this->nsecs_left = -1; + this->percent_left = -1; + } + } else { + this->power_state = POWERSTATE_ON_BATTERY; + } + } else { + this->power_state = POWERSTATE_UNKNOWN; + this->nsecs_left = -1; + this->percent_left = -1; + } + + return true; +} + +PowerState power_android::get_power_state() { + if (GetPowerInfo_Android()) { + return power_state; + } + else { + WARN_PRINT("Power management is not implemented on this platform, defaulting to POWERSTATE_UNKNOWN"); + return POWERSTATE_UNKNOWN; + } +} + +int power_android::get_power_seconds_left() { + if (GetPowerInfo_Android()) { + return nsecs_left; + } + else { + WARN_PRINT("Power management is not implemented on this platform, defaulting to -1"); + return -1; + } +} + +int power_android::get_power_percent_left() { + if (GetPowerInfo_Android()) { + return percent_left; + } + else { + WARN_PRINT("Power management is not implemented on this platform, defaulting to -1"); + return -1; + } +} + +power_android::power_android() : nsecs_left(-1), percent_left(-1), power_state(POWERSTATE_UNKNOWN) { + +} + +power_android::~power_android() { +} |