Skip to content

Commit

Permalink
Fix XML parsing error when using MIUI 12 on Pocophone X3 dtmilano#283
Browse files Browse the repository at this point in the history
My script uses `AndroidViewClient` but cannot create a `ViewClient`

```python3
from com.dtmilano.android.viewclient import ViewClient

def createViewClient():
    return ViewClient(*ViewClient.connectToDeviceOrExit(serialno='.*'))

vc = createViewClient()
```

The script returns the following stack trace:

```sh
  File "/home/bob/workspace/script.py", line 4, in createViewClient
    return ViewClient(*ViewClient.connectToDeviceOrExit(serialno='.*'))
  File "/home/bob/.local/lib/python3.6/site-packages/com/dtmilano/android/viewclient.py", line 2690, in __init__
    self.dump()
  File "/home/bob/.local/lib/python3.6/site-packages/com/dtmilano/android/viewclient.py", line 3522, in dump
    self.setViewsFromUiAutomatorDump(received)
  File "/home/bob/.local/lib/python3.6/site-packages/com/dtmilano/android/viewclient.py", line 3105, in setViewsFromUiAutomatorDump
    self.__parseTreeFromUiAutomatorDump(received)
  File "/home/bob/.local/lib/python3.6/site-packages/com/dtmilano/android/viewclient.py", line 3323, in __parseTreeFromUiAutomatorDump
    self.root = parser.Parse(receivedXml[start_xml_index:end_xml_index + 1])
  File "/home/bob/.local/lib/python3.6/site-packages/com/dtmilano/android/viewclient.py", line 2394, in Parse
    _ = parser.Parse(encoded, True)
  File "../Modules/pyexpat.c", line 284, in CharacterData
  File "/home/bob/.local/lib/python3.6/site-packages/com/dtmilano/android/viewclient.py", line 2381, in CharacterData
    element = self.nodeStack[-1]
IndexError: list index out of range
```

When I execute the command `adb shell uiautomator dump` on my device a Pocophone X3 with MIUI 12 installed, I get the following result:

```sh
adb shell uiautomator dump
java.io.FileNotFoundException: /data/system/theme_config/theme_compatibility.xml: open failed: ENOENT (No such file or directory)
	at libcore.io.IoBridge.open(IoBridge.java:496)
	at java.io.FileInputStream.<init>(FileInputStream.java:159)
	at java.io.FileInputStream.<init>(FileInputStream.java:115)
	at java.io.FileReader.<init>(FileReader.java:58)
	at miui.content.res.ThemeCompatibilityLoader.getVersion(ThemeCompatibilityLoader.java:108)
	at miui.content.res.ThemeCompatibilityLoader.getConfigDocumentTree(ThemeCompatibilityLoader.java:126)
	at miui.content.res.ThemeCompatibilityLoader.loadConfig(ThemeCompatibilityLoader.java:59)
	at miui.content.res.ThemeCompatibility.<clinit>(ThemeCompatibility.java:31)
	at miui.content.res.ThemeCompatibility.isThemeEnabled(ThemeCompatibility.java:111)
	at android.content.res.MiuiResourcesImpl.<clinit>(MiuiResourcesImpl.java:41)
	at android.content.res.Resources.<init>(Resources.java:285)
	at android.content.res.MiuiResources.<init>(MiuiResources.java:49)
	at android.content.res.Resources.getSystem(Resources.java:206)
	at android.util.MiuiMultiWindowAdapter.<clinit>(MiuiMultiWindowAdapter.java:79)
	at android.view.Display.getSize(Display.java:665)
	at com.android.commands.uiautomator.DumpCommand.run(DumpCommand.java:98)
	at com.android.commands.uiautomator.Launcher.main(Launcher.java:83)
	at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
	at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:380)
Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
	at libcore.io.Linux.open(Native Method)
	at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
	at libcore.io.BlockGuardOs.open(BlockGuardOs.java:252)
	at libcore.io.IoBridge.open(IoBridge.java:482)
	... 18 more
UI hierchary dumped to: /sdcard/window_dump.xml
```

So `uiautomator` throws an error, but still succeeds to dump the XML. The constructor of `ViewClient` calls `parser.Parse(receivedXml[start_xml_index:end_xml_index + 1])` [Ln 3323](https://github.com/dtmilano/AndroidViewClient/blob/master/src/com/dtmilano/android/viewclient.py#L3323), but the XML contained in `received` cannot be parsed because it still contains parts of the exceptions: `start_xml_index = receivedXml.index("<")` will return the first index of '<', which is in the exception (`java.io.FileInputStream.<init>`).

We fixed the issue by filtering out the exception from the `received` variable [Ln 3461](https://github.com/dtmilano/AndroidViewClient/blob/master/src/com/dtmilano/android/viewclient.py#L3460):

```python3
received = re.sub(re.compile('java.io.FileNotFoundException.*<\?xml', re.DOTALL),'<?xml', received)
```

But it would probably be cleaner to replace the value of `start_xml_index = receivedXml.index("<")` with `start_xml_index = receivedXml.index("<?xml")`.

@dtmilano What do you think? Would you be interested by a pull request?

Note that this error is similar to two issues in the `scrcpy` project:
- Genymobile/scrcpy#1116
- Genymobile/scrcpy#994

These issues were fixed by just ignoring the exceptions (see Genymobile/scrcpy@96bd2c9).
  • Loading branch information
Marc--Olivier committed Oct 6, 2020
1 parent 06cefca commit f8137ca
Showing 1 changed file with 1 addition and 1 deletion.
2 changes: 1 addition & 1 deletion src/com/dtmilano/android/viewclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -3316,7 +3316,7 @@ def __parseTreeFromUiAutomatorDump(self, receivedXml):
print("__parseTreeFromUiAutomatorDump(", receivedXml[:40], "...)", file=sys.stderr)
parser = UiAutomator2AndroidViewClient(self.device, self.build[VERSION_SDK_PROPERTY], self.uiAutomatorHelper)
try:
start_xml_index = receivedXml.index("<")
start_xml_index = receivedXml.index("<?xml")
end_xml_index = receivedXml.rindex(">")
except ValueError:
raise ValueError("received does not contain valid XML: " + receivedXml)
Expand Down

0 comments on commit f8137ca

Please sign in to comment.