Skip to content

Conversation

@brendanzagaeski
Copy link
Contributor

Context: c523107
Context: https://dev.azure.com/devdiv/DevDiv/_workitems/edit/1032105

As described in c5231075, we should be using the latest versions of
the Android tooling if possible, matching the major version with the max
API level we support. Xamarin.Android now supports Android 10 (API
level 29), so we should be using the 29.x.x versions of the tooling.

Update $(AndroidSdkBuildToolsVersion) to 29.0.2.
Update $(AndroidSdkPlatformToolsVersion) to 29.0.5.

Copy link
Member

@jonathanpeppers jonathanpeppers left a comment

Choose a reason for hiding this comment

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

I think this should update what we install when building Xamarin.Android, too. I think it would be these properties:

https://github.com/xamarin/xamarin-android/blob/0342fe5698b86e21e36c924732ff135b9a87e4af/Configuration.props#L101-L103

@brendanzagaeski
Copy link
Contributor Author

brendanzagaeski commented Dec 11, 2019

Sounds good. I've added a commit for that.

It looks like there are some tests that might also need to be updated to expect these versions. I'll take a look at those now. One consideration I'll keep in mind with those is that the template projects in Visual Studio are for the moment still defaulting to Android 9 Pie (API level 28), so it makes sense to have some tests using those versions.

@brendanzagaeski
Copy link
Contributor Author

brendanzagaeski commented Dec 11, 2019

The latest commit failed to build because Android SDK Platform-Tools 29.0.5 contains changes to the api-versions.xml file compared to Android SDK Platform-Tools 29.0.1.

generator.exe uses api-versions.xml as an input when generating the C# bindings, so this change causes the API compatibility check in Mono.Android.csproj to fail. Excerpt of the errors:

AfterBuild:
  CheckApiCompatibility for ApiLevel: v10.0
  CompatApi command: ../../packages/Microsoft.DotNet.ApiCompat.5.0.0-beta.19606.1/tools/net472/Microsoft.DotNet.ApiCompat.exe "../../tests/api-compatibility\reference\ApiCompatTemp" -i "F:\A\xamarin-v000006-1\_work\2\s\bin\Release\lib\xamarin.android\xbuild-frameworks\MonoAndroid\v10.0\ApiCompatTemp" --exclude-attributes ../../tests/api-compatibility\api-compat-exclude-attributes.txt 
  Compat issues with assembly Mono.Android:
  CannotChangeAttribute : Attribute 'Android.Runtime.RegisterAttribute' on 'System.String Android.Manifest.Permission.AccessBackgroundLocation' changed from '[RegisterAttribute("ACCESS_BACKGROUND_LOCATION")]' in the contract to '[RegisterAttribute("ACCESS_BACKGROUND_LOCATION", ApiSince=29)]' in the implementation.
  CannotChangeAttribute : Attribute 'Android.Runtime.RegisterAttribute' on 'System.String Android.Manifest.Permission.AccessMediaLocation' changed from '[RegisterAttribute("ACCESS_MEDIA_LOCATION")]' in the contract to '[RegisterAttribute("ACCESS_MEDIA_LOCATION", ApiSince=29)]' in the implementation.
  CannotChangeAttribute : Attribute 'Android.Runtime.RegisterAttribute' on 'System.String Android.Manifest.Permission.ActivityRecognition' changed from '[RegisterAttribute("ACTIVITY_RECOGNITION")]' in the contract to '[RegisterAttribute("ACTIVITY_RECOGNITION", ApiSince=29)]' in the implementation.

Excerpt of the diff of api-versions.xml showing where these changes came from:

--- "a/platform-tools-29.0.1\\api\\api-versions.xml"
+++ "b/platform-tools-29.0.5\\api\\api-versions.xml"
@@ -10,0 +11 @@
+               <field name="ACCESS_BACKGROUND_LOCATION" since="29"/>
@@ -14,0 +16 @@
+               <field name="ACCESS_MEDIA_LOCATION" since="29"/>
@@ -20,0 +23 @@
+               <field name="ACTIVITY_RECOGNITION" since="29"/>

Questions

I think having these ApiSince properties on the [Register] attributes might be a desirable change. Is it ok to bring in that change?

If so, I think I can resolve the build breakage by creating a new Mono.Android.dll.zip as describe in https://github.com/xamarin/xamarin-android/blob/master/tests/api-compatibility/README.md#assembly-reference and including in this PR.

@jonathanpeppers
Copy link
Member

@brendanzagaeski
Copy link
Contributor Author

Changes in the latest commit:

For the sake of being ready to accept the ApiSince API changes if those are approved, I worked through the steps to update the API compatibility files

To address the ApiSince changes, update the reference tests/api-compatibility/reference/Mono.Android.dll.zip file with a new version built using the api-versions.xml from Android SDK Platform-Tools 29.0.5. This new file was built locally on Windows and then stripped and zipped up following the steps on the API compatibility README.

One subtlety with this change is that previously the Mono.Android.dll.zip committed in the repo would return some expected API breaks when comparing it to a new Mono.Android.dll. In contrast, the updated Mono.Android.dll.zip now returns no API breaks, so acceptable-breakages-vReference.txt needs to be empty. Otherwise, the API compatibility check would fail with an error caused by the mismatch:

There is an invalid assembly listed on the acceptable breakages file: Compat issues with assembly Mono.Android:

