Skip to content

gRPC, Protobuf & When to Use What

TL;DR

gRPC is Google’s RPC framework: HTTP/2 transport, Protocol Buffers (protobuf) serialization, strongly typed service definitions in .proto files. It dominates inter-VM communication (QNX↔AAOS over vsock), cloud backends, and OTA orchestration: anywhere you control both endpoints and want high-throughput, typed APIs. SOME/IP dominates in-vehicle service discovery and ECU-to-ECU communication on Automotive Ethernet. They’re complementary, not competing. Your “lb” OTA tool uses SOME/IP to discover update services on the vehicle bus, then gRPC for the actual data transfer.

If you’ve written a .proto file, run grpcurl, or seen :50051 in a port dump, you’ve touched gRPC. If you’ve used Wireshark on SOME/IP-SD multicast, you’ve touched the other half. This page explains why both exist in the same vehicle and when to reach for which.

Layer Technology
IDL .proto files: define services, methods, messages
Serialization Protocol Buffers: binary, schema-evolvable, code-generated
Transport HTTP/2: multiplexed streams, header compression, flow control
RPC styles Unary, server streaming, client streaming, bidirectional streaming
Code gen protoc → stubs in C++, Java, Kotlin, Python, Go, etc.
update_service.proto
service UpdateManagement {
rpc StartDownload(StartDownloadRequest) returns (StartDownloadResponse);
rpc StreamProgress(ProgressRequest) returns (stream ProgressUpdate);
rpc GetStatus(StatusRequest) returns (StatusResponse);
}
message StartDownloadRequest {
string package_id = 1;
bytes manifest_hash = 2;
}

One .proto file → client and server stubs in every language. Change the schema, regenerate, compile. Type mismatches fail at build time, not in the field.

Mental Model

If SOME/IP is the vehicle’s internal phone system (departments, extensions, building directory), gRPC is the video conference link between buildings. It doesn’t need to discover who’s in the vehicle — both sides already know the .proto contract and connect directly over a known channel (vsock, TCP, TLS). High bandwidth, typed, streaming-capable. You use it when two systems you control need to talk efficiently, not when a random ECU needs to find a service at runtime.

Your cockpit SoC runs QNX and AAOS in separate VMs on the same die. They share no memory. Communication goes through the hypervisor via vsock (virtual socket, like TCP but VM-to-VM without hitting the physical network).

flowchart LR
subgraph AAOS_VM["AAOS VM"]
App["Body/HVAC App"]
HAL["Vehicle HAL<br/>(AIDL)"]
GRPC_C["gRPC Client"]
App --> HAL --> GRPC_C
end
subgraph Hypervisor["Hypervisor (vsock)"]
VS["vsock channel<br/>CID:port"]
end
subgraph QNX_VM["QNX VM"]
GRPC_S["gRPC Server"]
VAL["Vehicle Abstraction<br/>Layer"]
SOMEIP["SOME/IP Client"]
GRPC_S --> VAL --> SOMEIP
end
GRPC_C <-->|"gRPC / HTTP/2<br/>protobuf"| VS
VS <-->|"gRPC / HTTP/2<br/>protobuf"| GRPC_S
SOMEIP -->|"SOME/IP<br/>Automotive Ethernet"| ECU["Zone Controllers / ECUs"]

Why gRPC here, not SOME/IP?

  • Both VMs are controlled by the same team. No runtime discovery needed.
  • High throughput: camera metadata, log streams, bulk config
  • Multi-language: QNX (C++) server, AAOS (Java/Kotlin) client, same .proto
  • Streaming: server-streaming for progress updates during OTA

Telematics, fleet management, and remote diagnostics connect the vehicle to cloud backends:

Use Case Protocol Why
Telemetry upload gRPC streaming Efficient binary, backpressure via HTTP/2
Remote command gRPC unary Typed request/response with auth
Map tile delivery gRPC / HTTP/3 Large payload streaming
OTA manifest fetch gRPC or HTTPS Server-controlled, versioned schema

Cloud endpoints don’t speak SOME/IP. They speak HTTP/gRPC. Your telematics module (AMSS/QNX) terminates SOME/IP on-vehicle and gRPC/HTTPS to cloud.

Over-the-air updates involve multiple stages, and different protocols at each:

sequenceDiagram
participant Cloud as OTA Cloud
participant Telem as Telematics (QNX/AMSS)
participant Update as UpdateManagement (SOME/IP)
participant lb as lb OTA Tool (your laptop)
Cloud->>Telem: gRPC/HTTPS: push manifest
Telem->>Update: SOME/IP: notify update available
lb->>Update: SOME/IP-SD FIND UpdateManagement
Update->>lb: SOME/IP-SD OFFER (IP:port)
lb->>Update: SOME/IP method — prepareUpdate()
lb->>Update: gRPC — stream firmware binary (high bandwidth)
Update->>lb: gRPC stream — progress callbacks
lb->>Update: SOME/IP method — finalizeUpdate()
Common Gotcha

