@@ -38,8 +38,13 @@ constexpr auto SYSTEM_AUTHORITY = "org.khronos.openxr.system_runtime_broker";
3838constexpr auto BASE_PATH = " openxr" ;
3939constexpr auto ABI_PATH = " abi" ;
4040constexpr auto RUNTIMES_PATH = " runtimes" ;
41+ constexpr auto API_LAYERS_PATH = " api_layers" ;
42+ constexpr auto IMP_LAYER = " implicit" ;
43+ constexpr auto EXP_LAYER = " explicit" ;
4144
4245constexpr const char *getBrokerAuthority (bool systemBroker) { return systemBroker ? SYSTEM_AUTHORITY : AUTHORITY; }
46+ constexpr const char *getLayerTypePath (bool implicitLayer) { return implicitLayer ? IMP_LAYER : EXP_LAYER; }
47+ constexpr const char *getFunctionTypePath (bool runtimeFunctions) { return runtimeFunctions ? RUNTIMES_PATH : API_LAYERS_PATH; }
4348
4449struct BaseColumns {
4550 /* *
@@ -132,22 +137,27 @@ static constexpr auto TABLE_PATH = "functions";
132137 * runtime package and major version of OpenXR.
133138 *
134139 * @param systemBroker If the system runtime broker (instead of the installable one) should be queried.
140+ * @param runtimeFunctions If the runtime functions (instead of the API layer functions) should be queried.
135141 * @param majorVer The major version of OpenXR.
136142 * @param packageName The package name of the runtime.
137143 * @param abi The Android ABI name in use.
138144 * @return A content URI for the entire table: the function remapping for that runtime.
139145 */
140- static Uri makeContentUri (bool systemBroker, int majorVersion, std::string const &packageName, const char *abi) {
146+ static Uri makeContentUri (bool systemBroker, bool runtimeFunctions, int majorVersion, std::string const &packageName,
147+ const char *abi, std::string const &layerName) {
141148 auto builder = Uri_Builder::construct ();
142149 builder.scheme (" content" )
143150 .authority (getBrokerAuthority (systemBroker))
144151 .appendPath (BASE_PATH)
145152 .appendPath (std::to_string (majorVersion))
146153 .appendPath (ABI_PATH)
147154 .appendPath (abi)
148- .appendPath (RUNTIMES_PATH)
149- .appendPath (packageName)
150- .appendPath (TABLE_PATH);
155+ .appendPath (getFunctionTypePath (runtimeFunctions))
156+ .appendPath (packageName);
157+ if (!runtimeFunctions) {
158+ builder.appendPath (layerName);
159+ }
160+ builder.appendPath (TABLE_PATH);
151161 return builder.build ();
152162}
153163
@@ -164,6 +174,95 @@ struct Columns : BaseColumns {
164174};
165175} // namespace functions
166176
177+ namespace instance_extensions {
178+ /* *
179+ * Final path component to this URI.
180+ */
181+ static constexpr auto TABLE_PATH = " instance_extensions" ;
182+
183+ /* *
184+ * Create a content URI for querying all rows of the instance extensions supported by a given
185+ * API layer.
186+ *
187+ * @param systemBroker If the system runtime broker (instead of the installable one) should be queried.
188+ * @param majorVer The major version of OpenXR.
189+ * @param packageName The package name of the runtime.
190+ * @param abi The Android ABI name in use.
191+ * @param layerName The API layer name.
192+ * @return A content URI for the entire table: the function remapping for that runtime.
193+ */
194+ static Uri makeContentUri (bool systemBroker, int majorVersion, std::string const &packageName, const char *abi,
195+ std::string const &layerName) {
196+ auto builder = Uri_Builder::construct ();
197+ builder.scheme (" content" )
198+ .authority (getBrokerAuthority (systemBroker))
199+ .appendPath (BASE_PATH)
200+ .appendPath (std::to_string (majorVersion))
201+ .appendPath (ABI_PATH)
202+ .appendPath (abi)
203+ .appendPath (API_LAYERS_PATH)
204+ .appendPath (packageName)
205+ .appendPath (layerName)
206+ .appendPath (TABLE_PATH);
207+ return builder.build ();
208+ }
209+ struct Columns : BaseColumns {
210+ /* *
211+ * Constant for the INSTANCE_EXTENSION_NAMES column name
212+ */
213+ static constexpr auto INSTANCE_EXTENSION_NAMES = " instance_extension_names" ;
214+
215+ /* *
216+ * Constant for the INSTANCE_EXTENSION_VERSIONS column name
217+ */
218+ static constexpr auto INSTANCE_EXTENSION_VERSIONS = " instance_extension_versions" ;
219+ };
220+ } // namespace instance_extensions
221+
222+ namespace api_layer {
223+ /* *
224+ * Final path component to this URI.
225+ */
226+
227+ /* *
228+ * Create a content URI for querying all rows of the implicit/explicit API layer data for a given
229+ * runtime package and major version of OpenXR.
230+ *
231+ * @param systemBroker If the system runtime broker (instead of the installable one) should be queried.
232+ * @param majorVer The major version of OpenXR.
233+ * @param layerType The layer type of the API layer.
234+ * @param abi The Android ABI name in use.
235+ * @return A content URI for the entire table: the function remapping for that runtime.
236+ */
237+ static Uri makeContentUri (bool systemBroker, int majorVersion, std::string const &layerType, const char *abi) {
238+ auto builder = Uri_Builder::construct ();
239+ builder.scheme (" content" )
240+ .authority (getBrokerAuthority (systemBroker))
241+ .appendPath (BASE_PATH)
242+ .appendPath (std::to_string (majorVersion))
243+ .appendPath (ABI_PATH)
244+ .appendPath (abi)
245+ .appendPath (API_LAYERS_PATH)
246+ .appendPath (getLayerTypePath (layerType == IMP_LAYER));
247+ return builder.build ();
248+ }
249+ struct Columns : BaseColumns {
250+ // implicit or explicit
251+ static constexpr auto PACKAGE_NAME = " package_name" ;
252+ static constexpr auto FILE_FORMAT_VERSION = " file_format_version" ;
253+ static constexpr auto NAME = " name" ;
254+ static constexpr auto NATIVE_LIB_DIR = " native_lib_dir" ;
255+ static constexpr auto SO_FILENAME = " so_filename" ;
256+ static constexpr auto API_VERSION = " api_version" ;
257+ static constexpr auto IMPLEMENTATION_VERSION = " implementation_version" ;
258+ static constexpr auto DESCRIPTION = " description" ;
259+ static constexpr auto DISABLE_ENVIRONMENT = " disable_environment" ;
260+ static constexpr auto ENABLE_ENVIRONMENT = " enable_environment" ;
261+ static constexpr auto HAS_FUNCTIONS = " has_functions" ;
262+ static constexpr auto HAS_INSTANCE_EXTENSIONS = " has_instance_extensions" ;
263+ };
264+ } // namespace api_layer
265+
167266} // namespace
168267
169268static inline jni::Array<std::string> makeArray (std::initializer_list<const char *> &&list) {
@@ -221,7 +320,7 @@ static int populateFunctions(wrap::android::content::Context const &context, boo
221320 JsonManifestBuilder &builder) {
222321 jni::Array<std::string> projection = makeArray ({functions::Columns::FUNCTION_NAME, functions::Columns::SYMBOL_NAME});
223322
224- auto uri = functions::makeContentUri (systemBroker, XR_VERSION_MAJOR (XR_CURRENT_API_VERSION), packageName, ABI);
323+ auto uri = functions::makeContentUri (systemBroker, true , XR_VERSION_MAJOR (XR_CURRENT_API_VERSION), packageName, ABI, " " );
225324 ALOGI (" populateFunctions: Querying URI: %s" , uri.toString ().c_str ());
226325
227326 Cursor cursor = context.getContentResolver ().query (uri, projection);
@@ -245,11 +344,76 @@ static int populateFunctions(wrap::android::content::Context const &context, boo
245344 return 0 ;
246345}
247346
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 ());
347+ static int populateApiLayerFunctions (wrap::android::content::Context const &context, bool systemBroker,
348+ const std::string &packageName, std::string const &layerName, Json::Value &rootNode) {
349+ jni::Array<std::string> projection = makeArray ({functions::Columns::FUNCTION_NAME, functions::Columns::SYMBOL_NAME});
350+
351+ auto uri =
352+ functions::makeContentUri (systemBroker, false , XR_VERSION_MAJOR (XR_CURRENT_API_VERSION), packageName, ABI, layerName);
353+ ALOGI (" populateApiLayerFunctions: Querying URI: %s" , uri.toString ().c_str ());
354+
355+ Cursor cursor = context.getContentResolver ().query (uri, projection);
356+
357+ if (cursor.isNull ()) {
358+ ALOGE (" Null cursor when querying content resolver for API layer functions." );
359+ return -1 ;
360+ }
361+ if (cursor.getCount () < 1 ) {
362+ ALOGE (" Non-null but empty cursor when querying content resolver for API layer functions." );
363+ cursor.close ();
364+ return -1 ;
365+ }
366+ auto functionIndex = cursor.getColumnIndex (functions::Columns::FUNCTION_NAME);
367+ auto symbolIndex = cursor.getColumnIndex (functions::Columns::SYMBOL_NAME);
368+ while (cursor.moveToNext ()) {
369+ rootNode[" api_layer" ][" functions" ][cursor.getString (functionIndex)] = cursor.getString (symbolIndex);
370+ ALOGE (" function_name: %s, symbol_name: %s" , cursor.getString (functionIndex).c_str (), cursor.getString (symbolIndex).c_str ());
371+ }
372+
373+ cursor.close ();
374+ return 0 ;
375+ }
376+
377+ static int populateApiLayerInstanceExtensions (wrap::android::content::Context const &context, bool systemBroker,
378+ const std::string &packageName, std::string const &layerName, Json::Value &rootNode) {
379+ jni::Array<std::string> projection = makeArray (
380+ {instance_extensions::Columns::INSTANCE_EXTENSION_NAMES, instance_extensions::Columns::INSTANCE_EXTENSION_VERSIONS});
381+
382+ auto uri =
383+ instance_extensions::makeContentUri (systemBroker, XR_VERSION_MAJOR (XR_CURRENT_API_VERSION), packageName, ABI, layerName);
384+ ALOGI (" populateApiLayerInstanceExtensions: Querying URI: %s" , uri.toString ().c_str ());
385+
386+ Cursor cursor = context.getContentResolver ().query (uri, projection);
387+
388+ if (cursor.isNull ()) {
389+ ALOGE (" Null cursor when querying content resolver for API layer instance extensions." );
390+ return -1 ;
391+ }
392+ if (cursor.getCount () < 1 ) {
393+ ALOGE (" Non-null but empty cursor when querying content resolver for API layer instance extensions." );
394+ cursor.close ();
395+ return -1 ;
396+ }
397+ auto nameIndex = cursor.getColumnIndex (instance_extensions::Columns::INSTANCE_EXTENSION_NAMES);
398+ auto versionIndex = cursor.getColumnIndex (instance_extensions::Columns::INSTANCE_EXTENSION_VERSIONS);
399+ Json::Value extension (Json::objectValue);
400+ while (cursor.moveToNext ()) {
401+ extension[" name" ] = cursor.getString (nameIndex);
402+ extension[" extension_version" ] = cursor.getString (versionIndex);
403+ rootNode[" api_layer" ][" instance_extensions" ].append (extension);
404+ }
405+
406+ cursor.close ();
407+ return 0 ;
408+ }
409+
410+ // / Get cursor for active runtime or API layer, parameterized by target type and whether or not we use the system broker
411+ static bool getCursor (wrap::android::content::Context const &context, jni::Array<std::string> const &projection,
412+ std::string const &targetType, bool systemBroker, Cursor &cursor) {
413+ auto uri = (targetType == RUNTIMES_PATH)
414+ ? active_runtime::makeContentUri (systemBroker, XR_VERSION_MAJOR (XR_CURRENT_API_VERSION), ABI)
415+ : api_layer::makeContentUri (systemBroker, XR_VERSION_MAJOR (XR_CURRENT_API_VERSION), targetType, ABI);
416+ ALOGI (" getCursor: Querying URI: %s" , uri.toString ().c_str ());
253417 try {
254418 cursor = context.getContentResolver ().query (uri, projection);
255419 } catch (const std::exception &e) {
@@ -272,17 +436,19 @@ static bool getActiveRuntimeCursor(wrap::android::content::Context const &contex
272436 return true ;
273437}
274438
439+ static void getRuntimePackageName (std::string packageName) { return ; }
440+
275441int getActiveRuntimeVirtualManifest (wrap::android::content::Context const &context, Json::Value &virtualManifest) {
276442 jni::Array<std::string> projection = makeArray ({active_runtime::Columns::PACKAGE_NAME, active_runtime::Columns::NATIVE_LIB_DIR,
277443 active_runtime::Columns::SO_FILENAME, active_runtime::Columns::HAS_FUNCTIONS});
278444
279445 // First, try getting the installable broker's provider
280446 bool systemBroker = false ;
281447 Cursor cursor;
282- if (!getActiveRuntimeCursor (context, projection, systemBroker, cursor)) {
448+ if (!getCursor (context, projection, RUNTIMES_PATH , systemBroker, cursor)) {
283449 // OK, try the system broker as a fallback.
284450 systemBroker = true ;
285- getActiveRuntimeCursor (context, projection, systemBroker, cursor);
451+ getCursor (context, projection, RUNTIMES_PATH , systemBroker, cursor);
286452 }
287453
288454 if (cursor.isNull ()) {
@@ -314,6 +480,93 @@ int getActiveRuntimeVirtualManifest(wrap::android::content::Context const &conte
314480 virtualManifest = builder.build ();
315481 return 0 ;
316482}
483+
484+ static bool populateApiLayerManifest (bool systemBroker, std::string layerType, wrap::android::content::Context const &context,
485+ Cursor &cursor, std::vector<Json::Value> &layerRootNode) {
486+ auto packageName = cursor.getString (cursor.getColumnIndex (api_layer::Columns::PACKAGE_NAME));
487+ auto fileFormatVersion = cursor.getString (cursor.getColumnIndex (api_layer::Columns::FILE_FORMAT_VERSION));
488+ auto name = cursor.getString (cursor.getColumnIndex (api_layer::Columns::NAME));
489+ auto libDir = cursor.getString (cursor.getColumnIndex (active_runtime::Columns::NATIVE_LIB_DIR));
490+ auto fileName = cursor.getString (cursor.getColumnIndex (api_layer::Columns::SO_FILENAME));
491+ auto apiVersion = cursor.getString (cursor.getColumnIndex (api_layer::Columns::API_VERSION));
492+ auto implementationVersion = cursor.getString (cursor.getColumnIndex (api_layer::Columns::IMPLEMENTATION_VERSION));
493+ auto description = cursor.getString (cursor.getColumnIndex (api_layer::Columns::DESCRIPTION));
494+ auto has_instance_extensions = cursor.getString (cursor.getColumnIndex (api_layer::Columns::HAS_INSTANCE_EXTENSIONS));
495+ auto has_functions = cursor.getString (cursor.getColumnIndex (api_layer::Columns::HAS_FUNCTIONS));
496+
497+ __android_log_print (ANDROID_LOG_INFO, TAG, " Got api layer: type: %s, name: %s, native lib dir: %s, fileName: %s" ,
498+ layerType.c_str (), name.c_str (), libDir.c_str (), fileName.c_str ());
499+
500+ Json::Value rootNode (Json::objectValue);
501+ rootNode[" file_format_version" ] = fileFormatVersion;
502+ rootNode[" api_layer" ] = Json::objectValue;
503+ rootNode[" api_layer" ][" name" ] = name;
504+ rootNode[" api_layer" ][" library_path" ] = libDir + " /" + fileName;
505+ rootNode[" api_layer" ][" api_version" ] = apiVersion;
506+ rootNode[" api_layer" ][" implementation_version" ] = implementationVersion;
507+ rootNode[" api_layer" ][" description" ] = description;
508+ if (has_functions == " true" ) {
509+ rootNode[" api_layer" ][" functions" ] = Json::Value (Json::objectValue);
510+ populateApiLayerFunctions (context, systemBroker, packageName, name, rootNode);
511+ }
512+ if (has_instance_extensions == " true" ) {
513+ rootNode[" api_layer" ][" instance_extensions" ] = Json::Value (Json::arrayValue);
514+ populateApiLayerInstanceExtensions (context, systemBroker, packageName, name, rootNode);
515+ }
516+
517+ layerRootNode.push_back (rootNode);
518+
519+ return true ;
520+ }
521+
522+ static void enumerateApiLayerManifests (std::string layerType, wrap::android::content::Context const &context,
523+ jni::Array<std::string> &projection, std::vector<Json::Value> &virtualManifests) {
524+ Cursor cursor;
525+
526+ // First, try getting the installable broker's provider
527+ bool systemBroker = false ;
528+ if (!getCursor (context, projection, layerType, systemBroker, cursor)) {
529+ // OK, try the system broker as a fallback.
530+ systemBroker = true ;
531+ getCursor (context, projection, layerType, systemBroker, cursor);
532+ }
533+
534+ if (cursor.isNull ()) {
535+ return ;
536+ }
537+ cursor.moveToFirst ();
538+ for (int i = 0 ; i < cursor.getCount (); ++i) {
539+ populateApiLayerManifest (systemBroker, layerType, context, cursor, virtualManifests);
540+ cursor.moveToNext ();
541+ }
542+
543+ cursor.close ();
544+ }
545+
546+ int getApiLayerVirtualManifests (std::string layerType, wrap::android::content::Context const &context,
547+ std::vector<Json::Value> &virtualManifests) {
548+ static bool hasQueryBroker = false ;
549+ static std::vector<Json::Value> implicitLayerManifest;
550+ static std::vector<Json::Value> explicitLayerManifest;
551+
552+ __android_log_print (ANDROID_LOG_INFO, TAG, " Try to get %s API layer from broker!" , layerType.c_str ());
553+ if (!hasQueryBroker) {
554+ jni::Array<std::string> projection =
555+ makeArray ({api_layer::Columns::PACKAGE_NAME, api_layer::Columns::FILE_FORMAT_VERSION, api_layer::Columns::NAME,
556+ api_layer::Columns::NATIVE_LIB_DIR, api_layer::Columns::SO_FILENAME, api_layer::Columns::API_VERSION,
557+ api_layer::Columns::IMPLEMENTATION_VERSION, api_layer::Columns::DESCRIPTION,
558+ api_layer::Columns::HAS_FUNCTIONS, api_layer::Columns::HAS_INSTANCE_EXTENSIONS});
559+
560+ enumerateApiLayerManifests (IMP_LAYER, context, projection, implicitLayerManifest);
561+ enumerateApiLayerManifests (EXP_LAYER, context, projection, explicitLayerManifest);
562+
563+ hasQueryBroker = true ;
564+ }
565+
566+ virtualManifests = (layerType == IMP_LAYER) ? implicitLayerManifest : explicitLayerManifest;
567+ return 0 ;
568+ }
569+
317570} // namespace openxr_android
318571
319572#endif // __ANDROID__
0 commit comments