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

Commit 9249b41c authored by Devin Moore's avatar Devin Moore
Browse files

Change the native_transact to handle local binder txns

This is only enabled for IServiceManager for the fake HwNoService class
that replaces the remote hwservicemanager on devices that have HIDL
disabled.

Test: boot CF without hwservicemanager
Bug: 218588089

Change-Id: Ibd2ad90aad7b70d61b70ec29f654f99dcf7610d1
parent c141aaef
Loading
Loading
Loading
Loading
+53 −8
Original line number Diff line number Diff line
@@ -258,14 +258,59 @@ static void JHwBinder_native_setup(JNIEnv *env, jobject thiz) {
    JHwBinder::SetNativeContext(env, thiz, context);
}

static void JHwBinder_native_transact(
        JNIEnv * /* env */,
        jobject /* thiz */,
        jint /* code */,
        jobject /* requestObj */,
        jobject /* replyObj */,
        jint /* flags */) {
    CHECK(!"Should not be here");
static void JHwBinder_native_transact(JNIEnv *env, jobject thiz, jint code, jobject requestObj,
                                      jobject replyObj, jint flags) {
    if (requestObj == NULL) {
        jniThrowException(env, "java/lang/NullPointerException", NULL);
        return;
    }
    sp<hardware::IBinder> binder = JHwBinder::GetNativeBinder(env, thiz);
    sp<android::hidl::base::V1_0::IBase> base = new android::hidl::base::V1_0::BpHwBase(binder);
    hidl_string desc;
    auto ret = base->interfaceDescriptor(
            [&desc](const hidl_string &descriptor) { desc = descriptor; });
    ret.assertOk();
    // Only the fake hwservicemanager is allowed to be used locally like this.
    if (desc != "android.hidl.manager@1.2::IServiceManager" &&
        desc != "android.hidl.manager@1.1::IServiceManager" &&
        desc != "android.hidl.manager@1.0::IServiceManager") {
        LOG(FATAL) << "Local binders are not supported!";
    }
    if (replyObj == nullptr) {
        LOG(FATAL) << "Unexpected null replyObj. code: " << code;
        return;
    }
    const hardware::Parcel *request = JHwParcel::GetNativeContext(env, requestObj)->getParcel();
    sp<JHwParcel> replyContext = JHwParcel::GetNativeContext(env, replyObj);
    hardware::Parcel *reply = replyContext->getParcel();

    request->setDataPosition(0);

    bool isOneway = (flags & IBinder::FLAG_ONEWAY) != 0;
    if (!isOneway) {
        replyContext->setTransactCallback([](auto &replyParcel) {});
    }

    env->CallVoidMethod(thiz, gFields.onTransactID, code, requestObj, replyObj, flags);

    if (env->ExceptionCheck()) {
        jthrowable excep = env->ExceptionOccurred();
        env->ExceptionDescribe();
        env->ExceptionClear();

        binder_report_exception(env, excep, "Uncaught error or exception in hwbinder!");

        env->DeleteLocalRef(excep);
    }

    if (!isOneway) {
        if (!replyContext->wasSent()) {
            // The implementation never finished the transaction.
            LOG(ERROR) << "The reply failed to send!";
        }
    }

    reply->setDataPosition(0);
}

static void JHwBinder_native_registerService(