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