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/system/suspend/1.0/ISystemSuspend.h>
23 #include <android/system/suspend/ISuspendControlService.h>
24 #include <nativehelper/JNIHelp.h>
25 #include "jni.h"
26
27 #include <nativehelper/ScopedUtfChars.h>
28
29 #include <limits.h>
30
31 #include <android-base/chrono_utils.h>
32 #include <android_runtime/AndroidRuntime.h>
33 #include <android_runtime/Log.h>
34 #include <binder/IServiceManager.h>
35 #include <gui/SurfaceComposerClient.h>
36 #include <hardware/power.h>
37 #include <hardware_legacy/power.h>
38 #include <hidl/ServiceManagement.h>
39 #include <utils/Timers.h>
40 #include <utils/misc.h>
41 #include <utils/String8.h>
42 #include <utils/Log.h>
43
44 #include "com_android_server_power_PowerManagerService.h"
45
46 using android::hardware::Return;
47 using android::hardware::Void;
48 using android::hardware::power::V1_0::PowerHint;
49 using android::hardware::power::V1_0::Feature;
50 using android::String8;
51 using android::system::suspend::V1_0::ISystemSuspend;
52 using android::system::suspend::V1_0::IWakeLock;
53 using android::system::suspend::V1_0::WakeLockType;
54 using android::system::suspend::ISuspendControlService;
55 using IPowerV1_1 = android::hardware::power::V1_1::IPower;
56 using IPowerV1_0 = android::hardware::power::V1_0::IPower;
57
58 namespace android {
59
60 // ----------------------------------------------------------------------------
61
62 static struct {
63 jmethodID userActivityFromNative;
64 } gPowerManagerServiceClassInfo;
65
66 // ----------------------------------------------------------------------------
67
68 static jobject gPowerManagerServiceObj;
69 // Use getPowerHal* to retrieve a copy
70 static sp<IPowerV1_0> gPowerHalV1_0_ = nullptr;
71 static sp<IPowerV1_1> gPowerHalV1_1_ = nullptr;
72 static bool gPowerHalExists = true;
73 static std::mutex gPowerHalMutex;
74 static nsecs_t gLastEventTime[USER_ACTIVITY_EVENT_LAST + 1];
75
76 // Throttling interval for user activity calls.
77 static const nsecs_t MIN_TIME_BETWEEN_USERACTIVITIES = 100 * 1000000L; // 100ms
78
79 // ----------------------------------------------------------------------------
80
checkAndClearExceptionFromCallback(JNIEnv * env,const char * methodName)81 static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
82 if (env->ExceptionCheck()) {
83 ALOGE("An exception was thrown by callback '%s'.", methodName);
84 LOGE_EX(env);
85 env->ExceptionClear();
86 return true;
87 }
88 return false;
89 }
90
91 // Check validity of current handle to the power HAL service, and call getService() if necessary.
92 // The caller must be holding gPowerHalMutex.
connectPowerHalLocked()93 static void connectPowerHalLocked() {
94 if (gPowerHalExists && gPowerHalV1_0_ == nullptr) {
95 gPowerHalV1_0_ = IPowerV1_0::getService();
96 if (gPowerHalV1_0_ != nullptr) {
97 ALOGI("Loaded power HAL 1.0 service");
98 // Try cast to powerHAL V1_1
99 gPowerHalV1_1_ = IPowerV1_1::castFrom(gPowerHalV1_0_);
100 if (gPowerHalV1_1_ == nullptr) {
101 } else {
102 ALOGI("Loaded power HAL 1.1 service");
103 }
104 } else {
105 ALOGI("Couldn't load power HAL service");
106 gPowerHalExists = false;
107 }
108 }
109 }
110
111 // Retrieve a copy of PowerHAL V1_0
getPowerHalV1_0()112 sp<IPowerV1_0> getPowerHalV1_0() {
113 std::lock_guard<std::mutex> lock(gPowerHalMutex);
114 connectPowerHalLocked();
115 return gPowerHalV1_0_;
116 }
117
118 // Retrieve a copy of PowerHAL V1_1
getPowerHalV1_1()119 sp<IPowerV1_1> getPowerHalV1_1() {
120 std::lock_guard<std::mutex> lock(gPowerHalMutex);
121 connectPowerHalLocked();
122 return gPowerHalV1_1_;
123 }
124
125 // Check if a call to a power HAL function failed; if so, log the failure and invalidate the
126 // current handle to the power HAL service.
processPowerHalReturn(const Return<void> & ret,const char * functionName)127 bool processPowerHalReturn(const Return<void> &ret, const char* functionName) {
128 if (!ret.isOk()) {
129 ALOGE("%s() failed: power HAL service not available.", functionName);
130 gPowerHalMutex.lock();
131 gPowerHalV1_0_ = nullptr;
132 gPowerHalV1_1_ = nullptr;
133 gPowerHalMutex.unlock();
134 }
135 return ret.isOk();
136 }
137
sendPowerHint(PowerHint hintId,uint32_t data)138 static void sendPowerHint(PowerHint hintId, uint32_t data) {
139 sp<IPowerV1_1> powerHalV1_1 = getPowerHalV1_1();
140 Return<void> ret;
141 if (powerHalV1_1 != nullptr) {
142 ret = powerHalV1_1->powerHintAsync(hintId, data);
143 processPowerHalReturn(ret, "powerHintAsync");
144 } else {
145 sp<IPowerV1_0> powerHalV1_0 = getPowerHalV1_0();
146 if (powerHalV1_0 != nullptr) {
147 ret = powerHalV1_0->powerHint(hintId, data);
148 processPowerHalReturn(ret, "powerHint");
149 }
150 }
151
152 SurfaceComposerClient::notifyPowerHint(static_cast<int32_t>(hintId));
153 }
154
android_server_PowerManagerService_userActivity(nsecs_t eventTime,int32_t eventType)155 void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType) {
156 if (gPowerManagerServiceObj) {
157 // Throttle calls into user activity by event type.
158 // We're a little conservative about argument checking here in case the caller
159 // passes in bad data which could corrupt system state.
160 if (eventType >= 0 && eventType <= USER_ACTIVITY_EVENT_LAST) {
161 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
162 if (eventTime > now) {
163 eventTime = now;
164 }
165
166 if (gLastEventTime[eventType] + MIN_TIME_BETWEEN_USERACTIVITIES > eventTime) {
167 return;
168 }
169 gLastEventTime[eventType] = eventTime;
170
171 // Tell the power HAL when user activity occurs.
172 sendPowerHint(PowerHint::INTERACTION, 0);
173 }
174
175 JNIEnv* env = AndroidRuntime::getJNIEnv();
176
177 env->CallVoidMethod(gPowerManagerServiceObj,
178 gPowerManagerServiceClassInfo.userActivityFromNative,
179 nanoseconds_to_milliseconds(eventTime), eventType, 0);
180 checkAndClearExceptionFromCallback(env, "userActivityFromNative");
181 }
182 }
183
184 static sp<ISystemSuspend> gSuspendHal = nullptr;
185 static sp<ISuspendControlService> gSuspendControl = nullptr;
186 static sp<IWakeLock> gSuspendBlocker = nullptr;
187 static std::mutex gSuspendMutex;
188
189 // Assume SystemSuspend HAL is always alive.
190 // TODO: Force device to restart if SystemSuspend HAL dies.
getSuspendHal()191 sp<ISystemSuspend> getSuspendHal() {
192 static std::once_flag suspendHalFlag;
193 std::call_once(suspendHalFlag, [](){
194 ::android::hardware::details::waitForHwService(ISystemSuspend::descriptor, "default");
195 gSuspendHal = ISystemSuspend::getService();
196 assert(gSuspendHal != nullptr);
197 });
198 return gSuspendHal;
199 }
200
getSuspendControl()201 sp<ISuspendControlService> getSuspendControl() {
202 static std::once_flag suspendControlFlag;
203 std::call_once(suspendControlFlag, [](){
204 while(gSuspendControl == nullptr) {
205 sp<IBinder> control =
206 defaultServiceManager()->getService(String16("suspend_control"));
207 if (control != nullptr) {
208 gSuspendControl = interface_cast<ISuspendControlService>(control);
209 }
210 }
211 });
212 return gSuspendControl;
213 }
214
enableAutoSuspend()215 void enableAutoSuspend() {
216 static bool enabled = false;
217 if (!enabled) {
218 sp<ISuspendControlService> suspendControl = getSuspendControl();
219 suspendControl->enableAutosuspend(&enabled);
220 }
221
222 {
223 std::lock_guard<std::mutex> lock(gSuspendMutex);
224 if (gSuspendBlocker) {
225 gSuspendBlocker->release();
226 gSuspendBlocker.clear();
227 }
228 }
229 }
230
disableAutoSuspend()231 void disableAutoSuspend() {
232 std::lock_guard<std::mutex> lock(gSuspendMutex);
233 if (!gSuspendBlocker) {
234 sp<ISystemSuspend> suspendHal = getSuspendHal();
235 gSuspendBlocker = suspendHal->acquireWakeLock(WakeLockType::PARTIAL,
236 "PowerManager.SuspendLockout");
237 }
238 }
239
240 // ----------------------------------------------------------------------------
241
nativeInit(JNIEnv * env,jobject obj)242 static void nativeInit(JNIEnv* env, jobject obj) {
243 gPowerManagerServiceObj = env->NewGlobalRef(obj);
244
245 gPowerHalMutex.lock();
246 connectPowerHalLocked();
247 gPowerHalMutex.unlock();
248 }
249
nativeAcquireSuspendBlocker(JNIEnv * env,jclass,jstring nameStr)250 static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass /* clazz */, jstring nameStr) {
251 ScopedUtfChars name(env, nameStr);
252 acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());
253 }
254
nativeReleaseSuspendBlocker(JNIEnv * env,jclass,jstring nameStr)255 static void nativeReleaseSuspendBlocker(JNIEnv *env, jclass /* clazz */, jstring nameStr) {
256 ScopedUtfChars name(env, nameStr);
257 release_wake_lock(name.c_str());
258 }
259
nativeSetInteractive(JNIEnv *,jclass,jboolean enable)260 static void nativeSetInteractive(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
261 sp<IPowerV1_0> powerHalV1_0 = getPowerHalV1_0();
262 if (powerHalV1_0 != nullptr) {
263 android::base::Timer t;
264 Return<void> ret = powerHalV1_0->setInteractive(enable);
265 processPowerHalReturn(ret, "setInteractive");
266 if (t.duration() > 20ms) {
267 ALOGD("Excessive delay in setInteractive(%s) while turning screen %s",
268 enable ? "true" : "false", enable ? "on" : "off");
269 }
270 }
271 }
272
nativeSetAutoSuspend(JNIEnv *,jclass,jboolean enable)273 static void nativeSetAutoSuspend(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
274 if (enable) {
275 android::base::Timer t;
276 enableAutoSuspend();
277 if (t.duration() > 100ms) {
278 ALOGD("Excessive delay in autosuspend_enable() while turning screen off");
279 }
280 } else {
281 android::base::Timer t;
282 disableAutoSuspend();
283 if (t.duration() > 100ms) {
284 ALOGD("Excessive delay in autosuspend_disable() while turning screen on");
285 }
286 }
287 }
288
nativeSendPowerHint(JNIEnv *,jclass,jint hintId,jint data)289 static void nativeSendPowerHint(JNIEnv* /* env */, jclass /* clazz */, jint hintId, jint data) {
290 sendPowerHint(static_cast<PowerHint>(hintId), data);
291 }
292
nativeSetFeature(JNIEnv *,jclass,jint featureId,jint data)293 static void nativeSetFeature(JNIEnv* /* env */, jclass /* clazz */, jint featureId, jint data) {
294 sp<IPowerV1_0> powerHalV1_0 = getPowerHalV1_0();
295 if (powerHalV1_0 != nullptr) {
296 Return<void> ret = powerHalV1_0->setFeature((Feature)featureId, static_cast<bool>(data));
297 processPowerHalReturn(ret, "setFeature");
298 }
299 }
300
nativeForceSuspend(JNIEnv *,jclass)301 static bool nativeForceSuspend(JNIEnv* /* env */, jclass /* clazz */) {
302 bool retval = false;
303 getSuspendControl()->forceSuspend(&retval);
304 return retval;
305 }
306
307 // ----------------------------------------------------------------------------
308
309 static const JNINativeMethod gPowerManagerServiceMethods[] = {
310 /* name, signature, funcPtr */
311 { "nativeInit", "()V",
312 (void*) nativeInit },
313 { "nativeAcquireSuspendBlocker", "(Ljava/lang/String;)V",
314 (void*) nativeAcquireSuspendBlocker },
315 { "nativeForceSuspend", "()Z",
316 (void*) nativeForceSuspend },
317 { "nativeReleaseSuspendBlocker", "(Ljava/lang/String;)V",
318 (void*) nativeReleaseSuspendBlocker },
319 { "nativeSetInteractive", "(Z)V",
320 (void*) nativeSetInteractive },
321 { "nativeSetAutoSuspend", "(Z)V",
322 (void*) nativeSetAutoSuspend },
323 { "nativeSendPowerHint", "(II)V",
324 (void*) nativeSendPowerHint },
325 { "nativeSetFeature", "(II)V",
326 (void*) nativeSetFeature },
327 };
328
329 #define FIND_CLASS(var, className) \
330 var = env->FindClass(className); \
331 LOG_FATAL_IF(! (var), "Unable to find class " className);
332
333 #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
334 var = env->GetMethodID(clazz, methodName, methodDescriptor); \
335 LOG_FATAL_IF(! (var), "Unable to find method " methodName);
336
337 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
338 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
339 LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
340
register_android_server_PowerManagerService(JNIEnv * env)341 int register_android_server_PowerManagerService(JNIEnv* env) {
342 int res = jniRegisterNativeMethods(env, "com/android/server/power/PowerManagerService",
343 gPowerManagerServiceMethods, NELEM(gPowerManagerServiceMethods));
344 (void) res; // Faked use when LOG_NDEBUG.
345 LOG_FATAL_IF(res < 0, "Unable to register native methods.");
346
347 // Callbacks
348
349 jclass clazz;
350 FIND_CLASS(clazz, "com/android/server/power/PowerManagerService");
351
352 GET_METHOD_ID(gPowerManagerServiceClassInfo.userActivityFromNative, clazz,
353 "userActivityFromNative", "(JII)V");
354
355 // Initialize
356 for (int i = 0; i <= USER_ACTIVITY_EVENT_LAST; i++) {
357 gLastEventTime[i] = LLONG_MIN;
358 }
359 gPowerManagerServiceObj = NULL;
360 return 0;
361 }
362
363 } /* namespace android */
364