Questions:

I'm not sure if I've correctly understood how the acceptable-breakages-vReference.txt file works. I might not have created the new Mono.Android.dll.zip correctly. Why were there entries in that file for the version of Mono.Android.dll.zip that is currently in master?

It looks like the reason might be that the Mono.Android.dll.zip currently in master was originally built before 1a61fa8 but then committed after it. So it needed entries in acceptable-breakages-vReference.txt to account for the changes to the [Obsolete] attributes.

Maybe I've misunderstood when we want to update Mono.Android.dll.zip versus just updating acceptable-breakages-vReference.txt. Maybe I should have just updated acceptable-breakages-vReference.txt in this case. That would definitely cut down on the total repository download size since it would mean fewer changes to the Mono.Android.dll.zip binary artifact.

To do:

  • I think I need to rebuild the new Mono.Android.dll.zip in the Release configuration or just modify acceptable-breakages-vReference.txt instead. The build for the latest commit still failed the API check because the new Mono.Android.dll.zip had extra [DebuggerStepThrough] attributes.
  • I haven't yet addressed the original test breakages from the first commit. I'll take a look at those.
  • The error message I saw for the out-of-date acceptable-breakages-vReference.txt was a little confusing to me because the error said "invalid assembly listed," but then the problematic assembly name was "Compat issues with assembly Mono.Android" rather than just an assembly name. Additionally, in the case where this error appears because the new API compatibility check returns no errors, the current error message doesn't quite make sense. I'll submit a separate issue or PR about that.

@brendanzagaeski
Copy link
Contributor Author

Changes in the latest commits:

Revert the previous commit that changed Mono.Android.dll.zip, and instead update just acceptable-breakages-vReference.txt to account for the ApiSince changes to see if that does indeed allow the CI build to succeed like my local build.

@brendanzagaeski
Copy link
Contributor Author

Changes in the latest commit:

Fix the test failures. It turned out the failing tests were for the automatic SDK download feature. Those tests have hardcoded strings that are compared against the default build-tools version, so those strings needed to be updated.

That resolves the question I had earlier about making sure the updated tests would still cover the Android 9 Pie (API level 29) target framework version. Since the test fixes only touch the build-tools version, the coverage of target framework versions is unchanged.

Remaining questions

Do we want to take the ApiSince API changes that are currently included in this PR?

If so, is the current approach of updating acceptable-breakages-vReference.txt correct, or does Mono.Android.dll.zip need to be updated instead?

The answers might need to wait until January to make sure any team members who are away for the end of the year can weigh in.

@brendanzagaeski
Copy link
Contributor Author

@gugavaro, when you have a moment, I think a couple questions you'll be interested in are:

  • Should the missing ApiSince info be added in this particular case, and if so, should it be added to the reference Mono.Android.dll.zip or the acceptable breakages list?
  • Was this missing ApiSince info in the original version of the bindings for API level 29 unavoidable because the api-versions.xml in the platform-tools was incomplete? Or does generator.exe also have a way to determine the appropriate ApiSince without api-versions.xml that could help avoid similar issues in the future?

Thanks a bunch!

@gugavaro
Copy link
Contributor

gugavaro commented Jan 8, 2020

The latest commit failed to build because Android SDK Platform-Tools 29.0.5 contains changes to the api-versions.xml file compared to Android SDK Platform-Tools 29.0.1.

generator.exe uses api-versions.xml as an input when generating the C# bindings, so this change causes the API compatibility check in Mono.Android.csproj to fail. Excerpt of the errors:

AfterBuild:
  CheckApiCompatibility for ApiLevel: v10.0
  CompatApi command: ../../packages/Microsoft.DotNet.ApiCompat.5.0.0-beta.19606.1/tools/net472/Microsoft.DotNet.ApiCompat.exe "../../tests/api-compatibility\reference\ApiCompatTemp" -i "F:\A\xamarin-v000006-1\_work\2\s\bin\Release\lib\xamarin.android\xbuild-frameworks\MonoAndroid\v10.0\ApiCompatTemp" --exclude-attributes ../../tests/api-compatibility\api-compat-exclude-attributes.txt 
  Compat issues with assembly Mono.Android:
  CannotChangeAttribute : Attribute 'Android.Runtime.RegisterAttribute' on 'System.String Android.Manifest.Permission.AccessBackgroundLocation' changed from '[RegisterAttribute("ACCESS_BACKGROUND_LOCATION")]' in the contract to '[RegisterAttribute("ACCESS_BACKGROUND_LOCATION", ApiSince=29)]' in the implementation.
  CannotChangeAttribute : Attribute 'Android.Runtime.RegisterAttribute' on 'System.String Android.Manifest.Permission.AccessMediaLocation' changed from '[RegisterAttribute("ACCESS_MEDIA_LOCATION")]' in the contract to '[RegisterAttribute("ACCESS_MEDIA_LOCATION", ApiSince=29)]' in the implementation.
  CannotChangeAttribute : Attribute 'Android.Runtime.RegisterAttribute' on 'System.String Android.Manifest.Permission.ActivityRecognition' changed from '[RegisterAttribute("ACTIVITY_RECOGNITION")]' in the contract to '[RegisterAttribute("ACTIVITY_RECOGNITION", ApiSince=29)]' in the implementation.