“We switched everything to gRPC, so we don’t need SOME/IP” misses the point. gRPC requires both endpoints to know the .proto and connect directly. ECUs on Automotive Ethernet discover each other dynamically via SOME/IP-SD. They can’t assume a pre-shared .proto and static port. gRPC replaces SOME/IP only at boundaries where you control both sides (VM↔VM, tool↔known-service, vehicle↔cloud).

SOME/IP gRPC
Discovery Dynamic (SOME/IP-SD multicast) Static (known host:port or DNS)
Transport UDP + TCP (raw IP) HTTP/2 (TCP or vsock)
Serialization SOME/IP binary (from FIDL) Protocol Buffers (from .proto)
Schema FIDL / ARXML / Franca IDL .proto files
Streaming Events (pub/sub, no backpressure) Native bidirectional streaming with flow control
Ecosystem Automotive-specific (vsomeip, CANoe) Universal (Google, CNCF, every language)
Security SecOC (AUTOSAR), MACsec (Ethernet) TLS/mTLS (standard)
Typical scope In-vehicle ECU ↔ ECU VM ↔ VM, tool ↔ service, vehicle ↔ cloud
Bandwidth Automotive Ethernet (100M–1G) vsock, GigE, cloud (unlimited)
Who defines it AUTOSAR / GENIVI Google / CNCF
Your “lb” tool uses it for Discovering update services on vehicle bus Transferring firmware data and progress

One way to remember: SOME/IP searches on the bus (discovery); gRPC is a guaranteed pipe (direct connection).

Your “lb” OTA tool is a perfect case study in protocol layering:

The tool connects to the vehicle’s Automotive Ethernet (via diagnostic port, test bench, or DoIP gateway). It doesn’t know which IP/port hosts the update service. That depends on the vehicle variant, zone controller assignment, and runtime state.

lb tool → SOME/IP-SD FIND UpdateManagement → OFFER (192.168.1.10:30501)

SOME/IP-SD answers: “The update service is at this address.”

Initial handshake uses SOME/IP RPC, small and automotive-native:

lb tool → SOME/IP REQUEST prepareUpdate(packageId, manifestHash)
← SOME/IP RESPONSE (sessionId, status=READY)

This validates the vehicle is ready, checks version compatibility, and reserves resources, all through the vehicle’s native service layer.

Firmware binaries are hundreds of MB to GB. SOME/IP can handle this (with SOME/IP-TP segmentation), but gRPC is better suited:

  • HTTP/2 flow control: backpressure if the vehicle’s write buffer fills
  • Bidirectional streaming: send chunks while receiving progress
  • Efficient binary serialization: protobuf handles metadata alongside raw bytes
  • Tooling: your laptop runs Python/Go gRPC clients easily; vsomeip setup is heavier
lb tool → gRPC StreamDownload(sessionId) → chunks of firmware
← gRPC stream ProgressUpdate(percent, bytesWritten)

Post-transfer validation returns to SOME/IP. It’s the vehicle’s native service layer:

lb tool → SOME/IP REQUEST finalizeUpdate(sessionId, checksum)
← SOME/IP RESPONSE (status=SUCCESS, rebootRequired=true)
flowchart TB
subgraph VehicleBus["Vehicle (Automotive Ethernet)"]
SD["SOME/IP-SD<br/>224.244.224.245:30490"]
UM["UpdateManagement Service<br/>192.168.1.10:30501"]
SD --- UM
end
subgraph lbTool["lb OTA Tool (your laptop)"]
LB_SD["SOME/IP Client<br/>(discovery)"]
LB_GRPC["gRPC Client<br/>(data transfer)"]
LB_SD --- LB_GRPC
end
subgraph Protocols["Protocol Roles"]
P1["SOME/IP-SD → Find service"]
P2["SOME/IP RPC → Prepare / Finalize"]
P3["gRPC → Stream firmware binary"]
end
LB_SD -->|"1. FIND/OFFER"| SD
LB_SD -->|"2. prepareUpdate()"| UM
LB_GRPC -->|"3. StreamDownload()"| UM
LB_SD -->|"4. finalizeUpdate()"| UM
P1 -.-> LB_SD
P2 -.-> LB_SD
P3 -.-> LB_GRPC
vsock: Why Not Just Use TCP Between VMs?

