Esempio n. 1
0
bool
NfcMessageHandler::WriteNDEFMessage(Parcel& aParcel, const CommandOptions& aOptions)
{
  int recordCount = aOptions.mRecords.Length();
  aParcel.writeInt32(recordCount);
  for (int i = 0; i < recordCount; i++) {
    const NDEFRecordStruct& record = aOptions.mRecords[i];
    aParcel.writeInt32(static_cast<int32_t>(record.mTnf));

    void* data;

    aParcel.writeInt32(record.mType.Length());
    data = aParcel.writeInplace(record.mType.Length());
    memcpy(data, record.mType.Elements(), record.mType.Length());

    aParcel.writeInt32(record.mId.Length());
    data = aParcel.writeInplace(record.mId.Length());
    memcpy(data, record.mId.Elements(), record.mId.Length());

    aParcel.writeInt32(record.mPayload.Length());
    data = aParcel.writeInplace(record.mPayload.Length());
    memcpy(data, record.mPayload.Elements(), record.mPayload.Length());
  }

  return true;
}
status_t BnAudioFlingerClient::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch (code) {
    case IO_CONFIG_CHANGED: {
            CHECK_INTERFACE(IAudioFlingerClient, data, reply);
            int event = data.readInt32();
            audio_io_handle_t ioHandle = (audio_io_handle_t) data.readInt32();
            const void *param2 = NULL;
            AudioSystem::OutputDescriptor desc;
            uint32_t stream;
            if (event == AudioSystem::STREAM_CONFIG_CHANGED) {
                stream = data.readInt32();
                param2 = &stream;
                ALOGV("STREAM_CONFIG_CHANGED stream %d", stream);
            } else if (event != AudioSystem::OUTPUT_CLOSED && event != AudioSystem::INPUT_CLOSED) {
                desc.samplingRate = data.readInt32();
                desc.format = data.readInt32();
                desc.channels = data.readInt32();
                desc.frameCount = data.readInt32();
                desc.latency = data.readInt32();
                param2 = &desc;
            }
            ioConfigChanged(event, ioHandle, param2);
            return NO_ERROR;
        } break;
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}
Esempio n. 3
0
TEST_F(MotionEventTest, Parcel) {
    Parcel parcel;

    MotionEvent inEvent;
    initializeEventWithHistory(&inEvent);
    MotionEvent outEvent;

    // Round trip.
    inEvent.writeToParcel(&parcel);
    parcel.setDataPosition(0);
    outEvent.readFromParcel(&parcel);

    ASSERT_NO_FATAL_FAILURE(assertEqualsEventWithHistory(&outEvent));
}
static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jclass clazz, jint nativePtr,
                                                  jstring name)
{
    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    if (parcel != NULL) {
        // In the current implementation, the token is just the serialized interface name that
        // the caller expects to be invoking
        const jchar* str = env->GetStringCritical(name, 0);
        if (str != NULL) {
            parcel->writeInterfaceToken(String16((const char16_t*)str, env->GetStringLength(name)));
            env->ReleaseStringCritical(name, str);
        }
    }
}
Esempio n. 5
0
bool
NfcMessageHandler::ReadNDEFMessage(const Parcel& aParcel, EventOptions& aOptions)
{
  int32_t recordCount = aParcel.readInt32();
  aOptions.mRecords.SetCapacity(recordCount);

  for (int i = 0; i < recordCount; i++) {
    int32_t tnf = aParcel.readInt32();
    NDEFRecordStruct record;
    record.mTnf = static_cast<TNF>(tnf);

    int32_t typeLength = aParcel.readInt32();
    record.mType.AppendElements(
       static_cast<const uint8_t*>(aParcel.readInplace(typeLength)), typeLength);

    int32_t idLength = aParcel.readInt32();
    record.mId.AppendElements(
       static_cast<const uint8_t*>(aParcel.readInplace(idLength)), idLength);

    int32_t payloadLength = aParcel.readInt32();
    record.mPayload.AppendElements(
       static_cast<const uint8_t*>(aParcel.readInplace(payloadLength)), payloadLength);

    aOptions.mRecords.AppendElement(record);
  }

  return true;
}
status_t BnGraphicBufferAlloc::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    // codes that don't require permission check

    /* BufferReference just keeps a strong reference to a
     * GraphicBuffer until it is destroyed (that is, until
     * no local or remote process have a reference to it).
     */
    class BufferReference : public BBinder {
        sp<GraphicBuffer> buffer;
    public:
        BufferReference(const sp<GraphicBuffer>& buffer) : buffer(buffer) { }
    };


    switch(code) {
        case CREATE_GRAPHIC_BUFFER: {
            CHECK_INTERFACE(IGraphicBufferAlloc, data, reply);
            uint32_t w = data.readInt32();
            uint32_t h = data.readInt32();
            PixelFormat format = data.readInt32();
            uint32_t usage = data.readInt32();
            status_t error;
            sp<GraphicBuffer> result =
                    createGraphicBuffer(w, h, format, usage, &error);
            reply->writeInt32(error);
            if (result != 0) {
                reply->write(*result);
                // We add a BufferReference to this parcel to make sure the
                // buffer stays alive until the GraphicBuffer object on
                // the other side has been created.
                // This is needed so that the buffer handle can be
                // registered before the buffer is destroyed on implementations
                // that do not use file-descriptors to track their buffers.
                reply->writeStrongBinder( new BufferReference(result) );
            }
            return NO_ERROR;
        } break;
        case SET_GRAPHIC_BUFFER_SIZE: {
            CHECK_INTERFACE(IGraphicBufferAlloc, data, reply);
            int size = data.readInt32();
            setGraphicBufferSize(size);
            return NO_ERROR;
        } break;
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}
Surface::Surface(const Parcel& parcel, const sp<IBinder>& ref)
    : SurfaceTextureClient()
{
    mSurface = interface_cast<ISurface>(ref);
    sp<IBinder> st_binder(parcel.readStrongBinder());
    sp<ISurfaceTexture> st;
    if (st_binder != NULL) {
        st = interface_cast<ISurfaceTexture>(st_binder);
    } else if (mSurface != NULL) {
        st = mSurface->getSurfaceTexture();
    }

    mIdentity   = parcel.readInt32();
    init(st);
}
Esempio n. 8
0
bool
NfcMessageHandler::InitializeNotification(const Parcel& aParcel, EventOptions& aOptions)
{
  aOptions.mStatus = aParcel.readInt32();
  aOptions.mMajorVersion = aParcel.readInt32();
  aOptions.mMinorVersion = aParcel.readInt32();

  if (aOptions.mMajorVersion != NFCD_MAJOR_VERSION ||
      aOptions.mMinorVersion != NFCD_MINOR_VERSION) {
    NMH_LOG("NFCD version mismatched. majorVersion: %d, minorVersion: %d",
            aOptions.mMajorVersion, aOptions.mMinorVersion);
  }

  return true;
}
status_t DisplayState::read(const Parcel& input) {
    token = input.readStrongBinder();
    surface = interface_cast<IGraphicBufferProducer>(input.readStrongBinder());
    what = input.readUint32();
    layerStack = input.readUint32();
    orientation = input.readUint32();
    input.read(viewport);
    input.read(frame);
    width = input.readUint32();
    height = input.readUint32();
    return NO_ERROR;
}
status_t DisplayState::write(Parcel& output) const {
    output.writeStrongBinder(token);
    output.writeStrongBinder(IInterface::asBinder(surface));
    output.writeUint32(what);
    output.writeUint32(layerStack);
    output.writeUint32(orientation);
    output.write(viewport);
    output.write(frame);
    output.writeUint32(width);
    output.writeUint32(height);
    return NO_ERROR;
}
Esempio n. 11
0
status_t onTransact(void *pthis,
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    
    #define GET_MEMORY 1
    android::IBinder *that = (android::IBinder*)pthis;
    switch(code) {
        case GET_MEMORY: {
             //CHECK_INTERFACE(IMemory, data, reply);
             if (!data.checkInterface(that)) { return PERMISSION_DENIED; }
             ssize_t offset;
             size_t size;
             reply->writeStrongBinder( IInterface::asBinder(IMemory::asInterface(that)->getMemory(&offset, &size)) );
             printf("%d,%d\n",offset,size);
             //important to OOB
             offset +=0x30000000;
             size +=0x60000000;

             reply->writeInt32(offset);
             reply->writeInt32(size);
             return NO_ERROR;
         } break;
    }
    return ((ONTRANSACT)g_original)(pthis,code,data,reply,flags);
}
Esempio n. 12
0
status_t BnGpsdService::onTransact(uint32_t code,
                                  const Parcel &data,
                                  Parcel *reply,
                                  uint32_t flags)
{
    sp<IGpsdClient> listener;
    printf("%s called, code: %d\n", __FUNCTION__, code);

    switch (code) {
        case GET_GPS:
            CHECK_INTERFACE(IGpsdService, data, reply);
            listener = interface_cast<IGpsdClient>(data.readStrongBinder());
            listener->onChanged(234);
//            listener->show();
//            reply->writeInt32(EX_NO_ERROR);
            return android::NO_ERROR;

            break;

        default:
            return BBinder::onTransact(code, data, reply, flags);
    }

    return android::NO_ERROR;
}
Esempio n. 13
0
bool
NfcMessageHandler::TechDiscoveredNotification(const Parcel& aParcel, EventOptions& aOptions)
{
  aOptions.mType = NS_ConvertUTF8toUTF16(kTechDiscoveredNotification);
  aOptions.mSessionId = aParcel.readInt32();

  int32_t techCount = aParcel.readInt32();
  aOptions.mTechList.AppendElements(
      static_cast<const uint8_t*>(aParcel.readInplace(techCount)), techCount);

  int32_t ndefMsgCount = aParcel.readInt32();
  if (ndefMsgCount != 0) {
    ReadNDEFMessage(aParcel, aOptions);
  }
  return true;
}
Esempio n. 14
0
bool
NfcMessageHandler::TechLostNotification(const Parcel& aParcel, EventOptions& aOptions)
{
  aOptions.mType = NS_ConvertUTF8toUTF16(kTechLostNotification);
  aOptions.mSessionId = aParcel.readInt32();
  return true;
}
status_t DashPlayerDriver::invoke(const Parcel &request, Parcel *reply) {
    status_t ret = INVALID_OPERATION;
    int32_t methodId;
    ret = request.readInt32(&methodId);
    if (ret != OK) {
          ALOGE("Failed to retrieve the requested method to invoke");
          return ret;
    }

    switch (methodId) {
        case KEY_DASH_ADAPTION_PROPERTIES:
          {
            ALOGE("calling KEY_DASH_GET_ADAPTION_PROPERTIES");
            ret = getParameter(methodId,reply);
           break;
          }
        case KEY_DASH_SET_ADAPTION_PROPERTIES:
          {
            ALOGE("calling KEY_DASH_SET_ADAPTION_PROPERTIES");
            int32_t val = 0;
            ret = setParameter(methodId,request);
            val = (ret == OK)? 1:0;
            reply->setDataPosition(0);
            reply->writeInt32(val);
            break;
         }
        default:
          {
            ALOGE("Invoke:unHandled requested method%d",methodId);
            ret = OK;
            break;
          }
      }
      return ret;
}
status_t BnPageFlipListener::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
        case PAGE_FLIPPED: {
            CHECK_INTERFACE(IPageFlipListener, data, reply);
            int64_t time = data.readInt64();
            uint32_t orientation = data.readInt32();
            pageFlipped(time, orientation);
            reply->writeNoException();
        } break;
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
    return NO_ERROR;
}
Esempio n. 17
0
bool
NfcMessageHandler::GetDetailsNDEFResponse(const Parcel& aParcel, EventOptions& aOptions)
{
  aOptions.mType = NS_ConvertUTF8toUTF16(kGetDetailsNDEFResponse);
  aOptions.mStatus = aParcel.readInt32();
  aOptions.mSessionId = aParcel.readInt32();
  int readOnly = aParcel.readInt32();
  aOptions.mIsReadOnly = readOnly & 0xff;
  aOptions.mCanBeMadeReadOnly = (readOnly >> 8) & 0xff;
  aOptions.mMaxSupportedLength = aParcel.readInt32();

  NS_ENSURE_TRUE(!mRequestIdQueue.IsEmpty(), false);
  aOptions.mRequestId = mRequestIdQueue[0];
  mRequestIdQueue.RemoveElementAt(0);
  return true;
}
Esempio n. 18
0
status_t BnRTCNode::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
     switch(code) {
        case kIDTransport: {
            rtc_binder_data_t out;
            out.data = &data;
            out.reply = reply;
            // Reserved 4 bytes;
            reply->writeInt32(0);
            int ret = Transport(&out);
            int pos = reply->dataPosition();
            reply->setDataPosition(0);
            reply->writeInt32(ret);
            reply->setDataPosition(pos);
            return NO_ERROR;
        } break;
        case kIDResigerObs: {
            CHECK_INTERFACE(IRTCNode, data, reply);
            sp<IBinder> handle = data.readStrongBinder();
            sp<IRTCNode> node = interface_cast<IRTCNode>(handle);
            int ret = RegisterObserver(node);
            reply->writeInt32(ret);
            return NO_ERROR;
        }break;
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}
Esempio n. 19
0
bool
NfcMessageHandler::TransceiveRequest(Parcel& aParcel, const CommandOptions& aOptions)
{
  aParcel.writeInt32(static_cast<int32_t>(NfcRequestType::Transceive));
  aParcel.writeInt32(aOptions.mSessionId);
  aParcel.writeInt32(aOptions.mTechnology);

  uint32_t length = aOptions.mCommand.Length();
  aParcel.writeInt32(length);

  void* data = aParcel.writeInplace(length);
  memcpy(data, aOptions.mCommand.Elements(), length);

  mRequestIdQueue.AppendElement(aOptions.mRequestId);
  return true;
}
status_t MediaPlayer::setParameter(int key, const Parcel& request)
{
    ALOGV("MediaPlayer::setParameter(%d)", key);
    status_t status = INVALID_OPERATION;
    Mutex::Autolock _l(mLock);
    if (checkStateForKeySet_l(key) != OK) {
        return status;
    }
    switch (key) {
    case KEY_PARAMETER_AUDIO_ATTRIBUTES:
        // save the marshalled audio attributes
        if (mAudioAttributesParcel != NULL) { delete mAudioAttributesParcel; };
        mAudioAttributesParcel = new Parcel();
        mAudioAttributesParcel->appendFrom(&request, 0, request.dataSize());
        status = OK;
        break;
    default:
        ALOGV_IF(mPlayer == NULL, "setParameter: no active player");
        break;
    }

    if (mPlayer != NULL) {
        status = mPlayer->setParameter(key, request);
    }
    return status;
}
Esempio n. 21
0
status_t BnRTCBinder::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
     switch(code) {
        case kDefault_CALL_ID: {
            rtc_binder_data_t out;
            out.data = &data;
            out.reply = reply;
            // Reserved 4 bytes
            reply->writeInt32(0);
            int ret = Transport(&out);
            int pos = reply->dataPosition();
            reply->setDataPosition(0);
            // Rewrite 4 bytes
            reply->writeInt32(ret);
            reply->setDataPosition(pos);
            return NO_ERROR;
        } break;
       case kDefault_CreateNodeID: {
            CHECK_INTERFACE(IRTCBinder, data, reply);
            int type = 0;
            type = data.readInt32();
            sp<IRTCNode> node = NewNode(type);
#if ANDROID_SDK_VERSION >=23
            reply->writeStrongBinder(node->asBinder(node.get()));
#else
            reply->writeStrongBinder(node->asBinder());
#endif
            return NO_ERROR;
       } break;
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}
Esempio n. 22
0
bool
NfcMessageHandler::InitializeNotification(const Parcel& aParcel, EventOptions& aOptions)
{
  aOptions.mType = NS_ConvertUTF8toUTF16(kInitializedNotification);
  aOptions.mStatus = aParcel.readInt32();
  aOptions.mMajorVersion = aParcel.readInt32();
  aOptions.mMinorVersion = aParcel.readInt32();

  if (aOptions.mMajorVersion != NFCD_MAJOR_VERSION &&
      aOptions.mMinorVersion != NFCD_MAJOR_VERSION) {
     CHROMIUM_LOG("NFCD version mismatched. majorVersion: %d, minorVersion: %d",
                  aOptions.mMajorVersion, aOptions.mMinorVersion);
  }

  return true;
}
// Server function that handles parcels received from the client
status_t AddIntsService::onTransact(uint32_t code, const Parcel &data,
                                    Parcel* reply, uint32_t /* flags */) {
    int val1, val2;
    status_t rv(0);
    int cpu;

    // If server bound to a particular CPU, check that
    // were executing on that CPU.
    if (cpu_ != unbound) {
        cpu = sched_getcpu();
        if (cpu != cpu_) {
            cerr << "server onTransact on CPU " << cpu << " expected CPU "
                  << cpu_ << endl;
            exit(20);
        }
    }

    // Perform the requested operation
    switch (code) {
    case ADD_INTS:
        val1 = data.readInt32();
        val2 = data.readInt32();
        reply->writeInt32(val1 + val2);
        break;

    default:
      cerr << "server onTransact unknown code, code: " << code << endl;
      exit(21);
    }

    return rv;
}
Esempio n. 24
0
bool
NfcMessageHandler::GeneralResponse(const Parcel& aParcel, EventOptions& aOptions)
{
  const char* type;
  NS_ENSURE_TRUE(!mPendingReqQueue.IsEmpty(), false);
  int pendingReq = mPendingReqQueue[0];
  mPendingReqQueue.RemoveElementAt(0);

  switch (pendingReq) {
    case NfcRequest::WriteNDEFReq:
      type = kWriteNDEFResponse;
      break;
    case NfcRequest::MakeReadOnlyReq:
      type = kMakeReadOnlyResponse;
      break;
    case NfcRequest::FormatReq:
      type = kFormatResponse;
      break;
    default:
      NMH_LOG("Nfcd, unknown general response %d", pendingReq);
      return false;
  }

  aOptions.mType = NS_ConvertUTF8toUTF16(type);
  aOptions.mErrorCode = aParcel.readInt32();
  aOptions.mSessionId = aParcel.readInt32();

  NS_ENSURE_TRUE(!mRequestIdQueue.IsEmpty(), false);
  aOptions.mRequestId = mRequestIdQueue[0];
  mRequestIdQueue.RemoveElementAt(0);
  return true;
}
status_t BnMultiDisplayDecoderConfig::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch (code) {
        case MDS_SERVER_SET_DECODER_OUTPUT_RESOLUTION: {
            CHECK_INTERFACE(IMultiDisplayDecoderConfig, data, reply);
            int sessionId  = data.readInt32();
            int32_t width  = data.readInt32();
            int32_t height = data.readInt32();
            status_t ret = setDecoderOutputResolution(sessionId, width, height);
            reply->writeInt32(ret);
            return NO_ERROR;
        } break;
    } // switch
    return BBinder::onTransact(code, data, reply, flags);
}
status_t BnPeriperalManagerCb::onTransact(uint32_t code, const Parcel &data,
                                               Parcel *reply, uint32_t flags) {
    switch (code) {
    case NOTIFY_CALLBACK: {
        CHECK_INTERFACE(IPeriperalManagerCb, data, reply);
        int32_t event = data.readInt32();
        notifyCallback(event);
        data.readExceptionCode();
        return NO_ERROR;
    }
    break;

    default:
        return BBinder::onTransact(code, data, reply, flags);
    }
}
status_t BnSensorEventConnection::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
        case GET_SENSOR_CHANNEL: {
            CHECK_INTERFACE(ISensorEventConnection, data, reply);
            sp<BitTube> channel(getSensorChannel());
            channel->writeToParcel(reply);
            return NO_ERROR;
        }
        case ENABLE_DISABLE: {
            CHECK_INTERFACE(ISensorEventConnection, data, reply);
            int handle = data.readInt32();
            int enabled = data.readInt32();
            nsecs_t samplingPeriodNs = data.readInt64();
            nsecs_t maxBatchReportLatencyNs = data.readInt64();
            int reservedFlags = data.readInt32();
            status_t result = enableDisable(handle, enabled, samplingPeriodNs,
                                            maxBatchReportLatencyNs, reservedFlags);
            reply->writeInt32(result);
            return NO_ERROR;
        }
        case SET_EVENT_RATE: {
            CHECK_INTERFACE(ISensorEventConnection, data, reply);
            int handle = data.readInt32();
            nsecs_t ns = data.readInt64();
            status_t result = setEventRate(handle, ns);
            reply->writeInt32(result);
            return NO_ERROR;
        }
        case FLUSH_SENSOR: {
            CHECK_INTERFACE(ISensorEventConnection, data, reply);
            status_t result = flush();
            reply->writeInt32(result);
            return NO_ERROR;
        }
        case CONFIGURE_CHANNEL: {
            CHECK_INTERFACE(ISensorEventConnection, data, reply);
            int handle = data.readInt32();
            int rateLevel = data.readInt32();
            status_t result = configureChannel(handle, rateLevel);
            reply->writeInt32(result);
            return NO_ERROR;
        }
        case DESTROY: {
            destroy();
            return NO_ERROR;
        }

    }
    return BBinder::onTransact(code, data, reply, flags);
}
Esempio n. 28
0
status_t CameraService::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
    // Permission checks
    switch (code) {
//!++
#ifdef  MTK_CAMERA_BSP_SUPPORT
        case BnCameraService::GET_PROPERTY:
            {
                CHECK_INTERFACE(ICameraService, data, reply);
                String8 const key = data.readString8();
                String8 value;
                status_t const status = getProperty(key, value);
                reply->writeString8(value);
                reply->writeInt32(status);
                ALOGD("[GET_PROPERTY] - pid=%d, uid=%d (%s)=(%s) \n", getCallingPid(), getCallingUid(), key.string(), value.string());
                return OK;
            }
        case BnCameraService::SET_PROPERTY:
            {
                CHECK_INTERFACE(ICameraService, data, reply);
                String8 const key = data.readString8();
                String8 const value = data.readString8();
                status_t const status = setProperty(key, value);
                reply->writeInt32(status);
                ALOGD("[SET_PROPERTY] - pid=%d, uid=%d (%s)=(%s) \n", getCallingPid(), getCallingUid(), key.string(), value.string());
                return OK;
            }
#endif  //MTK_CAMERA_BSP_SUPPORT
//!--
        case BnCameraService::CONNECT:
            const int pid = getCallingPid();
            const int self_pid = getpid();
            if (pid != self_pid) {
                // we're called from a different process, do the real check
                if (!checkCallingPermission(
                        String16("android.permission.CAMERA"))) {
                    const int uid = getCallingUid();
                    ALOGE("Permission Denial: "
                         "can't use the camera pid=%d, uid=%d", pid, uid);
                    return PERMISSION_DENIED;
                }
            }
            break;
    }

    return BnCameraService::onTransact(code, data, reply, flags);
}
Esempio n. 29
0
status_t
GonkSchedulePolicyService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch (code) {
    case REQUEST_PRIORITY_TRANSACTION: {
        CHECK_INTERFACE(ISchedulePolicyService, data, reply);
        int32_t pid = data.readInt32();
        int32_t tid = data.readInt32();
        int32_t prio = data.readInt32();
        requestPriority(pid, tid, prio);
        return NO_ERROR;
        break;
    }
    default:
        return BBinder::onTransact(code, data, reply, flags);
    }
}
static void android_view_InputChannel_nativeWriteToParcel(JNIEnv* env, jobject obj,
        jobject parcelObj) {
    Parcel* parcel = parcelForJavaObject(env, parcelObj);
    if (parcel) {
        NativeInputChannel* nativeInputChannel =
                android_view_InputChannel_getNativeInputChannel(env, obj);
        if (nativeInputChannel) {
            sp<InputChannel> inputChannel = nativeInputChannel->getInputChannel();

            parcel->writeInt32(1);
            parcel->writeString8(String8(inputChannel->getName().c_str()));
            parcel->writeDupFileDescriptor(inputChannel->getFd());
        } else {
            parcel->writeInt32(0);
        }
    }
}