Merge "Add support for ADPF HintSession sendHint to JNI"
This commit is contained in:
@@ -32169,7 +32169,12 @@ package android.os {
|
||||
public static class PerformanceHintManager.Session implements java.io.Closeable {
|
||||
method public void close();
|
||||
method public void reportActualWorkDuration(long);
|
||||
method public void sendHint(int);
|
||||
method public void updateTargetWorkDuration(long);
|
||||
field public static final int CPU_LOAD_DOWN = 1; // 0x1
|
||||
field public static final int CPU_LOAD_RESET = 2; // 0x2
|
||||
field public static final int CPU_LOAD_RESUME = 3; // 0x3
|
||||
field public static final int CPU_LOAD_UP = 0; // 0x0
|
||||
}
|
||||
|
||||
public final class PersistableBundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
|
||||
|
||||
@@ -22,4 +22,5 @@ oneway interface IHintSession {
|
||||
void updateTargetWorkDuration(long targetDurationNanos);
|
||||
void reportActualWorkDuration(in long[] actualDurationNanos, in long[] timeStampNanos);
|
||||
void close();
|
||||
void sendHint(int hint);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.os;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SystemService;
|
||||
@@ -24,6 +25,10 @@ import android.content.Context;
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.ref.Reference;
|
||||
|
||||
|
||||
/** The PerformanceHintManager allows apps to send performance hint to system. */
|
||||
@SystemService(Context.PERFORMANCE_HINT_SERVICE)
|
||||
@@ -104,6 +109,40 @@ public final class PerformanceHintManager {
|
||||
mNativeSessionPtr = nativeSessionPtr;
|
||||
}
|
||||
|
||||
/**
|
||||
* This hint indicates a sudden increase in CPU workload intensity. It means
|
||||
* that this hint session needs extra CPU resources immediately to meet the
|
||||
* target duration for the current work cycle.
|
||||
*/
|
||||
public static final int CPU_LOAD_UP = 0;
|
||||
/**
|
||||
* This hint indicates a decrease in CPU workload intensity. It means that
|
||||
* this hint session can reduce CPU resources and still meet the target duration.
|
||||
*/
|
||||
public static final int CPU_LOAD_DOWN = 1;
|
||||
/*
|
||||
* This hint indicates an upcoming CPU workload that is completely changed and
|
||||
* unknown. It means that the hint session should reset CPU resources to a known
|
||||
* baseline to prepare for an arbitrary load, and must wake up if inactive.
|
||||
*/
|
||||
public static final int CPU_LOAD_RESET = 2;
|
||||
/*
|
||||
* This hint indicates that the most recent CPU workload is resuming after a
|
||||
* period of inactivity. It means that the hint session should allocate similar
|
||||
* CPU resources to what was used previously, and must wake up if inactive.
|
||||
*/
|
||||
public static final int CPU_LOAD_RESUME = 3;
|
||||
|
||||
/** @hide */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(prefix = {"CPU_LOAD_"}, value = {
|
||||
CPU_LOAD_UP,
|
||||
CPU_LOAD_DOWN,
|
||||
CPU_LOAD_RESET,
|
||||
CPU_LOAD_RESUME
|
||||
})
|
||||
public @interface Hint {}
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
@@ -152,6 +191,21 @@ public final class PerformanceHintManager {
|
||||
mNativeSessionPtr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends performance hints to inform the hint session of changes in the workload.
|
||||
*
|
||||
* @param hint The hint to send to the session.
|
||||
*/
|
||||
public void sendHint(@Hint int hint) {
|
||||
Preconditions.checkArgumentNonNegative(hint, "the hint ID should be at least"
|
||||
+ " zero.");
|
||||
try {
|
||||
nativeSendHint(mNativeSessionPtr, hint);
|
||||
} finally {
|
||||
Reference.reachabilityFence(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static native long nativeAcquireManager();
|
||||
@@ -163,4 +217,5 @@ public final class PerformanceHintManager {
|
||||
private static native void nativeReportActualWorkDuration(long nativeSessionPtr,
|
||||
long actualDurationNanos);
|
||||
private static native void nativeCloseSession(long nativeSessionPtr);
|
||||
private static native void nativeSendHint(long nativeSessionPtr, int hint);
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ typedef int64_t (*APH_getPreferredUpdateRateNanos)(APerformanceHintManager* mana
|
||||
typedef void (*APH_updateTargetWorkDuration)(APerformanceHintSession*, int64_t);
|
||||
typedef void (*APH_reportActualWorkDuration)(APerformanceHintSession*, int64_t);
|
||||
typedef void (*APH_closeSession)(APerformanceHintSession* session);
|
||||
typedef void (*APH_sendHint)(APerformanceHintSession*, int32_t);
|
||||
|
||||
bool gAPerformanceHintBindingInitialized = false;
|
||||
APH_getManager gAPH_getManagerFn = nullptr;
|
||||
@@ -48,6 +49,7 @@ APH_getPreferredUpdateRateNanos gAPH_getPreferredUpdateRateNanosFn = nullptr;
|
||||
APH_updateTargetWorkDuration gAPH_updateTargetWorkDurationFn = nullptr;
|
||||
APH_reportActualWorkDuration gAPH_reportActualWorkDurationFn = nullptr;
|
||||
APH_closeSession gAPH_closeSessionFn = nullptr;
|
||||
APH_sendHint gAPH_sendHintFn = nullptr;
|
||||
|
||||
void ensureAPerformanceHintBindingInitialized() {
|
||||
if (gAPerformanceHintBindingInitialized) return;
|
||||
@@ -88,6 +90,11 @@ void ensureAPerformanceHintBindingInitialized() {
|
||||
LOG_ALWAYS_FATAL_IF(gAPH_closeSessionFn == nullptr,
|
||||
"Failed to find required symbol APerformanceHint_closeSession!");
|
||||
|
||||
gAPH_sendHintFn = (APH_sendHint)dlsym(handle_, "APerformanceHint_sendHint");
|
||||
LOG_ALWAYS_FATAL_IF(gAPH_sendHintFn == nullptr,
|
||||
"Failed to find required symbol "
|
||||
"APerformanceHint_sendHint!");
|
||||
|
||||
gAPerformanceHintBindingInitialized = true;
|
||||
}
|
||||
|
||||
@@ -138,6 +145,11 @@ static void nativeCloseSession(JNIEnv* env, jclass clazz, jlong nativeSessionPtr
|
||||
gAPH_closeSessionFn(reinterpret_cast<APerformanceHintSession*>(nativeSessionPtr));
|
||||
}
|
||||
|
||||
static void nativeSendHint(JNIEnv* env, jclass clazz, jlong nativeSessionPtr, jint hint) {
|
||||
ensureAPerformanceHintBindingInitialized();
|
||||
gAPH_sendHintFn(reinterpret_cast<APerformanceHintSession*>(nativeSessionPtr), hint);
|
||||
}
|
||||
|
||||
static const JNINativeMethod gPerformanceHintMethods[] = {
|
||||
{"nativeAcquireManager", "()J", (void*)nativeAcquireManager},
|
||||
{"nativeGetPreferredUpdateRateNanos", "(J)J", (void*)nativeGetPreferredUpdateRateNanos},
|
||||
@@ -145,6 +157,7 @@ static const JNINativeMethod gPerformanceHintMethods[] = {
|
||||
{"nativeUpdateTargetWorkDuration", "(JJ)V", (void*)nativeUpdateTargetWorkDuration},
|
||||
{"nativeReportActualWorkDuration", "(JJ)V", (void*)nativeReportActualWorkDuration},
|
||||
{"nativeCloseSession", "(J)V", (void*)nativeCloseSession},
|
||||
{"nativeSendHint", "(JI)V", (void*)nativeSendHint},
|
||||
};
|
||||
|
||||
int register_android_os_PerformanceHintManager(JNIEnv* env) {
|
||||
|
||||
@@ -113,6 +113,23 @@ public class PerformanceHintManagerTest {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendHint() {
|
||||
Session s = createSession();
|
||||
assumeNotNull(s);
|
||||
s.sendHint(Session.CPU_LOAD_UP);
|
||||
s.sendHint(Session.CPU_LOAD_RESET);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendHintWithNegativeHint() {
|
||||
Session s = createSession();
|
||||
assumeNotNull(s);
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
s.sendHint(-1);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseHintSession() {
|
||||
Session s = createSession();
|
||||
|
||||
@@ -330,6 +330,7 @@ LIBANDROID {
|
||||
APerformanceHint_updateTargetWorkDuration; # introduced=Tiramisu
|
||||
APerformanceHint_reportActualWorkDuration; # introduced=Tiramisu
|
||||
APerformanceHint_closeSession; # introduced=Tiramisu
|
||||
APerformanceHint_sendHint; # introduced=UpsideDownCake
|
||||
local:
|
||||
*;
|
||||
};
|
||||
|
||||
@@ -61,6 +61,7 @@ public:
|
||||
|
||||
int updateTargetWorkDuration(int64_t targetDurationNanos);
|
||||
int reportActualWorkDuration(int64_t actualDurationNanos);
|
||||
int sendHint(int32_t hint);
|
||||
|
||||
private:
|
||||
friend struct APerformanceHintManager;
|
||||
@@ -159,7 +160,7 @@ int APerformanceHintSession::updateTargetWorkDuration(int64_t targetDurationNano
|
||||
}
|
||||
binder::Status ret = mHintSession->updateTargetWorkDuration(targetDurationNanos);
|
||||
if (!ret.isOk()) {
|
||||
ALOGE("%s: HintSessionn updateTargetWorkDuration failed: %s", __FUNCTION__,
|
||||
ALOGE("%s: HintSession updateTargetWorkDuration failed: %s", __FUNCTION__,
|
||||
ret.exceptionMessage().c_str());
|
||||
return EPIPE;
|
||||
}
|
||||
@@ -205,6 +206,21 @@ int APerformanceHintSession::reportActualWorkDuration(int64_t actualDurationNano
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APerformanceHintSession::sendHint(int32_t hint) {
|
||||
if (hint < 0) {
|
||||
ALOGE("%s: session hint value must be greater than zero", __FUNCTION__);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
binder::Status ret = mHintSession->sendHint(hint);
|
||||
|
||||
if (!ret.isOk()) {
|
||||
ALOGE("%s: HintSession sendHint failed: %s", __FUNCTION__, ret.exceptionMessage().c_str());
|
||||
return EPIPE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ===================================== C API
|
||||
APerformanceHintManager* APerformanceHint_getManager() {
|
||||
return APerformanceHintManager::getInstance();
|
||||
@@ -230,6 +246,10 @@ int APerformanceHint_reportActualWorkDuration(APerformanceHintSession* session,
|
||||
return session->reportActualWorkDuration(actualDurationNanos);
|
||||
}
|
||||
|
||||
int APerformanceHint_sendHint(APerformanceHintSession* session, int32_t hint) {
|
||||
return session->sendHint(hint);
|
||||
}
|
||||
|
||||
void APerformanceHint_closeSession(APerformanceHintSession* session) {
|
||||
delete session;
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ public:
|
||||
(const ::std::vector<int64_t>& actualDurationNanos,
|
||||
const ::std::vector<int64_t>& timeStampNanos),
|
||||
(override));
|
||||
MOCK_METHOD(Status, sendHint, (int32_t hints), (override));
|
||||
MOCK_METHOD(Status, close, (), (override));
|
||||
MOCK_METHOD(IBinder*, onAsBinder, (), (override));
|
||||
};
|
||||
@@ -121,6 +122,15 @@ TEST_F(PerformanceHintTest, TestSession) {
|
||||
result = APerformanceHint_reportActualWorkDuration(session, -1L);
|
||||
EXPECT_EQ(EINVAL, result);
|
||||
|
||||
// Send both valid and invalid session hints
|
||||
int hintId = 2;
|
||||
EXPECT_CALL(*iSession, sendHint(Eq(2))).Times(Exactly(1));
|
||||
result = APerformanceHint_sendHint(session, hintId);
|
||||
EXPECT_EQ(0, result);
|
||||
|
||||
result = APerformanceHint_sendHint(session, -1);
|
||||
EXPECT_EQ(EINVAL, result);
|
||||
|
||||
EXPECT_CALL(*iSession, close()).Times(Exactly(1));
|
||||
APerformanceHint_closeSession(session);
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ java_library_static {
|
||||
"android.hardware.rebootescrow-V1-java",
|
||||
"android.hardware.soundtrigger-V2.3-java",
|
||||
"android.hardware.power.stats-V1-java",
|
||||
"android.hardware.power-V3-java",
|
||||
"android.hardware.power-V4-java",
|
||||
"android.hidl.manager-V1.2-java",
|
||||
"capture_state_listener-aidl-java",
|
||||
"icu4j_calendar_astronomer",
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.IHintManager;
|
||||
import android.os.IHintSession;
|
||||
import android.os.PerformanceHintManager;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.util.ArrayMap;
|
||||
@@ -147,6 +148,8 @@ public final class HintManagerService extends SystemService {
|
||||
private static native void nativeReportActualWorkDuration(
|
||||
long halPtr, long[] actualDurationNanos, long[] timeStampNanos);
|
||||
|
||||
private static native void nativeSendHint(long halPtr, int hint);
|
||||
|
||||
private static native long nativeGetHintSessionPreferredRate();
|
||||
|
||||
/** Wrapper for HintManager.nativeInit */
|
||||
@@ -186,6 +189,11 @@ public final class HintManagerService extends SystemService {
|
||||
timeStampNanos);
|
||||
}
|
||||
|
||||
/** Wrapper for HintManager.sendHint */
|
||||
public void halSendHint(long halPtr, int hint) {
|
||||
nativeSendHint(halPtr, hint);
|
||||
}
|
||||
|
||||
/** Wrapper for HintManager.nativeGetHintSessionPreferredRate */
|
||||
public long halGetHintSessionPreferredRate() {
|
||||
return nativeGetHintSessionPreferredRate();
|
||||
@@ -475,6 +483,18 @@ public final class HintManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendHint(@PerformanceHintManager.Session.Hint int hint) {
|
||||
synchronized (mLock) {
|
||||
if (mHalSessionPtr == 0 || !updateHintAllowed()) {
|
||||
return;
|
||||
}
|
||||
Preconditions.checkArgument(hint >= 0, "the hint ID the hint value should be"
|
||||
+ " greater than zero.");
|
||||
mNativeWrapper.halSendHint(mHalSessionPtr, hint);
|
||||
}
|
||||
}
|
||||
|
||||
private void onProcStateChanged() {
|
||||
updateHintAllowed();
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ cc_defaults {
|
||||
"android.hardware.power@1.1",
|
||||
"android.hardware.power@1.2",
|
||||
"android.hardware.power@1.3",
|
||||
"android.hardware.power-V3-cpp",
|
||||
"android.hardware.power-V4-cpp",
|
||||
"android.hardware.power.stats@1.0",
|
||||
"android.hardware.power.stats-V1-ndk",
|
||||
"android.hardware.thermal@1.0",
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "jni.h"
|
||||
|
||||
using android::hardware::power::IPowerHintSession;
|
||||
using android::hardware::power::SessionHint;
|
||||
using android::hardware::power::WorkDuration;
|
||||
|
||||
using android::base::StringPrintf;
|
||||
@@ -81,6 +82,11 @@ static void reportActualWorkDuration(int64_t session_ptr,
|
||||
appSession->reportActualWorkDuration(actualDurations);
|
||||
}
|
||||
|
||||
static void sendHint(int64_t session_ptr, SessionHint hint) {
|
||||
sp<IPowerHintSession> appSession = reinterpret_cast<IPowerHintSession*>(session_ptr);
|
||||
appSession->sendHint(hint);
|
||||
}
|
||||
|
||||
static int64_t getHintSessionPreferredRate() {
|
||||
int64_t rate = -1;
|
||||
auto result = gPowerHalController.getHintSessionPreferredRate();
|
||||
@@ -139,6 +145,10 @@ static void nativeReportActualWorkDuration(JNIEnv* env, jclass /* clazz */, jlon
|
||||
reportActualWorkDuration(session_ptr, actualList);
|
||||
}
|
||||
|
||||
static void nativeSendHint(JNIEnv* env, jclass /* clazz */, jlong session_ptr, jint hint) {
|
||||
sendHint(session_ptr, static_cast<SessionHint>(hint));
|
||||
}
|
||||
|
||||
static jlong nativeGetHintSessionPreferredRate(JNIEnv* /* env */, jclass /* clazz */) {
|
||||
return static_cast<jlong>(getHintSessionPreferredRate());
|
||||
}
|
||||
@@ -153,6 +163,7 @@ static const JNINativeMethod sHintManagerServiceMethods[] = {
|
||||
{"nativeCloseHintSession", "(J)V", (void*)nativeCloseHintSession},
|
||||
{"nativeUpdateTargetWorkDuration", "(JJ)V", (void*)nativeUpdateTargetWorkDuration},
|
||||
{"nativeReportActualWorkDuration", "(J[J[J)V", (void*)nativeReportActualWorkDuration},
|
||||
{"nativeSendHint", "(JI)V", (void*)nativeSendHint},
|
||||
{"nativeGetHintSessionPreferredRate", "()J", (void*)nativeGetHintSessionPreferredRate},
|
||||
};
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ import android.content.Context;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.IHintSession;
|
||||
import android.os.PerformanceHintManager;
|
||||
import android.os.Process;
|
||||
|
||||
import com.android.server.FgThread;
|
||||
@@ -249,6 +250,32 @@ public class HintManagerServiceTest {
|
||||
verify(mNativeWrapperMock, never()).halReportActualWorkDuration(anyLong(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendHint() throws Exception {
|
||||
HintManagerService service = createService();
|
||||
IBinder token = new Binder();
|
||||
|
||||
AppHintSession a = (AppHintSession) service.getBinderServiceInstance()
|
||||
.createHintSession(token, SESSION_TIDS_A, DEFAULT_TARGET_DURATION);
|
||||
|
||||
a.sendHint(PerformanceHintManager.Session.CPU_LOAD_RESET);
|
||||
verify(mNativeWrapperMock, times(1)).halSendHint(anyLong(),
|
||||
eq(PerformanceHintManager.Session.CPU_LOAD_RESET));
|
||||
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
a.sendHint(-1);
|
||||
});
|
||||
|
||||
reset(mNativeWrapperMock);
|
||||
// Set session to background, then the duration would not be updated.
|
||||
service.mUidObserver.onUidStateChanged(
|
||||
a.mUid, ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND, 0, 0);
|
||||
FgThread.getHandler().runWithScissors(() -> { }, 500);
|
||||
assertFalse(a.updateHintAllowed());
|
||||
a.sendHint(PerformanceHintManager.Session.CPU_LOAD_RESET);
|
||||
verify(mNativeWrapperMock, never()).halSendHint(anyLong(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoHintInBackground() throws Exception {
|
||||
HintManagerService service = createService();
|
||||
|
||||
Reference in New Issue
Block a user