Excerpt of the diff of api-versions.xml showing where these changes came from:

--- "a/platform-tools-29.0.1\\api\\api-versions.xml"
+++ "b/platform-tools-29.0.5\\api\\api-versions.xml"
@@ -10,0 +11 @@
+               <field name="ACCESS_BACKGROUND_LOCATION" since="29"/>
@@ -14,0 +16 @@
+               <field name="ACCESS_MEDIA_LOCATION" since="29"/>
@@ -20,0 +23 @@
+               <field name="ACTIVITY_RECOGNITION" since="29"/>

Questions

I think having these ApiSince properties on the [Register] attributes might be a desirable change. Is it ok to bring in that change?

If so, I think I can resolve the build breakage by creating a new Mono.Android.dll.zip as describe in https://github.com/xamarin/xamarin-android/blob/master/tests/api-compatibility/README.md#assembly-reference and including in this PR.

Those are acceptable changes, we just need to update the acceptable files to allow those changes pass by.

@gugavaro
Copy link
Contributor

gugavaro commented Jan 8, 2020

Changes in the latest commit:

For the sake of being ready to accept the ApiSince API changes if those are approved, I worked through the steps to update the API compatibility files

To address the ApiSince changes, update the reference tests/api-compatibility/reference/Mono.Android.dll.zip file with a new version built using the api-versions.xml from Android SDK Platform-Tools 29.0.5. This new file was built locally on Windows and then stripped and zipped up following the steps on the API compatibility README.

One subtlety with this change is that previously the Mono.Android.dll.zip committed in the repo would return some expected API breaks when comparing it to a new Mono.Android.dll. In contrast, the updated Mono.Android.dll.zip now returns no API breaks, so acceptable-breakages-vReference.txt needs to be empty. Otherwise, the API compatibility check would fail with an error caused by the mismatch:

There is an invalid assembly listed on the acceptable breakages file: Compat issues with assembly Mono.Android:

Questions:

I'm not sure if I've correctly understood how the acceptable-breakages-vReference.txt file works. I might not have created the new Mono.Android.dll.zip correctly. Why were there entries in that file for the version of Mono.Android.dll.zip that is currently in master?

It looks like the reason might be that the Mono.Android.dll.zip currently in master was originally built before 1a61fa8 but then committed after it. So it needed entries in acceptable-breakages-vReference.txt to account for the changes to the [Obsolete] attributes.

Maybe I've misunderstood when we want to update Mono.Android.dll.zip versus just updating acceptable-breakages-vReference.txt. Maybe I should have just updated acceptable-breakages-vReference.txt in this case. That would definitely cut down on the total repository download size since it would mean fewer changes to the Mono.Android.dll.zip binary artifact.

To do:

  • I think I need to rebuild the new Mono.Android.dll.zip in the Release configuration or just modify acceptable-breakages-vReference.txt instead. The build for the latest commit still failed the API check because the new Mono.Android.dll.zip had extra [DebuggerStepThrough] attributes.
  • I haven't yet addressed the original test breakages from the first commit. I'll take a look at those.
  • The error message I saw for the out-of-date acceptable-breakages-vReference.txt was a little confusing to me because the error said "invalid assembly listed," but then the problematic assembly name was "Compat issues with assembly Mono.Android" rather than just an assembly name. Additionally, in the case where this error appears because the new API compatibility check returns no errors, the current error message doesn't quite make sense. I'll submit a separate issue or PR about that.

Where are you getting the Mono.Android.dll from? You should not use the one built locally, instead we use a released one.

If there is no breakage, we can remove the acceptable-breakages-vReference.txt file.

We can also remove the DebuggerStepThrough from our checks.
Those are the checks we currently exclude:
https://github.com/xamarin/xamarin-android/blob/master/tests/api-compatibility/api-compat-exclude-attributes.txt
If DebuggerStepThrough is something we don't care, lets exclude from our checks.

@gugavaro
Copy link
Contributor

gugavaro commented Jan 8, 2020

@gugavaro, when you have a moment, I think a couple questions you'll be interested in are:

  • Should the missing ApiSince info be added in this particular case, and if so, should it be added to the reference Mono.Android.dll.zip or the acceptable breakages list?
  • Was this missing ApiSince info in the original version of the bindings for API level 29 unavoidable because the api-versions.xml in the platform-tools was incomplete? Or does generator.exe also have a way to determine the appropriate ApiSince without api-versions.xml that could help avoid similar issues in the future?

Thanks a bunch!

@brendanzagaeski those are good questions:
I believe the right thing to do is to add the ApiSince as acceptable break changes like you did. The tool considers it a break since we are changing Attribute.
I don't know how the generator determines the ApiSince. @jpobst can you jump here? Do you know what the generate uses to determine ApiSince?

thanks!

@jpobst
Copy link
Contributor

jpobst commented Jan 8, 2020

You can see in a build log what's happening.

First we class-parse each .jar file in the platform sdks:

  Creating directory "c:\code\xamarin-android-backport\build-tools\api-xml-adjuster\..\..\bin\BuildDebug\api".
    c:\code\xamarin-android-backport\build-tools\api-xml-adjuster\..\..\bin\Debug\lib\xamarin.android\xbuild\Xamarin\Android\class-parse.exe C:\Users\jopobst\android-toolchain\sdk\platforms\android-10\android.jar -platform=10 -parameter-names="c:\code\xamarin-android-backport\build-tools\api-xml-adjuster\..\..\src\Mono.Android\Profiles\api-10.params.txt" -o="c:\code\xamarin-android-backport\build-tools\api-xml-adjuster\..\..\bin\BuildDebug\api\api-10.xml.class-parse"
