Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add more fields from AccessibilityNodeInfo #682

Conversation

ankahanets
Copy link
Contributor

@ankahanets ankahanets commented Jan 15, 2025

Add more field that the appium user can retrieve with getPageSource() or write tests that could previously only be done in the Espresso SDK, but not in the Appium SDK.

Copy link

linux-foundation-easycla bot commented Jan 15, 2025

CLA Signed

The committers listed above are authorized under a signed CLA.

@KazuCocoa KazuCocoa changed the title Add more fields from AccessibilityNodeInfo feat: add more fields from AccessibilityNodeInfo Jan 15, 2025
@KazuCocoa
Copy link
Member

Thank you.

This project's mini sdk is 21. This PR should add code for not-supported environment case.

https://github.com/appium/appium-uiautomator2-server/blob/master/app/build.gradle#L20

For example, isImportantForAccessibility was added in API level 24. Then, case IMPORTANT_FOR_ACCESSIBILITY: needs to return null to show not supported.
https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo#isImportantForAccessibility()

Also, please sign the CLA.

@mykola-mokhnach
Copy link
Contributor

mykola-mokhnach commented Jan 15, 2025

Consider testing the performance of the updated solution. As you could notice in the code we exclude "expensive" properties from the XML output as the attribute must be fetched for each node, which may significantly slow down the overall page source retrieval performance.

After the PR is merged please do not forget to document additional properties in https://github.com/appium/appium-uiautomator2-driver?tab=readme-ov-file#element-attributes

@ankahanets
Copy link
Contributor Author

Thanks for your input!

Added API level checks;

About performance, in the PR we add getters of already existing fields so it shouldn't significantly affect execution time. I can mention that XML parsing can be slower as each node has more attributes and to collect action list to one string we create a StringBuilder every time.

With my quick tests execution time looks a bit chaotic (with a debug build using ./gradlew app:installServerDebug), but I get the next metrics.

getPageSource master
Screen #1: 543 659 270 873 1373 avg 743 w/o minmax 691
Screen #2: 771 214 1248 692 704 avg 725 w/o minmax 722
Screen #3: 573 555 1098 561 1094 avg 776 w/o minmax 742
Screen #4: 466 778 426 779 772 avg 644 w/o minmax 672

getPageSource PR
Screen #1: 864 1218 921 1254 762 avg 1003 w/o minmax 1001
Screen #2: 1024 788 1146 773 1068 avg 959 w/o minmax 960
Screen #3: 583 587 1118 578 1132 avg 799 w/o minmax 762
Screen #4: 812 800 467 451 446 avg 595 w/o minmax 572

I can investigate it more deeply. For example, I can try using deprecated node.getActions() instead of node.getActionList() and parse it's bitmask on the client side.

@KazuCocoa
Copy link
Member

Thank you for the performance measurements. This change could affect various actions (I guess)

One idea is to defend settings.
https://github.com/appium/appium-uiautomator2-driver?tab=readme-ov-file#settings-api
Settings.get(SnapshotMaxDepth.class).getValue() in the UiElementSnapshot.java could be a hint to implement that. So, for example... adding pageSourceAdditionalAttributes and the value is all or comma separate attribute names like importantForAccessibility,textEntryKey etc....

Just an idea, but like this thing also could be available. (The basic concept here is from pageSourceExcludedAttributes in xcuitest driver)

@mykola-mokhnach
Copy link
Contributor

@KazuCocoa I've checked the actual source code for the newly added attributes and they seem to be simple getters, so I don't expect much influence to the actual performance.

Although, I tend to agree to the point that maybe not of all these attributes are actually useful in the XML tree output by default.

@ankahanets What exactly do you want to achieve by adding all of these attributes to the page source? Are they equally useful for your automation scenarios? Perhaps, we could still have all of them available for attributes fetching, but only have some (most useful ones) in the actual XML document?

@ankahanets
Copy link
Contributor Author

@mykola-mokhnach We are developing an Appium/Espresso tool for checking accessibility correctness, and we need some of the data for our internal validations.

I can remove the PANE_TITLE, ERROR_TEXT, and CONTENT_INVALID fields since we don’t use them right now. I added them “just in case for the future” and to make the input more similar to what we have in Espresso, but other fields will be really helpful for our SDK.

However, if the number of new fields is too large, we can introduce a new settings option and return the most obscure field for the ordinal user only if it is turned on in settings (like we have for extras). But I think that most of the new fields will be useful for different users as well.

Also, to reduce the xml size we can return nulls for the default values, like I've done for MAX_TEXT_LENGTH. The default value is -1, so there will be no such attribute for non-EditText nodes.

for (AccessibilityAction action : actionList) {
String[] split = action.toString().split(" ");
if (split.length < 2) {
return null;
Copy link
Contributor

Choose a reason for hiding this comment

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

should we continue instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No... actually is not possible, but even if this happens - than means something strange and all the data is broken

if (split.length < 2) {
return null;
}
actionsBuilder.append(split[1]);
Copy link
Contributor

@mykola-mokhnach mykola-mokhnach Jan 28, 2025

Choose a reason for hiding this comment

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

append returns this, so you could chain these calls

Copy link
Contributor Author

@ankahanets ankahanets Jan 28, 2025

Choose a reason for hiding this comment

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

yes... I think current variant looks a bit more clearly, but I can change if it's needed indeed

package io.appium.uiautomator2.model.settings;

public class IncludeA11yActionsInPageSource extends AbstractSetting<Boolean> {
private static final String SETTING_NAME = "includeA11yActionsInPageSource";
Copy link
Contributor

@mykola-mokhnach mykola-mokhnach Jan 28, 2025

Choose a reason for hiding this comment

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

Please also do not forget this new setting into UIA2 settings documentation after this PR is released

@mykola-mokhnach
Copy link
Contributor

@KazuCocoa Do you have any more comments to this PR?

Copy link
Member

@KazuCocoa KazuCocoa left a comment

Choose a reason for hiding this comment

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

No, lgtm 🚀

@mykola-mokhnach mykola-mokhnach merged commit ef9b24f into appium:master Jan 28, 2025
11 checks passed
github-actions bot pushed a commit that referenced this pull request Jan 28, 2025
## [7.2.0](v7.1.11...v7.2.0) (2025-01-28)

### Features

* add more fields from AccessibilityNodeInfo ([#682](#682)) ([ef9b24f](ef9b24f))
Copy link

🎉 This PR is included in version 7.2.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

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