Merge "PowerManagerService: Do not hold lock for the duration of PowerHal call"

This commit is contained in:
Wei Wang
2017-12-01 22:41:41 +00:00
committed by Android (Google) Code Review
2 changed files with 94 additions and 92 deletions

View File

@@ -43,13 +43,14 @@
using android::hardware::Return;
using android::hardware::Void;
using android::hardware::power::V1_0::IPower;
using android::hardware::power::V1_0::PowerStatePlatformSleepState;
using android::hardware::power::V1_0::PowerStateVoter;
using android::hardware::power::V1_0::Status;
using android::hardware::power::V1_1::PowerStateSubsystem;
using android::hardware::power::V1_1::PowerStateSubsystemSleepState;
using android::hardware::hidl_vec;
using IPowerV1_1 = android::hardware::power::V1_1::IPower;
using IPowerV1_0 = android::hardware::power::V1_0::IPower;
namespace android
{
@@ -59,9 +60,9 @@ namespace android
static bool wakeup_init = false;
static sem_t wakeup_sem;
extern sp<android::hardware::power::V1_0::IPower> gPowerHalV1_0;
extern std::mutex gPowerHalMutex;
extern bool getPowerHal();
extern sp<IPowerV1_0> getPowerHalV1_0();
extern sp<IPowerV1_1> getPowerHalV1_1();
extern bool processPowerHalReturn(const Return<void> &ret, const char* functionName);
// Java methods used in getLowPowerStats
static jmethodID jgetAndUpdatePlatformState = NULL;
@@ -203,13 +204,13 @@ static void getLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject jrpmStats
return;
}
std::lock_guard<std::mutex> lock(gPowerHalMutex);
if (!getPowerHal()) {
sp<IPowerV1_0> powerHalV1_0 = getPowerHalV1_0();
if (powerHalV1_0 == nullptr) {
ALOGE("Power Hal not loaded");
return;
}
Return<void> ret = gPowerHalV1_0->getPlatformLowPowerStats(
Return<void> ret = powerHalV1_0->getPlatformLowPowerStats(
[&env, &jrpmStats](hidl_vec<PowerStatePlatformSleepState> states, Status status) {
if (status != Status::SUCCESS) return;
@@ -236,20 +237,17 @@ static void getLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject jrpmStats
}
}
});
if (!ret.isOk()) {
ALOGE("getLowPowerStats() failed: power HAL service not available");
gPowerHalV1_0 = nullptr;
if (!processPowerHalReturn(ret, "getPlatformLowPowerStats")) {
return;
}
//Trying to cast to IPower 1.1, this will succeed only for devices supporting 1.1
sp<android::hardware::power::V1_1::IPower> gPowerHal_1_1
= android::hardware::power::V1_1::IPower::castFrom(gPowerHalV1_0);
if (gPowerHal_1_1 == nullptr) {
//This device does not support IPower@1.1, exiting gracefully
// Trying to get IPower 1.1, this will succeed only for devices supporting 1.1
sp<IPowerV1_1> powerHal_1_1 = getPowerHalV1_1();
if (powerHal_1_1 == nullptr) {
// This device does not support IPower@1.1, exiting gracefully
return;
}
ret = gPowerHal_1_1->getSubsystemLowPowerStats(
ret = powerHal_1_1->getSubsystemLowPowerStats(
[&env, &jrpmStats](hidl_vec<PowerStateSubsystem> subsystems, Status status) {
if (status != Status::SUCCESS) return;
@@ -275,11 +273,7 @@ static void getLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject jrpmStats
}
}
});
if (!ret.isOk()) {
ALOGE("getSubsystemLowPowerStats() failed: power HAL service not available");
gPowerHalV1_0 = nullptr;
}
// gPowerHalMutex released here
processPowerHalReturn(ret, "getSubsystemLowPowerStats");
}
static jint getPlatformLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject outBuf) {
@@ -294,13 +288,13 @@ static jint getPlatformLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject o
}
{
std::lock_guard<std::mutex> lock(gPowerHalMutex);
if (!getPowerHal()) {
sp<IPowerV1_0> powerHalV1_0 = getPowerHalV1_0();
if (powerHalV1_0 == nullptr) {
ALOGE("Power Hal not loaded");
return -1;
}
Return<void> ret = gPowerHalV1_0->getPlatformLowPowerStats(
Return<void> ret = powerHalV1_0->getPlatformLowPowerStats(
[&offset, &remaining, &total_added](hidl_vec<PowerStatePlatformSleepState> states,
Status status) {
if (status != Status::SUCCESS)
@@ -352,9 +346,7 @@ static jint getPlatformLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject o
}
);
if (!ret.isOk()) {
ALOGE("getPlatformLowPowerStats() failed: power HAL service not available");
gPowerHalV1_0 = nullptr;
if (!processPowerHalReturn(ret, "getPlatformLowPowerStats")) {
return -1;
}
}
@@ -369,8 +361,8 @@ static jint getSubsystemLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject
int remaining = (int)env->GetDirectBufferCapacity(outBuf);
int total_added = -1;
//This is a IPower 1.1 API
sp<android::hardware::power::V1_1::IPower> gPowerHal_1_1 = nullptr;
// This is a IPower 1.1 API
sp<IPowerV1_1> powerHal_1_1 = nullptr;
if (outBuf == NULL) {
jniThrowException(env, "java/lang/NullPointerException", "null argument");
@@ -378,20 +370,14 @@ static jint getSubsystemLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject
}
{
std::lock_guard<std::mutex> lock(gPowerHalMutex);
if (!getPowerHal()) {
ALOGE("Power Hal not loaded");
return -1;
}
//Trying to cast to 1.1, this will succeed only for devices supporting 1.1
gPowerHal_1_1 = android::hardware::power::V1_1::IPower::castFrom(gPowerHalV1_0);
if (gPowerHal_1_1 == nullptr) {
// Trying to get 1.1, this will succeed only for devices supporting 1.1
powerHal_1_1 = getPowerHalV1_1();
if (powerHal_1_1 == nullptr) {
//This device does not support IPower@1.1, exiting gracefully
return 0;
}
}
Return<void> ret = gPowerHal_1_1->getSubsystemLowPowerStats(
Return<void> ret = powerHal_1_1->getSubsystemLowPowerStats(
[&offset, &remaining, &total_added](hidl_vec<PowerStateSubsystem> subsystems,
Status status) {
@@ -452,9 +438,7 @@ static jint getSubsystemLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject
}
);
if (!ret.isOk()) {
ALOGE("getSubsystemLowPowerStats() failed: power HAL service not available");
gPowerHalV1_0 = nullptr;
if (!processPowerHalReturn(ret, "getSubsystemLowPowerStats")) {
return -1;
}
}

View File

@@ -41,10 +41,11 @@
using android::hardware::Return;
using android::hardware::Void;
using android::hardware::power::V1_1::IPower;
using android::hardware::power::V1_0::PowerHint;
using android::hardware::power::V1_0::Feature;
using android::String8;
using IPowerV1_1 = android::hardware::power::V1_1::IPower;
using IPowerV1_0 = android::hardware::power::V1_0::IPower;
namespace android {
@@ -57,10 +58,11 @@ static struct {
// ----------------------------------------------------------------------------
static jobject gPowerManagerServiceObj;
sp<android::hardware::power::V1_0::IPower> gPowerHalV1_0 = nullptr;
sp<android::hardware::power::V1_1::IPower> gPowerHalV1_1 = nullptr;
bool gPowerHalExists = true;
std::mutex gPowerHalMutex;
// Use getPowerHal* to retrieve a copy
static sp<IPowerV1_0> gPowerHalV1_0_ = nullptr;
static sp<IPowerV1_1> gPowerHalV1_1_ = nullptr;
static bool gPowerHalExists = true;
static std::mutex gPowerHalMutex;
static nsecs_t gLastEventTime[USER_ACTIVITY_EVENT_LAST + 1];
// Throttling interval for user activity calls.
@@ -80,26 +82,63 @@ static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodNa
// Check validity of current handle to the power HAL service, and call getService() if necessary.
// The caller must be holding gPowerHalMutex.
bool getPowerHal() {
if (gPowerHalExists && gPowerHalV1_0 == nullptr) {
gPowerHalV1_0 = android::hardware::power::V1_0::IPower::getService();
if (gPowerHalV1_0 != nullptr) {
gPowerHalV1_1 = android::hardware::power::V1_1::IPower::castFrom(gPowerHalV1_0);
ALOGI("Loaded power HAL service");
static void connectPowerHalLocked() {
if (gPowerHalExists && gPowerHalV1_0_ == nullptr) {
gPowerHalV1_0_ = IPowerV1_0::getService();
if (gPowerHalV1_0_ != nullptr) {
ALOGI("Loaded power HAL 1.0 service");
// Try cast to powerHAL V1_1
gPowerHalV1_1_ = IPowerV1_1::castFrom(gPowerHalV1_0_);
if (gPowerHalV1_1_ == nullptr) {
} else {
ALOGI("Loaded power HAL 1.1 service");
}
} else {
ALOGI("Couldn't load power HAL service");
gPowerHalExists = false;
}
}
return gPowerHalV1_0 != nullptr;
}
// Retrieve a copy of PowerHAL V1_0
sp<IPowerV1_0> getPowerHalV1_0() {
std::lock_guard<std::mutex> lock(gPowerHalMutex);
connectPowerHalLocked();
return gPowerHalV1_0_;
}
// Retrieve a copy of PowerHAL V1_1
sp<IPowerV1_1> getPowerHalV1_1() {
std::lock_guard<std::mutex> lock(gPowerHalMutex);
connectPowerHalLocked();
return gPowerHalV1_1_;
}
// Check if a call to a power HAL function failed; if so, log the failure and invalidate the
// current handle to the power HAL service. The caller must be holding gPowerHalMutex.
static void processReturn(const Return<void> &ret, const char* functionName) {
// current handle to the power HAL service.
bool processPowerHalReturn(const Return<void> &ret, const char* functionName) {
if (!ret.isOk()) {
ALOGE("%s() failed: power HAL service not available.", functionName);
gPowerHalV1_0 = nullptr;
gPowerHalMutex.lock();
gPowerHalV1_0_ = nullptr;
gPowerHalV1_1_ = nullptr;
gPowerHalMutex.unlock();
}
return ret.isOk();
}
static void sendPowerHint(PowerHint hintId, uint32_t data) {
sp<IPowerV1_1> powerHalV1_1 = getPowerHalV1_1();
Return<void> ret;
if (powerHalV1_1 != nullptr) {
ret = powerHalV1_1->powerHintAsync(hintId, data);
processPowerHalReturn(ret, "powerHintAsync");
} else {
sp<IPowerV1_0> powerHalV1_0 = getPowerHalV1_0();
if (powerHalV1_0 != nullptr) {
ret = powerHalV1_0->powerHint(hintId, data);
processPowerHalReturn(ret, "powerHint");
}
}
}
@@ -119,20 +158,8 @@ void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t
}
gLastEventTime[eventType] = eventTime;
// Tell the power HAL when user activity occurs.
gPowerHalMutex.lock();
if (getPowerHal()) {
Return<void> ret;
if (gPowerHalV1_1 != nullptr) {
ret = gPowerHalV1_1->powerHintAsync(PowerHint::INTERACTION, 0);
} else {
ret = gPowerHalV1_0->powerHint(PowerHint::INTERACTION, 0);
}
processReturn(ret, "powerHint");
}
gPowerHalMutex.unlock();
sendPowerHint(PowerHint::INTERACTION, 0);
}
JNIEnv* env = AndroidRuntime::getJNIEnv();
@@ -150,7 +177,7 @@ static void nativeInit(JNIEnv* env, jobject obj) {
gPowerManagerServiceObj = env->NewGlobalRef(obj);
gPowerHalMutex.lock();
getPowerHal();
connectPowerHalLocked();
gPowerHalMutex.unlock();
}
@@ -165,11 +192,11 @@ static void nativeReleaseSuspendBlocker(JNIEnv *env, jclass /* clazz */, jstring
}
static void nativeSetInteractive(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
std::lock_guard<std::mutex> lock(gPowerHalMutex);
if (getPowerHal()) {
sp<IPowerV1_0> powerHalV1_0 = getPowerHalV1_0();
if (powerHalV1_0 != nullptr) {
android::base::Timer t;
Return<void> ret = gPowerHalV1_0->setInteractive(enable);
processReturn(ret, "setInteractive");
Return<void> ret = powerHalV1_0->setInteractive(enable);
processPowerHalReturn(ret, "setInteractive");
if (t.duration() > 20ms) {
ALOGD("Excessive delay in setInteractive(%s) while turning screen %s",
enable ? "true" : "false", enable ? "on" : "off");
@@ -193,24 +220,15 @@ static void nativeSetAutoSuspend(JNIEnv* /* env */, jclass /* clazz */, jboolean
}
}
static void nativeSendPowerHint(JNIEnv *env, jclass clazz, jint hintId, jint data) {
std::lock_guard<std::mutex> lock(gPowerHalMutex);
if (getPowerHal()) {
Return<void> ret;
if (gPowerHalV1_1 != nullptr) {
ret = gPowerHalV1_1->powerHintAsync((PowerHint)hintId, data);
} else {
ret = gPowerHalV1_0->powerHint((PowerHint)hintId, data);
}
processReturn(ret, "powerHint");
}
static void nativeSendPowerHint(JNIEnv* /* env */, jclass /* clazz */, jint hintId, jint data) {
sendPowerHint(static_cast<PowerHint>(hintId), data);
}
static void nativeSetFeature(JNIEnv *env, jclass clazz, jint featureId, jint data) {
std::lock_guard<std::mutex> lock(gPowerHalMutex);
if (getPowerHal()) {
Return<void> ret = gPowerHalV1_0->setFeature((Feature)featureId, static_cast<bool>(data));
processReturn(ret, "setFeature");
static void nativeSetFeature(JNIEnv* /* env */, jclass /* clazz */, jint featureId, jint data) {
sp<IPowerV1_0> powerHalV1_0 = getPowerHalV1_0();
if (powerHalV1_0 != nullptr) {
Return<void> ret = powerHalV1_0->setFeature((Feature)featureId, static_cast<bool>(data));
processPowerHalReturn(ret, "setFeature");
}
}