_ClassParse:
    c:\code\xamarin-android-backport\build-tools\api-xml-adjuster\..\..\bin\Debug\lib\xamarin.android\xbuild\Xamarin\Android\class-parse.exe C:\Users\jopobst\android-toolchain\sdk\platforms\android-15\android.jar -platform=15 -parameter-names="c:\code\xamarin-android-backport\build-tools\api-xml-adjuster\..\..\src\Mono.Android\Profiles\api-15.params.txt" -o="c:\code\xamarin-android-backport\build-tools\api-xml-adjuster\..\..\bin\BuildDebug\api\api-15.xml.class-parse"
_ClassParse:
    c:\code\xamarin-android-backport\build-tools\api-xml-adjuster\..\..\bin\Debug\lib\xamarin.android\xbuild\Xamarin\Android\class-parse.exe C:\Users\jopobst\android-toolchain\sdk\platforms\android-16\android.jar -platform=16 -parameter-names="c:\code\xamarin-android-backport\build-tools\api-xml-adjuster\..\..\src\Mono.Android\Profiles\api-16.params.txt" -o="c:\code\xamarin-android-backport\build-tools\api-xml-adjuster\..\..\bin\BuildDebug\api\api-16.xml.class-parse"
_ClassParse:
    c:\code\xamarin-android-backport\build-tools\api-xml-adjuster\..\..\bin\Debug\lib\xamarin.android\xbuild\Xamarin\Android\class-parse.exe C:\Users\jopobst\android-toolchain\sdk\platforms\android-17\android.jar -platform=17 -parameter-names="c:\code\xamarin-android-backport\build-tools\api-xml-adjuster\..\..\src\Mono.Android\Profiles\api-17.params.txt" -o="c:\code\xamarin-android-backport\build-tools\api-xml-adjuster\..\..\bin\BuildDebug\api\api-17.xml.class-parse"

Then we api-xml-adjuster each level. I think this updates the parameter names from values scraped from JavaDoc.

_AdjustApiXml:
    c:\code\xamarin-android-backport\build-tools\api-xml-adjuster\..\..\bin\BuildDebug\api-xml-adjuster.exe c:\code\xamarin-android-backport\build-tools\api-xml-adjuster\..\..\bin\BuildDebug\api\api-10.xml.class-parse c:\code\xamarin-android-backport\build-tools\api-xml-adjuster\..\..\bin\BuildDebug\api\api-10.xml.in
_AdjustApiXml:
    c:\code\xamarin-android-backport\build-tools\api-xml-adjuster\..\..\bin\BuildDebug\api-xml-adjuster.exe c:\code\xamarin-android-backport\build-tools\api-xml-adjuster\..\..\bin\BuildDebug\api\api-15.xml.class-parse c:\code\xamarin-android-backport\build-tools\api-xml-adjuster\..\..\bin\BuildDebug\api\api-15.xml.in
_AdjustApiXml:
    c:\code\xamarin-android-backport\build-tools\api-xml-adjuster\..\..\bin\BuildDebug\api-xml-adjuster.exe c:\code\xamarin-android-backport\build-tools\api-xml-adjuster\..\..\bin\BuildDebug\api\api-16.xml.class-parse c:\code\xamarin-android-backport\build-tools\api-xml-adjuster\..\..\bin\BuildDebug\api\api-16.xml.in

Finally we api-merge them all into a single file, which adds the ApiSince attribute based on which file each element came from:

..\..\bin\BuildDebug\api-merge.exe -o "obj\Debug\android-29\mcw\api.xml" -s '..\..\bin\BuildDebug\api\api-*.xml.in' ..\..\bin\BuildDebug\api\api-10.xml.in ..\..\bin\BuildDebug\api\api-15.xml.in ..\..\bin\BuildDebug\api\api-16.xml.in ..\..\bin\BuildDebug\api\api-17.xml.in ..\..\bin\BuildDebug\api\api-18.xml.in ..\..\bin\BuildDebug\api\api-19.xml.in ..\..\bin\BuildDebug\api\api-20.xml.in ..\..\bin\BuildDebug\api\api-21.xml.in ..\..\bin\BuildDebug\api\api-22.xml.in ..\..\bin\BuildDebug\api\api-23.xml.in ..\..\bin\BuildDebug\api\api-24.xml.in ..\..\bin\BuildDebug\api\api-25.xml.in ..\..\bin\BuildDebug\api\api-26.xml.in ..\..\bin\BuildDebug\api\api-27.xml.in ..\..\bin\BuildDebug\api\api-28.xml.in ..\..\bin\BuildDebug\api\api-29.xml.in --last-description=..\..\bin\BuildDebug\api\api-29.xml.in

@jonpryor
Copy link
Contributor

...but that just raises a slightly different question:

Consider Android.Manifest.Permission.AccessBackgroundLocation:

CannotChangeAttribute : Attribute 'Android.Runtime.RegisterAttribute' on 'System.String Android.Manifest.Permission.AccessBackgroundLocation' changed from '[RegisterAttribute("ACCESS_BACKGROUND_LOCATION")]' in the contract to '[RegisterAttribute("ACCESS_BACKGROUND_LOCATION", ApiSince=29)]' in the implementation.