vsock (virtual socket) is a socket family where addresses are (CID, port) (Context ID and port) instead of (IP, port). The hypervisor routes vsock packets between VMs without touching the physical NIC. Benefits: no IP configuration, no port conflicts with vehicle Ethernet, lower latency (no network stack traversal), and security isolation (VMs can’t sniff each other’s vsock unless explicitly bridged). gRPC over vsock is the standard pattern for QNX↔AAOS on Qualcomm platforms. You’ll see CID 2 for AAOS and CID 3 for QNX (exact values vary by platform config).

flowchart TD
Start["Need to communicate?"]
Start --> Q1{"Both endpoints<br/>you control?"}
Q1 -->|"No — vehicle ECUs<br/>discover dynamically"| SOMEIP["Use SOME/IP<br/>+ SOME/IP-SD"]
Q1 -->|"Yes"| Q2{"On vehicle Ethernet<br/>with other ECUs?"}
Q2 -->|"Yes — but you control<br/>both sides (VM, tool)"| Q3{"High bandwidth<br/>or streaming?"}
Q2 -->|"No — VM, cloud,<br/>or dev tool"| GRPC["Use gRPC<br/>+ protobuf"]
Q3 -->|"Yes — firmware,<br/>logs, camera meta"| GRPC
Q3 -->|"No — small RPC,<br/>discovery needed"| SOMEIP
Scenario Protocol Reason
Zone controller ↔ QNX gateway SOME/IP Dynamic discovery, automotive-native
QNX ↔ AAOS (same SoC) gRPC over vsock Controlled endpoints, high throughput
OTA tool ↔ vehicle (discovery) SOME/IP-SD Don’t know service address at build time
OTA tool ↔ vehicle (data transfer) gRPC Streaming, flow control, large payloads
Vehicle ↔ cloud backend gRPC / HTTPS Standard internet protocols
ADAS sensor fusion DDS Rich QoS, topic-based pub/sub
Legacy body ECU ↔ zone controller CAN signals MCU can’t run SOME/IP or gRPC
Where You'll See This

You’ll interact with both protocols regularly:

  • .proto files in the repo: search for UpdateManagement, VehicleProperty, TelemetryService. These define the gRPC contract between QNX and AAOS (or tool and vehicle).
  • protoc / Gradle codegen: AAOS builds generate Java/Kotlin stubs; QNX builds generate C++ stubs. IDL mismatch between VMs = runtime deserialize errors.
  • grpcurl / lb tool: when testing OTA or vehicle services from your laptop, you’ll use gRPC for data and SOME/IP for discovery. Know which flag controls each.
  • vsock port maps: platform docs list which gRPC services listen on which (CID, port). “Connection refused on vsock:50051” = QNX gRPC server not running or wrong CID.
  • Wireshark: filter someip for vehicle bus traffic, filter grpc || http2 for vsock/cloud traffic. Different filters, different debug skills.
  • Logs: QNX gRPC server logs show StreamDownload started; vsomeip logs show OFFER/Find. Combined OTA failure? Check BOTH log streams.

Debugging checklist for “lb OTA failed”:

  1. SOME/IP-SD: Did Find get an Offer? (If no → network/VLAN issue)
  2. SOME/IP RPC: Did prepareUpdate succeed? (If no → version/state issue)
  3. gRPC: Did StreamDownload connect and send chunks? (If no → vsock/port/firewall)
  4. SOME/IP RPC: Did finalizeUpdate succeed? (If no → checksum/validation issue)

Each phase uses a different protocol. Debug them independently.

Connect the Dots

Module 3.1 (Signals) is the legacy layer still running on MCUs. Module 3.2 (SOA) explains the service paradigm. Module 3.3 (SOME/IP) is the in-vehicle wire protocol. This page completes the picture with gRPC for controlled-endpoint communication. Module 5 (Qualcomm Cockpit) shows vsock CID assignments. Module 8 (Flashing & OTA) walks through the full update flow your “lb” tool implements.

  1. gRPC = HTTP/2 + protobuf + strongly typed .proto, for when you control both endpoints.
  2. SOME/IP = dynamic discovery + automotive-native RPC, for in-vehicle ECU communication.
  3. They’re complementary: SOME/IP finds services, gRPC moves bulk data.
  4. Your “lb” OTA tool uses SOME/IP for discovery/prepare/finalize and gRPC for firmware streaming.
  5. QNX↔AAOS uses gRPC over vsock, not SOME/IP, not TCP to an IP address.

Check Your Understanding

1. Why does the lb OTA tool use SOME/IP for discovery but gRPC for firmware transfer?

2. QNX and AAOS on the same SoC communicate via gRPC over vsock instead of SOME/IP. Why?

3. A zone controller offers DoorService via SOME/IP. An AAOS app wants to lock a door. What's the typical communication chain?