Colocation Discovery OpenXR API Reference
The XR_META_colocation_discovery
extension allows applications to discover physically
colocated Quest devices running the same application.
The extension allows applications to start a colocation advertisement and discover
nearby colocation advertisements. Advertisements started by an application are only
discoverable by the same application running on other Quest devices.
When starting a colocation advertisement, the advertisement is assigned a random UUID to identify it.
Applications also have the option of providing 1024 bytes of metadata to broadcast to other devices.
Upon discovering nearby colocation advertisements, the application will receive an event with the discovered
advertisement UUID, as well as any metadata the application provided the advertisement.
Note
Currently the Colocation Discovery API requires devices to be connected to the internet.Managing Colocation Advertisements The xrStartColocationAdvertisementMETA
function requests starting a
colocation advertisement, while the xrStopColocationAdvertisementMETA
function
requests that colocation advertisement stop. Both of these functions initiate an
asynchronous operation with their
asynchronous completion results returned in an event structure
(XrEventDataStartColocationAdvertisementCompleteMETA
and
XrEventDataStopColocationAdvertisementCompleteMETA
, respectively).
Colocation advertisements may stop without being explicitly requested for a
variety of reasons (for example: the user disables connectivity). Whenever an ongoing colocation advertisement stops, whether subsequent to an
xrStopColocationAdvertisementMETA
call or not, an
XrEventDataColocationAdvertisementCompleteMETA
event is queued.
Your application may only have one ongoing colocation advertisement per device at a time.
Managing Colocation Discovery Discovering other physically colocated devices, running the same application
and currently advertising, is known as “colocation discovery”.
It is a background process that is controlled by
xrStartColocationDiscoveryMETA
and
xrStopColocationDiscoveryMETA
.
Both of these functions initiate an asynchronous operation with their
asynchronous completion results returned in an event structure
(XrEventDataStartColocationDiscoveryCompleteMETA
and
XrEventDataStopColocationDiscoveryCompleteMETA
, respectively).
Once discovery is successfully started, the runtime will enqueue an asynchronous
XrEventDataColocationDiscoveryResultMETA
event whenever a new nearby colocation advertisement is discovered.
When colocation discovery stops for any reason (application requesting xrStopColocationDiscovery
or
otherwise), an XrEventDataColocationDiscoveryCompleteMETA
event is
enqueued.
Your application may only have one ongoing colocation discovery process per device at a time.
Before you begin working with Colocation Discovery, you need the following:
- Follow the Device Setup instructions. This will walk you through how to setup your device with a developer account, which is required to start developing with the Colocation Discovery API.
- A Meta Quest 2 or later headset running Meta Quest operating system v71 or later.
- The latest version of the Oculus OpenXR Mobile SDK (v71 or later).
To check your version of the Meta Horizon OS:
- In the headset, go to Settings > System > Software Update.
- Check the version.
- If the version is not v71 or higher, update the software to the latest available version.
Follow the instructions
here to set up your project for OpenXR.
In the Android manifest, add the following permissions to unlock the Colocation Discovery functionality.
<!-- Tell the system this app uses the Colocation Discovery extensions -->
<uses-permission android:name="com.oculus.permission.USE_COLOCATION_DISCOVERY_API" />
Then, if you are using OpenXR 1.1.42 or before, you’ll need to include the extension header for Colocation Discovery in your source code:
#include <openxr/meta_colocation_discovery.h>
Creating an Instance and Session The following extension names are required to use Colocation Discovery:
XR_META_COLOCATION_DISCOVERY_EXTENSION_NAME
Before using Colocation Discovery, first you need to check if the feature is supported on your device. You can do this by calling xrGetSystemProperties
and passing XrSystemColocationDiscoveryPropertiesMETA
via the XrSystemProperties::next
pointer. If supportsColocationDiscovery
is XR_TRUE
then you are ready to use Virtual Keyboard.
bool IsColocationDiscoverySupported() {
XrSystemProperties systemProperties{XR_TYPE_SYSTEM_PROPERTIES};
XrSystemColocationDiscoveryPropertiesMETA colocationDiscoveryProps{
XR_TYPE_SYSTEM_COLOCATION_DISCOVERY_PROPERTIES_META};
systemProperties.next = &colocationDiscoveryProps;
OXR(xrGetSystemProperties(instance_, systemId_, &systemProperties));
return colocationDiscoveryProps.supportsColocationDiscovery == XR_TRUE;
}
To access the OpenXR extension API, you must call xrGetInstanceProcAddr
to obtain pointers to the exported functions. Call the following to obtain pointers to the Colocation Discovery extension functions:
OXR(xrGetInstanceProcAddr(
instance_,
"xrStartColocationAdvertisementMETA",
(PFN_xrVoidFunction*)(&xrStartColocationAdvertisementMETA_)));
OXR(xrGetInstanceProcAddr(
instance_,
"xrStopColocationAdvertisementMETA",
(PFN_xrVoidFunction*)(&xrStopColocationAdvertisementMETA_)));
OXR(xrGetInstanceProcAddr(
instance_,
"xrStartColocationDiscoveryMETA",
(PFN_xrVoidFunction*)(&xrStartColocationDiscoveryMETA_)));
OXR(xrGetInstanceProcAddr(
instance_,
"xrStopColocationDiscoveryMETA",
(PFN_xrVoidFunction*)(&xrStopColocationDiscoveryMETA_)));
Once you confirm that the device supports Colocation Discovery and you’ve initialized the function pointers, you are ready to start a colocation advertisement and discover nearby advertisements!
To start a colocation advertisement, you can make the following call:
void StartColocationAdvertisement() {
XrColocationAdvertisementStartInfoMETA info{
XR_TYPE_COLOCATION_ADVERTISEMENT_START_INFO_META, nullptr};
std::vector<uint8_t> metadata = {1, 2, 3};
info.buffer = metadata.data();
info.bufferSize = metadata.size();
XrAsyncRequestIdFB requestId;
XrResult r;
OXR(r = xrStartColocationAdvertisementMETA(session_, &info, &requestId));
if (r != XR_SUCCESS) {
// Runtime was not able to schedule start advertisement operation, handle failure
}
}
To start discovering nearby colocation advertisements, you can make the following call:
void StartColocationDiscovery() {
XrColocationDiscoveryStartInfoMETA info{
XR_TYPE_COLOCATION_DISCOVERY_START_INFO_META, nullptr};
XrAsyncRequestIdFB requestId;
XrResult r;
OXR(r = xrStartColocationDiscoveryMETA(session_, &info, &requestId));
if (r != XR_SUCCESS) {
// Runtime was not able to schedule start discovery operation, handle failure
}
}
The Colocation Discovery runtime may trigger events in response to API requests and background processes. You should add handlers to listen for the following events and react accordingly:
void HandleXrEvents() override {
XrEventDataBuffer eventDataBuffer{};
// Poll for events
for (;;) {
XrEventDataBaseHeader* baseEventHeader = (XrEventDataBaseHeader*)(&eventDataBuffer);
baseEventHeader->type = XR_TYPE_EVENT_DATA_BUFFER;
baseEventHeader->next = nullptr;
XrResult r = xrPollEvent(Instance, &eventDataBuffer);
if (r != XR_SUCCESS) {
break;
}
switch (baseEventHeader->type) {
case XR_TYPE_EVENT_DATA_START_COLOCATION_ADVERTISEMENT_COMPLETE_META: {
const auto* event =
(XrEventDataStartColocationAdvertisementCompleteMETA*)(baseEventHeader);
if (event->result == XR_SUCCESS) {
OnColocationAdvertisementStarted(event->advertisementUuid);
}
} break;
case XR_TYPE_EVENT_DATA_STOP_COLOCATION_ADVERTISEMENT_COMPLETE_META: {
const auto* event =
(XrEventDataStartColocationDiscoveryCompleteMETA*)(baseEventHeader);
if (event->result == XR_SUCCESS) {
OnColocationDiscoveryStopComplete();
}
} break;
case XR_TYPE_EVENT_DATA_COLOCATION_ADVERTISEMENT_COMPLETE_META: {
OnColocationAdvertisementStopped();
} break;
case XR_TYPE_EVENT_DATA_START_COLOCATION_DISCOVERY_COMPLETE_META: {
const auto* event =
(XrEventDataStartColocationDiscoveryCompleteMETA*)(baseEventHeader);
if (event->result == XR_SUCCESS) {
OnColocationDiscoveryStarted();
}
} break;
case XR_TYPE_EVENT_DATA_COLOCATION_DISCOVERY_RESULT_META: {
const auto* event =
(XrEventDataColocationDiscoveryResultMETA*)(baseEventHeader);
OnColocationDiscoveryResult(
event->advertisementUuid,
event->bufferSize,
event->buffer
);
} break;
case XR_TYPE_EVENT_DATA_COLOCATION_DISCOVERY_COMPLETE_META: {
const auto* event =
(XrEventDataColocationDiscoveryCompleteMETA*)(baseEventHeader);
if (event->result == XR_SUCCESS) {
OnColocationDiscoveryStopped();
}
} break;
case XR_TYPE_EVENT_DATA_STOP_COLOCATION_DISCOVERY_COMPLETE_META: {
const auto* event =
(XrEventDataStopColocationDiscoveryCompleteMETA*)(baseEventHeader);
if (event->result == XR_SUCCESS) {
OnColocationDiscoveryStopComplete();
}
} break;
...
}
}
}
For a more complete example of how to integrate with Colocation Discovery, please see our
Sample Apps page.
We will now go into a bit more detail on the entire Colocation Discovery API provided by the meta_colocation_discovery
OpenXR extension.
The application can call xrStartColocationAdvertisementMETA
to start a
colocation advertisement.
The function will return an XrResult
indicating the success or failure of scheduling the async operation.
If the async operation was scheduled successfully, the runtime will return an XrEventDataStartColocationAdvertisementCompleteMETA
event once the start advertisement operation has completed.
XRAPI_ATTR XrResult XRAPI_CALL xrStartColocationAdvertisementMETA(
XrSession session,
const XrColocationAdvertisementStartInfoMETA* info,
XrAsyncRequestIdFB* advertisementRequestId);
session
: The XrSession object representing the current XR session.info
: A pointer to the XrColocationAdvertisementStartInfoMETA
struct.requestId
: An XrAsyncRequestIdFB
output parameter, and the variable it
points to will be populated with the ID of this asynchronous request.
Note that this ID is used for associating additional events with this
original call, in addition to the typical completion event.
typedef struct XrColocationAdvertisementStartInfoMETA {
XrStructureType type; // XR_TYPE_COLOCATION_ADVERTISEMENT_START_INFO_META
const void* XR_MAY_ALIAS next;
uint32_t bufferSize;
uint8_t* buffer;
} XrColocationAdvertisementStartInfoMETA;
type
: The XrStructureType of this structure. This should be set to XR_TYPE_COLOCATION_ADVERTISEMENT_START_INFO_META
.next
: A pointer to the next structure in a structure chain. This should be set to nullptr
.bufferSize
: The count of bytes used in the buffer
array. This cannot exceed XR_MAX_COLOCATION_DISCOVERY_BUFFER_SIZE_META
.buffer
: A byte array which allows the application to broadcast metadata about the colocation advertisement.
typedef struct XrEventDataStartColocationAdvertisementCompleteMETA {
XrStructureType type; // XR_TYPE_EVENT_DATA_START_COLOCATION_ADVERTISEMENT_COMPLETE_META
const void* XR_MAY_ALIAS next;
XrAsyncRequestIdFB advertisementRequestId;
XrResult result;
XrUuid advertisementUuid;
} XrEventDataStartColocationAdvertisementCompleteMETA;
type
: This is the XrStructureType
of this structure. This should be set to XR_TYPE_EVENT_DATA_START_COLOCATION_ADVERTISEMENT_COMPLETE_META
.next
: A pointer to the next structure in a structure chain. This will be set to nullptr
.advertisementRequestId
: An XrAsyncRequestIdFB
that identifies which request this event is in response to. This will have the same value as the advertisementRequestId
returned during an xrStartColocationAdvertisementMETA
call.result
: An XrResult
that specifies the request result. The valid values are:
XR_SUCCESS
XR_ERROR_RUNTIME_FAILURE
XR_COLOCATION_DISCOVERY_ALREADY_ADVERTISING_META
XR_ERROR_COLOCATION_DISCOVERY_NO_DISCOVERY_METHOD_META
XR_ERROR_COLOCATION_DISCOVERY_NETWORK_FAILED_META
advertisementUuid
: A random UUID which is assigned to this colocation advertisement, and is discoverable by other physically colocated devices running the same application.
Whenever an ongoing colocation advertisement stops, whether subsequent to an
xrStopColocationAdvertisementMETA
call or not, an
XrEventDataColocationAdvertisementCompleteMETA
event is queued.
typedef struct XrEventDataColocationAdvertisementCompleteMETA {
XrStructureType type; // XR_TYPE_EVENT_DATA_COLOCATION_ADVERTISEMENT_COMPLETE_META
const void* XR_MAY_ALIAS next;
XrAsyncRequestIdFB advertisementRequestId;
XrResult result;
} XrEventDataColocationAdvertisementCompleteMETA;
type
: This is the XrStructureType of this structure. This should be set to XR_TYPE_EVENT_DATA_COLOCATION_ADVERTISEMENT_COMPLETE_META
.next
: A pointer to the next structure in a structure chain. This will be set to nullptr
.advertisementRequestId
: An XrAsyncRequestIdFB
that identifies which request this event is in response to. This will have the same value as the advertisementRequestId
returned during an xrStartColocationAdvertisementMETA
call.result
: An XrResult
that specifies the request result. The valid values are:
XR_SUCCESS
XR_ERROR_RUNTIME_FAILURE
XR_ERROR_COLOCATION_DISCOVERY_NO_DISCOVERY_METHOD_META
The application can call xrStopColocationAdvertisementMETA
to stop a
colocation advertisement.
The function will return an XrResult
indicating the success or failure of scheduling the async operation.
If the async operation was scheduled successfully, the runtime will return an XrEventDataStopColocationAdvertisementCompleteMETA
event once the stop advertisement operation has completed.
XRAPI_ATTR XrResult XRAPI_CALL xrStopColocationAdvertisementMETA(
XrSession session,
const XrColocationAdvertisementStopInfoMETA* info,
XrAsyncRequestIdFB* requestId);
session
: The XrSession object representing the current XR session.info
: A pointer to the XrColocationAdvertisementStopInfoMETA
struct.requestId
: An XrAsyncRequestIdFB
output parameter, and the variable it
points to will be populated with the ID of this asynchronous request.
typedef struct XrColocationAdvertisementStopInfoMETA {
XrStructureType type; // XR_TYPE_COLOCATION_DISCOVERY_STOP_INFO_META
const void* XR_MAY_ALIAS next;
} XrColocationAdvertisementStopInfoMETA;
type
: This is the XrStructureType of this structure. This should be set to XR_TYPE_COLOCATION_DISCOVERY_STOP_INFO_META
.next
: A pointer to the next structure in a structure chain. This should be set to nullptr
.
typedef struct XrEventDataStopColocationAdvertisementCompleteMETA {
XrStructureType type; // XR_TYPE_EVENT_DATA_STOP_COLOCATION_ADVERTISEMENT_COMPLETE_META
const void* XR_MAY_ALIAS next;
XrAsyncRequestIdFB requestId;
XrResult result;
} XrEventDataStopColocationAdvertisementCompleteMETA;
type
: This is the XrStructureType
of this structure. This should be set to XR_TYPE_EVENT_DATA_STOP_COLOCATION_ADVERTISEMENT_COMPLETE_META
.next
: A pointer to the next structure in a structure chain. This will be set to nullptr
.requestId
: An XrAsyncRequestIdFB
that identifies which request this event is in response to.result
: An XrResult
that specifies the request result. The valid values are:
XR_SUCCESS
XR_ERROR_RUNTIME_FAILURE
XR_ERROR_COLOCATION_DISCOVERY_NETWORK_FAILED_META
The application can call xrStartColocationDiscoveryMETA
to start
discovering physically colocated devices.
The function will return an XrResult
indicating the success or failure of scheduling the async operation.
If the async operation was scheduled successfully, the runtime will return an XrEventDataStartColocationDiscoveryCompleteMETA
event once the start discovery operation has completed.
XRAPI_ATTR XrResult XRAPI_CALL xrStartColocationDiscoveryMETA(
XrSession session,
const XrColocationDiscoveryStartInfoMETA* info,
XrAsyncRequestIdFB* discoveryRequestId);
session
: The XrSession object representing the current XR session.info
: A pointer to the XrColocationDiscoveryStartInfoMETA
struct.discoveryRequestId
: An XrAsyncRequestIdFB
output parameter, and the variable it
points to will be populated with the ID of this asynchronous request.
Note that this ID is used for associating additional events with this
original call, in addition to the typical completion event.
typedef struct XrColocationDiscoveryStartInfoMETA {
XrStructureType type; // XR_TYPE_COLOCATION_DISCOVERY_START_INFO_META
const void* XR_MAY_ALIAS next;
} XrColocationDiscoveryStartInfoMETA;
type
: This is the XrStructureType of this structure. This should be set to XR_TYPE_COLOCATION_DISCOVERY_START_INFO_META
.next
: A pointer to the next structure in a structure chain. This should be set to nullptr
.
typedef struct XrEventDataStartColocationDiscoveryCompleteMETA {
XrStructureType type; // XR_TYPE_EVENT_DATA_START_COLOCATION_DISCOVERY_COMPLETE_META
const void* XR_MAY_ALIAS next;
XrAsyncRequestIdFB discoveryRequestId;
XrResult result;
} XrEventDataStartColocationDiscoveryCompleteMETA;
type
: This is the XrStructureType
of this structure. This should be set to XR_TYPE_EVENT_DATA_START_COLOCATION_DISCOVERY_COMPLETE_META
.next
: A pointer to the next structure in a structure chain. This will be set to nullptr
.discoveryRequestId
: An XrAsyncRequestIdFB
that identifies which request this event is in response to. This will have the same value as the discoveryRequestId
returned during an xrStartColocationDiscoveryMETA
call.result
: An XrResult
that specifies the request result. The valid values are:
XR_SUCCESS
XR_ERROR_RUNTIME_FAILURE
XR_COLOCATION_DISCOVERY_ALREADY_DISCOVERING_META
XR_ERROR_COLOCATION_DISCOVERY_NO_DISCOVERY_METHOD_META
XR_ERROR_COLOCATION_DISCOVERY_NETWORK_FAILED_META
On discovery is successfully started, whenever a nearby colocation advertisement is discovered an XrEventDataColocationDiscoveryResultMETA
event is queued.
typedef struct XrEventDataColocationDiscoveryResultMETA {
XrStructureType type; // XR_TYPE_EVENT_DATA_COLOCATION_DISCOVERY_RESULT_META
const void* XR_MAY_ALIAS next;
XrAsyncRequestIdFB discoveryRequestId;
XrUuid advertisementUuid;
uint32_t bufferSize;
uint8_t buffer[XR_MAX_COLOCATION_DISCOVERY_BUFFER_SIZE_META];
} XrEventDataColocationDiscoveryResultMETA;
type
: This is the XrStructureType of this structure. This should be set to XR_TYPE_EVENT_DATA_COLOCATION_DISCOVERY_RESULT_META
.next
: A pointer to the next structure in a structure chain. This will be set to nullptr
.discoveryRequestId
: An XrAsyncRequestIdFB
that identifies which request this event is in response to. This will have the same value as the discoveryRequestId
returned during an xrStartColocationDiscoveryMETA
call.advertisementUuid
: The discovered colocation advertisement UUID, which was assigned when the discovered device called xrStartColocationAdvertisementMETA
.bufferSize
: The count of bytes used in the buffer
array.buffer
: The byte array which is the application may set when the application starts the advertisement.
Whenever an ongoing colocation discovery stops, whether subsequent to an
xrStopColocationDiscoveryMETA
call or not, an
XrEventDataColocationDiscoveryCompleteMETA
event is queued.
typedef struct XrEventDataColocationDiscoveryCompleteMETA {
XrStructureType type; // XR_TYPE_EVENT_DATA_COLOCATION_DISCOVERY_COMPLETE_META
const void* XR_MAY_ALIAS next;
XrAsyncRequestIdFB discoveryRequestId;
XrResult result;
} XrEventDataColocationDiscoveryCompleteMETA;
type
: This is the XrStructureType of this structure. This should be set to XR_TYPE_EVENT_DATA_COLOCATION_DISCOVERY_COMPLETE_META
.next
: A pointer to the next structure in a structure chain. This will be set to nullptr
.discoveryRequestId
: An XrAsyncRequestIdFB
that identifies which request this event is in response to. This will have the same value as the discoveryRequestId
returned during an xrStartColocationDiscoveryMETA
call.result
: An XrResult
that specifies the request result. The valid values are:
XR_SUCCESS
XR_ERROR_RUNTIME_FAILURE
XR_ERROR_COLOCATION_DISCOVERY_NO_DISCOVERY_METHOD_META
The application can call xrStopColocationDiscoveryMETA
to stop a
colocation discovery.
The function will return an XrResult
indicating the success or failure of scheduling the async operation.
If the async operation was scheduled successfully, the runtime will return an XrEventDataStopColocationDiscoveryCompleteMETA
event once the stop discovery operation has completed.
XRAPI_ATTR XrResult XRAPI_CALL xrStopColocationDiscoveryMETA(
XrSession session,
const XrColocationDiscoveryStopInfoMETA* info,
XrAsyncRequestIdFB* requestId);
session
: The XrSession object representing the current XR session.info
: A pointer to the XrColocationDiscoveryStopInfoMETA
struct.requestId
: An XrAsyncRequestIdFB
output parameter, and the variable it
points to will be populated with the ID of this asynchronous request.
typedef struct XrColocationDiscoveryStopInfoMETA {
XrStructureType type; // XR_TYPE_COLOCATION_DISCOVERY_STOP_INFO_META
const void* XR_MAY_ALIAS next;
} XrColocationDiscoveryStopInfoMETA;
type
: This is the XrStructureType of this structure. This should be set to XR_TYPE_COLOCATION_DISCOVERY_STOP_INFO_META
.next
: A pointer to the next structure in a structure chain. This should be set to nullptr
.
typedef struct XrEventDataStopColocationDiscoveryCompleteMETA {
XrStructureType type; // XR_TYPE_EVENT_DATA_STOP_COLOCATION_DISCOVERY_COMPLETE_META
const void* XR_MAY_ALIAS next;
XrAsyncRequestIdFB requestId;
XrResult result;
} XrEventDataStopColocationDiscoveryCompleteMETA;
type
: This is the XrStructureType
of this structure. This should be set to XR_TYPE_EVENT_DATA_STOP_COLOCATION_DISCOVERY_COMPLETE_META
.next
: A pointer to the next structure in a structure chain. This will be set to nullptr
.requestId
: An XrAsyncRequestIdFB
that identifies which request this event is in response to.result
: An XrResult
that specifies the request result. The valid values are:
XR_SUCCESS
XR_ERROR_RUNTIME_FAILURE
XR_ERROR_COLOCATION_DISCOVERY_NETWORK_FAILED_META (-1000571001)
: The Colocation Discovery API currently requires internet access. This result indicates that the device was not able to reach Meta’s servers.XR_ERROR_COLOCATION_DISCOVERY_NO_DISCOVERY_METHOD_META (-1000571002)
: Colocation Discovery runtime was not able to find a discovery method. One common work around is ensuring the user has Bluetooth enabled on the device.XR_COLOCATION_DISCOVERY_ALREADY_ADVERTISING_META (1000571003)
: The runtime only supports one ongoing colocation advertisement for the application per device. If you receive this code upon attempting to start a colocation advertisement, it means there is already a colocation advertisement running.XR_COLOCATION_DISCOVERY_ALREADY_DISCOVERING_META (1000571004)
: The runtime only supports one ongoing colocation discovery for the application per device. If you receive this code upon attempting to start a colocation discovery, it means there is already a colocation discovery running.XR_ERROR_VALIDATION_FAILURE (-1)
: The function usage was invalid in some way. Please confirm your input parameters are valid. Check the device logs for additional information on what did not pass validation.XR_ERROR_RUNTIME_FAILURE (-2)
: The runtime failed to handle the function in an unexpected way that is not covered by another error result. Please refer to the device logs to gain additional information.XR_ERROR_FUNCTION_UNSUPPORTED (-7)
: The requested function was not found or is otherwise unsupported. Please read the Prerequisites section above to ensure the device supports the extension, and that your app has the requirement permissions to access it.XR_ERROR_FEATURE_UNSUPPORTED (-8)
: The extension is not currently available on the device. Please read the Prerequisites section above to ensure the device supports the extension, and that your app has the requirement permissions to access it.