Skip to content

[QA] Add content provider to handle settings in QA variant#4776

Open
jesmrec wants to merge 5 commits intomasterfrom
feature/add_provider_settings_qa_variant
Open

[QA] Add content provider to handle settings in QA variant#4776
jesmrec wants to merge 5 commits intomasterfrom
feature/add_provider_settings_qa_variant

Conversation

@jesmrec
Copy link
Collaborator

@jesmrec jesmrec commented Feb 16, 2026

Summary

Adds a ContentProvider to the qa variant that allows to handle the shared preferences with testing purposes.

The ContentProvider overrides the call function that receives three parameters:

method : name of the method that will execute the action. In this case, only one method set_boolean since it's intended (for the moment) for boolean preferences
arg: the name of the preference
extras: value of the preference (in this case, true or false)

How it works

  1. Build the branch with qa variant to get an apk.
  2. Plug on a device/emu and install the apk
  3. With an adb command, the content provider is called with the proper arguments

F. ex:

to enable the show_disabled_spaces preference:

adb shell content call --uri content://com.owncloud.android.test.preferences --method set_boolean --arg show_disabled_spaces --extra value:b:true

to disable the show_hidden_files preference:

adb shell content call --uri content://com.owncloud.android.test.preferences --method set_boolean --arg show_hidden_files --extra value:b:false

Security

In order to assure that this implementation is only available in the qa variant, the following checks have been performed:

1. Check that Manifest is OK

Firstly, a Manifest for every variant is generated:

./gradlew clean
./gradlew :owncloudApp:processQaReleaseMainManifest
./gradlew :owncloudApp:processOriginalReleaseMainManifest

Then, inspect them:

grep -n "TestPreferencesProvider" owncloudApp/build/intermediates/merged_manifest/qaRelease/processQaReleaseMainManifest/AndroidManifest.xml

Result: 81: android:name="com.owncloud.android.test.TestPreferencesProvider"

That means, the qa manifest contains the TestPreferencesProvider class.

Let's check in the original:

grep -n "TestPreferencesProvider" owncloudApp/build/intermediates/merged_manifest/originalRelease/processOriginalReleaseMainManifest/AndroidManifest.xml 

That returns no results, so the original manifest does not contain the TestPreferencesProvider class

2. Check if the compilings contain the TestPreferencesProvider class

Execute the following commands

./gradlew clean -> clean up directory
./gradlew :owncloudApp:compileOriginalReleaseKotlin -> compile the originalRelease variant
find owncloudApp/build/tmp/kotlin-classes/originalRelease -iname '*TestPreferencesProvider*' -> tries to find the TestPreferencesProvider inside of it. It shouldn't find anything.

./gradlew clean -> clean up again
./gradlew :owncloudApp:compileQaReleaseKotlin -> compile the qaRelease variant
find owncloudApp/build/tmp/kotlin-classes/qaRelease -iname '*TestPreferencesProvider*' -> it should return owncloudApp/build/tmp/kotlin-classes/qaRelease/com/owncloud/android/test/TestPreferencesProvider.class

3. Check the presence of TestPreferencesProvider in the artifacts

Build a signed apk with both original and qa variant, and execute over both of them:

$ANDROID_HOME/cmdline-tools/latest/bin/apkanalyzer dex packages owncloud.apk | grep -i testpreferencesprovider

(set the right apk name in the command fot every case)

That command list the code files inside the apk. The TestPreferencesProvider class should be listed only in the apk that was built with the qa variant.

Those checks show that the originalXXX variants will never include the TestPreferencesProvider and the qa Manifest.

(open to other ideas)

App:

  • Add changelog files for the fixed issues in folder changelog/unreleased. More info here
  • Add feature to Release Notes in ReleaseNotesViewModel.kt creating a new ReleaseNote() with String resources (if required)

QA

@jesmrec jesmrec added the QA label Feb 16, 2026
@jesmrec jesmrec self-assigned this Feb 16, 2026
@jesmrec jesmrec force-pushed the feature/add_provider_settings_qa_variant branch from 9144fc1 to 40c93c5 Compare February 18, 2026 13:14
@jesmrec jesmrec marked this pull request as ready for review February 18, 2026 13:49
@jesmrec jesmrec requested a review from joragua February 18, 2026 15:54
Copy link
Collaborator

@joragua joragua left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some comments @jesmrec!

android:exported="true" />
</application>

</manifest> No newline at end of file
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No newline at end of file

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Added

): Bundle {

val prefs = context!!.getSharedPreferences(prefsName, Context.MODE_PRIVATE)
if (method == "set_boolean") {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to create a variable for set_boolean (similar to prefsName)?

Copy link
Collaborator Author

@jesmrec jesmrec Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, since the name of the method is static, i'll add it as a companion string, and same for the prefs_name. What do you think?

Copy link
Collaborator

@joragua joragua Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! 💯 Is prefsName also a static value? We could move both values to the companion object

prefs.edit {
putBoolean(arg!!, extras!!.getBoolean("value"))
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would happen if context, arg or extras were null? Would it be possible to use a safe calls (?.) for these arguments? 🤔

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it shouldn't, or the call to the provider will fail. Anyway, let's do some control over its nullability

override fun update(
uri: Uri, values: ContentValues?,
selection: String?, selectionArgs: Array<out String>?
): Int = 0
Copy link
Collaborator

@joragua joragua Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would write this method on a single line for clarity (just my personal opinion) 🙌🏻

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, no problem 👍

@jesmrec jesmrec force-pushed the feature/add_provider_settings_qa_variant branch from f817712 to 2319fd5 Compare February 18, 2026 17:32
@jesmrec jesmrec requested a review from joragua February 18, 2026 17:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Comments