• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <android/hardware/power/1.1/IPower.h>
22 #include <android/hardware/power/Boost.h>
23 #include <android/hardware/power/IPower.h>
24 #include <android/hardware/power/Mode.h>
25 #include <android/system/suspend/1.0/ISystemSuspend.h>
26 #include <android/system/suspend/ISuspendControlService.h>
27 #include <nativehelper/JNIHelp.h>
28 #include "jni.h"
29 
30 #include <nativehelper/ScopedUtfChars.h>
31 
32 #include <limits.h>
33 
34 #include <android-base/chrono_utils.h>
35 #include <android_runtime/AndroidRuntime.h>
36 #include <android_runtime/Log.h>
37 #include <binder/IServiceManager.h>
38 #include <gui/SurfaceComposerClient.h>
39 #include <hardware/power.h>
40 #include <hardware_legacy/power.h>
41 #include <hidl/ServiceManagement.h>
42 #include <utils/Timers.h>
43 #include <utils/misc.h>
44 #include <utils/String8.h>
45 #include <utils/Log.h>
46 
47 #include "com_android_server_power_PowerManagerService.h"
48 
49 using android::hardware::Return;
50 using android::hardware::Void;
51 using android::hardware::power::Boost;
52 using android::hardware::power::Mode;
53 using android::hardware::power::V1_0::PowerHint;
54 using android::hardware::power::V1_0::Feature;
55 using android::String8;
56 using android::system::suspend::V1_0::ISystemSuspend;
57 using android::system::suspend::V1_0::IWakeLock;
58 using android::system::suspend::V1_0::WakeLockType;
59 using android::system::suspend::ISuspendControlService;
60 using IPowerV1_1 = android::hardware::power::V1_1::IPower;
61 using IPowerV1_0 = android::hardware::power::V1_0::IPower;
62 using IPowerAidl = android::hardware::power::IPower;
63 
64 namespace android {
65 
66 // ----------------------------------------------------------------------------
67 
68 static struct {
69     jmethodID userActivityFromNative;
70 } gPowerManagerServiceClassInfo;
71 
72 // ----------------------------------------------------------------------------
73 
74 static jobject gPowerManagerServiceObj;
75 static sp<IPowerV1_0> gPowerHalHidlV1_0_ = nullptr;
76 static sp<IPowerV1_1> gPowerHalHidlV1_1_ = nullptr;
77 static sp<IPowerAidl> gPowerHalAidl_ = nullptr;
78 static std::mutex gPowerHalMutex;
79 
80 enum class HalVersion {
81     NONE,
82     HIDL_1_0,
83     HIDL_1_1,
84     AIDL,
85 };
86 
87 static nsecs_t gLastEventTime[USER_ACTIVITY_EVENT_LAST + 1];
88 
89 // Throttling interval for user activity calls.
90 static const nsecs_t MIN_TIME_BETWEEN_USERACTIVITIES = 100 * 1000000L; // 100ms
91 
92 // ----------------------------------------------------------------------------
93 
checkAndClearExceptionFromCallback(JNIEnv * env,const char * methodName)94 static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
95     if (env->ExceptionCheck()) {
96         ALOGE("An exception was thrown by callback '%s'.", methodName);
97         LOGE_EX(env);
98         env->ExceptionClear();
99         return true;
100     }
101     return false;
102 }
103 
104 // Check validity of current handle to the power HAL service, and connect to it if necessary.
105 // The caller must be holding gPowerHalMutex.
connectPowerHalLocked()106 static HalVersion connectPowerHalLocked() {
107     static bool gPowerHalHidlExists = true;
108     static bool gPowerHalAidlExists = true;
109     if (!gPowerHalHidlExists && !gPowerHalAidlExists) {
110         return HalVersion::NONE;
111     }
112     if (gPowerHalAidlExists) {
113         if (!gPowerHalAidl_) {
114             gPowerHalAidl_ = waitForVintfService<IPowerAidl>();
115         }
116         if (gPowerHalAidl_) {
117             ALOGV("Successfully connected to Power HAL AIDL service.");
118             return HalVersion::AIDL;
119         } else {
120             gPowerHalAidlExists = false;
121         }
122     }
123     if (gPowerHalHidlExists && gPowerHalHidlV1_0_ == nullptr) {
124         gPowerHalHidlV1_0_ = IPowerV1_0::getService();
125         if (gPowerHalHidlV1_0_) {
126             ALOGV("Successfully connected to Power HAL HIDL 1.0 service.");
127             // Try cast to powerHAL HIDL V1_1
128             gPowerHalHidlV1_1_ = IPowerV1_1::castFrom(gPowerHalHidlV1_0_);
129             if (gPowerHalHidlV1_1_) {
130                 ALOGV("Successfully connected to Power HAL HIDL 1.1 service.");
131             }
132         } else {
133             ALOGV("Couldn't load power HAL HIDL service");
134             gPowerHalHidlExists = false;
135             return HalVersion::NONE;
136         }
137     }
138     if (gPowerHalHidlV1_1_) {
139         return HalVersion::HIDL_1_1;
140     } else if (gPowerHalHidlV1_0_) {
141         return HalVersion::HIDL_1_0;
142     }
143     return HalVersion::NONE;
144 }
145 
146 // Retrieve a copy of PowerHAL HIDL V1_0
getPowerHalHidlV1_0()147 sp<IPowerV1_0> getPowerHalHidlV1_0() {
148     std::lock_guard<std::mutex> lock(gPowerHalMutex);
149     HalVersion halVersion = connectPowerHalLocked();
150     if (halVersion == HalVersion::HIDL_1_0 || halVersion == HalVersion::HIDL_1_1) {
151         return gPowerHalHidlV1_0_;
152     }
153 
154     return nullptr;
155 }
156 
157 // Retrieve a copy of PowerHAL HIDL V1_1
getPowerHalHidlV1_1()158 sp<IPowerV1_1> getPowerHalHidlV1_1() {
159     std::lock_guard<std::mutex> lock(gPowerHalMutex);
160     if (connectPowerHalLocked() == HalVersion::HIDL_1_1) {
161         return gPowerHalHidlV1_1_;
162     }
163 
164     return nullptr;
165 }
166 
167 // Check if a call to a power HAL function failed; if so, log the failure and invalidate the
168 // current handle to the power HAL service.
processPowerHalReturn(bool isOk,const char * functionName)169 bool processPowerHalReturn(bool isOk, const char* functionName) {
170     if (!isOk) {
171         ALOGE("%s() failed: power HAL service not available.", functionName);
172         gPowerHalMutex.lock();
173         gPowerHalHidlV1_0_ = nullptr;
174         gPowerHalHidlV1_1_ = nullptr;
175         gPowerHalAidl_ = nullptr;
176         gPowerHalMutex.unlock();
177     }
178     return isOk;
179 }
180 
181 enum class HalSupport {
182     UNKNOWN = 0,
183     ON,
184     OFF,
185 };
186 
setPowerBoostWithHandle(sp<IPowerAidl> handle,Boost boost,int32_t durationMs)187 static void setPowerBoostWithHandle(sp<IPowerAidl> handle, Boost boost, int32_t durationMs) {
188     // Android framework only sends boost upto DISPLAY_UPDATE_IMMINENT.
189     // Need to increase the array size if more boost supported.
190     static std::array<std::atomic<HalSupport>,
191                       static_cast<int32_t>(Boost::DISPLAY_UPDATE_IMMINENT) + 1>
192             boostSupportedArray = {HalSupport::UNKNOWN};
193     size_t idx = static_cast<size_t>(boost);
194 
195     // Quick return if boost is not supported by HAL
196     if (idx >= boostSupportedArray.size() || boostSupportedArray[idx] == HalSupport::OFF) {
197         ALOGV("Skipped setPowerBoost %s because HAL doesn't support it", toString(boost).c_str());
198         return;
199     }
200 
201     if (boostSupportedArray[idx] == HalSupport::UNKNOWN) {
202         bool isSupported = false;
203         handle->isBoostSupported(boost, &isSupported);
204         boostSupportedArray[idx] = isSupported ? HalSupport::ON : HalSupport::OFF;
205         if (!isSupported) {
206             ALOGV("Skipped setPowerBoost %s because HAL doesn't support it",
207                   toString(boost).c_str());
208             return;
209         }
210     }
211 
212     auto ret = handle->setBoost(boost, durationMs);
213     processPowerHalReturn(ret.isOk(), "setPowerBoost");
214 }
215 
setPowerBoost(Boost boost,int32_t durationMs)216 static void setPowerBoost(Boost boost, int32_t durationMs) {
217     std::unique_lock<std::mutex> lock(gPowerHalMutex);
218     if (connectPowerHalLocked() != HalVersion::AIDL) {
219         ALOGV("Power HAL AIDL not available");
220         return;
221     }
222     sp<IPowerAidl> handle = gPowerHalAidl_;
223     lock.unlock();
224     setPowerBoostWithHandle(handle, boost, durationMs);
225 }
226 
setPowerModeWithHandle(sp<IPowerAidl> handle,Mode mode,bool enabled)227 static bool setPowerModeWithHandle(sp<IPowerAidl> handle, Mode mode, bool enabled) {
228     // Android framework only sends mode upto DISPLAY_INACTIVE.
229     // Need to increase the array if more mode supported.
230     static std::array<std::atomic<HalSupport>, static_cast<int32_t>(Mode::DISPLAY_INACTIVE) + 1>
231             modeSupportedArray = {HalSupport::UNKNOWN};
232     size_t idx = static_cast<size_t>(mode);
233 
234     // Quick return if mode is not supported by HAL
235     if (idx >= modeSupportedArray.size() || modeSupportedArray[idx] == HalSupport::OFF) {
236         ALOGV("Skipped setPowerMode %s because HAL doesn't support it", toString(mode).c_str());
237         return false;
238     }
239 
240     if (modeSupportedArray[idx] == HalSupport::UNKNOWN) {
241         bool isSupported = false;
242         handle->isModeSupported(mode, &isSupported);
243         modeSupportedArray[idx] = isSupported ? HalSupport::ON : HalSupport::OFF;
244         if (!isSupported) {
245             ALOGV("Skipped setPowerMode %s because HAL doesn't support it", toString(mode).c_str());
246             return false;
247         }
248     }
249 
250     auto ret = handle->setMode(mode, enabled);
251     processPowerHalReturn(ret.isOk(), "setPowerMode");
252     return ret.isOk();
253 }
254 
setPowerMode(Mode mode,bool enabled)255 static bool setPowerMode(Mode mode, bool enabled) {
256     std::unique_lock<std::mutex> lock(gPowerHalMutex);
257     if (connectPowerHalLocked() != HalVersion::AIDL) {
258         ALOGV("Power HAL AIDL not available");
259         return false;
260     }
261     sp<IPowerAidl> handle = gPowerHalAidl_;
262     lock.unlock();
263     return setPowerModeWithHandle(handle, mode, enabled);
264 }
265 
sendPowerHint(PowerHint hintId,uint32_t data)266 static void sendPowerHint(PowerHint hintId, uint32_t data) {
267     std::unique_lock<std::mutex> lock(gPowerHalMutex);
268     switch (connectPowerHalLocked()) {
269         case HalVersion::NONE:
270             return;
271         case HalVersion::HIDL_1_0: {
272             sp<IPowerV1_0> handle = gPowerHalHidlV1_0_;
273             lock.unlock();
274             auto ret = handle->powerHint(hintId, data);
275             processPowerHalReturn(ret.isOk(), "powerHint");
276             break;
277         }
278         case HalVersion::HIDL_1_1: {
279             sp<IPowerV1_1> handle = gPowerHalHidlV1_1_;
280             lock.unlock();
281             auto ret = handle->powerHintAsync(hintId, data);
282             processPowerHalReturn(ret.isOk(), "powerHintAsync");
283             break;
284         }
285         case HalVersion::AIDL: {
286             if (hintId == PowerHint::INTERACTION) {
287                 sp<IPowerAidl> handle = gPowerHalAidl_;
288                 lock.unlock();
289                 setPowerBoostWithHandle(handle, Boost::INTERACTION, data);
290                 break;
291             } else if (hintId == PowerHint::LAUNCH) {
292                 sp<IPowerAidl> handle = gPowerHalAidl_;
293                 lock.unlock();
294                 setPowerModeWithHandle(handle, Mode::LAUNCH, static_cast<bool>(data));
295                 break;
296             } else if (hintId == PowerHint::LOW_POWER) {
297                 sp<IPowerAidl> handle = gPowerHalAidl_;
298                 lock.unlock();
299                 setPowerModeWithHandle(handle, Mode::LOW_POWER, static_cast<bool>(data));
300                 break;
301             } else if (hintId == PowerHint::SUSTAINED_PERFORMANCE) {
302                 sp<IPowerAidl> handle = gPowerHalAidl_;
303                 lock.unlock();
304                 setPowerModeWithHandle(handle, Mode::SUSTAINED_PERFORMANCE,
305                                        static_cast<bool>(data));
306                 break;
307             } else if (hintId == PowerHint::VR_MODE) {
308                 sp<IPowerAidl> handle = gPowerHalAidl_;
309                 lock.unlock();
310                 setPowerModeWithHandle(handle, Mode::VR, static_cast<bool>(data));
311                 break;
312             } else {
313                 ALOGE("Unsupported power hint: %s.", toString(hintId).c_str());
314                 return;
315             }
316         }
317         default: {
318             ALOGE("Unknown power HAL state");
319             return;
320         }
321     }
322     SurfaceComposerClient::notifyPowerHint(static_cast<int32_t>(hintId));
323 }
324 
android_server_PowerManagerService_userActivity(nsecs_t eventTime,int32_t eventType)325 void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType) {
326     if (gPowerManagerServiceObj) {
327         // Throttle calls into user activity by event type.
328         // We're a little conservative about argument checking here in case the caller
329         // passes in bad data which could corrupt system state.
330         if (eventType >= 0 && eventType <= USER_ACTIVITY_EVENT_LAST) {
331             nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
332             if (eventTime > now) {
333                 eventTime = now;
334             }
335 
336             if (gLastEventTime[eventType] + MIN_TIME_BETWEEN_USERACTIVITIES > eventTime) {
337                 return;
338             }
339             gLastEventTime[eventType] = eventTime;
340 
341             // Tell the power HAL when user activity occurs.
342             sendPowerHint(PowerHint::INTERACTION, 0);
343         }
344 
345         JNIEnv* env = AndroidRuntime::getJNIEnv();
346 
347         env->CallVoidMethod(gPowerManagerServiceObj,
348                 gPowerManagerServiceClassInfo.userActivityFromNative,
349                 nanoseconds_to_milliseconds(eventTime), eventType, 0);
350         checkAndClearExceptionFromCallback(env, "userActivityFromNative");
351     }
352 }
353 
354 static sp<ISystemSuspend> gSuspendHal = nullptr;
355 static sp<ISuspendControlService> gSuspendControl = nullptr;
356 static sp<IWakeLock> gSuspendBlocker = nullptr;
357 static std::mutex gSuspendMutex;
358 
359 // Assume SystemSuspend HAL is always alive.
360 // TODO: Force device to restart if SystemSuspend HAL dies.
getSuspendHal()361 sp<ISystemSuspend> getSuspendHal() {
362     static std::once_flag suspendHalFlag;
363     std::call_once(suspendHalFlag, [](){
364         ::android::hardware::details::waitForHwService(ISystemSuspend::descriptor, "default");
365         gSuspendHal = ISystemSuspend::getService();
366         assert(gSuspendHal != nullptr);
367     });
368     return gSuspendHal;
369 }
370 
getSuspendControl()371 sp<ISuspendControlService> getSuspendControl() {
372     static std::once_flag suspendControlFlag;
373     std::call_once(suspendControlFlag, [](){
374         gSuspendControl = waitForService<ISuspendControlService>(String16("suspend_control"));
375         LOG_ALWAYS_FATAL_IF(gSuspendControl == nullptr);
376     });
377     return gSuspendControl;
378 }
379 
enableAutoSuspend()380 void enableAutoSuspend() {
381     static bool enabled = false;
382     if (!enabled) {
383         sp<ISuspendControlService> suspendControl = getSuspendControl();
384         suspendControl->enableAutosuspend(&enabled);
385     }
386 
387     {
388         std::lock_guard<std::mutex> lock(gSuspendMutex);
389         if (gSuspendBlocker) {
390             gSuspendBlocker->release();
391             gSuspendBlocker.clear();
392         }
393     }
394 }
395 
disableAutoSuspend()396 void disableAutoSuspend() {
397     std::lock_guard<std::mutex> lock(gSuspendMutex);
398     if (!gSuspendBlocker) {
399         sp<ISystemSuspend> suspendHal = getSuspendHal();
400         gSuspendBlocker = suspendHal->acquireWakeLock(WakeLockType::PARTIAL,
401                 "PowerManager.SuspendLockout");
402     }
403 }
404 
405 // ----------------------------------------------------------------------------
406 
nativeInit(JNIEnv * env,jobject obj)407 static void nativeInit(JNIEnv* env, jobject obj) {
408     gPowerManagerServiceObj = env->NewGlobalRef(obj);
409 
410     gPowerHalMutex.lock();
411     connectPowerHalLocked();
412     gPowerHalMutex.unlock();
413 }
414 
nativeAcquireSuspendBlocker(JNIEnv * env,jclass,jstring nameStr)415 static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass /* clazz */, jstring nameStr) {
416     ScopedUtfChars name(env, nameStr);
417     acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());
418 }
419 
nativeReleaseSuspendBlocker(JNIEnv * env,jclass,jstring nameStr)420 static void nativeReleaseSuspendBlocker(JNIEnv *env, jclass /* clazz */, jstring nameStr) {
421     ScopedUtfChars name(env, nameStr);
422     release_wake_lock(name.c_str());
423 }
424 
nativeSetInteractive(JNIEnv *,jclass,jboolean enable)425 static void nativeSetInteractive(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
426     std::unique_lock<std::mutex> lock(gPowerHalMutex);
427     switch (connectPowerHalLocked()) {
428         case HalVersion::NONE:
429             return;
430         case HalVersion::HIDL_1_0:
431             FALLTHROUGH_INTENDED;
432         case HalVersion::HIDL_1_1: {
433             android::base::Timer t;
434             sp<IPowerV1_0> handle = gPowerHalHidlV1_0_;
435             lock.unlock();
436             auto ret = handle->setInteractive(enable);
437             processPowerHalReturn(ret.isOk(), "setInteractive");
438             if (t.duration() > 20ms) {
439                 ALOGD("Excessive delay in setInteractive(%s) while turning screen %s",
440                       enable ? "true" : "false", enable ? "on" : "off");
441             }
442             return;
443         }
444         case HalVersion::AIDL: {
445             sp<IPowerAidl> handle = gPowerHalAidl_;
446             lock.unlock();
447             setPowerModeWithHandle(handle, Mode::INTERACTIVE, enable);
448             return;
449         }
450         default: {
451             ALOGE("Unknown power HAL state");
452             return;
453         }
454     }
455 }
456 
nativeSetAutoSuspend(JNIEnv *,jclass,jboolean enable)457 static void nativeSetAutoSuspend(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
458     if (enable) {
459         android::base::Timer t;
460         enableAutoSuspend();
461         if (t.duration() > 100ms) {
462             ALOGD("Excessive delay in autosuspend_enable() while turning screen off");
463         }
464     } else {
465         android::base::Timer t;
466         disableAutoSuspend();
467         if (t.duration() > 100ms) {
468             ALOGD("Excessive delay in autosuspend_disable() while turning screen on");
469         }
470     }
471 }
472 
nativeSendPowerHint(JNIEnv *,jclass,jint hintId,jint data)473 static void nativeSendPowerHint(JNIEnv* /* env */, jclass /* clazz */, jint hintId, jint data) {
474     sendPowerHint(static_cast<PowerHint>(hintId), data);
475 }
476 
nativeSetPowerBoost(JNIEnv *,jclass,jint boost,jint durationMs)477 static void nativeSetPowerBoost(JNIEnv* /* env */, jclass /* clazz */, jint boost,
478                                 jint durationMs) {
479     setPowerBoost(static_cast<Boost>(boost), durationMs);
480 }
481 
nativeSetPowerMode(JNIEnv *,jclass,jint mode,jboolean enabled)482 static jboolean nativeSetPowerMode(JNIEnv* /* env */, jclass /* clazz */, jint mode,
483                                    jboolean enabled) {
484     return setPowerMode(static_cast<Mode>(mode), enabled);
485 }
486 
nativeSetFeature(JNIEnv *,jclass,jint featureId,jint data)487 static void nativeSetFeature(JNIEnv* /* env */, jclass /* clazz */, jint featureId, jint data) {
488     std::unique_lock<std::mutex> lock(gPowerHalMutex);
489     switch (connectPowerHalLocked()) {
490         case HalVersion::NONE:
491             return;
492         case HalVersion::HIDL_1_0:
493             FALLTHROUGH_INTENDED;
494         case HalVersion::HIDL_1_1: {
495             sp<IPowerV1_0> handle = gPowerHalHidlV1_0_;
496             lock.unlock();
497             auto ret = handle->setFeature(static_cast<Feature>(featureId), static_cast<bool>(data));
498             processPowerHalReturn(ret.isOk(), "setFeature");
499             return;
500         }
501         case HalVersion::AIDL: {
502             sp<IPowerAidl> handle = gPowerHalAidl_;
503             lock.unlock();
504             setPowerModeWithHandle(handle, Mode::DOUBLE_TAP_TO_WAKE, static_cast<bool>(data));
505             return;
506         }
507         default: {
508             ALOGE("Unknown power HAL state");
509             return;
510         }
511     }
512 }
513 
nativeForceSuspend(JNIEnv *,jclass)514 static bool nativeForceSuspend(JNIEnv* /* env */, jclass /* clazz */) {
515     bool retval = false;
516     getSuspendControl()->forceSuspend(&retval);
517     return retval;
518 }
519 
520 // ----------------------------------------------------------------------------
521 
522 static const JNINativeMethod gPowerManagerServiceMethods[] = {
523         /* name, signature, funcPtr */
524         {"nativeInit", "()V", (void*)nativeInit},
525         {"nativeAcquireSuspendBlocker", "(Ljava/lang/String;)V",
526          (void*)nativeAcquireSuspendBlocker},
527         {"nativeForceSuspend", "()Z", (void*)nativeForceSuspend},
528         {"nativeReleaseSuspendBlocker", "(Ljava/lang/String;)V",
529          (void*)nativeReleaseSuspendBlocker},
530         {"nativeSetInteractive", "(Z)V", (void*)nativeSetInteractive},
531         {"nativeSetAutoSuspend", "(Z)V", (void*)nativeSetAutoSuspend},
532         {"nativeSendPowerHint", "(II)V", (void*)nativeSendPowerHint},
533         {"nativeSetPowerBoost", "(II)V", (void*)nativeSetPowerBoost},
534         {"nativeSetPowerMode", "(IZ)Z", (void*)nativeSetPowerMode},
535         {"nativeSetFeature", "(II)V", (void*)nativeSetFeature},
536 };
537 
538 #define FIND_CLASS(var, className) \
539         var = env->FindClass(className); \
540         LOG_FATAL_IF(! (var), "Unable to find class " className);
541 
542 #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
543         var = env->GetMethodID(clazz, methodName, methodDescriptor); \
544         LOG_FATAL_IF(! (var), "Unable to find method " methodName);
545 
546 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
547         var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
548         LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
549 
register_android_server_PowerManagerService(JNIEnv * env)550 int register_android_server_PowerManagerService(JNIEnv* env) {
551     int res = jniRegisterNativeMethods(env, "com/android/server/power/PowerManagerService",
552             gPowerManagerServiceMethods, NELEM(gPowerManagerServiceMethods));
553     (void) res;  // Faked use when LOG_NDEBUG.
554     LOG_FATAL_IF(res < 0, "Unable to register native methods.");
555 
556     // Callbacks
557 
558     jclass clazz;
559     FIND_CLASS(clazz, "com/android/server/power/PowerManagerService");
560 
561     GET_METHOD_ID(gPowerManagerServiceClassInfo.userActivityFromNative, clazz,
562             "userActivityFromNative", "(JII)V");
563 
564     // Initialize
565     for (int i = 0; i <= USER_ACTIVITY_EVENT_LAST; i++) {
566         gLastEventTime[i] = LLONG_MIN;
567     }
568     gPowerManagerServiceObj = NULL;
569     return 0;
570 }
571 
572 } /* namespace android */
573