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