Bundle inside Intent from Native cpp application using Binder

旧巷老猫 提交于 2019-12-12 09:36:19

问题


I'm trying to call an intent from native cpp code. Basically, from what i've understand, i have to compose a Parcel to match the exact deserialization sequence from frameworks/base/core/java/android/app/ActivityManagerNative.java ; case BROADCAST_INTENT_TRANSACTION.

The progress so far is that i've received the intent in a Java app, but i have some problem with the bundle payload. I've debugged the Java app and it seems that it reads garbage as an int instead of reading the int which holds the type for the keys of the bundle.

W/System.err( 1386): java.lang.RuntimeException: Parcel android.os.Parcel@71aa5c5: Unmarshalling unknown type code 6815843 at offset 12
W/System.err( 1386):    at android.os.Parcel.readValue(Parcel.java:2228)
W/System.err( 1386):    at android.os.Parcel.readArrayMapInternal(Parcel.java:2485)
W/System.err( 1386):    at android.os.BaseBundle.unparcel(BaseBundle.java:221

Here is the native code used

#include <unistd.h>
#include <binder/IBinder.h>
#include <binder/IServiceManager.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <assert.h>

namespace android {

static const int BROADCAST_INTENT_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 13;

int send_intent()
{
    int NULL_TYPE_ID = 0;

    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> am = sm->checkService(String16("activity"));
    assert(am != NULL);

    Parcel data, reply;
    data.writeInterfaceToken(String16("android.app.IActivityManager"));
    data.writeStrongBinder(NULL);

    /*intent*/

    data.writeString16(String16("com.etc.etc.receiver")); /* action */

    data.writeInt32(NULL_TYPE_ID); /* mData */
    data.writeString16(NULL, 0); /* type */
    data.writeInt32(0); /* flags */
    data.writeString16(NULL, 0); /* package name  */
    data.writeString16(NULL, 0); /* ComponentName - class */

    data.writeInt32(0); /*  no source bounds */
    data.writeInt32(0); /* no categories  */

    /* skip categories */

    data.writeInt32(0); /* no selector  */
    data.writeInt32(0); /* no clip data  */
    data.writeInt32(0); /* content user hint */


    { /* Extras Bundle */
        data.writeInt32(0); /* dummy, will hold length */

        data.writeInt32(0x4C444E42); // 'B' 'N' 'D' 'L'
        int oldPos = data.dataPosition();
        { /* writeMapInternal */
            data.writeInt32(2); /* writeMapInternal - size in pairs */

            data.writeInt32(VAL_STRING); /* type for key */
            data.writeString16(String16("first")); /* key */
            data.writeInt32(VAL_INTEGER); /* type for value */
            data.writeInt32(1337); /* value */

            data.writeInt32(VAL_STRING); /* type for key */
            data.writeString16(String16("second")); /* key */
            data.writeInt32(VAL_INTEGER);   /* type for value */
            data.writeInt32(1338); /* value */


        }
        int newPos = data.dataPosition();
        data.setDataPosition(oldPos - 8); /* eight bytes: size integer + bundle integer  */
        int difference = newPos - oldPos;
        data.writeInt32(difference); /* total length of the bundle */

        data.setDataPosition(newPos);
    }

    data.writeString16(NULL, 0); /* resolvedType */
    data.writeStrongBinder(NULL); /* resultTo */
    data.writeInt32(-1);          /* resultCode */
    data.writeString16(NULL, 0);  /* resultData */
    data.writeInt32(-1);        /* result extras */

    data.writeString16(NULL, 0);  /* grant all permissions */
    data.writeInt32(0); /* appOp */
    data.writeInt32(0); /* serialized */
    data.writeInt32(0); /* sticky */
    data.writeInt32(0); /* userid */

    status_t ret = am->transact(BROADCAST_INTENT_TRANSACTION, data, &reply);

    if (ret == NO_ERROR)
    {
        int32_t exceptionCode = reply.readExceptionCode();
        if (!exceptionCode)
        {
            ALOGD("sendBroadcast succeed\n");
        }
        else
        {
            // An exception was thrown back; fall through to return failure
            ALOGE("sendBroadcastcaught exception %d\n", exceptionCode);
        }
    }
    else
    {
        ALOGD("am->transact returned: %d", ret);
    }

    return 0;
}
};

回答1:


remove code below:

data.writeInt32(VAL_STRING); /* type for key */

the key type is not needed because it is always a string. This field is not marshalled, then don't unmarshall it.



来源:https://stackoverflow.com/questions/37300703/bundle-inside-intent-from-native-cpp-application-using-binder

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!