android.Manifest.permission.ACCESS_BACKGROUND_LOCATION was added in API-29.

Why, then, are we binding it with no RegisterAttribute.ApiSince value? My current build tree has:

			[Register ("ACCESS_BACKGROUND_LOCATION")]
			public const string AccessBackgroundLocation = (string) "android.permission.ACCESS_BACKGROUND_LOCATION";

obj/Debug/android-29/mcw/api.xml, meanwhile, contains:

<field deprecated="not deprecated"
    final="true"
    name="ACCESS_BACKGROUND_LOCATION"
    jni-signature="Ljava/lang/String;"
    static="true"
    transient="false"
    type="java.lang.String"
    type-generic-aware="java.lang.String"
    value="&quot;android.permission.ACCESS_BACKGROUND_LOCATION&quot;"
    visibility="public"
    volatile="false"
    merge.SourceFile="../../bin/BuildDebug/api/api-29.xml.in"
/>

(Newlines added for readability.)

Note that //field/@merge.SourceFile is set, and thus, ApiVersionSupport.ApiAvailableSince should be set (...right?), and thus we should be including RegisterAttribute.ApiSince!

https://github.com/xamarin/java.interop/blob/4565369743a58a1d43e5a79c406c27d46b81bb08/tools/generator/ApiVersionsSupport.cs#L12
https://github.com/xamarin/java.interop/blob/4565369743a58a1d43e5a79c406c27d46b81bb08/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs#L439

...yet the fact that we're not emitting RegisterAttribute.ApiSince implies that something is missing. What's missing? Why aren't we always emitting ApiSince on every member?

@jpobst
Copy link
Contributor

jpobst commented Jan 14, 2020

It looks like we actually pull our ApiSince versions from C:\Users\jopobst\android-toolchain\sdk\platform-tools\api\api-versions.xml which ships with the Android SDK.

