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

fix: add an empty AccessibilityNodeInfo creation for future androidx.test.uiautomator:uiautomator:2.3.0 update #589

Merged
merged 5 commits into from
Dec 31, 2023

Conversation

KazuCocoa
Copy link
Member

@KazuCocoa KazuCocoa commented Dec 31, 2023

Investigating appium/appium#19597

According to the androidx.test.uiautomator:uiautomator:2.3.0 beta01, UiObject2's constructor has changed as below, thus we must pass an empty AccessibilityNodeInfo instance as node instead of null.

    private UiObject2(UiDevice device, BySelector selector, AccessibilityNodeInfo cachedNode) {
        mDevice = device;
        mSelector = selector;
        mCachedNode = cachedNode;
        mGestureController = GestureController.getInstance(device);

        // Fetch and cache display information. This is safe as moving the underlying view to
        // another display would invalidate the cached node and require recreating this UiObject2.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            AccessibilityWindowInfo window = Api21Impl.getWindow(cachedNode);
            mDisplayId = window == null ? Display.DEFAULT_DISPLAY : Api30Impl.getDisplayId(window);
        } else {
            mDisplayId = Display.DEFAULT_DISPLAY;
        }
        Context uiContext = device.getUiContext(mDisplayId);
        int densityDpi = uiContext.getResources().getConfiguration().densityDpi;
        mDisplayDensity = (float) densityDpi / DisplayMetrics.DENSITY_DEFAULT;
    }

In addition to the node, selector has also been changed to NonNull in some places in the UiObject2 file. We should pass proper selector for the 2.3.0 update, but such change will be large, thus I have updated only AccessibilityNodeInfo which is pretty safe as a PR here.
(I haven't investigated about the selector thing yet)

I have tested this code with an Android 11 real device. This code affects click for example as below code. It worked without issues

> e = driver.find_element id: 'com.android.chrome:id/url_bar'
=> #<Appium::Core::Element:0x..f88f6ee1501acc89e id="00000000-0000-00dc-ffff-ffff00000313">
> e.click
=> nil

An error with androidx.test.uiautomator:uiautomator:2.3.0 with null node when click occurred.

12-31 00:57:14.609 31495 31528 E appium  : Cannot create UiObject2 instance with 'null' selector
12-31 00:57:14.609 31495 31528 E appium  : java.lang.reflect.InvocationTargetException
12-31 00:57:14.609 31495 31528 E appium  : 	at java.lang.reflect.Constructor.newInstance0(Native Method)
12-31 00:57:14.609 31495 31528 E appium  : 	at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.appium.uiautomator2.model.internal.CustomUiDevice.toUiObject2(CustomUiDevice.java:100)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.appium.uiautomator2.model.internal.CustomUiDevice.getGestureController(CustomUiDevice.java:135)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.appium.uiautomator2.core.AxNodeInfoHelper.click(AxNodeInfoHelper.java:131)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.appium.uiautomator2.model.BaseElement.click(BaseElement.java:70)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.appium.uiautomator2.handler.Click.safeHandle(Click.java:37)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.appium.uiautomator2.handler.request.SafeRequestHandler.handle(SafeRequestHandler.java:59)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.appium.uiautomator2.server.AppiumServlet.handleRequest(AppiumServlet.java:277)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.appium.uiautomator2.server.AppiumServlet.handleHttpRequest(AppiumServlet.java:271)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.appium.uiautomator2.http.ServerHandler.channelRead(ServerHandler.java:77)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:435)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:267)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:250)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:266)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1294)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:911)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:611)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:552)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:466)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:438)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:140)
12-31 00:57:14.609 31495 31528 E appium  : 	at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:144)
12-31 00:57:14.609 31495 31528 E appium  : 	at java.lang.Thread.run(Thread.java:923)
12-31 00:57:14.610 31495 31528 E appium  : Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.accessibility.AccessibilityWindowInfo android.view.accessibility.AccessibilityNodeInfo.getWindow()' on a null object reference
12-31 00:57:14.610 31495 31528 E appium  : 	at androidx.test.uiautomator.UiObject2$Api21Impl.getWindow(UiObject2.java:1061)
12-31 00:57:14.610 31495 31528 E appium  : 	at androidx.test.uiautomator.UiObject2.<init>(UiObject2.java:100)
12-31 00:57:14.610 31495 31528 E appium  : 	... 41 more

@KazuCocoa KazuCocoa changed the title chore: add am empty AccessibilityNodeInfo creation for future androidx.test.uiautomator:uiautomator:2.3.0 update fix: add am empty AccessibilityNodeInfo creation for future androidx.test.uiautomator:uiautomator:2.3.0 update Dec 31, 2023
@mykola-mokhnach
Copy link
Contributor

I will create another PR later to avoid passing nullable selectors

@KazuCocoa KazuCocoa changed the title fix: add am empty AccessibilityNodeInfo creation for future androidx.test.uiautomator:uiautomator:2.3.0 update fix: add an empty AccessibilityNodeInfo creation for future androidx.test.uiautomator:uiautomator:2.3.0 update Dec 31, 2023
@KazuCocoa
Copy link
Member Author

Thanks > selector
I saw a comment in the lib 2.2.0 that the selector variable in the uiobject2 was for debugging purposes, thus maybe nothing will break with the lib 2.2.0 with any values, but will affect in 2.3.0

// }
AccessibilityNodeInfo accessibilityNodeInfo =
(node == null && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R)
? new AccessibilityNodeInfo()
Copy link
Contributor

Choose a reason for hiding this comment

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

extra space here

Copy link
Member Author

Choose a reason for hiding this comment

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

Removed cd5692b
I used AS's config so it added these spaces automatically. I guess we could modify config file etc?

@KazuCocoa KazuCocoa merged commit 182d338 into master Dec 31, 2023
17 checks passed
@KazuCocoa KazuCocoa deleted the fix-for-uia-2-3-0 branch December 31, 2023 21:19
github-actions bot pushed a commit that referenced this pull request Dec 31, 2023
## [5.15.3](v5.15.2...v5.15.3) (2023-12-31)

### Bug Fixes

* add an empty AccessibilityNodeInfo creation for future androidx.test.uiautomator:uiautomator:2.3.0 update ([#589](#589)) ([182d338](182d338))
Copy link

🎉 This PR is included in version 5.15.3 🎉

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.

None yet

2 participants