C
Car Rendering Service Example
Demonstrates how to render multiple Qt Quick3D views in a service and simultaneously display them from surfaces managed by multiple activities.

Building and deploying the example
See specific steps relating to building and deploying Qt for Android Automotive examples.
Overview
The Car Rendering Service example shows how to integrate a QtRaaSApplication rendering engine into an Android Service that can render individual QML items onto surfaces provided by Android activities.
Each activity hosts one or more ObservableSurfaceView objects that wrap and simplify the management of native Surface lifecycles. These surfaces are sent through an AIDL interface to the background RenderingService, which associates them with specific QML items identified by their IDs.
In this example, each Item, hosts a View3D. Each View3D object renders a shared standalone 3D scene, from POV of a separate Camera. This reference architecture demonstrates how to save system resources by sharing the same graphical resources in a single process while the results can be displayed by external applications.
The service renders those items offscreen using QAndroidSurfaceRenderEngine and composes the results directly onto the provided Android surfaces. Android surfaces can also send the touch input events that they receive to the service, which will be separately dispatched to the Quick items. This enables complex multi-surface, multi-display rendering scenarios suitable for automotive display systems and multi-window Android environments.
How It Works
The architecture consists of:
- Activities: Create and manage
ObservableSurfaceViewinstances, which are lightweight wrappers aroundSurfaceViewthat simplify handling surface lifecycle callbacks. When a surface becomes available, it is registered with the rendering service using the AIDL interface. - Rendering Service: To simplify this example, runs in the same process and owns the Qt rendering engine. It maintains a mapping between Android surfaces and corresponding QML item IDs. When notified, it starts pushing the rendered frames of an item to the associated surface.
- Qt Quick Item: Defined in
Main.qml. The root object is an Item, and only its **direct children** can be referenced by ID from the Android side. Each registered surface is associated with one of these direct child items for rendering. - AIDL Interface: Facilitates communication between the
RenderingServiceand client Activities. Activities bind to the service and call remote methods such assetSurface()andsendTouchEvent()to connect or disconnect rendering targets and send touch input events to the Quick Items.
C++ Entry Point
The C++ side initializes Qt, sets up the QAndroidSurfaceRenderEngine, and loads the Main.qml of the Quick application.
int main(int argc, char *argv[]) { QAndroidRaaSApplication app(argc, argv); QAndroidSurfaceRenderEngine *renderEngine = new QAndroidSurfaceRenderEngine(); renderEngine->load(QLatin1String(":/qt/qml/car_rendering_service_module/Main.qml")); return app.exec(); }
QML Scene
The QML scene is defined in Main.qml and uses an Item as its root object. Only direct children of this root Item can be referenced by their IDs from the Android side. Each surface registered through the AIDL interface is associated with one of these direct child items.
Item { id: orbitingCameraView View3D { id: orbitingView3d anchors.fill: parent importScene: standAloneScene camera: cameraPerspectiveOrb } }
Note: The QAndroidSurfaceRenderEngine manages the position and size of the referenced items. This means that if you set any anchors or sizing properties on an Item that is bound to a surface, those properties will be ignored. The item's geometry is automatically adjusted to match the size of the bound surface.
Android Integration
The Android service is implemented in Java and defined in the manifest as a service. It instantiates a QtRaaSApplication this loads the Qt runtime and starts the Qt Quick application. It implements the AIDL-defined IRenderingService interface to bridge the bound clients to the rendering engine.
interface IRenderingService {
void setSurface(in Surface surface, String itemId);
void unsetSurface(String itemId);
void motionEvent(in MotionEvent event, String itemId);
}The service class implements and instantiates the binder and returns it when clients bind.
public class RenderingService extends Service {
private static final String TAG = "RenderService";
private QtRaaSApplication qtService;
// Single Binder instance exposed to all clients
private final IRenderingService.Stub binder = new IRenderingService.Stub() {
@Override
public void setSurface(Surface surface, String itemId) {
qtService.setSurface(surface, itemId);
}
@Override
public void unsetSurface(String itemId) {
qtService.unsetSurface(itemId);
}
@Override
public void motionEvent(MotionEvent event, String itemId) {
qtService.sendTouchEvent(event, itemId);
}
};
}Each activity creates its own ObservableSurfaceView instances and binds to the service. When the surface becomes available, the activity passes it together with a QML item ID to the service. When the surface becomes invalid or is destroyed, it notifies the service to unset the surface for that particular item, so that the QtRaaSApplication stops rendering that item.
private void updateSurface(Surface surface, String qmlItemId)
{
if (m_renderingService == null)
return;
try {
if (surface != null)
m_renderingService.setSurface(surface, qmlItemId);
else
m_renderingService.unsetSurface(qmlItemId);
} catch (RemoteException ignored) {
}
}Available under certain Qt licenses.
Find out more.