Skip to content

Modal on android make app crash when any accessibility service is ON #7377

Closed

Description

@levinqdl

the Modal component throws an exception when the modal is opening with any accessibilty service is ON (like TalkBack)
I have found the cause of the issue, and paste some related code. But I haven't known how to solve the problem. Any helps will be great.

the stack trace:

java.lang.IllegalArgumentException:` parameter must be a descendant of this view
                    at android.view.ViewGroup.offsetRectBetweenParentAndChild(ViewGroup.java:5334)
                    at android.view.ViewGroup.offsetDescendantRectToMyCoords(ViewGroup.java:5263)
                    at android.view.ViewGroup$ViewLocationHolder.init(ViewGroup.java:7730)
                    at android.view.ViewGroup$ViewLocationHolder.obtain(ViewGroup.java:7664)
                    at android.view.ViewGroup$ChildListForAccessibility.init(ViewGroup.java:7599)
                    at android.view.ViewGroup$ChildListForAccessibility.obtain(ViewGroup.java:7567)
                    at android.view.ViewGroup.addChildrenForAccessibility(ViewGroup.java:1927)
                    at android.view.ViewGroup.addChildrenForAccessibility(ViewGroup.java:1936)
                    at android.view.ViewGroup.onInitializeAccessibilityNodeInfoInternal(ViewGroup.java:2978)
                    at android.view.View.onInitializeAccessibilityNodeInfo(View.java:6084)
                    at android.view.View.createAccessibilityNodeInfoInternal(View.java:6043)
                    at android.view.View.createAccessibilityNodeInfo(View.java:6028)
                    at android.view.accessibility.AccessibilityRecord.setSource(AccessibilityRecord.java:145)
                    at android.view.accessibility.AccessibilityRecord.setSource(AccessibilityRecord.java:119)
                    at android.view.View.onInitializeAccessibilityEventInternal(View.java:5980)
                    at android.view.View.onInitializeAccessibilityEvent(View.java:5968)
                    at android.view.View.sendAccessibilityEventUncheckedInternal(View.java:5833)
                    at android.view.View.sendAccessibilityEventUnchecked(View.java:5818)
                    at android.view.ViewRootImpl$SendWindowContentChangedAccessibilityEvent.run(ViewRootImpl.java:7154)
                    at android.os.Handler.handleCallback(Handler.java:739)
                    at android.os.Handler.dispatchMessage(Handler.java:95)
                    at android.os.Looper.loop(Looper.java:148)
                    at android.app.ActivityThread.main(ActivityThread.java:5417)
                    at java.lang.reflect.Method.invoke(Native Method)
                    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

related code:
android.view.View:

    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
            return;
        }
       if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
            if (mParent != null) {
                try {
                    mParent.notifySubtreeAccessibilityStateChanged(
                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
                } catch (AbstractMethodError e) {
                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
                            " does not fully implement ViewParent", e);
                }
            }
        }
    }

When no accessibility service is on, the method notifySubtreeAccessibilityStateChangedIfNeeded return immediately, but, when any accessibility is on, the method will do more things.
The program will run into offsetRectBetweenParentAndChild method in ViewGroup, which throws the exception.
android.view.ViewGroup:

void offsetRectBetweenParentAndChild(View descendant, Rect rect,
            boolean offsetFromChildToParent, boolean clipToBounds) {

        // already in the same coord system :)
        if (descendant == this) {
            return;
        }

        ViewParent theParent = descendant.mParent;

        // search and offset up to the parent
        while ((theParent != null)
                && (theParent instanceof View)
                && (theParent != this)) {

            if (offsetFromChildToParent) {
                rect.offset(descendant.mLeft - descendant.mScrollX,
                        descendant.mTop - descendant.mScrollY);
                if (clipToBounds) {
                    View p = (View) theParent;
                    boolean intersected = rect.intersect(0, 0, p.mRight - p.mLeft,
                            p.mBottom - p.mTop);
                    if (!intersected) {
                        rect.setEmpty();
                    }
                }
            } else {
                if (clipToBounds) {
                    View p = (View) theParent;
                    boolean intersected = rect.intersect(0, 0, p.mRight - p.mLeft,
                            p.mBottom - p.mTop);
                    if (!intersected) {
                        rect.setEmpty();
                    }
                }
                rect.offset(descendant.mScrollX - descendant.mLeft,
                        descendant.mScrollY - descendant.mTop);
            }

            descendant = (View) theParent;
            theParent = descendant.mParent;
        }

        // now that we are up to this view, need to offset one more time
        // to get into our coordinate space
        if (theParent == this) {
            if (offsetFromChildToParent) {
                rect.offset(descendant.mLeft - descendant.mScrollX,
                        descendant.mTop - descendant.mScrollY);
            } else {
                rect.offset(descendant.mScrollX - descendant.mLeft,
                        descendant.mScrollY - descendant.mTop);
            }
        } else {
            throw new IllegalArgumentException("parameter must be a descendant of this view");
        }
    }

In the method, it walks through the view hierarchy from the descendant with the while loop, until it reaches the GroupView instance. But when it comes the Modal component, the loop quit with theParent is an instance of ViewRootImpl, and the condition as last of the method fails, so the method throws the exception.

Activity

  1. changed the title [-]Modal - parameter must be a descendant of this view exception[/-] [+]Modal on android make app crash when any accessibility service is ON[/+] on May 4, 2016
  2. zerob4wl commented on May 4, 2016

    @zerob4wl

    I have this problem too.
    In emulator thats work and in android 4.4.2 that is depend on indent components.

  3. levinqdl commented on May 4, 2016

    @levinqdl
    Author

    @zerob4wl please see my update

  4. levinqdl commented on May 4, 2016

    @levinqdl
    Author

    @zerob4wl A workaround is to turn off all accessibility services, then the Modal will work properly.

  5. zerob4wl commented on May 4, 2016

    @zerob4wl

    @levinqdl I don't undrestand how to fix this error. when I just use <Modal><Text>hi</Text></Modal>, I get this error.

  6. levinqdl commented on May 4, 2016

    @levinqdl
    Author

    @zerob4wl the error happens when the phone enables any accessibility service, so turn off the services in settings. But this is just a workaround, I currently don't know how to solve it, too. I will look into it soon.

  7. charpeni commented on May 5, 2016

    @charpeni
    Contributor

    @facebook-github-bot label android

  8. ghost added
    Ran CommandsOne of our bots successfully processed a command.
    on May 5, 2016
  9. rasom commented on May 25, 2016

    @rasom

    We have the same problem. Did someone find how to fix it?

  10. zerob4wl commented on May 25, 2016

    @zerob4wl

    @rasom I use "react-native-root-modal", but it is so slow in rendering complex components.

  11. satya164 commented on May 25, 2016

    @satya164
    Contributor

    cc @dmmiller I think you had fixed this?

  12. dmmiller commented on May 25, 2016

    @dmmiller
  13. satya164 commented on May 25, 2016

    @satya164
    Contributor

    Closing this since it has been fixed.

  14. locked as resolved and limited conversation to collaborators on May 29, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Ran CommandsOne of our bots successfully processed a command.Resolution: LockedThis issue was locked by the bot.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions