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
194 // Quick return if boost is not supported by HAL
195 if (boost > Boost::DISPLAY_UPDATE_IMMINENT ||
196 boostSupportedArray[static_cast<int32_t>(boost)] == HalSupport::OFF) {
197 ALOGV("Skipped setPowerBoost %s because HAL doesn't support it", toString(boost).c_str());
198 return;
199 }
200
201 if (boostSupportedArray[static_cast<int32_t>(boost)] == HalSupport::UNKNOWN) {
202 bool isSupported = false;
203 handle->isBoostSupported(boost, &isSupported);
204 boostSupportedArray[static_cast<int32_t>(boost)] =
205 isSupported ? HalSupport::ON : HalSupport::OFF;
206 if (!isSupported) {
207 ALOGV("Skipped setPowerBoost %s because HAL doesn't support it",
208 toString(boost).c_str());
209 return;
210 }
211 }
212
213 auto ret = handle->setBoost(boost, durationMs);
214 processPowerHalReturn(ret.isOk(), "setPowerBoost");
215 }
216
setPowerBoost(Boost boost,int32_t durationMs)217 static void setPowerBoost(Boost boost, int32_t durationMs) {
218 std::unique_lock<std::mutex> lock(gPowerHalMutex);
219 if (connectPowerHalLocked() != HalVersion::AIDL) {
220 ALOGV("Power HAL AIDL not available");
221 return;
222 }
223 sp<IPowerAidl> handle = gPowerHalAidl_;
224 lock.unlock();
225 setPowerBoostWithHandle(handle, boost, durationMs);
226 }
227
setPowerModeWithHandle(sp<IPowerAidl> handle,Mode mode,bool enabled)228 static bool setPowerModeWithHandle(sp<IPowerAidl> handle, Mode mode, bool enabled) {
229 // Android framework only sends mode upto DISPLAY_INACTIVE.
230 // Need to increase the array if more mode supported.
231 static std::array<std::atomic<HalSupport>, static_cast<int32_t>(Mode::DISPLAY_INACTIVE) + 1>
232 modeSupportedArray = {HalSupport::UNKNOWN};
233
234 // Quick return if mode is not supported by HAL
235 if (mode > Mode::DISPLAY_INACTIVE ||
236 modeSupportedArray[static_cast<int32_t>(mode)] == HalSupport::OFF) {
237 ALOGV("Skipped setPowerMode %s because HAL doesn't support it", toString(mode).c_str());
238 return false;
239 }
240
241 if (modeSupportedArray[static_cast<int32_t>(mode)] == HalSupport::UNKNOWN) {
242 bool isSupported = false;
243 handle->isModeSupported(mode, &isSupported);
244 modeSupportedArray[static_cast<int32_t>(mode)] =
245 isSupported ? HalSupport::ON : HalSupport::OFF;
246 if (!isSupported) {
247 ALOGV("Skipped setPowerMode %s because HAL doesn't support it", toString(mode).c_str());
248 return false;
249 }
250 }
251
252 auto ret = handle->setMode(mode, enabled);
253 processPowerHalReturn(ret.isOk(), "setPowerMode");
254 return ret.isOk();
255 }
256
setPowerMode(Mode mode,bool enabled)257 static bool setPowerMode(Mode mode, bool enabled) {
258 std::unique_lock<std::mutex> lock(gPowerHalMutex);
259 if (connectPowerHalLocked() != HalVersion::AIDL) {
260 ALOGV("Power HAL AIDL not available");
261 return false;
262 }
263 sp<IPowerAidl> handle = gPowerHalAidl_;
264 lock.unlock();
265 return setPowerModeWithHandle(handle, mode, enabled);
266 }
267
sendPowerHint(PowerHint hintId,uint32_t data)268 static void sendPowerHint(PowerHint hintId, uint32_t data) {
269 std::unique_lock<std::mutex> lock(gPowerHalMutex);
270 switch (connectPowerHalLocked()) {
271 case HalVersion::NONE:
272 return;
273 case HalVersion::HIDL_1_0: {
274 sp<IPowerV1_0> handle = gPowerHalHidlV1_0_;
275 lock.unlock();
276 auto ret = handle->powerHint(hintId, data);
277 processPowerHalReturn(ret.isOk(), "powerHint");
278 break;
279 }
280 case HalVersion::HIDL_1_1: {
281 sp<IPowerV1_1> handle = gPowerHalHidlV1_1_;
282 lock.unlock();
283 auto ret = handle->powerHintAsync(hintId, data);
284 processPowerHalReturn(ret.isOk(), "powerHintAsync");
285 break;
286 }
287 case HalVersion::AIDL: {
288 if (hintId == PowerHint::INTERACTION) {
289 sp<IPowerAidl> handle = gPowerHalAidl_;
290 lock.unlock();
291 setPowerBoostWithHandle(handle, Boost::INTERACTION, data);
292 break;
293 } else if (hintId == PowerHint::LAUNCH) {
294 sp<IPowerAidl> handle = gPowerHalAidl_;
295 lock.unlock();
296 setPowerModeWithHandle(handle, Mode::LAUNCH, static_cast<bool>(data));
297 break;
298 } else if (hintId == PowerHint::LOW_POWER) {
299 sp<IPowerAidl> handle = gPowerHalAidl_;
300 lock.unlock();
301 setPowerModeWithHandle(handle, Mode::LOW_POWER, static_cast<bool>(data));
302 break;
303 } else if (hintId == PowerHint::SUSTAINED_PERFORMANCE) {
304 sp<IPowerAidl> handle = gPowerHalAidl_;
305 lock.unlock();
306 setPowerModeWithHandle(handle, Mode::SUSTAINED_PERFORMANCE,
307 static_cast<bool>(data));
308 break;
309 } else if (hintId == PowerHint::VR_MODE) {
310 sp<IPowerAidl> handle = gPowerHalAidl_;
311 lock.unlock();
312 setPowerModeWithHandle(handle, Mode::VR, static_cast<bool>(data));
313 break;
314 } else {
315 ALOGE("Unsupported power hint: %s.", toString(hintId).c_str());
316 return;
317 }
318 }
319 default: {
320 ALOGE("Unknown power HAL state");
321 return;
322 }
323 }
324 SurfaceComposerClient::notifyPowerHint(static_cast<int32_t>(hintId));
325 }
326
android_server_PowerManagerService_userActivity(nsecs_t eventTime,int32_t eventType)327 void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType) {
328 if (gPowerManagerServiceObj) {
329 // Throttle calls into user activity by event type.
330 // We're a little conservative about argument checking here in case the caller
331 // passes in bad data which could corrupt system state.
332 if (eventType >= 0 && eventType <= USER_ACTIVITY_EVENT_LAST) {
333 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
334 if (eventTime > now) {
335 eventTime = now;
336 }
337
338 if (gLastEventTime[eventType] + MIN_TIME_BETWEEN_USERACTIVITIES > eventTime) {
339 return;
340 }
341 gLastEventTime[eventType] = eventTime;
342
343 // Tell the power HAL when user activity occurs.
344 sendPowerHint(PowerHint::INTERACTION, 0);
345 }
346
347 JNIEnv* env = AndroidRuntime::getJNIEnv();
348
349 env->CallVoidMethod(gPowerManagerServiceObj,
350 gPowerManagerServiceClassInfo.userActivityFromNative,
351 nanoseconds_to_milliseconds(eventTime), eventType, 0);
352 checkAndClearExceptionFromCallback(env, "userActivityFromNative");
353 }
354 }
355
356 static sp<ISystemSuspend> gSuspendHal = nullptr;
357 static sp<ISuspendControlService> gSuspendControl = nullptr;
358 static sp<IWakeLock> gSuspendBlocker = nullptr;
359 static std::mutex gSuspendMutex;
360
361 // Assume SystemSuspend HAL is always alive.
362 // TODO: Force device to restart if SystemSuspend HAL dies.
getSuspendHal()363 sp<ISystemSuspend> getSuspendHal() {
364 static std::once_flag suspendHalFlag;
365 std::call_once(suspendHalFlag, [](){
366 ::android::hardware::details::waitForHwService(ISystemSuspend::descriptor, "default");
367 gSuspendHal = ISystemSuspend::getService();
368 assert(gSuspendHal != nullptr);
369 });
370 return gSuspendHal;
371 }
372
getSuspendControl()373 sp<ISuspendControlService> getSuspendControl() {
374 static std::once_flag suspendControlFlag;
375 std::call_once(suspendControlFlag, [](){
376 gSuspendControl = waitForService<ISuspendControlService>(String16("suspend_control"));
377 LOG_ALWAYS_FATAL_IF(gSuspendControl == nullptr);
378 });
379 return gSuspendControl;
380 }
381
enableAutoSuspend()382 void enableAutoSuspend() {
383 static bool enabled = false;
384 if (!enabled) {
385 sp<ISuspendControlService> suspendControl = getSuspendControl();
386 suspendControl->enableAutosuspend(&enabled);
387 }
388
389 {
390 std::lock_guard<std::mutex> lock(gSuspendMutex);
391 if (gSuspendBlocker) {
392 gSuspendBlocker->release();
393 gSuspendBlocker.clear();
394 }
395 }
396 }
397
disableAutoSuspend()398 void disableAutoSuspend() {
399 std::lock_guard<std::mutex> lock(gSuspendMutex);
400 if (!gSuspendBlocker) {
401 sp<ISystemSuspend> suspendHal = getSuspendHal();
402 gSuspendBlocker = suspendHal->acquireWakeLock(WakeLockType::PARTIAL,
403 "PowerManager.SuspendLockout");
404 }
405 }
406
407 // ----------------------------------------------------------------------------
408
nativeInit(JNIEnv * env,jobject obj)409 static void nativeInit(JNIEnv* env, jobject obj) {
410 gPowerManagerServiceObj = env->NewGlobalRef(obj);
411
412 gPowerHalMutex.lock();
413 connectPowerHalLocked();
414 gPowerHalMutex.unlock();
415 }
416
nativeAcquireSuspendBlocker(JNIEnv * env,jclass,jstring nameStr)417 static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass /* clazz */, jstring nameStr) {
418 ScopedUtfChars name(env, nameStr);
419 acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());
420 }
421
nativeReleaseSuspendBlocker(JNIEnv * env,jclass,jstring nameStr)422 static void nativeReleaseSuspendBlocker(JNIEnv *env, jclass /* clazz */, jstring nameStr) {
423 ScopedUtfChars name(env, nameStr);
424 release_wake_lock(name.c_str());
425 }
426
nativeSetInteractive(JNIEnv *,jclass,jboolean enable)427 static void nativeSetInteractive(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
428 std::unique_lock<std::mutex> lock(gPowerHalMutex);
429 switch (connectPowerHalLocked()) {
430 case HalVersion::NONE:
431 return;
432 case HalVersion::HIDL_1_0:
433 FALLTHROUGH_INTENDED;
434 case HalVersion::HIDL_1_1: {
435 android::base::Timer t;
436 sp<IPowerV1_0> handle = gPowerHalHidlV1_0_;
437 lock.unlock();
438 auto ret = handle->setInteractive(enable);
439 processPowerHalReturn(ret.isOk(), "setInteractive");
440 if (t.duration() > 20ms) {
441 ALOGD("Excessive delay in setInteractive(%s) while turning screen %s",
442 enable ? "true" : "false", enable ? "on" : "off");
443 }
444 return;
445 }
446 case HalVersion::AIDL: {
447 sp<IPowerAidl> handle = gPowerHalAidl_;
448 lock.unlock();
449 setPowerModeWithHandle(handle, Mode::INTERACTIVE, enable);
450 return;
451 }
452 default: {
453 ALOGE("Unknown power HAL state");
454 return;
455 }
456 }
457 }
458
nativeSetAutoSuspend(JNIEnv *,jclass,jboolean enable)459 static void nativeSetAutoSuspend(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
460 if (enable) {
461 android::base::Timer t;
462 enableAutoSuspend();
463 if (t.duration() > 100ms) {
464 ALOGD("Excessive delay in autosuspend_enable() while turning screen off");
465 }
466 } else {
467 android::base::Timer t;
468 disableAutoSuspend();
469 if (t.duration() > 100ms) {
470 ALOGD("Excessive delay in autosuspend_disable() while turning screen on");
471 }
472 }
473 }
474
nativeSendPowerHint(JNIEnv *,jclass,jint hintId,jint data)475 static void nativeSendPowerHint(JNIEnv* /* env */, jclass /* clazz */, jint hintId, jint data) {
476 sendPowerHint(static_cast<PowerHint>(hintId), data);
477 }
478
nativeSetPowerBoost(JNIEnv *,jclass,jint boost,jint durationMs)479 static void nativeSetPowerBoost(JNIEnv* /* env */, jclass /* clazz */, jint boost,
480 jint durationMs) {
481 setPowerBoost(static_cast<Boost>(boost), durationMs);
482 }
483
nativeSetPowerMode(JNIEnv *,jclass,jint mode,jboolean enabled)484 static jboolean nativeSetPowerMode(JNIEnv* /* env */, jclass /* clazz */, jint mode,
485 jboolean enabled) {
486 return setPowerMode(static_cast<Mode>(mode), enabled);
487 }
488
nativeSetFeature(JNIEnv *,jclass,jint featureId,jint data)489 static void nativeSetFeature(JNIEnv* /* env */, jclass /* clazz */, jint featureId, jint data) {
490 std::unique_lock<std::mutex> lock(gPowerHalMutex);
491 switch (connectPowerHalLocked()) {
492 case HalVersion::NONE:
493 return;
494 case HalVersion::HIDL_1_0:
495 FALLTHROUGH_INTENDED;
496 case HalVersion::HIDL_1_1: {
497 sp<IPowerV1_0> handle = gPowerHalHidlV1_0_;
498 lock.unlock();
499 auto ret = handle->setFeature(static_cast<Feature>(featureId), static_cast<bool>(data));
500 processPowerHalReturn(ret.isOk(), "setFeature");
501 return;
502 }
503 case HalVersion::AIDL: {
504 sp<IPowerAidl> handle = gPowerHalAidl_;
505 lock.unlock();
506 setPowerModeWithHandle(handle, Mode::DOUBLE_TAP_TO_WAKE, static_cast<bool>(data));
507 return;
508 }
509 default: {
510 ALOGE("Unknown power HAL state");
511 return;
512 }
513 }
514 }
515
nativeForceSuspend(JNIEnv *,jclass)516 static bool nativeForceSuspend(JNIEnv* /* env */, jclass /* clazz */) {
517 bool retval = false;
518 getSuspendControl()->forceSuspend(&retval);
519 return retval;
520 }
521
522 // ----------------------------------------------------------------------------
523
524 static const JNINativeMethod gPowerManagerServiceMethods[] = {
525 /* name, signature, funcPtr */
526 {"nativeInit", "()V", (void*)nativeInit},
527 {"nativeAcquireSuspendBlocker", "(Ljava/lang/String;)V",
528 (void*)nativeAcquireSuspendBlocker},
529 {"nativeForceSuspend", "()Z", (void*)nativeForceSuspend},
530 {"nativeReleaseSuspendBlocker", "(Ljava/lang/String;)V",
531 (void*)nativeReleaseSuspendBlocker},
532 {"nativeSetInteractive", "(Z)V", (void*)nativeSetInteractive},
533 {"nativeSetAutoSuspend", "(Z)V", (void*)nativeSetAutoSuspend},
534 {"nativeSendPowerHint", "(II)V", (void*)nativeSendPowerHint},
535 {"nativeSetPowerBoost", "(II)V", (void*)nativeSetPowerBoost},
536 {"nativeSetPowerMode", "(IZ)Z", (void*)nativeSetPowerMode},
537 {"nativeSetFeature", "(II)V", (void*)nativeSetFeature},
538 };
539
540 #define FIND_CLASS(var, className) \
541 var = env->FindClass(className); \
542 LOG_FATAL_IF(! (var), "Unable to find class " className);
543
544 #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
545 var = env->GetMethodID(clazz, methodName, methodDescriptor); \
546 LOG_FATAL_IF(! (var), "Unable to find method " methodName);
547
548 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
549 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
550 LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
551
register_android_server_PowerManagerService(JNIEnv * env)552 int register_android_server_PowerManagerService(JNIEnv* env) {
553 int res = jniRegisterNativeMethods(env, "com/android/server/power/PowerManagerService",
554 gPowerManagerServiceMethods, NELEM(gPowerManagerServiceMethods));
555 (void) res; // Faked use when LOG_NDEBUG.
556 LOG_FATAL_IF(res < 0, "Unable to register native methods.");
557
558 // Callbacks
559
560 jclass clazz;
561 FIND_CLASS(clazz, "com/android/server/power/PowerManagerService");
562
563 GET_METHOD_ID(gPowerManagerServiceClassInfo.userActivityFromNative, clazz,
564 "userActivityFromNative", "(JII)V");
565
566 // Initialize
567 for (int i = 0; i <= USER_ACTIVITY_EVENT_LAST; i++) {
568 gLastEventTime[i] = LLONG_MIN;
569 }
570 gPowerManagerServiceObj = NULL;
571 return 0;
572 }
573
574 } /* namespace android */
575