@@ -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,75 @@ 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+ }
371+
372+ cursor.close ();
373+ return 0 ;
374+ }
375+
376+ static int populateApiLayerInstanceExtensions (wrap::android::content::Context const &context, bool systemBroker,
377+ const std::string &packageName, std::string const &layerName, Json::Value &rootNode) {
378+ jni::Array<std::string> projection = makeArray (
379+ {instance_extensions::Columns::INSTANCE_EXTENSION_NAMES, instance_extensions::Columns::INSTANCE_EXTENSION_VERSIONS});
380+
381+ auto uri =
382+ instance_extensions::makeContentUri (systemBroker, XR_VERSION_MAJOR (XR_CURRENT_API_VERSION), packageName, ABI, layerName);
383+ ALOGI (" populateApiLayerInstanceExtensions: Querying URI: %s" , uri.toString ().c_str ());
384+
385+ Cursor cursor = context.getContentResolver ().query (uri, projection);
386+
387+ if (cursor.isNull ()) {
388+ ALOGE (" Null cursor when querying content resolver for API layer instance extensions." );
389+ return -1 ;
390+ }
391+ if (cursor.getCount () < 1 ) {
392+ ALOGE (" Non-null but empty cursor when querying content resolver for API layer instance extensions." );
393+ cursor.close ();
394+ return -1 ;
395+ }
396+ auto nameIndex = cursor.getColumnIndex (instance_extensions::Columns::INSTANCE_EXTENSION_NAMES);
397+ auto versionIndex = cursor.getColumnIndex (instance_extensions::Columns::INSTANCE_EXTENSION_VERSIONS);
398+ Json::Value extension (Json::objectValue);
399+ while (cursor.moveToNext ()) {
400+ extension[" name" ] = cursor.getString (nameIndex);
401+ extension[" extension_version" ] = cursor.getString (versionIndex);
402+ rootNode[" api_layer" ][" instance_extensions" ].append (extension);
403+ }
404+
405+ cursor.close ();
406+ return 0 ;
407+ }
408+
409+ // / Get cursor for active runtime or API layer, parameterized by target type and whether or not we use the system broker
410+ static bool getCursor (wrap::android::content::Context const &context, jni::Array<std::string> const &projection,
411+ std::string const &targetType, bool systemBroker, Cursor &cursor) {
412+ auto uri = (targetType == RUNTIMES_PATH)
413+ ? active_runtime::makeContentUri (systemBroker, XR_VERSION_MAJOR (XR_CURRENT_API_VERSION), ABI)
414+ : api_layer::makeContentUri (systemBroker, XR_VERSION_MAJOR (XR_CURRENT_API_VERSION), targetType, ABI);
415+ ALOGI (" getCursor: Querying URI: %s" , uri.toString ().c_str ());
253416 try {
254417 cursor = context.getContentResolver ().query (uri, projection);
255418 } catch (const std::exception &e) {
@@ -279,10 +442,10 @@ int getActiveRuntimeVirtualManifest(wrap::android::content::Context const &conte
279442 // First, try getting the installable broker's provider
280443 bool systemBroker = false ;
281444 Cursor cursor;
282- if (!getActiveRuntimeCursor (context, projection, systemBroker, cursor)) {
445+ if (!getCursor (context, projection, RUNTIMES_PATH , systemBroker, cursor)) {
283446 // OK, try the system broker as a fallback.
284447 systemBroker = true ;
285- getActiveRuntimeCursor (context, projection, systemBroker, cursor);
448+ getCursor (context, projection, RUNTIMES_PATH , systemBroker, cursor);
286449 }
287450
288451 if (cursor.isNull ()) {
@@ -314,6 +477,93 @@ int getActiveRuntimeVirtualManifest(wrap::android::content::Context const &conte
314477 virtualManifest = builder.build ();
315478 return 0 ;
316479}
480+
481+ static bool populateApiLayerManifest (bool systemBroker, std::string layerType, wrap::android::content::Context const &context,
482+ Cursor &cursor, std::vector<Json::Value> &layerRootNode) {
483+ auto packageName = cursor.getString (cursor.getColumnIndex (api_layer::Columns::PACKAGE_NAME));
484+ auto fileFormatVersion = cursor.getString (cursor.getColumnIndex (api_layer::Columns::FILE_FORMAT_VERSION));
485+ auto name = cursor.getString (cursor.getColumnIndex (api_layer::Columns::NAME));
486+ auto libDir = cursor.getString (cursor.getColumnIndex (active_runtime::Columns::NATIVE_LIB_DIR));
487+ auto fileName = cursor.getString (cursor.getColumnIndex (api_layer::Columns::SO_FILENAME));
488+ auto apiVersion = cursor.getString (cursor.getColumnIndex (api_layer::Columns::API_VERSION));
489+ auto implementationVersion = cursor.getString (cursor.getColumnIndex (api_layer::Columns::IMPLEMENTATION_VERSION));
490+ auto description = cursor.getString (cursor.getColumnIndex (api_layer::Columns::DESCRIPTION));
491+ auto has_instance_extensions = cursor.getString (cursor.getColumnIndex (api_layer::Columns::HAS_INSTANCE_EXTENSIONS));
492+ auto has_functions = cursor.getString (cursor.getColumnIndex (api_layer::Columns::HAS_FUNCTIONS));
493+
494+ __android_log_print (ANDROID_LOG_INFO, TAG, " Got api layer: type: %s, name: %s, native lib dir: %s, fileName: %s" ,
495+ layerType.c_str (), name.c_str (), libDir.c_str (), fileName.c_str ());
496+
497+ Json::Value rootNode (Json::objectValue);
498+ rootNode[" file_format_version" ] = fileFormatVersion;
499+ rootNode[" api_layer" ] = Json::objectValue;
500+ rootNode[" api_layer" ][" name" ] = name;
501+ rootNode[" api_layer" ][" library_path" ] = libDir + " /" + fileName;
502+ rootNode[" api_layer" ][" api_version" ] = apiVersion;
503+ rootNode[" api_layer" ][" implementation_version" ] = implementationVersion;
504+ rootNode[" api_layer" ][" description" ] = description;
505+ if (has_functions == " true" ) {
506+ rootNode[" api_layer" ][" functions" ] = Json::Value (Json::objectValue);
507+ populateApiLayerFunctions (context, systemBroker, packageName, name, rootNode);
508+ }
509+ if (has_instance_extensions == " true" ) {
510+ rootNode[" api_layer" ][" instance_extensions" ] = Json::Value (Json::arrayValue);
511+ populateApiLayerInstanceExtensions (context, systemBroker, packageName, name, rootNode);
512+ }
513+
514+ layerRootNode.push_back (rootNode);
515+
516+ return true ;
517+ }
518+
519+ static void enumerateApiLayerManifests (std::string layerType, wrap::android::content::Context const &context,
520+ jni::Array<std::string> &projection, std::vector<Json::Value> &virtualManifests) {
521+ Cursor cursor;
522+
523+ // First, try getting the installable broker's provider
524+ bool systemBroker = false ;
525+ if (!getCursor (context, projection, layerType, systemBroker, cursor)) {
526+ // OK, try the system broker as a fallback.
527+ systemBroker = true ;
528+ getCursor (context, projection, layerType, systemBroker, cursor);
529+ }
530+
531+ if (cursor.isNull ()) {
532+ return ;
533+ }
534+ cursor.moveToFirst ();
535+ for (int i = 0 ; i < cursor.getCount (); ++i) {
536+ populateApiLayerManifest (systemBroker, layerType, context, cursor, virtualManifests);
537+ cursor.moveToNext ();
538+ }
539+
540+ cursor.close ();
541+ }
542+
543+ int getApiLayerVirtualManifests (std::string layerType, wrap::android::content::Context const &context,
544+ std::vector<Json::Value> &virtualManifests) {
545+ static bool hasQueryBroker = false ;
546+ static std::vector<Json::Value> implicitLayerManifest;
547+ static std::vector<Json::Value> explicitLayerManifest;
548+
549+ __android_log_print (ANDROID_LOG_INFO, TAG, " Try to get %s API layer from broker!" , layerType.c_str ());
550+ if (!hasQueryBroker) {
551+ jni::Array<std::string> projection =
552+ makeArray ({api_layer::Columns::PACKAGE_NAME, api_layer::Columns::FILE_FORMAT_VERSION, api_layer::Columns::NAME,
553+ api_layer::Columns::NATIVE_LIB_DIR, api_layer::Columns::SO_FILENAME, api_layer::Columns::API_VERSION,
554+ api_layer::Columns::IMPLEMENTATION_VERSION, api_layer::Columns::DESCRIPTION,
555+ api_layer::Columns::HAS_FUNCTIONS, api_layer::Columns::HAS_INSTANCE_EXTENSIONS});
556+
557+ enumerateApiLayerManifests (IMP_LAYER, context, projection, implicitLayerManifest);
558+ enumerateApiLayerManifests (EXP_LAYER, context, projection, explicitLayerManifest);
559+
560+ hasQueryBroker = true ;
561+ }
562+
563+ virtualManifests = (layerType == IMP_LAYER) ? implicitLayerManifest : explicitLayerManifest;
564+ return 0 ;
565+ }
566+
317567} // namespace openxr_android
318568
319569#endif // __ANDROID__
0 commit comments