Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8d6a66e1 authored by Xiang Wang's avatar Xiang Wang Committed by Android (Google) Code Review
Browse files

Merge "Fix the setThreads JNI to throw SecurityException" into main

parents ea22c81e bee6f16d
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import java.io.Closeable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.Reference;
import java.util.Objects;


/** The PerformanceHintManager allows apps to send performance hint to system. */
@@ -239,6 +240,7 @@ public final class PerformanceHintManager {
            if (mNativeSessionPtr == 0) {
                return;
            }
            Objects.requireNonNull(tids, "tids cannot be null");
            if (tids.length == 0) {
                throw new IllegalArgumentException("Thread id list can't be empty.");
            }
+20 −3
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ 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);
typedef void (*APH_setThreads)(APerformanceHintSession*, const pid_t*, size_t);
typedef int (*APH_setThreads)(APerformanceHintSession*, const pid_t*, size_t);
typedef void (*APH_getThreadIds)(APerformanceHintSession*, int32_t* const, size_t* const);

bool gAPerformanceHintBindingInitialized = false;
@@ -112,6 +112,20 @@ void ensureAPerformanceHintBindingInitialized() {

} // namespace

static void throwExceptionForErrno(JNIEnv* env, int err, const std::string& msg) {
    switch (err) {
        case EINVAL:
            jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", msg.c_str());
            break;
        case EPERM:
            jniThrowExceptionFmt(env, "java/lang/SecurityException", msg.c_str());
            break;
        default:
            jniThrowException(env, "java/lang/RuntimeException", msg.c_str());
            break;
    }
}

static jlong nativeAcquireManager(JNIEnv* env, jclass clazz) {
    ensureAPerformanceHintBindingInitialized();
    return reinterpret_cast<jlong>(gAPH_getManagerFn());
@@ -174,8 +188,11 @@ static void nativeSetThreads(JNIEnv* env, jclass clazz, jlong nativeSessionPtr,
    for (size_t i = 0; i < tidsArray.size(); ++i) {
        tidsVector.push_back(static_cast<int32_t>(tidsArray[i]));
    }
    gAPH_setThreadsFn(reinterpret_cast<APerformanceHintSession*>(nativeSessionPtr),
    int err = gAPH_setThreadsFn(reinterpret_cast<APerformanceHintSession*>(nativeSessionPtr),
                                tidsVector.data(), tidsVector.size());
    if (err != 0) {
        throwExceptionForErrno(env, err, "Failed to set threads for hint session");
    }
}

// This call should only be used for validation in tests only. This call will initiate two IPC
+11 −2
Original line number Diff line number Diff line
@@ -139,11 +139,20 @@ public class PerformanceHintManagerTest {
    }

    @Test
    public void testSetThreadsWithIllegalArgument() {
    public void testSetThreads_emptyTids() {
        Session session = createSession();
        assumeNotNull(session);
        assertThrows(IllegalArgumentException.class, () -> {
            session.setThreads(new int[]{});
        });
    }

    @Test
    public void testSetThreads_invalidTids() {
        Session session = createSession();
        assumeNotNull(session);
        assertThrows(SecurityException.class, () -> {
            session.setThreads(new int[]{-1});
        });
    }
}
+3 −2
Original line number Diff line number Diff line
@@ -274,9 +274,10 @@ int APerformanceHintSession::setThreads(const int32_t* threadIds, size_t size) {
    binder::Status ret = mHintManager->setHintSessionThreads(mHintSession, tids);
    if (!ret.isOk()) {
        ALOGE("%s: failed: %s", __FUNCTION__, ret.exceptionMessage().c_str());
        if (ret.exceptionCode() == binder::Status::Exception::EX_SECURITY ||
            ret.exceptionCode() == binder::Status::Exception::EX_ILLEGAL_ARGUMENT) {
        if (ret.exceptionCode() == binder::Status::Exception::EX_ILLEGAL_ARGUMENT) {
            return EINVAL;
        } else if (ret.exceptionCode() == binder::Status::Exception::EX_SECURITY) {
            return EPERM;
        }
        return EPIPE;
    }
+11 −0
Original line number Diff line number Diff line
@@ -178,4 +178,15 @@ TEST_F(PerformanceHintTest, SetThreads) {
            .WillOnce(Return(Status()));
    result = APerformanceHint_setThreads(session, newTids.data(), newTids.size());
    EXPECT_EQ(0, result);

    testing::Mock::VerifyAndClearExpectations(mMockIHintManager);
    std::vector<int32_t> invalidTids;
    auto status = Status::fromExceptionCode(binder::Status::Exception::EX_SECURITY);
    invalidTids.push_back(4);
    invalidTids.push_back(6);
    EXPECT_CALL(*mMockIHintManager, setHintSessionThreads(_, Eq(invalidTids)))
            .Times(Exactly(1))
            .WillOnce(Return(status));
    result = APerformanceHint_setThreads(session, invalidTids.data(), invalidTids.size());
    EXPECT_EQ(EPERM, result);
}