Merge "Support PowerHAL AIDL service" into rvc-dev

This commit is contained in:
Jia-yi Chen
2020-03-07 06:27:22 +00:00
committed by Android (Google) Code Review
7 changed files with 438 additions and 65 deletions

View File

@@ -38,6 +38,8 @@ interface IPowerManager
void releaseWakeLock(IBinder lock, int flags); void releaseWakeLock(IBinder lock, int flags);
void updateWakeLockUids(IBinder lock, in int[] uids); void updateWakeLockUids(IBinder lock, in int[] uids);
oneway void powerHint(int hintId, int data); oneway void powerHint(int hintId, int data);
oneway void setPowerBoost(int boost, int durationMs);
oneway void setPowerMode(int mode, boolean enabled);
void updateWakeLockWorkSource(IBinder lock, in WorkSource ws, String historyTag); void updateWakeLockWorkSource(IBinder lock, in WorkSource ws, String historyTag);
boolean isWakeLockLevelSupported(int level); boolean isWakeLockLevelSupported(int level);

View File

@@ -201,6 +201,119 @@ public abstract class PowerManagerInternal {
*/ */
public abstract void powerHint(int hintId, int data); public abstract void powerHint(int hintId, int data);
/**
* Boost: It is sent when user interacting with the device, for example,
* touchscreen events are incoming.
* Defined in hardware/interfaces/power/aidl/android/hardware/power/Boost.aidl
*/
public static final int BOOST_INTERACTION = 0;
/**
* Boost: It indicates that the framework is likely to provide a new display
* frame soon. This implies that the device should ensure that the display
* processing path is powered up and ready to receive that update.
* Defined in hardware/interfaces/power/aidl/android/hardware/power/Boost.aidl
*/
public static final int BOOST_DISPLAY_UPDATE_IMMINENT = 1;
/**
* SetPowerBoost() indicates the device may need to boost some resources, as
* the load is likely to increase before the kernel governors can react.
* Depending on the boost, it may be appropriate to raise the frequencies of
* CPU, GPU, memory subsystem, or stop CPU from going into deep sleep state.
*
* @param boost Boost which is to be set with a timeout.
* @param durationMs The expected duration of the user's interaction, if
* known, or 0 if the expected duration is unknown.
* a negative value indicates canceling previous boost.
* A given platform can choose to boost some time based on durationMs,
* and may also pick an appropriate timeout for 0 case.
*/
public abstract void setPowerBoost(int boost, int durationMs);
/**
* Mode: It indicates that the device is to allow wake up when the screen
* is tapped twice.
* Defined in hardware/interfaces/power/aidl/android/hardware/power/Mode.aidl
*/
public static final int MODE_DOUBLE_TAP_TO_WAKE = 0;
/**
* Mode: It indicates Low power mode is activated or not. Low power mode
* is intended to save battery at the cost of performance.
* Defined in hardware/interfaces/power/aidl/android/hardware/power/Mode.aidl
*/
public static final int MODE_LOW_POWER = 1;
/**
* Mode: It indicates Sustained Performance mode is activated or not.
* Sustained performance mode is intended to provide a consistent level of
* performance for a prolonged amount of time.
* Defined in hardware/interfaces/power/aidl/android/hardware/power/Mode.aidl
*/
public static final int MODE_SUSTAINED_PERFORMANCE = 2;
/**
* Mode: It sets the device to a fixed performance level which can be sustained
* under normal indoor conditions for at least 10 minutes.
* Fixed performance mode puts both upper and lower bounds on performance such
* that any workload run while in a fixed performance mode should complete in
* a repeatable amount of time.
* Defined in hardware/interfaces/power/aidl/android/hardware/power/Mode.aidl
*/
public static final int MODE_FIXED_PERFORMANCE = 3;
/**
* Mode: It indicates VR Mode is activated or not. VR mode is intended to
* provide minimum guarantee for performance for the amount of time the device
* can sustain it.
* Defined in hardware/interfaces/power/aidl/android/hardware/power/Mode.aidl
*/
public static final int MODE_VR = 4;
/**
* Mode: It indicates that an application has been launched.
* Defined in hardware/interfaces/power/aidl/android/hardware/power/Mode.aidl
*/
public static final int MODE_LAUNCH = 5;
/**
* Mode: It indicates that the device is about to enter a period of expensive
* rendering.
* Defined in hardware/interfaces/power/aidl/android/hardware/power/Mode.aidl
*/
public static final int MODE_EXPENSIVE_RENDERING = 6;
/**
* Mode: It indicates that the device is about entering/leaving interactive
* state or on-interactive state.
* Defined in hardware/interfaces/power/aidl/android/hardware/power/Mode.aidl
*/
public static final int MODE_INTERACTIVE = 7;
/**
* Mode: It indicates the device is in device idle, externally known as doze.
* Defined in hardware/interfaces/power/aidl/android/hardware/power/Mode.aidl
*/
public static final int MODE_DEVICE_IDLE = 8;
/**
* Mode: It indicates that display is either off or still on but is optimized
* for low power.
* Defined in hardware/interfaces/power/aidl/android/hardware/power/Mode.aidl
*/
public static final int MODE_DISPLAY_INACTIVE = 9;
/**
* SetPowerMode() is called to enable/disable specific hint mode, which
* may result in adjustment of power/performance parameters of the
* cpufreq governor and other controls on device side.
*
* @param mode Mode which is to be enable/disable.
* @param enabled true to enable, false to disable the mode.
*/
public abstract void setPowerMode(int mode, boolean enabled);
/** Returns whether there hasn't been a user activity event for the given number of ms. */ /** Returns whether there hasn't been a user activity event for the given number of ms. */
public abstract boolean wasDeviceIdleFor(long ms); public abstract boolean wasDeviceIdleFor(long ms);

View File

@@ -94,6 +94,7 @@ java_library_static {
"services-stubs", "services-stubs",
"services.net", "services.net",
"android.hardware.light-V2.0-java", "android.hardware.light-V2.0-java",
"android.hardware.power-java",
"android.hardware.power-V1.0-java", "android.hardware.power-V1.0-java",
"android.hardware.tv.cec-V1.0-java", "android.hardware.tv.cec-V1.0-java",
"android.hardware.vibrator-java", "android.hardware.vibrator-java",

View File

@@ -42,6 +42,8 @@ import android.hardware.SystemSensorManager;
import android.hardware.display.AmbientDisplayConfiguration; import android.hardware.display.AmbientDisplayConfiguration;
import android.hardware.display.DisplayManagerInternal; import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest; import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
import android.hardware.power.Boost;
import android.hardware.power.Mode;
import android.hardware.power.V1_0.PowerHint; import android.hardware.power.V1_0.PowerHint;
import android.net.Uri; import android.net.Uri;
import android.os.BatteryManager; import android.os.BatteryManager;
@@ -732,6 +734,16 @@ public final class PowerManagerService extends SystemService
PowerManagerService.nativeSendPowerHint(hintId, data); PowerManagerService.nativeSendPowerHint(hintId, data);
} }
/** Wrapper for PowerManager.nativeSetPowerBoost */
public void nativeSetPowerBoost(int boost, int durationMs) {
PowerManagerService.nativeSetPowerBoost(boost, durationMs);
}
/** Wrapper for PowerManager.nativeSetPowerMode */
public void nativeSetPowerMode(int mode, boolean enabled) {
PowerManagerService.nativeSetPowerMode(mode, enabled);
}
/** Wrapper for PowerManager.nativeSetFeature */ /** Wrapper for PowerManager.nativeSetFeature */
public void nativeSetFeature(int featureId, int data) { public void nativeSetFeature(int featureId, int data) {
PowerManagerService.nativeSetFeature(featureId, data); PowerManagerService.nativeSetFeature(featureId, data);
@@ -817,6 +829,8 @@ public final class PowerManagerService extends SystemService
private static native void nativeSetInteractive(boolean enable); private static native void nativeSetInteractive(boolean enable);
private static native void nativeSetAutoSuspend(boolean enable); private static native void nativeSetAutoSuspend(boolean enable);
private static native void nativeSendPowerHint(int hintId, int data); private static native void nativeSendPowerHint(int hintId, int data);
private static native void nativeSetPowerBoost(int boost, int durationMs);
private static native void nativeSetPowerMode(int mode, boolean enabled);
private static native void nativeSetFeature(int featureId, int data); private static native void nativeSetFeature(int featureId, int data);
private static native boolean nativeForceSuspend(); private static native boolean nativeForceSuspend();
@@ -3608,6 +3622,16 @@ public final class PowerManagerService extends SystemService
mNativeWrapper.nativeSendPowerHint(hintId, data); mNativeWrapper.nativeSendPowerHint(hintId, data);
} }
private void setPowerBoostInternal(int boost, int durationMs) {
// Maybe filter the event.
mNativeWrapper.nativeSetPowerBoost(boost, durationMs);
}
private void setPowerModeInternal(int mode, boolean enabled) {
// Maybe filter the event.
mNativeWrapper.nativeSetPowerMode(mode, enabled);
}
@VisibleForTesting @VisibleForTesting
boolean wasDeviceIdleForInternal(long ms) { boolean wasDeviceIdleForInternal(long ms) {
synchronized (mLock) { synchronized (mLock) {
@@ -4663,6 +4687,26 @@ public final class PowerManagerService extends SystemService
powerHintInternal(hintId, data); powerHintInternal(hintId, data);
} }
@Override // Binder call
public void setPowerBoost(int boost, int durationMs) {
if (!mSystemReady) {
// Service not ready yet, so who the heck cares about power hints, bah.
return;
}
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
setPowerBoostInternal(boost, durationMs);
}
@Override // Binder call
public void setPowerMode(int mode, boolean enabled) {
if (!mSystemReady) {
// Service not ready yet, so who the heck cares about power hints, bah.
return;
}
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
setPowerModeInternal(mode, enabled);
}
@Override // Binder call @Override // Binder call
public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName, public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName,
WorkSource ws, String historyTag) { WorkSource ws, String historyTag) {
@@ -5456,6 +5500,15 @@ public final class PowerManagerService extends SystemService
powerHintInternal(hintId, data); powerHintInternal(hintId, data);
} }
@Override
public void setPowerBoost(int boost, int durationMs) {
setPowerBoostInternal(boost, durationMs);
}
@Override
public void setPowerMode(int mode, boolean enabled) {
setPowerModeInternal(mode, enabled);
}
@Override @Override
public boolean wasDeviceIdleFor(long ms) { public boolean wasDeviceIdleFor(long ms) {
return wasDeviceIdleForInternal(ms); return wasDeviceIdleForInternal(ms);

View File

@@ -146,6 +146,7 @@ cc_defaults {
"android.hardware.light@2.0", "android.hardware.light@2.0",
"android.hardware.power@1.0", "android.hardware.power@1.0",
"android.hardware.power@1.1", "android.hardware.power@1.1",
"android.hardware.power-cpp",
"android.hardware.power.stats@1.0", "android.hardware.power.stats@1.0",
"android.hardware.thermal@1.0", "android.hardware.thermal@1.0",
"android.hardware.tv.cec@1.0", "android.hardware.tv.cec@1.0",

View File

@@ -67,9 +67,9 @@ namespace android
static bool wakeup_init = false; static bool wakeup_init = false;
static sem_t wakeup_sem; static sem_t wakeup_sem;
extern sp<IPowerV1_0> getPowerHalV1_0(); extern sp<IPowerV1_0> getPowerHalHidlV1_0();
extern sp<IPowerV1_1> getPowerHalV1_1(); extern sp<IPowerV1_1> getPowerHalHidlV1_1();
extern bool processPowerHalReturn(const Return<void> &ret, const char* functionName); extern bool processPowerHalReturn(bool isOk, const char* functionName);
extern sp<ISuspendControlService> getSuspendControl(); extern sp<ISuspendControlService> getSuspendControl();
// Java methods used in getLowPowerStats // Java methods used in getLowPowerStats
@@ -596,7 +596,7 @@ static void getPowerStatsHalRailEnergyData(JNIEnv* env, jobject jrailStats) {
// The caller must be holding powerHalMutex. // The caller must be holding powerHalMutex.
static void getPowerHalLowPowerData(JNIEnv* env, jobject jrpmStats) { static void getPowerHalLowPowerData(JNIEnv* env, jobject jrpmStats) {
sp<IPowerV1_0> powerHalV1_0 = getPowerHalV1_0(); sp<IPowerV1_0> powerHalV1_0 = getPowerHalHidlV1_0();
if (powerHalV1_0 == nullptr) { if (powerHalV1_0 == nullptr) {
ALOGE("Power Hal not loaded"); ALOGE("Power Hal not loaded");
return; return;
@@ -629,12 +629,12 @@ static void getPowerHalLowPowerData(JNIEnv* env, jobject jrpmStats) {
} }
} }
}); });
if (!processPowerHalReturn(ret, "getPlatformLowPowerStats")) { if (!processPowerHalReturn(ret.isOk(), "getPlatformLowPowerStats")) {
return; return;
} }
// Trying to get IPower 1.1, this will succeed only for devices supporting 1.1 // Trying to get IPower 1.1, this will succeed only for devices supporting 1.1
sp<IPowerV1_1> powerHal_1_1 = getPowerHalV1_1(); sp<IPowerV1_1> powerHal_1_1 = getPowerHalHidlV1_1();
if (powerHal_1_1 == nullptr) { if (powerHal_1_1 == nullptr) {
// This device does not support IPower@1.1, exiting gracefully // This device does not support IPower@1.1, exiting gracefully
return; return;
@@ -665,7 +665,7 @@ static void getPowerHalLowPowerData(JNIEnv* env, jobject jrpmStats) {
} }
} }
}); });
processPowerHalReturn(ret, "getSubsystemLowPowerStats"); processPowerHalReturn(ret.isOk(), "getSubsystemLowPowerStats");
} }
static jint getPowerHalPlatformData(JNIEnv* env, jobject outBuf) { static jint getPowerHalPlatformData(JNIEnv* env, jobject outBuf) {
@@ -675,7 +675,7 @@ static jint getPowerHalPlatformData(JNIEnv* env, jobject outBuf) {
int total_added = -1; int total_added = -1;
{ {
sp<IPowerV1_0> powerHalV1_0 = getPowerHalV1_0(); sp<IPowerV1_0> powerHalV1_0 = getPowerHalHidlV1_0();
if (powerHalV1_0 == nullptr) { if (powerHalV1_0 == nullptr) {
ALOGE("Power Hal not loaded"); ALOGE("Power Hal not loaded");
return -1; return -1;
@@ -733,7 +733,7 @@ static jint getPowerHalPlatformData(JNIEnv* env, jobject outBuf) {
} }
); );
if (!processPowerHalReturn(ret, "getPlatformLowPowerStats")) { if (!processPowerHalReturn(ret.isOk(), "getPlatformLowPowerStats")) {
return -1; return -1;
} }
} }
@@ -753,7 +753,7 @@ static jint getPowerHalSubsystemData(JNIEnv* env, jobject outBuf) {
{ {
// Trying to get 1.1, this will succeed only for devices supporting 1.1 // Trying to get 1.1, this will succeed only for devices supporting 1.1
powerHal_1_1 = getPowerHalV1_1(); powerHal_1_1 = getPowerHalHidlV1_1();
if (powerHal_1_1 == nullptr) { if (powerHal_1_1 == nullptr) {
//This device does not support IPower@1.1, exiting gracefully //This device does not support IPower@1.1, exiting gracefully
return 0; return 0;
@@ -820,7 +820,7 @@ static jint getPowerHalSubsystemData(JNIEnv* env, jobject outBuf) {
} }
); );
if (!processPowerHalReturn(ret, "getSubsystemLowPowerStats")) { if (!processPowerHalReturn(ret.isOk(), "getSubsystemLowPowerStats")) {
return -1; return -1;
} }
} }

View File

@@ -19,6 +19,9 @@
//#define LOG_NDEBUG 0 //#define LOG_NDEBUG 0
#include <android/hardware/power/1.1/IPower.h> #include <android/hardware/power/1.1/IPower.h>
#include <android/hardware/power/Boost.h>
#include <android/hardware/power/IPower.h>
#include <android/hardware/power/Mode.h>
#include <android/system/suspend/1.0/ISystemSuspend.h> #include <android/system/suspend/1.0/ISystemSuspend.h>
#include <android/system/suspend/ISuspendControlService.h> #include <android/system/suspend/ISuspendControlService.h>
#include <nativehelper/JNIHelp.h> #include <nativehelper/JNIHelp.h>
@@ -45,6 +48,8 @@
using android::hardware::Return; using android::hardware::Return;
using android::hardware::Void; using android::hardware::Void;
using android::hardware::power::Boost;
using android::hardware::power::Mode;
using android::hardware::power::V1_0::PowerHint; using android::hardware::power::V1_0::PowerHint;
using android::hardware::power::V1_0::Feature; using android::hardware::power::V1_0::Feature;
using android::String8; using android::String8;
@@ -54,6 +59,7 @@ using android::system::suspend::V1_0::WakeLockType;
using android::system::suspend::ISuspendControlService; using android::system::suspend::ISuspendControlService;
using IPowerV1_1 = android::hardware::power::V1_1::IPower; using IPowerV1_1 = android::hardware::power::V1_1::IPower;
using IPowerV1_0 = android::hardware::power::V1_0::IPower; using IPowerV1_0 = android::hardware::power::V1_0::IPower;
using IPowerAidl = android::hardware::power::IPower;
namespace android { namespace android {
@@ -66,11 +72,18 @@ static struct {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
static jobject gPowerManagerServiceObj; static jobject gPowerManagerServiceObj;
// Use getPowerHal* to retrieve a copy static sp<IPowerV1_0> gPowerHalHidlV1_0_ = nullptr;
static sp<IPowerV1_0> gPowerHalV1_0_ = nullptr; static sp<IPowerV1_1> gPowerHalHidlV1_1_ = nullptr;
static sp<IPowerV1_1> gPowerHalV1_1_ = nullptr; static sp<IPowerAidl> gPowerHalAidl_ = nullptr;
static bool gPowerHalExists = true;
static std::mutex gPowerHalMutex; static std::mutex gPowerHalMutex;
enum class HalVersion {
NONE,
HIDL_1_0,
HIDL_1_1,
AIDL,
};
static nsecs_t gLastEventTime[USER_ACTIVITY_EVENT_LAST + 1]; static nsecs_t gLastEventTime[USER_ACTIVITY_EVENT_LAST + 1];
// Throttling interval for user activity calls. // Throttling interval for user activity calls.
@@ -88,68 +101,207 @@ static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodNa
return false; return false;
} }
// Check validity of current handle to the power HAL service, and call getService() if necessary. // Check validity of current handle to the power HAL service, and connect to it if necessary.
// The caller must be holding gPowerHalMutex. // The caller must be holding gPowerHalMutex.
static void connectPowerHalLocked() { static HalVersion connectPowerHalLocked() {
if (gPowerHalExists && gPowerHalV1_0_ == nullptr) { static bool gPowerHalHidlExists = true;
gPowerHalV1_0_ = IPowerV1_0::getService(); static bool gPowerHalAidlExists = true;
if (gPowerHalV1_0_ != nullptr) { if (!gPowerHalHidlExists && !gPowerHalAidlExists) {
ALOGI("Loaded power HAL 1.0 service"); return HalVersion::NONE;
// Try cast to powerHAL V1_1 }
gPowerHalV1_1_ = IPowerV1_1::castFrom(gPowerHalV1_0_); if (gPowerHalAidlExists) {
if (gPowerHalV1_1_ == nullptr) { if (!gPowerHalAidl_) {
gPowerHalAidl_ = waitForVintfService<IPowerAidl>();
}
if (gPowerHalAidl_) {
ALOGI("Successfully connected to Power HAL AIDL service.");
return HalVersion::AIDL;
} else { } else {
ALOGI("Loaded power HAL 1.1 service"); gPowerHalAidlExists = false;
}
}
if (gPowerHalHidlExists && gPowerHalHidlV1_0_ == nullptr) {
gPowerHalHidlV1_0_ = IPowerV1_0::getService();
if (gPowerHalHidlV1_0_) {
ALOGI("Successfully connected to Power HAL HIDL 1.0 service.");
// Try cast to powerHAL HIDL V1_1
gPowerHalHidlV1_1_ = IPowerV1_1::castFrom(gPowerHalHidlV1_0_);
if (gPowerHalHidlV1_1_) {
ALOGI("Successfully connected to Power HAL HIDL 1.1 service.");
} }
} else { } else {
ALOGI("Couldn't load power HAL service"); ALOGI("Couldn't load power HAL HIDL service");
gPowerHalExists = false; gPowerHalHidlExists = false;
return HalVersion::NONE;
} }
} }
if (gPowerHalHidlV1_1_) {
return HalVersion::HIDL_1_1;
} else if (gPowerHalHidlV1_0_) {
return HalVersion::HIDL_1_0;
}
return HalVersion::NONE;
} }
// Retrieve a copy of PowerHAL V1_0 // Retrieve a copy of PowerHAL HIDL V1_0
sp<IPowerV1_0> getPowerHalV1_0() { sp<IPowerV1_0> getPowerHalHidlV1_0() {
std::lock_guard<std::mutex> lock(gPowerHalMutex); std::lock_guard<std::mutex> lock(gPowerHalMutex);
connectPowerHalLocked(); HalVersion halVersion = connectPowerHalLocked();
return gPowerHalV1_0_; if (halVersion == HalVersion::HIDL_1_0 || halVersion == HalVersion::HIDL_1_1) {
return gPowerHalHidlV1_0_;
}
return nullptr;
} }
// Retrieve a copy of PowerHAL V1_1 // Retrieve a copy of PowerHAL HIDL V1_1
sp<IPowerV1_1> getPowerHalV1_1() { sp<IPowerV1_1> getPowerHalHidlV1_1() {
std::lock_guard<std::mutex> lock(gPowerHalMutex); std::lock_guard<std::mutex> lock(gPowerHalMutex);
connectPowerHalLocked(); if (connectPowerHalLocked() == HalVersion::HIDL_1_1) {
return gPowerHalV1_1_; return gPowerHalHidlV1_1_;
}
return nullptr;
} }
// Check if a call to a power HAL function failed; if so, log the failure and invalidate the // 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. // current handle to the power HAL service.
bool processPowerHalReturn(const Return<void> &ret, const char* functionName) { bool processPowerHalReturn(bool isOk, const char* functionName) {
if (!ret.isOk()) { if (!isOk) {
ALOGE("%s() failed: power HAL service not available.", functionName); ALOGE("%s() failed: power HAL service not available.", functionName);
gPowerHalMutex.lock(); gPowerHalMutex.lock();
gPowerHalV1_0_ = nullptr; gPowerHalHidlV1_0_ = nullptr;
gPowerHalV1_1_ = nullptr; gPowerHalHidlV1_1_ = nullptr;
gPowerHalAidl_ = nullptr;
gPowerHalMutex.unlock(); gPowerHalMutex.unlock();
} }
return ret.isOk(); return isOk;
} }
static void sendPowerHint(PowerHint hintId, uint32_t data) { static void sendPowerHint(PowerHint hintId, uint32_t data) {
sp<IPowerV1_1> powerHalV1_1 = getPowerHalV1_1(); std::unique_lock<std::mutex> lock(gPowerHalMutex);
Return<void> ret; switch (connectPowerHalLocked()) {
if (powerHalV1_1 != nullptr) { case HalVersion::NONE:
ret = powerHalV1_1->powerHintAsync(hintId, data); return;
processPowerHalReturn(ret, "powerHintAsync"); case HalVersion::HIDL_1_0: {
sp<IPowerV1_0> handle = gPowerHalHidlV1_0_;
lock.unlock();
auto ret = handle->powerHint(hintId, data);
processPowerHalReturn(ret.isOk(), "powerHint");
break;
}
case HalVersion::HIDL_1_1: {
sp<IPowerV1_1> handle = gPowerHalHidlV1_1_;
lock.unlock();
auto ret = handle->powerHintAsync(hintId, data);
processPowerHalReturn(ret.isOk(), "powerHintAsync");
break;
}
case HalVersion::AIDL: {
if (hintId == PowerHint::INTERACTION) {
sp<IPowerAidl> handle = gPowerHalAidl_;
lock.unlock();
auto ret = handle->setBoost(Boost::INTERACTION, data);
processPowerHalReturn(ret.isOk(), "setBoost");
break;
} else if (hintId == PowerHint::LAUNCH) {
sp<IPowerAidl> handle = gPowerHalAidl_;
lock.unlock();
auto ret = handle->setMode(Mode::LAUNCH, static_cast<bool>(data));
processPowerHalReturn(ret.isOk(), "setMode");
break;
} else { } else {
sp<IPowerV1_0> powerHalV1_0 = getPowerHalV1_0(); ALOGE("Unsupported power hint: %s.", toString(hintId).c_str());
if (powerHalV1_0 != nullptr) { return;
ret = powerHalV1_0->powerHint(hintId, data); }
processPowerHalReturn(ret, "powerHint"); }
default: {
ALOGE("Unknown power HAL state");
return;
}
}
SurfaceComposerClient::notifyPowerHint(static_cast<int32_t>(hintId));
}
enum class HalSupport {
UNKNOWN = 0,
ON,
OFF,
};
static void setPowerBoost(Boost boost, int32_t durationMs) {
// Android framework only sends boost upto DISPLAY_UPDATE_IMMINENT.
// Need to increase the array size if more boost supported.
static std::array<std::atomic<HalSupport>,
static_cast<int32_t>(Boost::DISPLAY_UPDATE_IMMINENT) + 1>
boostSupportedArray = {HalSupport::UNKNOWN};
// Quick return if boost is not supported by HAL
if (boost > Boost::DISPLAY_UPDATE_IMMINENT ||
boostSupportedArray[static_cast<int32_t>(boost)] == HalSupport::OFF) {
ALOGV("Skipped setPowerBoost %s because HAL doesn't support it", toString(boost).c_str());
return;
}
std::unique_lock<std::mutex> lock(gPowerHalMutex);
if (connectPowerHalLocked() != HalVersion::AIDL) {
ALOGV("Power HAL AIDL not available");
return;
}
sp<IPowerAidl> handle = gPowerHalAidl_;
lock.unlock();
if (boostSupportedArray[static_cast<int32_t>(boost)] == HalSupport::UNKNOWN) {
bool isSupported = false;
handle->isBoostSupported(boost, &isSupported);
boostSupportedArray[static_cast<int32_t>(boost)] =
isSupported ? HalSupport::ON : HalSupport::OFF;
if (!isSupported) {
ALOGV("Skipped setPowerBoost %s because HAL doesn't support it",
toString(boost).c_str());
return;
} }
} }
SurfaceComposerClient::notifyPowerHint(static_cast<int32_t>(hintId)); auto ret = handle->setBoost(boost, durationMs);
processPowerHalReturn(ret.isOk(), "setPowerBoost");
}
static void setPowerMode(Mode mode, bool enabled) {
// Android framework only sends mode upto DISPLAY_INACTIVE.
// Need to increase the array if more mode supported.
static std::array<std::atomic<HalSupport>,
static_cast<int32_t>(Mode::DISPLAY_INACTIVE) + 1>
modeSupportedArray = {HalSupport::UNKNOWN};
// Quick return if mode is not supported by HAL
if (mode > Mode::DISPLAY_INACTIVE ||
modeSupportedArray[static_cast<int32_t>(mode)] == HalSupport::OFF) {
ALOGV("Skipped setPowerMode %s because HAL doesn't support it", toString(mode).c_str());
return;
}
std::unique_lock<std::mutex> lock(gPowerHalMutex);
if (connectPowerHalLocked() != HalVersion::AIDL) {
ALOGV("Power HAL AIDL not available");
return;
}
sp<IPowerAidl> handle = gPowerHalAidl_;
lock.unlock();
if (modeSupportedArray[static_cast<int32_t>(mode)] == HalSupport::UNKNOWN) {
bool isSupported = false;
handle->isModeSupported(mode, &isSupported);
modeSupportedArray[static_cast<int32_t>(mode)] =
isSupported ? HalSupport::ON : HalSupport::OFF;
if (!isSupported) {
ALOGV("Skipped setPowerMode %s because HAL doesn't support it", toString(mode).c_str());
return;
}
}
auto ret = handle->setMode(mode, enabled);
processPowerHalReturn(ret.isOk(), "setPowerMode");
} }
void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType) { void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType) {
@@ -253,15 +405,35 @@ static void nativeReleaseSuspendBlocker(JNIEnv *env, jclass /* clazz */, jstring
} }
static void nativeSetInteractive(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) { static void nativeSetInteractive(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
sp<IPowerV1_0> powerHalV1_0 = getPowerHalV1_0(); std::unique_lock<std::mutex> lock(gPowerHalMutex);
if (powerHalV1_0 != nullptr) { switch (connectPowerHalLocked()) {
case HalVersion::NONE:
return;
case HalVersion::HIDL_1_0:
FALLTHROUGH_INTENDED;
case HalVersion::HIDL_1_1: {
android::base::Timer t; android::base::Timer t;
Return<void> ret = powerHalV1_0->setInteractive(enable); sp<IPowerV1_0> handle = gPowerHalHidlV1_0_;
processPowerHalReturn(ret, "setInteractive"); lock.unlock();
auto ret = handle->setInteractive(enable);
processPowerHalReturn(ret.isOk(), "setInteractive");
if (t.duration() > 20ms) { if (t.duration() > 20ms) {
ALOGD("Excessive delay in setInteractive(%s) while turning screen %s", ALOGD("Excessive delay in setInteractive(%s) while turning screen %s",
enable ? "true" : "false", enable ? "on" : "off"); enable ? "true" : "false", enable ? "on" : "off");
} }
return;
}
case HalVersion::AIDL: {
sp<IPowerAidl> handle = gPowerHalAidl_;
lock.unlock();
auto ret = handle->setMode(Mode::INTERACTIVE, enable);
processPowerHalReturn(ret.isOk(), "setMode");
return;
}
default: {
ALOGE("Unknown power HAL state");
return;
}
} }
} }
@@ -285,11 +457,38 @@ static void nativeSendPowerHint(JNIEnv* /* env */, jclass /* clazz */, jint hint
sendPowerHint(static_cast<PowerHint>(hintId), data); sendPowerHint(static_cast<PowerHint>(hintId), data);
} }
static void nativeSetPowerBoost(JNIEnv* /* env */, jclass /* clazz */, jint boost,
jint durationMs) {
setPowerBoost(static_cast<Boost>(boost), durationMs);
}
static void nativeSetPowerMode(JNIEnv* /* env */, jclass /* clazz */, jint mode, jboolean enabled) {
setPowerMode(static_cast<Mode>(mode), enabled);
}
static void nativeSetFeature(JNIEnv* /* env */, jclass /* clazz */, jint featureId, jint data) { static void nativeSetFeature(JNIEnv* /* env */, jclass /* clazz */, jint featureId, jint data) {
sp<IPowerV1_0> powerHalV1_0 = getPowerHalV1_0(); std::unique_lock<std::mutex> lock(gPowerHalMutex);
if (powerHalV1_0 != nullptr) { switch (connectPowerHalLocked()) {
Return<void> ret = powerHalV1_0->setFeature((Feature)featureId, static_cast<bool>(data)); case HalVersion::NONE:
processPowerHalReturn(ret, "setFeature"); return;
case HalVersion::HIDL_1_0:
FALLTHROUGH_INTENDED;
case HalVersion::HIDL_1_1: {
sp<IPowerV1_0> handle = gPowerHalHidlV1_0_;
lock.unlock();
auto ret = handle->setFeature(static_cast<Feature>(featureId), static_cast<bool>(data));
processPowerHalReturn(ret.isOk(), "setFeature");
return;
}
case HalVersion::AIDL: {
auto ret = gPowerHalAidl_->setMode(Mode::DOUBLE_TAP_TO_WAKE, static_cast<bool>(data));
processPowerHalReturn(ret.isOk(), "setMode");
return;
}
default: {
ALOGE("Unknown power HAL state");
return;
}
} }
} }
@@ -317,6 +516,10 @@ static const JNINativeMethod gPowerManagerServiceMethods[] = {
(void*) nativeSetAutoSuspend }, (void*) nativeSetAutoSuspend },
{ "nativeSendPowerHint", "(II)V", { "nativeSendPowerHint", "(II)V",
(void*) nativeSendPowerHint }, (void*) nativeSendPowerHint },
{ "nativeSetPowerBoost", "(II)V",
(void*) nativeSetPowerBoost },
{ "nativeSetPowerMode", "(IZ)V",
(void*) nativeSetPowerMode },
{ "nativeSetFeature", "(II)V", { "nativeSetFeature", "(II)V",
(void*) nativeSetFeature }, (void*) nativeSetFeature },
}; };