com_android_server_power_PowerManagerService.cpp revision 80cd819a0488d2ce2354e0f11a59e4f01d82ed54
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "PowerManagerService-JNI" 18 19//#define LOG_NDEBUG 0 20 21#include "JNIHelp.h" 22#include "jni.h" 23 24#include <ScopedUtfChars.h> 25 26#include <limits.h> 27 28#include <android_runtime/AndroidRuntime.h> 29#include <gui/ISurfaceComposer.h> 30#include <utils/Timers.h> 31#include <utils/misc.h> 32#include <utils/String8.h> 33#include <utils/Log.h> 34#include <hardware/power.h> 35#include <hardware_legacy/power.h> 36#include <cutils/android_reboot.h> 37#include <suspend/autosuspend.h> 38 39#include <private/gui/ComposerService.h> 40 41#include "com_android_server_power_PowerManagerService.h" 42 43namespace android { 44 45// ---------------------------------------------------------------------------- 46 47static struct { 48 jmethodID wakeUpFromNative; 49 jmethodID goToSleepFromNative; 50 jmethodID userActivityFromNative; 51} gPowerManagerServiceClassInfo; 52 53// ---------------------------------------------------------------------------- 54 55static jobject gPowerManagerServiceObj; 56static struct power_module* gPowerModule; 57 58static Mutex gPowerManagerLock; 59static bool gScreenOn; 60static bool gScreenBright; 61 62static nsecs_t gLastEventTime[USER_ACTIVITY_EVENT_LAST + 1]; 63 64// Throttling interval for user activity calls. 65static const nsecs_t MIN_TIME_BETWEEN_USERACTIVITIES = 500 * 1000000L; // 500ms 66 67// ---------------------------------------------------------------------------- 68 69static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) { 70 if (env->ExceptionCheck()) { 71 ALOGE("An exception was thrown by callback '%s'.", methodName); 72 LOGE_EX(env); 73 env->ExceptionClear(); 74 return true; 75 } 76 return false; 77} 78 79bool android_server_PowerManagerService_isScreenOn() { 80 AutoMutex _l(gPowerManagerLock); 81 return gScreenOn; 82} 83 84bool android_server_PowerManagerService_isScreenBright() { 85 AutoMutex _l(gPowerManagerLock); 86 return gScreenBright; 87} 88 89void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType) { 90 // Tell the power HAL when user activity occurs. 91 if (gPowerModule && gPowerModule->powerHint) { 92 gPowerModule->powerHint(gPowerModule, POWER_HINT_INTERACTION, NULL); 93 } 94 95 if (gPowerManagerServiceObj) { 96 // Throttle calls into user activity by event type. 97 // We're a little conservative about argument checking here in case the caller 98 // passes in bad data which could corrupt system state. 99 if (eventType >= 0 && eventType <= USER_ACTIVITY_EVENT_LAST) { 100 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); 101 if (eventTime > now) { 102 eventTime = now; 103 } 104 105 if (gLastEventTime[eventType] + MIN_TIME_BETWEEN_USERACTIVITIES > eventTime) { 106 return; 107 } 108 gLastEventTime[eventType] = eventTime; 109 } 110 111 JNIEnv* env = AndroidRuntime::getJNIEnv(); 112 113 env->CallVoidMethod(gPowerManagerServiceObj, 114 gPowerManagerServiceClassInfo.userActivityFromNative, 115 nanoseconds_to_milliseconds(eventTime), eventType, 0); 116 checkAndClearExceptionFromCallback(env, "userActivityFromNative"); 117 } 118} 119 120void android_server_PowerManagerService_wakeUp(nsecs_t eventTime) { 121 if (gPowerManagerServiceObj) { 122 JNIEnv* env = AndroidRuntime::getJNIEnv(); 123 124 env->CallVoidMethod(gPowerManagerServiceObj, 125 gPowerManagerServiceClassInfo.wakeUpFromNative, 126 nanoseconds_to_milliseconds(eventTime)); 127 checkAndClearExceptionFromCallback(env, "wakeUpFromNative"); 128 } 129} 130 131void android_server_PowerManagerService_goToSleep(nsecs_t eventTime) { 132 if (gPowerManagerServiceObj) { 133 JNIEnv* env = AndroidRuntime::getJNIEnv(); 134 135 env->CallVoidMethod(gPowerManagerServiceObj, 136 gPowerManagerServiceClassInfo.goToSleepFromNative, 137 nanoseconds_to_milliseconds(eventTime), 0); 138 checkAndClearExceptionFromCallback(env, "goToSleepFromNative"); 139 } 140} 141 142// ---------------------------------------------------------------------------- 143 144static void nativeInit(JNIEnv* env, jobject obj) { 145 gPowerManagerServiceObj = env->NewGlobalRef(obj); 146 147 status_t err = hw_get_module(POWER_HARDWARE_MODULE_ID, 148 (hw_module_t const**)&gPowerModule); 149 if (!err) { 150 gPowerModule->init(gPowerModule); 151 } else { 152 ALOGE("Couldn't load %s module (%s)", POWER_HARDWARE_MODULE_ID, strerror(-err)); 153 } 154} 155 156static void nativeSetPowerState(JNIEnv* env, 157 jclass clazz, jboolean screenOn, jboolean screenBright) { 158 AutoMutex _l(gPowerManagerLock); 159 gScreenOn = screenOn; 160 gScreenBright = screenBright; 161} 162 163static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) { 164 ScopedUtfChars name(env, nameStr); 165 acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str()); 166} 167 168static void nativeReleaseSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) { 169 ScopedUtfChars name(env, nameStr); 170 release_wake_lock(name.c_str()); 171} 172 173static void nativeSetScreenState(JNIEnv *env, jclass clazz, jboolean on) { 174 sp<ISurfaceComposer> s(ComposerService::getComposerService()); 175 if (on) { 176 { 177 ALOGD_IF_SLOW(100, "Excessive delay in autosuspend_disable() while turning screen on"); 178 autosuspend_disable(); 179 } 180 181 if (gPowerModule) { 182 ALOGD_IF_SLOW(20, "Excessive delay in setInteractive(true) while turning screen on"); 183 gPowerModule->setInteractive(gPowerModule, true); 184 } 185 186 { 187 ALOGD_IF_SLOW(100, "Excessive delay in unblank() while turning screen on"); 188 s->unblank(); 189 } 190 } else { 191 { 192 ALOGD_IF_SLOW(100, "Excessive delay in blank() while turning screen off"); 193 s->blank(); 194 } 195 196 if (gPowerModule) { 197 ALOGD_IF_SLOW(20, "Excessive delay in setInteractive(false) while turning screen off"); 198 gPowerModule->setInteractive(gPowerModule, false); 199 } 200 201 { 202 ALOGD_IF_SLOW(100, "Excessive delay in autosuspend_enable() while turning screen off"); 203 autosuspend_enable(); 204 } 205 } 206} 207 208static void nativeShutdown(JNIEnv *env, jclass clazz) { 209 android_reboot(ANDROID_RB_POWEROFF, 0, 0); 210} 211 212static void nativeReboot(JNIEnv *env, jclass clazz, jstring reason) { 213 if (reason == NULL) { 214 android_reboot(ANDROID_RB_RESTART, 0, 0); 215 } else { 216 const char *chars = env->GetStringUTFChars(reason, NULL); 217 android_reboot(ANDROID_RB_RESTART2, 0, (char *) chars); 218 env->ReleaseStringUTFChars(reason, chars); // In case it fails. 219 } 220 jniThrowIOException(env, errno); 221} 222 223 224// ---------------------------------------------------------------------------- 225 226static JNINativeMethod gPowerManagerServiceMethods[] = { 227 /* name, signature, funcPtr */ 228 { "nativeInit", "()V", 229 (void*) nativeInit }, 230 { "nativeSetPowerState", "(ZZ)V", 231 (void*) nativeSetPowerState }, 232 { "nativeAcquireSuspendBlocker", "(Ljava/lang/String;)V", 233 (void*) nativeAcquireSuspendBlocker }, 234 { "nativeReleaseSuspendBlocker", "(Ljava/lang/String;)V", 235 (void*) nativeReleaseSuspendBlocker }, 236 { "nativeSetScreenState", "(Z)V", 237 (void*) nativeSetScreenState }, 238 { "nativeShutdown", "()V", 239 (void*) nativeShutdown }, 240 { "nativeReboot", "(Ljava/lang/String;)V", 241 (void*) nativeReboot }, 242}; 243 244#define FIND_CLASS(var, className) \ 245 var = env->FindClass(className); \ 246 LOG_FATAL_IF(! var, "Unable to find class " className); 247 248#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \ 249 var = env->GetMethodID(clazz, methodName, methodDescriptor); \ 250 LOG_FATAL_IF(! var, "Unable to find method " methodName); 251 252#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ 253 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ 254 LOG_FATAL_IF(! var, "Unable to find field " fieldName); 255 256int register_android_server_PowerManagerService(JNIEnv* env) { 257 int res = jniRegisterNativeMethods(env, "com/android/server/power/PowerManagerService", 258 gPowerManagerServiceMethods, NELEM(gPowerManagerServiceMethods)); 259 LOG_FATAL_IF(res < 0, "Unable to register native methods."); 260 261 // Callbacks 262 263 jclass clazz; 264 FIND_CLASS(clazz, "com/android/server/power/PowerManagerService"); 265 266 GET_METHOD_ID(gPowerManagerServiceClassInfo.wakeUpFromNative, clazz, 267 "wakeUpFromNative", "(J)V"); 268 269 GET_METHOD_ID(gPowerManagerServiceClassInfo.goToSleepFromNative, clazz, 270 "goToSleepFromNative", "(JI)V"); 271 272 GET_METHOD_ID(gPowerManagerServiceClassInfo.userActivityFromNative, clazz, 273 "userActivityFromNative", "(JII)V"); 274 275 // Initialize 276 for (int i = 0; i <= USER_ACTIVITY_EVENT_LAST; i++) { 277 gLastEventTime[i] = LLONG_MIN; 278 } 279 gScreenOn = true; 280 gScreenBright = true; 281 gPowerManagerServiceObj = NULL; 282 gPowerModule = NULL; 283 return 0; 284} 285 286} /* namespace android */ 287