Skip to content
This repository was archived by the owner on Jul 6, 2026. It is now read-only.
This repository was archived by the owner on Jul 6, 2026. It is now read-only.

AndroidAnnotationSupport needs better invalid XML fixup #883

Description

@jonpryor

Context: https://issuetracker.google.com/issues/116182838
Context: 4073f3e

In 2018-September, Google started providing various XML files which were not valid XML. We worked around this in commit 4073f3e by using HtmlAgilityPack to "loosely parse" the XML.

The problem with commit 4073f3e is that the resulting "intermediate" XML isn't "the same". Given XML of:

<!-- valid XML; API-28 -->
<itemname="android.accounts.AccountManager android.accounts.AccountManagerFuture&lt;android.os.Bundle&gt; addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback&lt;android.os.Bundle&gt;, android.os.Handler)">
<annotationname="android.support.annotation.RequiresPermission">
<valname="value"val="&quot;android.permission.MANAGE_ACCOUNTS&quot;" />
<valname="apis"val="&quot;..22&quot;" />
</annotation>
</item>
<!-- invalid XML; API-29 -->
<itemname="android.accounts.AccountManager android.accounts.AccountManagerFuture&lt;android.os.Bundle&gt; addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler)">
<annotationname="androidx.annotation.RequiresPermission">
<valname="value"val="&quot;android.permission.MANAGE_ACCOUNTS&quot;" />
<valname="apis"val="&quot;..22&quot;" />
</annotation>
</item>

Consider this fragment:

usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingXamarin.AndroidTools.AnnotationSupport;classApp{publicstaticvoidMain(){Console.WriteLine("- API-28");vara28=AndroidAnnotationsSupport.ParseArchive("$HOME/android-toolchain/sdk/platforms/android-28/data/annotations.zip");Console.WriteLine("- API-29");vara29=AndroidAnnotationsSupport.ParseArchive("$HOME/android-toolchain/sdk/platforms/android-29/data/annotations.zip");varaddAccount_28=a28.Where(a =>a.TypeName=="android.accounts.AccountManager"&&a.MemberName=="addAccount").First();varaddAccount_29=a29.Where(a =>a.TypeName=="android.accounts.AccountManager"&&a.MemberName=="addAccount").First();Console.WriteLine($"API-28: {addAccount_28}");foreach(varainaddAccount_28.Annotations){Console.WriteLine($" Name={a.Name}");varv=string.Join(", ",a.Values);Console.WriteLine($" Values={v}");}Console.WriteLine($"API-29: {addAccount_29}");foreach(varainaddAccount_29.Annotations){Console.WriteLine($" Name={a.Name}");varv=string.Join(", ",a.Values);Console.WriteLine($" Values={v}");}}}

When run, we get:

API-28: @RequiresPermission(value=System.String[], apis=System.String[]) android.accounts.AccountManager.addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler)
Name=RequiresPermission
Values=value = "android.permission.MANAGE_ACCOUNTS", apis = "..22"
API-29: @RequiresPermission(value=System.String[], apis=System.String[]) android.accounts.AccountManager.addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler)
Name=RequiresPermission
Values=value = &quot;android.permission.MANAGE_ACCOUNTS&quot;, apis = &quot;..22&quot;

Note how the Values value changes, from android.permission.MANAGE_ACCOUNTS to &quot;android.permission.MANAGE_ACCOUNTS&quot. This value eventually becomes the RequiresPermission attribute value, resulting in "downstream" Mono.Android.dll changes:

-[global::Android.Runtime.RequiresPermission ("android.permission.MANAGE_ACCOUNTS")]+[global::Android.Runtime.RequiresPermission ("quot;android.permission.MANAGE_ACCOUNTS&quot")]

which results in hundreds of "API changes" reported by the _CheckApiCompatibility target.

For Great Sanity™, we want the "invalid XML" path to produce the same value as the "valid XML" path, especially considering that the //item/annotation/val/@val attribute value is the same.

Metadata

Metadata

Assignees

Labels

enhancementProposed change to current functionalitygeneratorIssues binding a Java library (generator, class-parse, etc.)

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions