Home | History | Annotate | Download | only in jni
      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 <limits.h>
     25 
     26 #include <android_runtime/AndroidRuntime.h>
     27 #include <utils/Timers.h>
     28 #include <surfaceflinger/ISurfaceComposer.h>
     29 #include <surfaceflinger/SurfaceComposerClient.h>
     30 
     31 #include "com_android_server_PowerManagerService.h"
     32 
     33 namespace android {
     34 
     35 // ----------------------------------------------------------------------------
     36 
     37 static struct {
     38     jclass clazz;
     39 
     40     jmethodID goToSleep;
     41     jmethodID userActivity;
     42 } gPowerManagerServiceClassInfo;
     43 
     44 // ----------------------------------------------------------------------------
     45 
     46 static jobject gPowerManagerServiceObj;
     47 
     48 static Mutex gPowerManagerLock;
     49 static bool gScreenOn;
     50 static bool gScreenBright;
     51 
     52 static nsecs_t gLastEventTime[POWER_MANAGER_LAST_EVENT + 1];
     53 
     54 // Throttling interval for user activity calls.
     55 static const nsecs_t MIN_TIME_BETWEEN_USERACTIVITIES = 500 * 1000000L; // 500ms
     56 
     57 // ----------------------------------------------------------------------------
     58 
     59 static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
     60     if (env->ExceptionCheck()) {
     61         LOGE("An exception was thrown by callback '%s'.", methodName);
     62         LOGE_EX(env);
     63         env->ExceptionClear();
     64         return true;
     65     }
     66     return false;
     67 }
     68 
     69 bool android_server_PowerManagerService_isScreenOn() {
     70     AutoMutex _l(gPowerManagerLock);
     71     return gScreenOn;
     72 }
     73 
     74 bool android_server_PowerManagerService_isScreenBright() {
     75     AutoMutex _l(gPowerManagerLock);
     76     return gScreenBright;
     77 }
     78 
     79 void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType) {
     80     if (gPowerManagerServiceObj) {
     81         // Throttle calls into user activity by event type.
     82         // We're a little conservative about argument checking here in case the caller
     83         // passes in bad data which could corrupt system state.
     84         if (eventType >= 0 && eventType <= POWER_MANAGER_LAST_EVENT) {
     85             nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
     86             if (eventTime > now) {
     87                 eventTime = now;
     88             }
     89 
     90             if (gLastEventTime[eventType] + MIN_TIME_BETWEEN_USERACTIVITIES > eventTime) {
     91                 return;
     92             }
     93             gLastEventTime[eventType] = eventTime;
     94         }
     95 
     96         JNIEnv* env = AndroidRuntime::getJNIEnv();
     97 
     98         env->CallVoidMethod(gPowerManagerServiceObj, gPowerManagerServiceClassInfo.userActivity,
     99                 nanoseconds_to_milliseconds(eventTime), false, eventType, false);
    100         checkAndClearExceptionFromCallback(env, "userActivity");
    101     }
    102 }
    103 
    104 void android_server_PowerManagerService_goToSleep(nsecs_t eventTime) {
    105     if (gPowerManagerServiceObj) {
    106         JNIEnv* env = AndroidRuntime::getJNIEnv();
    107 
    108         env->CallVoidMethod(gPowerManagerServiceObj, gPowerManagerServiceClassInfo.goToSleep,
    109                 nanoseconds_to_milliseconds(eventTime));
    110         checkAndClearExceptionFromCallback(env, "goToSleep");
    111     }
    112 }
    113 
    114 // ----------------------------------------------------------------------------
    115 
    116 static void android_server_PowerManagerService_nativeInit(JNIEnv* env, jobject obj) {
    117     gPowerManagerServiceObj = env->NewGlobalRef(obj);
    118 }
    119 
    120 static void android_server_PowerManagerService_nativeSetPowerState(JNIEnv* env,
    121         jobject serviceObj, jboolean screenOn, jboolean screenBright) {
    122     AutoMutex _l(gPowerManagerLock);
    123     gScreenOn = screenOn;
    124     gScreenBright = screenBright;
    125 }
    126 
    127 static void android_server_PowerManagerService_nativeStartSurfaceFlingerAnimation(JNIEnv* env,
    128         jobject obj, jint mode) {
    129     sp<ISurfaceComposer> s(ComposerService::getComposerService());
    130     s->turnElectronBeamOff(mode);
    131 }
    132 
    133 // ----------------------------------------------------------------------------
    134 
    135 static JNINativeMethod gPowerManagerServiceMethods[] = {
    136     /* name, signature, funcPtr */
    137     { "nativeInit", "()V",
    138             (void*) android_server_PowerManagerService_nativeInit },
    139     { "nativeSetPowerState", "(ZZ)V",
    140             (void*) android_server_PowerManagerService_nativeSetPowerState },
    141     { "nativeStartSurfaceFlingerAnimation", "(I)V",
    142             (void*) android_server_PowerManagerService_nativeStartSurfaceFlingerAnimation },
    143 };
    144 
    145 #define FIND_CLASS(var, className) \
    146         var = env->FindClass(className); \
    147         LOG_FATAL_IF(! var, "Unable to find class " className); \
    148         var = jclass(env->NewGlobalRef(var));
    149 
    150 #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
    151         var = env->GetMethodID(clazz, methodName, methodDescriptor); \
    152         LOG_FATAL_IF(! var, "Unable to find method " methodName);
    153 
    154 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
    155         var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
    156         LOG_FATAL_IF(! var, "Unable to find field " fieldName);
    157 
    158 int register_android_server_PowerManagerService(JNIEnv* env) {
    159     int res = jniRegisterNativeMethods(env, "com/android/server/PowerManagerService",
    160             gPowerManagerServiceMethods, NELEM(gPowerManagerServiceMethods));
    161     LOG_FATAL_IF(res < 0, "Unable to register native methods.");
    162 
    163     // Callbacks
    164 
    165     FIND_CLASS(gPowerManagerServiceClassInfo.clazz, "com/android/server/PowerManagerService");
    166 
    167     GET_METHOD_ID(gPowerManagerServiceClassInfo.goToSleep, gPowerManagerServiceClassInfo.clazz,
    168             "goToSleep", "(J)V");
    169 
    170     GET_METHOD_ID(gPowerManagerServiceClassInfo.userActivity, gPowerManagerServiceClassInfo.clazz,
    171             "userActivity", "(JZIZ)V");
    172 
    173     // Initialize
    174     for (int i = 0; i < POWER_MANAGER_LAST_EVENT; i++) {
    175         gLastEventTime[i] = LLONG_MIN;
    176     }
    177     gScreenOn = true;
    178     gScreenBright = true;
    179     return 0;
    180 }
    181 
    182 } /* namespace android */
    183