@@ -38,8 +38,12 @@ constexpr auto SYSTEM_AUTHORITY = "org.khronos.openxr.system_runtime_broker";
38
38
constexpr auto BASE_PATH = " openxr" ;
39
39
constexpr auto ABI_PATH = " abi" ;
40
40
constexpr auto RUNTIMES_PATH = " runtimes" ;
41
+ constexpr auto API_LAYERS_PATH = " api_layer" ;
42
+ constexpr auto IMP_LAYER = " implicit" ;
43
+ constexpr auto EXP_LAYER = " explicit" ;
41
44
42
45
constexpr const char *getBrokerAuthority (bool systemBroker) { return systemBroker ? SYSTEM_AUTHORITY : AUTHORITY; }
46
+ constexpr const char *getLayerTypePath (bool isImplicitLayer) { return isImplicitLayer ? IMP_LAYER : EXP_LAYER; }
43
47
44
48
struct BaseColumns {
45
49
/* *
@@ -164,6 +168,51 @@ struct Columns : BaseColumns {
164
168
};
165
169
} // namespace functions
166
170
171
+ namespace api_layer {
172
+ /* *
173
+ * Final path component to this URI.
174
+ */
175
+
176
+ /* *
177
+ * Create a content URI for querying all rows of the implicit/explicit API layer data for a given
178
+ * runtime package and major version of OpenXR.
179
+ *
180
+ * @param systemBroker If the system runtime broker (instead of the installable one) should be queried.
181
+ * @param majorVer The major version of OpenXR.
182
+ * @param layerType The layer type of the API layer.
183
+ * @param abi The Android ABI name in use.
184
+ * @return A content URI for the entire table: the function remapping for that runtime.
185
+ */
186
+ static Uri makeContentUri (bool systemBroker, int majorVersion, std::string const &layerType, const char *abi) {
187
+ auto builder = Uri_Builder::construct ();
188
+ builder.scheme (" content" )
189
+ .authority (getBrokerAuthority (systemBroker))
190
+ .appendPath (BASE_PATH)
191
+ .appendPath (std::to_string (majorVersion))
192
+ .appendPath (ABI_PATH)
193
+ .appendPath (abi)
194
+ .appendPath (API_LAYERS_PATH)
195
+ .appendPath (getLayerTypePath (layerType == IMP_LAYER));
196
+ return builder.build ();
197
+ }
198
+ struct Columns : BaseColumns {
199
+ // implicit or explicit
200
+ static constexpr auto FILE_FORMAT_VERSION = " file_format_version" ;
201
+ static constexpr auto NAME = " name" ;
202
+ static constexpr auto NATIVE_LIB_DIR = " native_lib_dir" ;
203
+ static constexpr auto SO_FILENAME = " so_filename" ;
204
+ static constexpr auto API_VERSION = " api_version" ;
205
+ static constexpr auto IMPLEMENTATION_VERSION = " implementation_version" ;
206
+ static constexpr auto DESCRIPTION = " description" ;
207
+ static constexpr auto ENABLE_ENVIRONMENT = " enable_environment" ;
208
+ static constexpr auto DISABLE_ENVIRONMENT = " disable_environment" ;
209
+ static constexpr auto FUNCTIONS = " functions" ;
210
+ // extensions names will be combined like "extension1&extension2"
211
+ static constexpr auto INSTANCE_EXTENSION_NAMES = " instance_extension_names" ;
212
+ static constexpr auto INSTANCE_EXTENSION_VERSIONS = " instance_extension_versions" ;
213
+ };
214
+ } // namespace api_layer
215
+
167
216
} // namespace
168
217
169
218
static inline jni::Array<std::string> makeArray (std::initializer_list<const char *> &&list) {
@@ -245,11 +294,13 @@ static int populateFunctions(wrap::android::content::Context const &context, boo
245
294
return 0 ;
246
295
}
247
296
248
- // / Get cursor for active runtime, parameterized by whether or not we use the system broker
249
- static bool getActiveRuntimeCursor (wrap::android::content::Context const &context, jni::Array<std::string> const &projection,
250
- bool systemBroker, Cursor &cursor) {
251
- auto uri = active_runtime::makeContentUri (systemBroker, XR_VERSION_MAJOR (XR_CURRENT_API_VERSION), ABI);
252
- ALOGI (" getActiveRuntimeCursor: Querying URI: %s" , uri.toString ().c_str ());
297
+ // / Get cursor for active runtime or API layer, parameterized by target type and whether or not we use the system broker
298
+ static bool getCursor (wrap::android::content::Context const &context, jni::Array<std::string> const &projection,
299
+ std::string const &targetType, bool systemBroker, Cursor &cursor) {
300
+ auto uri = (targetType == RUNTIMES_PATH)
301
+ ? active_runtime::makeContentUri (systemBroker, XR_VERSION_MAJOR (XR_CURRENT_API_VERSION), ABI)
302
+ : api_layer::makeContentUri (systemBroker, XR_VERSION_MAJOR (XR_CURRENT_API_VERSION), targetType, ABI);
303
+ ALOGI (" getCursor: Querying URI: %s" , uri.toString ().c_str ());
253
304
try {
254
305
cursor = context.getContentResolver ().query (uri, projection);
255
306
} catch (const std::exception &e) {
@@ -279,10 +330,10 @@ int getActiveRuntimeVirtualManifest(wrap::android::content::Context const &conte
279
330
// First, try getting the installable broker's provider
280
331
bool systemBroker = false ;
281
332
Cursor cursor;
282
- if (!getActiveRuntimeCursor (context, projection, systemBroker, cursor)) {
333
+ if (!getCursor (context, projection, RUNTIMES_PATH , systemBroker, cursor)) {
283
334
// OK, try the system broker as a fallback.
284
335
systemBroker = true ;
285
- getActiveRuntimeCursor (context, projection, systemBroker, cursor);
336
+ getCursor (context, projection, RUNTIMES_PATH , systemBroker, cursor);
286
337
}
287
338
288
339
if (cursor.isNull ()) {
@@ -314,6 +365,132 @@ int getActiveRuntimeVirtualManifest(wrap::android::content::Context const &conte
314
365
virtualManifest = builder.build ();
315
366
return 0 ;
316
367
}
368
+
369
+ static bool populateApiLayerManifest (std::string layerType, Cursor &cursor, std::vector<Json::Value> &layerRootNode) {
370
+ auto fileFormatVersion = cursor.getString (cursor.getColumnIndex (api_layer::Columns::FILE_FORMAT_VERSION));
371
+ auto name = cursor.getString (cursor.getColumnIndex (api_layer::Columns::NAME));
372
+ auto libDir = cursor.getString (cursor.getColumnIndex (active_runtime::Columns::NATIVE_LIB_DIR));
373
+ auto fileName = cursor.getString (cursor.getColumnIndex (api_layer::Columns::SO_FILENAME));
374
+ auto apiVersion = cursor.getString (cursor.getColumnIndex (api_layer::Columns::API_VERSION));
375
+ auto implementationVersion = cursor.getString (cursor.getColumnIndex (api_layer::Columns::IMPLEMENTATION_VERSION));
376
+ auto description = cursor.getString (cursor.getColumnIndex (api_layer::Columns::DESCRIPTION));
377
+ auto disableEnv = cursor.getString (cursor.getColumnIndex (api_layer::Columns::DISABLE_ENVIRONMENT));
378
+ auto enableEnv = cursor.getString (cursor.getColumnIndex (api_layer::Columns::ENABLE_ENVIRONMENT));
379
+ auto extensionNames = cursor.getString (cursor.getColumnIndex (api_layer::Columns::INSTANCE_EXTENSION_NAMES));
380
+ auto extensionVersions = cursor.getString (cursor.getColumnIndex (api_layer::Columns::INSTANCE_EXTENSION_VERSIONS));
381
+ auto functions = cursor.getString (cursor.getColumnIndex (api_layer::Columns::FUNCTIONS));
382
+
383
+ __android_log_print (ANDROID_LOG_INFO, TAG, " Got api layer: type: %s, name: %s, native lib dir: %s, fileName: %s, functions: %s" ,
384
+ layerType.c_str (), name.c_str (), libDir.c_str (), fileName.c_str (), functions.c_str ());
385
+
386
+ Json::Value rootNode (Json::objectValue);
387
+ rootNode[" file_format_version" ] = fileFormatVersion;
388
+ rootNode[" api_layer" ] = Json::objectValue;
389
+ rootNode[" api_layer" ][" name" ] = name;
390
+ rootNode[" api_layer" ][" library_path" ] = libDir + " /" + fileName;
391
+ rootNode[" api_layer" ][" api_version" ] = apiVersion;
392
+ rootNode[" api_layer" ][" implementation_version" ] = implementationVersion;
393
+ rootNode[" api_layer" ][" description" ] = description;
394
+ rootNode[" api_layer" ][" disable_environment" ] = disableEnv;
395
+ rootNode[" api_layer" ][" enable_environment" ] = enableEnv;
396
+
397
+ rootNode[" api_layer" ][" instance_extensions" ] = Json::Value (Json::arrayValue);
398
+ std::vector<std::string> nameVec;
399
+ std::vector<std::string> versionVec;
400
+ // extract extension names
401
+ std::istringstream issNames (extensionNames);
402
+ std::string item;
403
+ while (std::getline (issNames, item, ' &' )) {
404
+ nameVec.push_back (item);
405
+ }
406
+ // extract extension versions
407
+ std::istringstream issVersions (extensionVersions);
408
+ while (std::getline (issVersions, item, ' &' )) {
409
+ versionVec.push_back (item);
410
+ }
411
+
412
+ Json::Value extension (Json::objectValue);
413
+ if (nameVec.size () == versionVec.size ()) {
414
+ for (int i = 0 ; i < nameVec.size (); ++i) {
415
+ extension[" name" ] = nameVec[i];
416
+ extension[" extension_version" ] = versionVec[i];
417
+ rootNode[" api_layer" ][" instance_extensions" ].append (extension);
418
+ __android_log_print (ANDROID_LOG_INFO, TAG, " extension name: %s, extension version: %s" , nameVec[i].c_str (),
419
+ versionVec[i].c_str ());
420
+ }
421
+ } else {
422
+ __android_log_print (ANDROID_LOG_INFO, TAG, " api layer extension name not match extension version!" );
423
+ }
424
+
425
+ std::vector<std::string> functionNameVec;
426
+ std::vector<std::string> symbolVec;
427
+ std::istringstream issFunctions (functions);
428
+ while (std::getline (issFunctions, item, ' &' )) {
429
+ std::size_t pos = item.find (' :' );
430
+ if (pos != item.npos ) {
431
+ functionNameVec.push_back (item.substr (0 , pos));
432
+ symbolVec.push_back (item.substr (pos + 1 , item.size ()));
433
+ }
434
+ }
435
+
436
+ rootNode[" api_layer" ][" functions" ] = Json::Value (Json::objectValue);
437
+ if (functions != " None" ) {
438
+ for (int i = 0 ; i < functionNameVec.size (); ++i) {
439
+ rootNode[" api_layer" ][" functions" ][functionNameVec[i]] = symbolVec[i];
440
+ __android_log_print (ANDROID_LOG_INFO, TAG, " function name: %s, symbol: %s" , functionNameVec[i].c_str (),
441
+ symbolVec[i].c_str ());
442
+ }
443
+ } else {
444
+ __android_log_print (ANDROID_LOG_INFO, TAG, " functions field not existed!" );
445
+ }
446
+
447
+ layerRootNode.push_back (rootNode);
448
+
449
+ return true ;
450
+ }
451
+
452
+ static void enumerateApiLayerManifests (std::string layerType, wrap::android::content::Context const &context,
453
+ jni::Array<std::string> &projection, std::vector<Json::Value> &virtualManifests) {
454
+ Cursor cursor;
455
+
456
+ getCursor (context, projection, layerType, false , cursor);
457
+ if (cursor.isNull ()) {
458
+ return ;
459
+ }
460
+ cursor.moveToFirst ();
461
+ for (int i = 0 ; i < cursor.getCount (); ++i) {
462
+ populateApiLayerManifest (layerType, cursor, virtualManifests);
463
+ cursor.moveToNext ();
464
+ }
465
+
466
+ cursor.close ();
467
+ }
468
+
469
+ int getApiLayerVirtualManifests (std::string layerType, wrap::android::content::Context const &context,
470
+ std::vector<Json::Value> &virtualManifests) {
471
+ static bool hasQueryBroker = false ;
472
+ static std::vector<Json::Value> implicitLayerManifest;
473
+ static std::vector<Json::Value> explicitLayerManifest;
474
+
475
+ __android_log_print (ANDROID_LOG_INFO, TAG, " Try to get %s API layer from broker!" , layerType.c_str ());
476
+ if (!hasQueryBroker) {
477
+ jni::Array<std::string> projection =
478
+ makeArray ({api_layer::Columns::FILE_FORMAT_VERSION, api_layer::Columns::NAME, api_layer::Columns::NATIVE_LIB_DIR,
479
+ api_layer::Columns::SO_FILENAME, api_layer::Columns::API_VERSION, api_layer::Columns::IMPLEMENTATION_VERSION,
480
+ api_layer::Columns::DESCRIPTION, api_layer::Columns::ENABLE_ENVIRONMENT,
481
+ api_layer::Columns::DISABLE_ENVIRONMENT, api_layer::Columns::FUNCTIONS,
482
+ api_layer::Columns::INSTANCE_EXTENSION_NAMES, api_layer::Columns::INSTANCE_EXTENSION_VERSIONS});
483
+
484
+ enumerateApiLayerManifests (IMP_LAYER, context, projection, implicitLayerManifest);
485
+ enumerateApiLayerManifests (EXP_LAYER, context, projection, explicitLayerManifest);
486
+
487
+ hasQueryBroker = true ;
488
+ }
489
+
490
+ virtualManifests = (layerType == IMP_LAYER) ? implicitLayerManifest : explicitLayerManifest;
491
+ return 0 ;
492
+ }
493
+
317
494
} // namespace openxr_android
318
495
319
496
#endif // __ANDROID__
0 commit comments