• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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