(https://android.googlesource.com/platform/development/+/refs/heads/master/sdk/api-versions.xml).

Therefore I suspect that this file was updated in this Android SDK version.

I have 28.0.2 installed and it does not contain an entry for ACCESS_BACKGROUND_LOCATION.

https://github.com/xamarin/java.interop/blob/master/tools/generator/CodeGenerator.cs#L158

@jonpryor
Copy link
Contributor

@jpobst wrote:

It looks like we actually pull our ApiSince versions from C:\Users\jopobst\android-toolchain\sdk\platform-tools\api\api-versions.xml which ships with the Android SDK.

That explains a lot.

"Doubly" fun and interesting is that I have platform-tools 29.0.1 installed -- which matches the previous $(XAPlatformToolsVersion) value -- and that likewise doesn't have the ACCESS_BACKGROUND_LOCATION entry.

Apparently platform-tools 29.0.5 does add it and others, hence all the breakage in this PR.

Which leads me to believe that api-versions.xml cannot be trusted: it (apparently) isn't updated alongside platforms/android-*/android.jar, at least not in any "short" timeframe.

How hard would it be to update generator to instead use the //*/@merge.SourceFile attribute values?

@jpobst
Copy link
Contributor

jpobst commented Jan 17, 2020

Not very hard, though I would probably prefer to change api-merge to add an @api-since attribute that we read instead. I'd like any new generator change we make to be as generic as possible and not Mono.Android.dll specific.

jonpryor pushed a commit that referenced this pull request Jan 29, 2020
A "funny" thing happened when we bumped `$(XAPlatformToolsVersion)`
in PR #4012: ~all of the API compat checks started failing!

	AfterBuild:
	  CheckApiCompatibility for ApiLevel: v10.0
	  CompatApi command: ../../packages/Microsoft.DotNet.ApiCompat.5.0.0-beta.19606.1/tools/net472/Microsoft.DotNet.ApiCompat.exe "../../tests/api-compatibility\reference\ApiCompatTemp" -i "F:\A\xamarin-v000006-1\_work\2\s\bin\Release\lib\xamarin.android\xbuild-frameworks\MonoAndroid\v10.0\ApiCompatTemp" --exclude-attributes ../../tests/api-compatibility\api-compat-exclude-attributes.txt 
	  Compat issues with assembly Mono.Android:
	  CannotChangeAttribute : Attribute 'Android.Runtime.RegisterAttribute' on 'System.String Android.Manifest.Permission.AccessBackgroundLocation' changed from '[RegisterAttribute("ACCESS_BACKGROUND_LOCATION")]' in the contract to '[RegisterAttribute("ACCESS_BACKGROUND_LOCATION", ApiSince=29)]' in the implementation.
	  ...

The API compat checks are failing because of the *introduction* of
`RegisterAttribute.ApiSince` property values for members added in
API-29, and these errors didn't "make sense" to use because we had
expected all these members to *already* have `ApiSince=29`!

What Went Wrong™?

For starters, our memory and expectations were...incomplete.
`RegisterAttribute.ApiSince` is set based on the contents of the
Android SDK file `platform-tools/api/api-versions.xml`, which is part
of the "platform-tools" package.

Turns Out™ that `api-versions.xml` was *not* updated by Google when
the platform-tools package was updated to r29.  Specifically, the
`platform-tools/api/api-versions.xml` file within
`platform-tools_r29.0.1-darwin.zip` doesn't contain *any* members
from API-29, and `RegisterAttribute.ApiSince` is only emitted when
the member is found within `api-versions.xml`.

This explains why PR #4012 "caused" the API breakage: The
platform-tools r29.0.5 package *does* contain an `api-versions.xml`
which contains API-29 members; thus updating platform-tools "caused"
the emission of the `RegisterAttribute.ApiSince` property values.

Which is a long-winded way of saying that *we cannot trust* the
`api-versions.xml` file within the platform-tools package.

With that trust lost, what do we use instead?  There is another set
of `api-version.xml` files: starting with API-26, there are
`platforms/android-*/data/api-versions.xml` files.  Furthermore, the
`api-versions.xml` file included with API-Q -- the preview for API-29
-- *did* contain the members added in API-29, and *did* indicate that
those members were added in API-29.  As such, we do consider this
source of data to be trustworthy (this week, anyway).

Update `Mono.Android.targets` to use
`$(AndroidSdkDirectory)\platforms\android-$(AndroidApiLevel)\data\api-versions.xml`
for `RegisterAttribute.ApiSince` information, if it exists.  If it
doesn't exist, we fallback and use the previously used platform-tools
copy of `api-versions.xml`.

Finally, two related changes:

 1. Update to use `Microsoft.DotNet.GenAPI` and
    `Microsoft.DotNet.ApiCompat` package versions of
    5.0.0-beta.20078.1, up from 5.0.0-beta.20078.1.
    This was done as it supposedly contains performance improvements.

 2. Improve the mono crash detection from 5b1422c.  With 5b1422c,
    sometimes there would be "odd behavior" when re-using the same
    `Process` object after the crash was detected.  The `Process`
    usage recommendation is to use a new `Process` object for each
    process invocation; implement this recommendation.
@jonpryor
Copy link
Contributor

With the merging of #4186, this PR (hopefully) will no longer trigger API compat breakage. Let's find out!

@jonpryor
Copy link
Contributor

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@brendanzagaeski
Copy link
Contributor Author

I think I can now I can remove the acceptable-breakages-vReference.txt changes from this PR. I'll take a look at that now.

@brendanzagaeski
Copy link
Contributor Author

Ah ha. 4cd2060 contains identical changes to acceptable-breakages-vReference.txt, so a squashed merge would handle that with no complaints. But I'll pre-squash it on this branch so the commit history is a little easier to review before the final merge.

Context: dotnet@c523107
Context: https://dev.azure.com/devdiv/DevDiv/_workitems/edit/1032105

As described in [c523107][0], we should be using the latest versions of
the Android tooling if possible, matching the major version with the max
API level we support.  Xamarin.Android now supports Android 10 (API
level 29), so we should be using the 29.x.x versions of the tooling.

Update `$(AndroidSdkBuildToolsVersion)` and `$(XABuildToolsVersion)` to
29.0.2.

Update `$(AndroidSdkPlatformToolsVersion)` and
`$(XAPlatformToolsVersion)` to 29.0.5.

[0]: dotnet@c523107
@brendanzagaeski
Copy link
Contributor Author

Changes in the latest force-push:

Rebased on master and squashed the commits, removing the API compatibility adjustments along the way since those are now already in master.

@dellis1972
Copy link
Contributor

@brendanzagaeski how is this PR going? Looks like we might need to get it into d16-5?

@brendanzagaeski
Copy link
Contributor Author

I think this PR is all set to merge to master. The CI test failures are unrelated to this PR specifically. So for the question of merging to master, I think this is ready to go.

Thoughts on backporting:

On the one hand, backporting this PR would address some oddness in Visual Studio 2019 version 16.5 Preview where the automatic SDK installation feature currently installs Android SDK Build-Tools version 29.0.2 even though it isn't used. And Build-Tools versions usually have good backwards compatibility, so using version 29.0.2 would in theory be fine for all of the current Android 9 Pie (API level 28) templates and users' existing projects.

On the other hand, as long as users don't manually adjust the installed Build-Tools versions after accepting the auto SDK prompt, the experience is fairly smooth. And there could be some risk in changing the default Build-Tools at this point in the Xamarin.Android 10.2 schedule.

If we do decide to backport, the Visual Studio Installer should probably also be adjusted to install Build-Tools 29.0.2 instead of 28.0.3.

Separate from whatever we decide on this PR, for the next anticipated Build-Tools update (30.0), I think it might be worth updating the default $(AndroidSdkBuildToolsVersion) version earlier, as part of the general availability release of the corresponding Android 11 (API level 30) bindings, even though the templates will still be on Android 10 (API level 29).

Background info:

In Visual Studio 2019 version 16.5 Preview 2 (and also the latest internal preview):

  1. The Visual Studio Installer installs only Android SDK Build-Tools version 28.0.3.

  2. The Android templates target Android 9.0 Pie (API level 28). The switch to Android 10 (API level 29) is planned for the d16-6 branch (internal work item).

  3. The first time an Android project is loaded (for example, when creating a new project from a template), the automatic SDK installation (Auto Install Android SDKs) feature requests permission to install Android SDK Build-Tools version 29.0.2.

  4. If the user cancels the installation at step 3, then the auto SDK installation feature will block building within Visual Studio:

    Project 'AndroidApp1' requires the following components installed on your machine: 
    Android Emulator, Android SDK Build-Tools 29.0.2
    

    (The behavior that aborts the build comes from AndroidSetup.cs lines 83-118 in the proprietary Visual Studio Tools for Xamarin source code. It's not part of the MSBuild targets themselves.)

  5. If the user accepts the installation at step 3 or builds on the command line, they will be able to build the project successfully. The build will use the default $(AndroidSdkBuildToolsVersion) of 28.0.3 (what this PR is changing).

  6. If the user installs Build-Tools version 29.0.2 and also uninstalls Build-Tools version 28.0.3, then the auto SDK installation feature will again block building in the IDE, this time requiring Build-Tools version 28.0.3 because of the default $(AndroidSdkBuildToolsVersion) (what this PR is changing).

    The workaround is to set $(AndroidSdkBuildToolsVersion) in the .csproj file:

    <PropertyGroup>
      <AndroidSdkBuildToolsVersion>29.0.2</AndroidSdkBuildToolsVersion>
    </PropertyGroup>

    (In contrast, for command line builds, even if $(AndroidSdkBuildToolsVersion) is left at the default of 28.0.3, the build will automatically use Build-Tools version 29.0.2 if it can't find the preferred version 28.0.3.)

Overall, the current first-run user experience does work, but it's a little odd. In particular, it's odd that auto SDK asks to install Build-Tools version 29.0.2 when that version won't be used.

I haven't studied the Visual Studio Tools for Xamarin AndroidToolsBuildService.cs file enough to understand where the Build-Tools version 29.0.2 dependency is coming from, but I have a hunch it might come from the Android SDK Manager manifest, which now offers Build-Tools version 29.0.2 to satisfy a request I helped submit.

(On a side note, with all of the various tools Xamarin.Android now has in its own installer, it's interesting how little of Android SDK Build-Tools Xamarin.Android uses for projects that are configured to use AAPT2, D8, and the Android App Bundle publishing format. I think it might only use zipalign and aidl. For APKs, it also uses apksigner.jar.)

@jonpryor jonpryor merged commit 4f7fda7 into dotnet:master Feb 4, 2020
jonpryor pushed a commit that referenced this pull request May 13, 2020
Context: #4012 (comment)
Context: #4012 (comment)
Context: dotnet/java-interop@005e273
Context: a348617

Changes: dotnet/java-interop@377c4c7...186174c

  * dotnet/java-interop@186174c: [generator] Use //*/@api-since for RegisterAttribute.ApiSince (#644)
  * dotnet/java-interop@010161d: [generator] slnf file should use relative path. (#641)
  * dotnet/java-interop@942f787: [CI] Add a .NET Core Windows lane. (#640)

When `generator --apiversions=FILE` is used, then the
`RegisterAttribute.ApiSince` field will be set to contain the API
version which introduced a method, e.g. when building
`src/Mono.Android`:

	$ generator.exe --apiversions=$HOME/android-toolchain/sdk/platform-tools/api/api-versions.xml …

and `$HOME/android-toolchain/sdk/platform-tools/api/api-versions.xml`
contains:

	<class name="android/view/inspector/IntFlagMapping" since="29">
	  <extends name="java/lang/Object"/>

then `generator` will emit:

	[Register ("android/view/inspector/IntFlagMapping", DoNotGenerateAcw=true, ApiSince=29)]
	partial class IntFlagMapping {}

Unfortunately, we have found that Google's support of this file isn't
guaranteed.  Sometimes it is missing, other times it changes in
unexpected ways; either can causes `ApiCompat` breakage when
building `Mono.Android`, resulting in the removal or modification of
the `RegisterAttribute.ApiSince` values.

In short, we have lost faith in `api-versions.xml`.

dotnet/java-interop@186174c updates `generator` so that *instead of*
using an `api-versions.xml` file to provide `RegisterAttribute.ApiSince`
values, those values can instead come from `//*/@api-since` attributes.

The `//*/@api-since` attributes in turn can come from
`src/Mono.Android/metadata`, based on the `//*/@merge.SourceFile`
attribute values that `build-tools/api-merge` emits (a073d99).  This
data is computed directly from the `android.jar` files, and should
always be updated and (reasonably) correct.


~~ Notable differences ~~

Our current method provides data for API levels that we do not use for
`api-merge`, such as 2, 4, 11, and 14.  However we feel it is ok to
"lose" this data, as it isn't really useful to our users.  That is, if
the minimum Xamarin.Android can target is API-21 (a648981), it is not
useful to know that an API was added in API-9, since there is no way to
target an API level where the member is not available.

As such, we are not collecting data for API levels 21 or below, and all
members added in any of those levels are considered to "always" have
been available, with no `RegisterAttribute.ApiSince` value.

~~ ApiCompat ~~

This change creates a significant amount of API "breakages" where
`RegisterAttribute.ApiSince` is either getting added or removed.
Rather than add an additional 25K lines to `acceptable-breakages`, we
are updating the reference assembly.

[Elsewhere][0] is a list of the `ApiSince` info that changed as a
result, for reference.  There are no non-`ApiSince` changes.

  * ~12.3K members previously had no `ApiSince` and now have
    `ApiSince=22-29`.

  * ~12.1K members previously had `ApiSince=1-21` and now have
    no `ApiSince` value.

  * ~200 related fields changed from `28` to `29`, this seems to be
    correct from looking at the source files.

A snippet of the file:

	System.String Android.Service.Carrier.CarrierMessagingService.ServiceInterface - 0 => 22
	Android.Service.Carrier.CarrierMessagingService..ctor() - 0 => 22
	Android.Service.Carrier.CarrierMessagingService.OnBind(Android.Content.Intent) - 0 => 22
	Android.Service.Carrier.CarrierMessagingService.OnDownloadMms(Android.Net.Uri, System.Int32, Android.Net.Uri, Android.Service.Carrier.CarrierMessagingService.IResultCallback) - 0 => 22
	…

Finally, ignore the attribute
`T:System.Diagnostics.DebuggerStepThroughAttribute`, which seems to be
generated in some versions of Roslyn when using an `async Task` method.
My local compiler (VS2019 16.5) generates it but apparently the version
on the Mac agents does not.

[0]: https://github.com/xamarin/xamarin-android/files/4616691/api-compat-parsed.txt
jonpryor pushed a commit that referenced this pull request May 15, 2020
Context: #4012 (comment)
Context: #4012 (comment)
Context: dotnet/java-interop@005e273
Context: a348617

Changes: dotnet/java-interop@e599781...d6024f1

  * dotnet/java-interop@d6024f1: [generator] Use //*/@api-since for RegisterAttribute.ApiSince (#644)
  * dotnet/java-interop@3968236: [generator] slnf file should use relative path. (#641)
  * dotnet/java-interop@67b6f70: [CI] Add a .NET Core Windows lane. (#640)

When `generator --apiversions=FILE` is used, then the
`RegisterAttribute.ApiSince` field will be set to contain the API
version which introduced a method, e.g. when building
`src/Mono.Android`:

	$ generator.exe --apiversions=$HOME/android-toolchain/sdk/platform-tools/api/api-versions.xml …

and `$HOME/android-toolchain/sdk/platform-tools/api/api-versions.xml`
contains:

	<class name="android/view/inspector/IntFlagMapping" since="29">
	  <extends name="java/lang/Object"/>

then `generator` will emit:

	[Register ("android/view/inspector/IntFlagMapping", DoNotGenerateAcw=true, ApiSince=29)]
	partial class IntFlagMapping {}

Unfortunately, we have found that Google's support of this file isn't
guaranteed.  Sometimes it is missing, other times it changes in
unexpected ways; either can causes `ApiCompat` breakage when
building `Mono.Android`, resulting in the removal or modification of
the `RegisterAttribute.ApiSince` values.

In short, we have lost faith in `api-versions.xml`.

dotnet/java-interop@186174c updates `generator` so that *instead of*
using an `api-versions.xml` file to provide `RegisterAttribute.ApiSince`
values, those values can instead come from `//*/@api-since` attributes.

The `//*/@api-since` attributes in turn can come from
`src/Mono.Android/metadata`, based on the `//*/@merge.SourceFile`
attribute values that `build-tools/api-merge` emits (a073d99).  This
data is computed directly from the `android.jar` files, and should
always be updated and (reasonably) correct.

~~ Notable differences ~~

Our current method provides data for API levels that we do not use for
`api-merge`, such as 2, 4, 11, and 14.  However we feel it is ok to
"lose" this data, as it isn't really useful to our users.  That is, if
the minimum Xamarin.Android can target is API-21 (a648981), it is not
useful to know that an API was added in API-9, since there is no way to
target an API level where the member is not available.

As such, we are not collecting data for API levels 21 or below, and all
members added in any of those levels are considered to "always" have
been available, with no `RegisterAttribute.ApiSince` value.

~~ ApiCompat ~~

This change creates a significant amount of API "breakages" where
`RegisterAttribute.ApiSince` is either getting added or removed.
Rather than add an additional 25K lines to `acceptable-breakages`, we
are updating the reference assembly.

[Elsewhere][0] is a list of the `ApiSince` info that changed as a
result, for reference.  There are no non-`ApiSince` changes.

  * ~12.3K members previously had no `ApiSince` and now have
    `ApiSince=22-29`.

  * ~12.1K members previously had `ApiSince=1-21` and now have
    no `ApiSince` value.

  * ~200 related fields changed from `28` to `29`, this seems to be
    correct from looking at the source files.

A snippet of the file:

	System.String Android.Service.Carrier.CarrierMessagingService.ServiceInterface - 0 => 22
	Android.Service.Carrier.CarrierMessagingService..ctor() - 0 => 22
	Android.Service.Carrier.CarrierMessagingService.OnBind(Android.Content.Intent) - 0 => 22
	Android.Service.Carrier.CarrierMessagingService.OnDownloadMms(Android.Net.Uri, System.Int32, Android.Net.Uri, Android.Service.Carrier.CarrierMessagingService.IResultCallback) - 0 => 22
	…

Finally, ignore the attribute
`T:System.Diagnostics.DebuggerStepThroughAttribute`, which seems to be
generated in some versions of Roslyn when using an `async Task` method.
My local compiler (VS2019 16.5) generates it but apparently the version
on the Mac agents does not.

[0]: https://github.com/xamarin/xamarin-android/files/4616691/api-compat-parsed.txt
@github-actions github-actions bot locked and limited conversation to collaborators Jan 28, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants