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 <android/system/suspend/internal/ISuspendControlServiceInternal.h>
28 #include <nativehelper/JNIHelp.h>
29 #include "jni.h"
30
31 #include <nativehelper/ScopedUtfChars.h>
32 #include <powermanager/PowerHalController.h>
33
34 #include <limits.h>
35
36 #include <android-base/chrono_utils.h>
37 #include <android_runtime/AndroidRuntime.h>
38 #include <android_runtime/Log.h>
39 #include <binder/IServiceManager.h>
40 #include <gui/SurfaceComposerClient.h>
41 #include <hardware/power.h>
42 #include <hardware_legacy/power.h>
43 #include <hidl/ServiceManagement.h>
44 #include <utils/Timers.h>
45 #include <utils/misc.h>
46 #include <utils/String8.h>
47 #include <utils/Log.h>
48
49 #include "com_android_server_power_PowerManagerService.h"
50
51 using android::String8;
52 using android::hardware::power::Boost;
53 using android::hardware::power::Mode;
54 using android::system::suspend::ISuspendControlService;
55 using android::system::suspend::V1_0::ISystemSuspend;
56 using android::system::suspend::V1_0::IWakeLock;
57 using android::system::suspend::V1_0::WakeLockType;
58 using IPowerV1_1 = android::hardware::power::V1_1::IPower;
59 using IPowerV1_0 = android::hardware::power::V1_0::IPower;
60 using IPowerAidl = android::hardware::power::IPower;
61
62 namespace android {
63
64 // ----------------------------------------------------------------------------
65
66 static struct {
67 jmethodID userActivityFromNative;
68 } gPowerManagerServiceClassInfo;
69
70 // ----------------------------------------------------------------------------
71
72 static jobject gPowerManagerServiceObj;
73 static power::PowerHalController gPowerHalController;
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
setPowerBoost(Boost boost,int32_t durationMs)91 static void setPowerBoost(Boost boost, int32_t durationMs) {
92 gPowerHalController.setBoost(boost, durationMs);
93 SurfaceComposerClient::notifyPowerBoost(static_cast<int32_t>(boost));
94 }
95
setPowerMode(Mode mode,bool enabled)96 static bool setPowerMode(Mode mode, bool enabled) {
97 android::base::Timer t;
98 auto result = gPowerHalController.setMode(mode, enabled);
99 if (mode == Mode::INTERACTIVE && t.duration() > 20ms) {
100 ALOGD("Excessive delay in setting interactive mode to %s while turning screen %s",
101 enabled ? "true" : "false", enabled ? "on" : "off");
102 }
103 return result.isOk();
104 }
105
android_server_PowerManagerService_userActivity(nsecs_t eventTime,int32_t eventType,int32_t displayId)106 void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType,
107 int32_t displayId) {
108 if (gPowerManagerServiceObj) {
109 // Throttle calls into user activity by event type.
110 // We're a little conservative about argument checking here in case the caller
111 // passes in bad data which could corrupt system state.
112 if (eventType >= 0 && eventType <= USER_ACTIVITY_EVENT_LAST) {
113 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
114 if (eventTime > now) {
115 eventTime = now;
116 }
117
118 if (gLastEventTime[eventType] + MIN_TIME_BETWEEN_USERACTIVITIES > eventTime) {
119 return;
120 }
121 gLastEventTime[eventType] = eventTime;
122
123 // Tell the power HAL when user activity occurs.
124 setPowerBoost(Boost::INTERACTION, 0);
125 }
126
127 JNIEnv* env = AndroidRuntime::getJNIEnv();
128
129 env->CallVoidMethod(gPowerManagerServiceObj,
130 gPowerManagerServiceClassInfo.userActivityFromNative,
131 nanoseconds_to_milliseconds(eventTime), eventType, displayId, 0);
132 checkAndClearExceptionFromCallback(env, "userActivityFromNative");
133 }
134 }
135
136 static sp<ISystemSuspend> gSuspendHal = nullptr;
137 static sp<ISuspendControlService> gSuspendControl = nullptr;
138 static sp<system::suspend::internal::ISuspendControlServiceInternal> gSuspendControlInternal =
139 nullptr;
140 static sp<IWakeLock> gSuspendBlocker = nullptr;
141 static std::mutex gSuspendMutex;
142
143 // Assume SystemSuspend HAL is always alive.
144 // TODO: Force device to restart if SystemSuspend HAL dies.
getSuspendHal()145 sp<ISystemSuspend> getSuspendHal() {
146 static std::once_flag suspendHalFlag;
147 std::call_once(suspendHalFlag, [](){
148 ::android::hardware::details::waitForHwService(ISystemSuspend::descriptor, "default");
149 gSuspendHal = ISystemSuspend::getService();
150 assert(gSuspendHal != nullptr);
151 });
152 return gSuspendHal;
153 }
154
getSuspendControl()155 sp<ISuspendControlService> getSuspendControl() {
156 static std::once_flag suspendControlFlag;
157 std::call_once(suspendControlFlag, [](){
158 gSuspendControl = waitForService<ISuspendControlService>(String16("suspend_control"));
159 LOG_ALWAYS_FATAL_IF(gSuspendControl == nullptr);
160 });
161 return gSuspendControl;
162 }
163
getSuspendControlInternal()164 sp<system::suspend::internal::ISuspendControlServiceInternal> getSuspendControlInternal() {
165 static std::once_flag suspendControlFlag;
166 std::call_once(suspendControlFlag, []() {
167 gSuspendControlInternal =
168 waitForService<system::suspend::internal::ISuspendControlServiceInternal>(
169 String16("suspend_control_internal"));
170 LOG_ALWAYS_FATAL_IF(gSuspendControlInternal == nullptr);
171 });
172 return gSuspendControlInternal;
173 }
174
enableAutoSuspend()175 void enableAutoSuspend() {
176 static bool enabled = false;
177 if (!enabled) {
178 sp<system::suspend::internal::ISuspendControlServiceInternal> suspendControl =
179 getSuspendControlInternal();
180 suspendControl->enableAutosuspend(&enabled);
181 }
182
183 {
184 std::lock_guard<std::mutex> lock(gSuspendMutex);
185 if (gSuspendBlocker) {
186 gSuspendBlocker->release();
187 gSuspendBlocker.clear();
188 }
189 }
190 }
191
disableAutoSuspend()192 void disableAutoSuspend() {
193 std::lock_guard<std::mutex> lock(gSuspendMutex);
194 if (!gSuspendBlocker) {
195 sp<ISystemSuspend> suspendHal = getSuspendHal();
196 gSuspendBlocker = suspendHal->acquireWakeLock(WakeLockType::PARTIAL,
197 "PowerManager.SuspendLockout");
198 }
199 }
200
201 // ----------------------------------------------------------------------------
202
nativeInit(JNIEnv * env,jobject obj)203 static void nativeInit(JNIEnv* env, jobject obj) {
204 gPowerManagerServiceObj = env->NewGlobalRef(obj);
205 gPowerHalController.init();
206 }
207
nativeAcquireSuspendBlocker(JNIEnv * env,jclass,jstring nameStr)208 static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass /* clazz */, jstring nameStr) {
209 ScopedUtfChars name(env, nameStr);
210 acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());
211 }
212
nativeReleaseSuspendBlocker(JNIEnv * env,jclass,jstring nameStr)213 static void nativeReleaseSuspendBlocker(JNIEnv *env, jclass /* clazz */, jstring nameStr) {
214 ScopedUtfChars name(env, nameStr);
215 release_wake_lock(name.c_str());
216 }
217
nativeSetAutoSuspend(JNIEnv *,jclass,jboolean enable)218 static void nativeSetAutoSuspend(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
219 if (enable) {
220 android::base::Timer t;
221 enableAutoSuspend();
222 if (t.duration() > 100ms) {
223 ALOGD("Excessive delay in autosuspend_enable() while turning screen off");
224 }
225 } else {
226 android::base::Timer t;
227 disableAutoSuspend();
228 if (t.duration() > 100ms) {
229 ALOGD("Excessive delay in autosuspend_disable() while turning screen on");
230 }
231 }
232 }
233
nativeSetPowerBoost(JNIEnv *,jclass,jint boost,jint durationMs)234 static void nativeSetPowerBoost(JNIEnv* /* env */, jclass /* clazz */, jint boost,
235 jint durationMs) {
236 setPowerBoost(static_cast<Boost>(boost), durationMs);
237 }
238
nativeSetPowerMode(JNIEnv *,jclass,jint mode,jboolean enabled)239 static jboolean nativeSetPowerMode(JNIEnv* /* env */, jclass /* clazz */, jint mode,
240 jboolean enabled) {
241 return setPowerMode(static_cast<Mode>(mode), enabled);
242 }
243
nativeForceSuspend(JNIEnv *,jclass)244 static bool nativeForceSuspend(JNIEnv* /* env */, jclass /* clazz */) {
245 bool retval = false;
246 getSuspendControlInternal()->forceSuspend(&retval);
247 return retval;
248 }
249
250 // ----------------------------------------------------------------------------
251
252 static const JNINativeMethod gPowerManagerServiceMethods[] = {
253 /* name, signature, funcPtr */
254 {"nativeInit", "()V", (void*)nativeInit},
255 {"nativeAcquireSuspendBlocker", "(Ljava/lang/String;)V",
256 (void*)nativeAcquireSuspendBlocker},
257 {"nativeForceSuspend", "()Z", (void*)nativeForceSuspend},
258 {"nativeReleaseSuspendBlocker", "(Ljava/lang/String;)V",
259 (void*)nativeReleaseSuspendBlocker},
260 {"nativeSetAutoSuspend", "(Z)V", (void*)nativeSetAutoSuspend},
261 {"nativeSetPowerBoost", "(II)V", (void*)nativeSetPowerBoost},
262 {"nativeSetPowerMode", "(IZ)Z", (void*)nativeSetPowerMode},
263 };
264
265 #define FIND_CLASS(var, className) \
266 var = env->FindClass(className); \
267 LOG_FATAL_IF(! (var), "Unable to find class " className);
268
269 #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
270 var = env->GetMethodID(clazz, methodName, methodDescriptor); \
271 LOG_FATAL_IF(! (var), "Unable to find method " methodName);
272
273 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
274 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
275 LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
276
register_android_server_PowerManagerService(JNIEnv * env)277 int register_android_server_PowerManagerService(JNIEnv* env) {
278 int res = jniRegisterNativeMethods(env, "com/android/server/power/PowerManagerService",
279 gPowerManagerServiceMethods, NELEM(gPowerManagerServiceMethods));
280 (void) res; // Faked use when LOG_NDEBUG.
281 LOG_FATAL_IF(res < 0, "Unable to register native methods.");
282
283 // Callbacks
284
285 jclass clazz;
286 FIND_CLASS(clazz, "com/android/server/power/PowerManagerService");
287
288 GET_METHOD_ID(gPowerManagerServiceClassInfo.userActivityFromNative, clazz,
289 "userActivityFromNative", "(JIII)V");
290
291 // Initialize
292 for (int i = 0; i <= USER_ACTIVITY_EVENT_LAST; i++) {
293 gLastEventTime[i] = LLONG_MIN;
294 }
295 gPowerManagerServiceObj = NULL;
296 return 0;
297 }
298
299 } /* namespace android */
300