Android: Get rid of init classes mechanism

Make it more the responsibility of the module to ensure
any initialization is done under JNI_OnLoad().

Qt for Android have these mechanism to set the context to Java static
classes used by various modules, where the QtLoader tries to look for
setContext(Context), setActivity(Activity) and setService(Service)
methods defined under certain modules where it uses reflection to,
for example, assign the context to them before actually loading their
respective shared libraries where some initialization is needed and
requires the context to be already set.

This mechanism is not really necessary, since the respective libraries
are going to be loaded first anyways, and they could ensure to init
the context, if needed, under JNI_OnLoad() instead of those static
classes and through reflection which requires the class to be public.
Also, this way it would be more explicit behavior where the context is
set exactly before it's needed by the module's library.

Fixes: QTBUG-126478
Change-Id: I4cb39b8ef057ff7a99b66c268d85ba6da0c591ce
Reviewed-by: Ville Voutilainen <ville.voutilainen@qt.io>
This commit is contained in:
Assam Boudjelthia 2024-08-08 11:32:40 +03:00
parent c49aeeceff
commit c6ac461ed2
4 changed files with 2 additions and 71 deletions

View File

@ -166,12 +166,9 @@ function(qt_internal_android_dependencies_content target file_content_out)
if(arg_JAR_DEPENDENCIES)
foreach(jar_dependency IN LISTS arg_JAR_DEPENDENCIES)
section(${jar_dependency} ":" jar_file init_class)
if (init_class)
set(init_class "initClass=\"${init_class}\"")
endif()
# Use unix path to allow using files on any host platform.
file(TO_CMAKE_PATH ${jar_file} jar_file_unix_path)
string(APPEND file_contents "<jar file=\"${jar_file_unix_path}\" ${init_class} />\n")
string(APPEND file_contents "<jar file=\"${jar_file_unix_path}\" />\n")
endforeach()
endif()
@ -179,13 +176,10 @@ function(qt_internal_android_dependencies_content target file_content_out)
if(arg_BUNDLED_JAR_DEPENDENCIES)
foreach(jar_bundle IN LISTS arg_BUNDLED_JAR_DEPENDENCIES)
section(${jar_bundle} ":" bundle_file init_class)
if (init_class)
set(init_class "initClass=\"${init_class}\"")
endif()
# Use unix path to allow using files on any host platform.
file(TO_CMAKE_PATH ${bundle_file} jar_bundle_unix_path)
string(APPEND file_contents
"<jar bundling=\"1\" file=\"${jar_bundle_unix_path}\" ${init_class} />\n")
"<jar bundling=\"1\" file=\"${jar_bundle_unix_path}\" />\n")
endforeach()
endif()

View File

@ -70,7 +70,6 @@ abstract class QtLoader {
}
initClassLoader(baseContext);
initStaticClasses(baseContext);
try {
initContextInfo(baseContext);
} catch (NameNotFoundException e) {
@ -146,45 +145,6 @@ abstract class QtLoader {
return new ArrayList<>();
}
private void initStaticClasses(Context context) {
boolean isActivity = context instanceof Activity;
for (String className : getStaticInitClasses()) {
try {
Class<?> initClass = m_classLoader.loadClass(className);
Object staticInitDataObject = initClass.newInstance(); // create an instance
if (isActivity) {
try {
Method m = initClass.getMethod("setActivity", Activity.class, Object.class);
m.invoke(staticInitDataObject, (Activity) context, this);
} catch (InvocationTargetException | NoSuchMethodException e) {
Log.d(QtTAG, "Class " + initClass.getName() + " does not implement " +
"setActivity method");
}
} else {
try {
Method m = initClass.getMethod("setService", Service.class, Object.class);
m.invoke(staticInitDataObject, (Service) context, this);
} catch (InvocationTargetException | NoSuchMethodException e) {
Log.d(QtTAG, "Class " + initClass.getName() + " does not implement " +
"setService method");
}
}
try {
// For modules that don't need/have setActivity/setService
Method m = initClass.getMethod("setContext", Context.class);
m.invoke(staticInitDataObject, context);
} catch (InvocationTargetException | NoSuchMethodException e) {
Log.d(QtTAG, "Class " + initClass.getName() + " does not implement " +
"setContext method");
}
} catch (IllegalAccessException | ClassNotFoundException | InstantiationException e) {
Log.d(QtTAG, "Could not instantiate class " + className + ", " + e);
}
}
}
/**
* Initialize the class loader instance and sets it via QtNative.
* This would also be used by QJniObject API.
@ -394,19 +354,6 @@ abstract class QtLoader {
return localLibs;
}
@SuppressLint("DiscouragedApi")
private ArrayList<String> getStaticInitClasses() {
int id = m_resources.getIdentifier("static_init_classes", "string", m_packageName);
String[] classes = m_resources.getString(id).split(":");
ArrayList<String> finalClasses = new ArrayList<>();
for (String element : classes) {
if (!element.isEmpty()) {
finalClasses.add(element);
}
}
return finalClasses;
}
@SuppressLint("DiscouragedApi")
private String[] getBundledLibs() {
int id = m_resources.getIdentifier("bundled_libs", "array", m_packageName);

View File

@ -14,7 +14,6 @@
<!-- %%INSERT_LOCAL_LIBS%% -->
</array>
<string name="static_init_classes"><!-- %%INSERT_INIT_CLASSES%% --></string>
<string name="use_local_qt_libs"><!-- %%USE_LOCAL_QT_LIBS%% --></string>
<string name="bundle_local_qt_libs"><!-- %%BUNDLE_LOCAL_QT_LIBS%% --></string>
<string name="system_libs_prefix"><!-- %%SYSTEM_LIBS_PREFIX%% --></string>

View File

@ -237,7 +237,6 @@ struct Options
bool usesOpenGL = false;
// Per package collected information
QStringList initClasses;
// permissions 'name' => 'optional additional attributes'
QMap<QString, QString> permissions;
QStringList features;
@ -1789,14 +1788,10 @@ bool updateLibsXml(Options *options)
allLocalLibs += " <item>%1;%2</item>\n"_L1.arg(it.key(), localLibs.join(u':'));
}
options->initClasses.removeDuplicates();
QHash<QString, QString> replacements;
replacements[QStringLiteral("<!-- %%INSERT_QT_LIBS%% -->")] += qtLibs.trimmed();
replacements[QStringLiteral("<!-- %%INSERT_LOCAL_LIBS%% -->")] = allLocalLibs.trimmed();
replacements[QStringLiteral("<!-- %%INSERT_EXTRA_LIBS%% -->")] = extraLibs.trimmed();
const QString initClasses = options->initClasses.join(u':');
replacements[QStringLiteral("<!-- %%INSERT_INIT_CLASSES%% -->")] = initClasses;
// Set BUNDLE_LOCAL_QT_LIBS based on the deployment used
replacements[QStringLiteral("<!-- %%BUNDLE_LOCAL_QT_LIBS%% -->")]
@ -2117,10 +2112,6 @@ bool readAndroidDependencyXml(Options *options,
usedDependencies->insert(dependency.absolutePath);
}
}
if (reader.attributes().hasAttribute("initClass"_L1)) {
options->initClasses.append(reader.attributes().value("initClass"_L1).toString());
}
} else if (reader.name() == "lib"_L1) {
QString fileName = QDir::cleanPath(reader.attributes().value("file"_L1).toString());
if (reader.attributes().hasAttribute("replaces"_L1)) {