diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl index 1cefbd9afa80b..c44a0bd11cf72 100644 --- a/core/java/android/os/IPowerManager.aidl +++ b/core/java/android/os/IPowerManager.aidl @@ -38,6 +38,8 @@ interface IPowerManager void releaseWakeLock(IBinder lock, int flags); void updateWakeLockUids(IBinder lock, in int[] uids); 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); boolean isWakeLockLevelSupported(int level); diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java index 9661a08464dd9..51f01cac81388 100644 --- a/core/java/android/os/PowerManagerInternal.java +++ b/core/java/android/os/PowerManagerInternal.java @@ -201,6 +201,119 @@ public abstract class PowerManagerInternal { */ 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. */ public abstract boolean wasDeviceIdleFor(long ms); diff --git a/services/core/Android.bp b/services/core/Android.bp index 4da60b8e4ffd2..f2cb3c250346e 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -94,6 +94,7 @@ java_library_static { "services-stubs", "services.net", "android.hardware.light-V2.0-java", + "android.hardware.power-java", "android.hardware.power-V1.0-java", "android.hardware.tv.cec-V1.0-java", "android.hardware.vibrator-java", diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 8483c774cb8e2..69615cbe4fef9 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -42,6 +42,8 @@ import android.hardware.SystemSensorManager; import android.hardware.display.AmbientDisplayConfiguration; import android.hardware.display.DisplayManagerInternal; 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.net.Uri; import android.os.BatteryManager; @@ -736,6 +738,16 @@ public final class PowerManagerService extends SystemService 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 */ public void nativeSetFeature(int featureId, int data) { PowerManagerService.nativeSetFeature(featureId, data); @@ -816,6 +828,8 @@ public final class PowerManagerService extends SystemService private static native void nativeSetInteractive(boolean enable); private static native void nativeSetAutoSuspend(boolean enable); 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 boolean nativeForceSuspend(); @@ -3625,6 +3639,16 @@ public final class PowerManagerService extends SystemService 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 boolean wasDeviceIdleForInternal(long ms) { synchronized (mLock) { @@ -4678,6 +4702,26 @@ public final class PowerManagerService extends SystemService 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 public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName, WorkSource ws, String historyTag) { @@ -5473,6 +5517,15 @@ public final class PowerManagerService extends SystemService } @Override + public void setPowerBoost(int boost, int durationMs) { + setPowerBoostInternal(boost, durationMs); + } + + @Override + public void setPowerMode(int mode, boolean enabled) { + setPowerModeInternal(mode, enabled); + } + @Override public boolean wasDeviceIdleFor(long ms) { return wasDeviceIdleForInternal(ms); } diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 27bd58ec30100..be6ba38a9292e 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -147,6 +147,7 @@ cc_defaults { "android.hardware.light@2.0", "android.hardware.power@1.0", "android.hardware.power@1.1", + "android.hardware.power-cpp", "android.hardware.power.stats@1.0", "android.hardware.thermal@1.0", "android.hardware.tv.cec@1.0", diff --git a/services/core/jni/com_android_server_am_BatteryStatsService.cpp b/services/core/jni/com_android_server_am_BatteryStatsService.cpp index 9cbb58d35b9f0..b08868e2c7f8c 100644 --- a/services/core/jni/com_android_server_am_BatteryStatsService.cpp +++ b/services/core/jni/com_android_server_am_BatteryStatsService.cpp @@ -67,9 +67,9 @@ namespace android static bool wakeup_init = false; static sem_t wakeup_sem; -extern sp getPowerHalV1_0(); -extern sp getPowerHalV1_1(); -extern bool processPowerHalReturn(const Return &ret, const char* functionName); +extern sp getPowerHalHidlV1_0(); +extern sp getPowerHalHidlV1_1(); +extern bool processPowerHalReturn(bool isOk, const char* functionName); extern sp getSuspendControl(); // Java methods used in getLowPowerStats @@ -596,7 +596,7 @@ static void getPowerStatsHalRailEnergyData(JNIEnv* env, jobject jrailStats) { // The caller must be holding powerHalMutex. static void getPowerHalLowPowerData(JNIEnv* env, jobject jrpmStats) { - sp powerHalV1_0 = getPowerHalV1_0(); + sp powerHalV1_0 = getPowerHalHidlV1_0(); if (powerHalV1_0 == nullptr) { ALOGE("Power Hal not loaded"); return; @@ -629,12 +629,12 @@ static void getPowerHalLowPowerData(JNIEnv* env, jobject jrpmStats) { } } }); - if (!processPowerHalReturn(ret, "getPlatformLowPowerStats")) { + if (!processPowerHalReturn(ret.isOk(), "getPlatformLowPowerStats")) { return; } // Trying to get IPower 1.1, this will succeed only for devices supporting 1.1 - sp powerHal_1_1 = getPowerHalV1_1(); + sp powerHal_1_1 = getPowerHalHidlV1_1(); if (powerHal_1_1 == nullptr) { // This device does not support IPower@1.1, exiting gracefully 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) { @@ -675,7 +675,7 @@ static jint getPowerHalPlatformData(JNIEnv* env, jobject outBuf) { int total_added = -1; { - sp powerHalV1_0 = getPowerHalV1_0(); + sp powerHalV1_0 = getPowerHalHidlV1_0(); if (powerHalV1_0 == nullptr) { ALOGE("Power Hal not loaded"); return -1; @@ -733,7 +733,7 @@ static jint getPowerHalPlatformData(JNIEnv* env, jobject outBuf) { } ); - if (!processPowerHalReturn(ret, "getPlatformLowPowerStats")) { + if (!processPowerHalReturn(ret.isOk(), "getPlatformLowPowerStats")) { 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 - powerHal_1_1 = getPowerHalV1_1(); + powerHal_1_1 = getPowerHalHidlV1_1(); if (powerHal_1_1 == nullptr) { //This device does not support IPower@1.1, exiting gracefully return 0; @@ -820,7 +820,7 @@ static jint getPowerHalSubsystemData(JNIEnv* env, jobject outBuf) { } ); - if (!processPowerHalReturn(ret, "getSubsystemLowPowerStats")) { + if (!processPowerHalReturn(ret.isOk(), "getSubsystemLowPowerStats")) { return -1; } } diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp index 4e0434873944b..239a1011422c0 100644 --- a/services/core/jni/com_android_server_power_PowerManagerService.cpp +++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp @@ -19,6 +19,9 @@ //#define LOG_NDEBUG 0 #include +#include +#include +#include #include #include #include @@ -45,6 +48,8 @@ using android::hardware::Return; 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::Feature; using android::String8; @@ -54,6 +59,7 @@ using android::system::suspend::V1_0::WakeLockType; using android::system::suspend::ISuspendControlService; using IPowerV1_1 = android::hardware::power::V1_1::IPower; using IPowerV1_0 = android::hardware::power::V1_0::IPower; +using IPowerAidl = android::hardware::power::IPower; namespace android { @@ -66,11 +72,18 @@ static struct { // ---------------------------------------------------------------------------- static jobject gPowerManagerServiceObj; -// Use getPowerHal* to retrieve a copy -static sp gPowerHalV1_0_ = nullptr; -static sp gPowerHalV1_1_ = nullptr; -static bool gPowerHalExists = true; +static sp gPowerHalHidlV1_0_ = nullptr; +static sp gPowerHalHidlV1_1_ = nullptr; +static sp gPowerHalAidl_ = nullptr; static std::mutex gPowerHalMutex; + +enum class HalVersion { + NONE, + HIDL_1_0, + HIDL_1_1, + AIDL, +}; + static nsecs_t gLastEventTime[USER_ACTIVITY_EVENT_LAST + 1]; // Throttling interval for user activity calls. @@ -88,68 +101,207 @@ static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodNa 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. -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"); - } +static HalVersion connectPowerHalLocked() { + static bool gPowerHalHidlExists = true; + static bool gPowerHalAidlExists = true; + if (!gPowerHalHidlExists && !gPowerHalAidlExists) { + return HalVersion::NONE; + } + if (gPowerHalAidlExists) { + if (!gPowerHalAidl_) { + gPowerHalAidl_ = waitForVintfService(); + } + if (gPowerHalAidl_) { + ALOGI("Successfully connected to Power HAL AIDL service."); + return HalVersion::AIDL; } else { - ALOGI("Couldn't load power HAL service"); - gPowerHalExists = false; + 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 { + ALOGI("Couldn't load power HAL HIDL service"); + 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 -sp getPowerHalV1_0() { +// Retrieve a copy of PowerHAL HIDL V1_0 +sp getPowerHalHidlV1_0() { std::lock_guard lock(gPowerHalMutex); - connectPowerHalLocked(); - return gPowerHalV1_0_; + HalVersion halVersion = connectPowerHalLocked(); + if (halVersion == HalVersion::HIDL_1_0 || halVersion == HalVersion::HIDL_1_1) { + return gPowerHalHidlV1_0_; + } + + return nullptr; } -// Retrieve a copy of PowerHAL V1_1 -sp getPowerHalV1_1() { +// Retrieve a copy of PowerHAL HIDL V1_1 +sp getPowerHalHidlV1_1() { std::lock_guard lock(gPowerHalMutex); - connectPowerHalLocked(); - return gPowerHalV1_1_; + if (connectPowerHalLocked() == HalVersion::HIDL_1_1) { + return gPowerHalHidlV1_1_; + } + + return nullptr; } // 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. -bool processPowerHalReturn(const Return &ret, const char* functionName) { - if (!ret.isOk()) { +bool processPowerHalReturn(bool isOk, const char* functionName) { + if (!isOk) { ALOGE("%s() failed: power HAL service not available.", functionName); gPowerHalMutex.lock(); - gPowerHalV1_0_ = nullptr; - gPowerHalV1_1_ = nullptr; + gPowerHalHidlV1_0_ = nullptr; + gPowerHalHidlV1_1_ = nullptr; + gPowerHalAidl_ = nullptr; gPowerHalMutex.unlock(); } - return ret.isOk(); + return isOk; } static void sendPowerHint(PowerHint hintId, uint32_t data) { - sp powerHalV1_1 = getPowerHalV1_1(); - Return ret; - if (powerHalV1_1 != nullptr) { - ret = powerHalV1_1->powerHintAsync(hintId, data); - processPowerHalReturn(ret, "powerHintAsync"); - } else { - sp powerHalV1_0 = getPowerHalV1_0(); - if (powerHalV1_0 != nullptr) { - ret = powerHalV1_0->powerHint(hintId, data); - processPowerHalReturn(ret, "powerHint"); + std::unique_lock lock(gPowerHalMutex); + switch (connectPowerHalLocked()) { + case HalVersion::NONE: + return; + case HalVersion::HIDL_1_0: { + sp handle = gPowerHalHidlV1_0_; + lock.unlock(); + auto ret = handle->powerHint(hintId, data); + processPowerHalReturn(ret.isOk(), "powerHint"); + break; + } + case HalVersion::HIDL_1_1: { + sp handle = gPowerHalHidlV1_1_; + lock.unlock(); + auto ret = handle->powerHintAsync(hintId, data); + processPowerHalReturn(ret.isOk(), "powerHintAsync"); + break; + } + case HalVersion::AIDL: { + if (hintId == PowerHint::INTERACTION) { + sp handle = gPowerHalAidl_; + lock.unlock(); + auto ret = handle->setBoost(Boost::INTERACTION, data); + processPowerHalReturn(ret.isOk(), "setBoost"); + break; + } else if (hintId == PowerHint::LAUNCH) { + sp handle = gPowerHalAidl_; + lock.unlock(); + auto ret = handle->setMode(Mode::LAUNCH, static_cast(data)); + processPowerHalReturn(ret.isOk(), "setMode"); + break; + } else { + ALOGE("Unsupported power hint: %s.", toString(hintId).c_str()); + return; + } + } + default: { + ALOGE("Unknown power HAL state"); + return; + } + } + SurfaceComposerClient::notifyPowerHint(static_cast(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, + static_cast(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(boost)] == HalSupport::OFF) { + ALOGV("Skipped setPowerBoost %s because HAL doesn't support it", toString(boost).c_str()); + return; + } + + std::unique_lock lock(gPowerHalMutex); + if (connectPowerHalLocked() != HalVersion::AIDL) { + ALOGV("Power HAL AIDL not available"); + return; + } + sp handle = gPowerHalAidl_; + lock.unlock(); + + if (boostSupportedArray[static_cast(boost)] == HalSupport::UNKNOWN) { + bool isSupported = false; + handle->isBoostSupported(boost, &isSupported); + boostSupportedArray[static_cast(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(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, + static_cast(Mode::DISPLAY_INACTIVE) + 1> + modeSupportedArray = {HalSupport::UNKNOWN}; + + // Quick return if mode is not supported by HAL + if (mode > Mode::DISPLAY_INACTIVE || + modeSupportedArray[static_cast(mode)] == HalSupport::OFF) { + ALOGV("Skipped setPowerMode %s because HAL doesn't support it", toString(mode).c_str()); + return; + } + + std::unique_lock lock(gPowerHalMutex); + if (connectPowerHalLocked() != HalVersion::AIDL) { + ALOGV("Power HAL AIDL not available"); + return; + } + sp handle = gPowerHalAidl_; + lock.unlock(); + + if (modeSupportedArray[static_cast(mode)] == HalSupport::UNKNOWN) { + bool isSupported = false; + handle->isModeSupported(mode, &isSupported); + modeSupportedArray[static_cast(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) { @@ -253,14 +405,34 @@ static void nativeReleaseSuspendBlocker(JNIEnv *env, jclass /* clazz */, jstring } static void nativeSetInteractive(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) { - sp powerHalV1_0 = getPowerHalV1_0(); - if (powerHalV1_0 != nullptr) { - android::base::Timer t; - Return 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"); + std::unique_lock lock(gPowerHalMutex); + switch (connectPowerHalLocked()) { + case HalVersion::NONE: + return; + case HalVersion::HIDL_1_0: + FALLTHROUGH_INTENDED; + case HalVersion::HIDL_1_1: { + android::base::Timer t; + sp handle = gPowerHalHidlV1_0_; + lock.unlock(); + auto ret = handle->setInteractive(enable); + processPowerHalReturn(ret.isOk(), "setInteractive"); + if (t.duration() > 20ms) { + ALOGD("Excessive delay in setInteractive(%s) while turning screen %s", + enable ? "true" : "false", enable ? "on" : "off"); + } + return; + } + case HalVersion::AIDL: { + sp 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(hintId), data); } +static void nativeSetPowerBoost(JNIEnv* /* env */, jclass /* clazz */, jint boost, + jint durationMs) { + setPowerBoost(static_cast(boost), durationMs); +} + +static void nativeSetPowerMode(JNIEnv* /* env */, jclass /* clazz */, jint mode, jboolean enabled) { + setPowerMode(static_cast(mode), enabled); +} + static void nativeSetFeature(JNIEnv* /* env */, jclass /* clazz */, jint featureId, jint data) { - sp powerHalV1_0 = getPowerHalV1_0(); - if (powerHalV1_0 != nullptr) { - Return ret = powerHalV1_0->setFeature((Feature)featureId, static_cast(data)); - processPowerHalReturn(ret, "setFeature"); + std::unique_lock lock(gPowerHalMutex); + switch (connectPowerHalLocked()) { + case HalVersion::NONE: + return; + case HalVersion::HIDL_1_0: + FALLTHROUGH_INTENDED; + case HalVersion::HIDL_1_1: { + sp handle = gPowerHalHidlV1_0_; + lock.unlock(); + auto ret = handle->setFeature(static_cast(featureId), static_cast(data)); + processPowerHalReturn(ret.isOk(), "setFeature"); + return; + } + case HalVersion::AIDL: { + auto ret = gPowerHalAidl_->setMode(Mode::DOUBLE_TAP_TO_WAKE, static_cast(data)); + processPowerHalReturn(ret.isOk(), "setMode"); + return; + } + default: { + ALOGE("Unknown power HAL state"); + return; + } } } @@ -317,6 +516,10 @@ static const JNINativeMethod gPowerManagerServiceMethods[] = { (void*) nativeSetAutoSuspend }, { "nativeSendPowerHint", "(II)V", (void*) nativeSendPowerHint }, + { "nativeSetPowerBoost", "(II)V", + (void*) nativeSetPowerBoost }, + { "nativeSetPowerMode", "(IZ)V", + (void*) nativeSetPowerMode }, { "nativeSetFeature", "(II)V", (void*) nativeSetFeature }, };