From ca4ae3873a6b541a06168ad8c0a4c1ca18c732a9 Mon Sep 17 00:00:00 2001
From: Dean Ellis <dellis1972@googlemail.com>
Date: Tue, 28 Sep 2021 10:20:44 +0100
Subject: [PATCH 01/18] First Pass at using Resource Designer assembly [WIP]

Context #6310

Ignore Java.Interop-Tests IntermediateDir

Try StrongNaming. Based on code in https://github.com/brutaldev/StrongNameSigner/blob/master/src/Brutal.Dev.StrongNameSigner/SigningHelper.cs

Use ICSharpCode.Decompiler to read Resource Designer Assembly

Fix breakage

Fix error with Aapt2 R.txt

Use latest Xamarin.Forms for dotnet tests

Disable StrongNaming for now

Removed unused code and logging

Remove StrongNaming support

Revert "Remove StrongNaming support"

This reverts commit 7f90638f1788adfa37c4ec4ab3fed9fc48569cb5.

Use a cstom snk for the designer strong name

Update apkdesc

Change to Microsoft.Android.Resource.Designer

new test

Move CryptoConvert to src-ThirdParty

Add StrongNameSigner code and TPN

Fix missing file

Fix another build error

Fix a test

Update and Fix the UnitTest

update docs

Switch to _Microsoft.Android.Resource.Designer.dll

update apkdesc

update apkdesc
---
 .../guides/building-apps/build-properties.md  |  28 ++
 .../installers/create-installers.targets      |   1 +
 .../ThirdPartyNotices/StrongNameSigner.cs     |  33 ++
 .../CryptoConvert.cs                          | 338 +++++++++++++++
 .../StrongNameSigner/SigningHelper.cs         |  35 ++
 .../FixLegacyResourceDesignerStep.cs          | 163 ++++++++
 .../MonoDroid.Tuner/LinkDesignerBase.cs       |  20 +-
 .../Linker/MonoDroid.Tuner/Linker.cs          |   2 +
 .../Linker/MonoDroid.Tuner/LinkerOptions.cs   |   1 +
 .../Android/Xamarin.Android.Aapt2.targets     |   2 +-
 .../Android/Xamarin.Android.Designer.targets  |   2 +-
 .../Xamarin.Android.Resource.Designer.targets | 217 ++++++++++
 ...oft.Android.Sdk.AssemblyResolution.targets |   8 +
 .../Microsoft.Android.Sdk.BuildOrder.targets  |  14 +-
 ...soft.Android.Sdk.DefaultProperties.targets |   2 +
 .../Microsoft.Android.Sdk.ILLink.targets      |   7 +-
 .../Microsoft.Android.Sdk.Publish.targets     |   1 +
 .../Properties/Resources.Designer.cs          |   9 +
 .../Properties/Resources.resx                 |   4 +
 .../Resources/Resource.Designer.snk           | Bin 0 -> 596 bytes
 .../Tasks/Aapt2Link.cs                        |   7 +-
 .../Tasks/AppendCustomMetadataToItemGroup.cs  |   5 +
 .../Tasks/ConvertCustomView.cs                |   6 +-
 .../Tasks/FilterAssemblies.cs                 |   2 +
 .../Tasks/GenerateLibraryResources.cs         |   3 +-
 .../Tasks/GeneratePackageManagerJava.cs       |   2 +-
 .../Tasks/GenerateResourceCaseMap.cs          | 121 ++++++
 .../Tasks/GenerateResourceDesigner.cs         |  32 +-
 .../Tasks/GenerateResourceDesignerAssembly.cs | 350 ++++++++++++++++
 ...nerateResourceDesignerIntermediateClass.cs |  53 +++
 .../Tasks/GenerateRtxt.cs                     |  48 +++
 .../Tasks/LinkAssemblies.cs                   |   3 +
 .../Tasks/LinkAssembliesNoShrink.cs           |  40 +-
 .../Tasks/ResolveLibraryProjectImports.cs     |   8 +-
 .../AndroidUpdateResourcesTest.cs             | 112 +++--
 .../Xamarin.Android.Build.Tests/AotTests.cs   |   7 +
 .../Xamarin.Android.Build.Tests/BuildTest.cs  |  30 +-
 .../DesignerTests.cs                          |   6 +
 .../IncrementalBuildTest.cs                   |   5 +
 .../PackagingTest.cs                          |   1 +
 .../Tasks/GenerateResourceCaseMapTests.cs     |  51 +++
 .../Tasks/ManagedResourceParserTests.cs       |  62 ++-
 .../Utilities/BaseTest.cs                     |  27 ++
 .../Xamarin.Android.Build.Tests/XASdkTests.cs |  82 +++-
 .../Xamarin.Android.Build.Tests.csproj        |   1 +
 .../Android/KnownPackages.cs                  |  15 +
 .../Android/XamarinAndroidCommonProject.cs    |   6 +-
 .../Android/XamarinAndroidProjectLanguage.cs  |   2 +-
 .../Xamarin.ProjectTools/Common/DotNetCLI.cs  |   4 +-
 .../BuildReleaseArm64SimpleDotNet.apkdesc     |   5 +-
 .../BuildReleaseArm64SimpleLegacy.apkdesc     |  16 +-
 .../BuildReleaseArm64XFormsDotNet.apkdesc     |   9 +-
 .../BuildReleaseArm64XFormsLegacy.apkdesc     |  85 ++--
 .../Utilities/FileResourceParser.cs           | 389 ++++++++++++++++++
 .../Utilities/ManagedResourceParser.cs        | 126 +-----
 .../Utilities/MonoAndroidHelper.cs            |  44 +-
 .../ResourceDesignerImportGenerator.cs        |   1 +
 .../Utilities/ResourceIdentifier.cs           |  18 +-
 .../Utilities/ResourceParser.cs               |  12 +-
 .../Utilities/RtxtParser.cs                   | 156 +++++++
 .../Utilities/RtxtWriter.cs                   |  23 ++
 .../Xamarin.Android.Build.Tasks.csproj        |   9 +
 .../Xamarin.Android.Build.Tasks.targets       |   4 +
 .../Xamarin.Android.Common.targets            |  64 ++-
 .../Xamarin.Android.DesignTime.targets        |   1 +
 .../Xamarin.Android.Legacy.targets            |   7 +-
 .../MSBuildDeviceIntegration.csproj           |   1 +
 .../Tests/InstallAndRunTests.cs               |  86 ++++
 .../Tests/InstantRunTest.cs                   |   1 +
 .../Java.Interop-Tests.csproj                 |   1 +
 .../Mono.Android-Test.Shared.projitems        |   1 -
 .../Mono.Android-Tests.csproj                 |   1 +
 .../Mono.Android-TestsMultiDex.csproj         |   2 +-
 73 files changed, 2739 insertions(+), 301 deletions(-)
 create mode 100644 build-tools/xaprepare/xaprepare/ThirdPartyNotices/StrongNameSigner.cs
 create mode 100644 src-ThirdParty/Mono.Security.Cryptography/CryptoConvert.cs
 create mode 100644 src-ThirdParty/StrongNameSigner/SigningHelper.cs
 create mode 100644 src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs
 create mode 100644 src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets
 create mode 100644 src/Xamarin.Android.Build.Tasks/Resources/Resource.Designer.snk
 create mode 100644 src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceCaseMap.cs
 create mode 100644 src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerAssembly.cs
 create mode 100644 src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerIntermediateClass.cs
 create mode 100644 src/Xamarin.Android.Build.Tasks/Tasks/GenerateRtxt.cs
 create mode 100644 src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GenerateResourceCaseMapTests.cs
 create mode 100644 src/Xamarin.Android.Build.Tasks/Utilities/FileResourceParser.cs
 create mode 100644 src/Xamarin.Android.Build.Tasks/Utilities/RtxtParser.cs
 create mode 100644 src/Xamarin.Android.Build.Tasks/Utilities/RtxtWriter.cs

diff --git a/Documentation/guides/building-apps/build-properties.md b/Documentation/guides/building-apps/build-properties.md
index ee48b5653fe..72b17d2806d 100644
--- a/Documentation/guides/building-apps/build-properties.md
+++ b/Documentation/guides/building-apps/build-properties.md
@@ -1364,6 +1364,34 @@ To suppress the default AOT profiles, set the property to `false`.
 
 Added in Xamarin.Android 10.1.
 
+## AndroidUseDesignerAssembly
+
+A bool property which controls if the build system will generate an
+`_Microsoft.Android.Resource.Designer.dll` as apposed to a `Resource.Designer.cs` file. The benefits of this are smaller applications and
+faster startup time.
+
+The default value is `true` in .NET 8.
+
+This setting is not backward compatible with Classic Xamarin.Android.
+As a Nuget Author it is recommended that you ship three versions of
+the assembly if you want to maintain backward compatibility.
+One for MonoAndroid, one for net6.0-android and
+one for net8.0-android. You can do this by using [Xamarin.Legacy.Sdk](https://www.nuget.org/packages/Xamarin.Legacy.Sdk).
+
+```
+<TargetFrameworks>monoandroid90;net6.0-android;net8.0-android</TargetFrameworks>
+```
+
+Alternatively turn this setting off until such time as both Classic and
+net7.0-android have been deprecated.
+
+.NET 8 Projects which choose to turn this setting off will not be able to
+consume references which do use it. If you try to use an assembly
+which does have this feature enabled in a project that does not, you will
+get a `XA1031` build error.
+
+Added in .NET 8.  Unsupported in Classic Xamarin.Android.
+
 ## AndroidUseInterpreter
 
 A boolean property that causes the `.apk` to contain the mono
diff --git a/build-tools/installers/create-installers.targets b/build-tools/installers/create-installers.targets
index 51ff5bb9a1d..3e589147ceb 100644
--- a/build-tools/installers/create-installers.targets
+++ b/build-tools/installers/create-installers.targets
@@ -303,6 +303,7 @@
     <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.CSharp.targets" ExcludeFromAndroidNETSdk="true" />
     <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.D8.targets" />
     <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.Designer.targets" />
+    <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.Resource.Designer.targets" />
     <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.DesignTime.targets" />
     <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.EmbeddedResource.targets" />
     <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.FSharp.targets" ExcludeFromAndroidNETSdk="true" />
diff --git a/build-tools/xaprepare/xaprepare/ThirdPartyNotices/StrongNameSigner.cs b/build-tools/xaprepare/xaprepare/ThirdPartyNotices/StrongNameSigner.cs
new file mode 100644
index 00000000000..45ab44b28b4
--- /dev/null
+++ b/build-tools/xaprepare/xaprepare/ThirdPartyNotices/StrongNameSigner.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Xamarin.Android.Prepare
+{
+	[TPN]
+	class StrongNameSigner_TPN : ThirdPartyNotice
+	{
+		static readonly Uri    url         = new Uri ("https://github.com/brutaldev/StrongNameSigner/");
+
+		public override string LicenseFile => string.Empty;
+		public override string Name        => "brutaldev/StrongNameSigner";
+		public override Uri    SourceUrl   => url;
+		public override string LicenseText => @"
+Copyright (c) Werner van Deventer (werner@brutaldev.com).  All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the 'License'); you
+may not use this file except in compliance with the License. You may
+obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an 'AS IS' BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+implied. See the License for the specific language governing permissions
+and limitations under the License.
+";
+
+		public override bool   Include (bool includeExternalDeps, bool includeBuildDeps) => includeExternalDeps;
+	}
+}
diff --git a/src-ThirdParty/Mono.Security.Cryptography/CryptoConvert.cs b/src-ThirdParty/Mono.Security.Cryptography/CryptoConvert.cs
new file mode 100644
index 00000000000..5a5eecc1468
--- /dev/null
+++ b/src-ThirdParty/Mono.Security.Cryptography/CryptoConvert.cs
@@ -0,0 +1,338 @@
+//
+// CryptoConvert.cs - Crypto Conversion Routines
+//
+// Author:
+//	Sebastien Pouliot  <sebastien@ximian.com>
+//
+// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
+// Copyright (C) 2004-2006 Novell Inc. (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Original source can be found at
+// https://github.com/mono/mono/blob/e2c5f4b0ad1a6b21ca0735f0b35b8611d4ad87b3/mcs/class/Mono.Security/Mono.Security.Cryptography/CryptoConvert.cs#L4
+
+using System;
+using System.Security.Cryptography;
+
+namespace Mono.Security.Cryptography
+{
+  internal static class CryptoConvert
+  {
+    static private int ToInt32LE(byte[] bytes, int offset)
+    {
+      return (bytes[offset + 3] << 24) | (bytes[offset + 2] << 16) | (bytes[offset + 1] << 8) | bytes[offset];
+    }
+
+    static private uint ToUInt32LE(byte[] bytes, int offset)
+    {
+      return (uint)((bytes[offset + 3] << 24) | (bytes[offset + 2] << 16) | (bytes[offset + 1] << 8) | bytes[offset]);
+    }
+
+    static private byte[] GetBytesLE(int val)
+    {
+      return new byte[] {
+        (byte) (val & 0xff),
+        (byte) ((val >> 8) & 0xff),
+        (byte) ((val >> 16) & 0xff),
+        (byte) ((val >> 24) & 0xff)
+      };
+    }
+
+    static private byte[] Trim(byte[] array)
+    {
+      for (int i = 0; i < array.Length; i++)
+      {
+        if (array[i] != 0x00)
+        {
+          byte[] result = new byte[array.Length - i];
+          Buffer.BlockCopy(array, i, result, 0, result.Length);
+          return result;
+        }
+      }
+
+#pragma warning disable S1168 // Empty arrays and collections should be returned instead of null
+      return null;
+#pragma warning restore S1168 // Empty arrays and collections should be returned instead of null
+    }
+
+    private static RSA FromCapiPrivateKeyBlob(byte[] blob, int offset)
+    {
+      var rsap = new RSAParameters();
+
+      try
+      {
+        if ((blob[offset] != 0x07) ||       // PRIVATEKEYBLOB (0x07)
+            (blob[offset + 1] != 0x02) ||       // Version (0x02)
+            (blob[offset + 2] != 0x00) ||       // Reserved (word)
+            (blob[offset + 3] != 0x00) ||
+            (ToUInt32LE(blob, offset + 8) != 0x32415352)) // DWORD magic = RSA2
+        {
+          throw new CryptographicException("Invalid blob header");
+        }
+
+        //// ALGID (CALG_RSA_SIGN, CALG_RSA_KEYX, ...)
+        //// int algId = ToInt32LE (blob, offset+4);
+
+        //// DWORD bitlen
+        int bitLen = ToInt32LE(blob, offset + 12);
+
+        //// DWORD public exponent
+        byte[] exp = new byte[4];
+        Buffer.BlockCopy(blob, offset + 16, exp, 0, 4);
+        Array.Reverse(exp);
+        rsap.Exponent = Trim(exp);
+
+        int pos = offset + 20;
+        //// BYTE modulus[rsapubkey.bitlen/8];
+        int byteLen = (bitLen >> 3);
+        rsap.Modulus = new byte[byteLen];
+        Buffer.BlockCopy(blob, pos, rsap.Modulus, 0, byteLen);
+        Array.Reverse(rsap.Modulus);
+        pos += byteLen;
+
+        //// BYTE prime1[rsapubkey.bitlen/16];
+        int byteHalfLen = (byteLen >> 1);
+        rsap.P = new byte[byteHalfLen];
+        Buffer.BlockCopy(blob, pos, rsap.P, 0, byteHalfLen);
+        Array.Reverse(rsap.P);
+        pos += byteHalfLen;
+
+        //// BYTE prime2[rsapubkey.bitlen/16];
+        rsap.Q = new byte[byteHalfLen];
+        Buffer.BlockCopy(blob, pos, rsap.Q, 0, byteHalfLen);
+        Array.Reverse(rsap.Q);
+        pos += byteHalfLen;
+
+        //// BYTE exponent1[rsapubkey.bitlen/16];
+        rsap.DP = new byte[byteHalfLen];
+        Buffer.BlockCopy(blob, pos, rsap.DP, 0, byteHalfLen);
+        Array.Reverse(rsap.DP);
+        pos += byteHalfLen;
+
+        //// BYTE exponent2[rsapubkey.bitlen/16];
+        rsap.DQ = new byte[byteHalfLen];
+        Buffer.BlockCopy(blob, pos, rsap.DQ, 0, byteHalfLen);
+        Array.Reverse(rsap.DQ);
+        pos += byteHalfLen;
+
+        //// BYTE coefficient[rsapubkey.bitlen/16];
+        rsap.InverseQ = new byte[byteHalfLen];
+        Buffer.BlockCopy(blob, pos, rsap.InverseQ, 0, byteHalfLen);
+        Array.Reverse(rsap.InverseQ);
+        pos += byteHalfLen;
+
+        // ok, this is hackish but CryptoAPI support it so...
+        // note: only works because CRT is used by default
+        // http://bugzilla.ximian.com/show_bug.cgi?id=57941
+        rsap.D = new byte[byteLen]; // must be allocated
+        if (pos + byteLen + offset <= blob.Length)
+        {
+          //// BYTE privateExponent[rsapubkey.bitlen/8];
+          Buffer.BlockCopy(blob, pos, rsap.D, 0, byteLen);
+          Array.Reverse(rsap.D);
+        }
+      }
+      catch (Exception e)
+      {
+        throw new CryptographicException("Invalid blob.", e);
+      }
+
+      RSA rsa = null;
+      try
+      {
+        rsa = RSA.Create();
+        rsa.ImportParameters(rsap);
+      }
+      catch (CryptographicException)
+      {
+        // this may cause problem when this code is run under
+        // the SYSTEM identity on Windows (e.g. ASP.NET). See
+        // http://bugzilla.ximian.com/show_bug.cgi?id=77559
+        bool throws = false;
+        try
+        {
+          var csp = new CspParameters
+          {
+            Flags = CspProviderFlags.UseMachineKeyStore
+          };
+
+#pragma warning disable S4426 // Cryptographic keys should be robust
+          rsa = new RSACryptoServiceProvider(csp);
+#pragma warning restore S4426 // Cryptographic keys should be robust
+          rsa.ImportParameters(rsap);
+        }
+        catch
+        {
+          throws = true;
+        }
+
+        if (throws)
+        {
+          // rethrow original, not the latter, exception if this fails
+          throw;
+        }
+      }
+      return rsa;
+    }
+
+    private static RSA FromCapiPublicKeyBlob(byte[] blob, int offset)
+    {
+      try
+      {
+        if ((blob[offset] != 0x06) ||       // PUBLICKEYBLOB (0x06)
+            (blob[offset + 1] != 0x02) ||       // Version (0x02)
+            (blob[offset + 2] != 0x00) ||       // Reserved (word)
+            (blob[offset + 3] != 0x00) ||
+            (ToUInt32LE(blob, offset + 8) != 0x31415352)) // DWORD magic = RSA1
+        {
+          throw new CryptographicException("Invalid blob header");
+        }
+
+        //// ALGID (CALG_RSA_SIGN, CALG_RSA_KEYX, ...)
+        //// int algId = ToInt32LE (blob, offset+4);
+
+        // DWORD bitlen
+        int bitLen = ToInt32LE(blob, offset + 12);
+
+        //// DWORD public exponent
+        var rsap = new RSAParameters
+        {
+          Exponent = new byte[3]
+        };
+
+        rsap.Exponent[0] = blob[offset + 18];
+        rsap.Exponent[1] = blob[offset + 17];
+        rsap.Exponent[2] = blob[offset + 16];
+
+        int pos = offset + 20;
+        //// BYTE modulus[rsapubkey.bitlen/8];
+        int byteLen = bitLen >> 3;
+        rsap.Modulus = new byte[byteLen];
+        Buffer.BlockCopy(blob, pos, rsap.Modulus, 0, byteLen);
+        Array.Reverse(rsap.Modulus);
+
+        RSA rsa = null;
+        try
+        {
+          rsa = RSA.Create();
+          rsa.ImportParameters(rsap);
+        }
+        catch (CryptographicException)
+        {
+          // this may cause problem when this code is run under
+          // the SYSTEM identity on Windows (e.g. ASP.NET). See
+          // http://bugzilla.ximian.com/show_bug.cgi?id=77559
+          var csp = new CspParameters
+          {
+            Flags = CspProviderFlags.UseMachineKeyStore
+          };
+
+#pragma warning disable S4426 // Cryptographic keys should be robust
+          rsa = new RSACryptoServiceProvider(csp);
+#pragma warning restore S4426 // Cryptographic keys should be robust
+          rsa.ImportParameters(rsap);
+        }
+
+        return rsa;
+      }
+      catch (Exception e)
+      {
+        throw new CryptographicException("Invalid blob.", e);
+      }
+    }
+
+    // PRIVATEKEYBLOB
+    // PUBLICKEYBLOB
+    static public RSA FromCapiKeyBlob(byte[] blob)
+    {
+      return FromCapiKeyBlob(blob, 0);
+    }
+
+    static public RSA FromCapiKeyBlob(byte[] blob, int offset)
+    {
+      if (blob == null)
+      {
+        throw new ArgumentNullException(nameof(blob));
+      }
+
+      if (offset >= blob.Length)
+      {
+        throw new ArgumentException("blob is too small.");
+      }
+
+      switch (blob[offset])
+      {
+        case 0x00:
+          // this could be a public key inside an header
+          // like "sn -e" would produce
+          if (blob[offset + 12] == 0x06)
+          {
+            return FromCapiPublicKeyBlob(blob, offset + 12);
+          }
+          break;
+        case 0x06:
+          return FromCapiPublicKeyBlob(blob, offset);
+        case 0x07:
+          return FromCapiPrivateKeyBlob(blob, offset);
+      }
+      throw new CryptographicException("Unknown blob format.");
+    }
+
+    static public byte[] ToCapiPublicKeyBlob(RSA rsa)
+    {
+      var p = rsa.ExportParameters(false);
+      int keyLength = p.Modulus.Length; // in bytes
+      byte[] blob = new byte[20 + keyLength];
+
+      blob[0] = 0x06; // Type - PUBLICKEYBLOB (0x06)
+      blob[1] = 0x02; // Version - Always CUR_BLOB_VERSION (0x02)
+                      // [2], [3]		// RESERVED - Always 0
+      blob[5] = 0x24; // ALGID - Always 00 24 00 00 (for CALG_RSA_SIGN)
+      blob[8] = 0x52; // Magic - RSA1 (ASCII in hex)
+      blob[9] = 0x53;
+      blob[10] = 0x41;
+      blob[11] = 0x31;
+
+      byte[] bitlen = GetBytesLE(keyLength << 3);
+      blob[12] = bitlen[0]; // bitlen
+      blob[13] = bitlen[1];
+      blob[14] = bitlen[2];
+      blob[15] = bitlen[3];
+
+      // public exponent (DWORD)
+      int pos = 16;
+      int n = p.Exponent.Length;
+      while (n > 0)
+      {
+        blob[pos++] = p.Exponent[--n];
+      }
+
+      // modulus
+      pos = 20;
+      byte[] part = p.Modulus;
+      int len = part.Length;
+      Array.Reverse(part, 0, len);
+      Buffer.BlockCopy(part, 0, blob, pos, len);
+
+      return blob;
+    }
+  }
+}
diff --git a/src-ThirdParty/StrongNameSigner/SigningHelper.cs b/src-ThirdParty/StrongNameSigner/SigningHelper.cs
new file mode 100644
index 00000000000..260e1c92147
--- /dev/null
+++ b/src-ThirdParty/StrongNameSigner/SigningHelper.cs
@@ -0,0 +1,35 @@
+// Original source can be found at
+// https://github.com/brutaldev/StrongNameSigner/blob/c38d42ab8d1444504720a62736b310303236cd85/src/Brutal.Dev.StrongNameSigner/SigningHelper.cs#L437
+using System;
+using Mono.Security.Cryptography;
+
+
+namespace Brutal.Dev.StrongNameSigner {
+	/// <summary>
+	/// Static helper class for easily getting assembly information and strong-name signing .NET assemblies.
+	/// </summary>
+	public static class SigningHelper
+	{
+		internal static byte[] GetPublicKey (byte[] keyBlob)
+		{
+			using var rsa = CryptoConvert.FromCapiKeyBlob(keyBlob);
+			var cspBlob = CryptoConvert.ToCapiPublicKeyBlob(rsa);
+			var publicKey = new byte[12 + cspBlob.Length];
+			Buffer.BlockCopy(cspBlob, 0, publicKey, 12, cspBlob.Length);
+			// The first 12 bytes are documented at:
+			// http://msdn.microsoft.com/library/en-us/cprefadd/html/grfungethashfromfile.asp
+			// ALG_ID - Signature
+			publicKey[1] = 36;
+			// ALG_ID - Hash
+			publicKey[4] = 4;
+			publicKey[5] = 128;
+			// Length of Public Key (in bytes)
+			publicKey[8] = (byte)(cspBlob.Length >> 0);
+			publicKey[9] = (byte)(cspBlob.Length >> 8);
+			publicKey[10] = (byte)(cspBlob.Length >> 16);
+			publicKey[11] = (byte)(cspBlob.Length >> 24);
+
+			return publicKey;
+		}
+	}
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs
new file mode 100644
index 00000000000..8a88408c42d
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs
@@ -0,0 +1,163 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+using Java.Interop.Tools.Cecil;
+
+using Mono.Linker;
+using Mono.Linker.Steps;
+
+using Mono.Tuner;
+#if ILLINK
+using Microsoft.Android.Sdk.ILLink;
+#endif  // ILLINK
+
+namespace MonoDroid.Tuner
+{
+	public class FixLegacyResourceDesignerStep : LinkDesignerBase
+	{
+		internal const string DesignerAssemblyName = "_Microsoft.Android.Resource.Designer";
+		internal const string DesignerAssemblyNamespace = "Microsoft.Android.Resource.Designer";
+#if ILLINK
+		protected override void Process ()
+		{
+			cache = Context;
+		}
+#else // ILLINK
+		public FixLegacyResourceDesignerStep (IMetadataResolver cache)
+		{
+			this.cache = cache;
+		}
+
+		readonly
+#endif // ILLINK
+		IMetadataResolver cache;
+		AssemblyDefinition designerAssembly = null;
+		TypeDefinition designerType = null;
+		Dictionary<string, MethodDefinition> lookup;
+
+		protected override void EndProcess ()
+		{
+			if (designerAssembly != null) {
+				LogMessage ($"  Setting Action on {designerAssembly.Name} to Link.");
+				Annotations.SetAction (designerAssembly, AssemblyAction.Link);
+			}
+		}
+
+		protected override void LoadDesigner ()
+		{
+			if (designerAssembly != null)
+				return;
+			var designerNameAssembly = AssemblyNameReference.Parse ($"{DesignerAssemblyName}, Version=1.0.0.0");
+			try {
+				designerAssembly = Resolve (designerNameAssembly);
+			} catch (Mono.Cecil.AssemblyResolutionException) {
+				LogMessage ($"   Could not resolve assembly {DesignerAssemblyName}.");
+			} catch (System.IO.FileNotFoundException) {
+				LogMessage ($"   Assembly {DesignerAssemblyName} did not exist.");
+			}
+			if (designerAssembly == null) {
+				return;
+			}
+			designerType = designerAssembly.MainModule.GetTypes ().FirstOrDefault (x => x.FullName == $"{DesignerAssemblyNamespace}.Resource");
+			if (designerType == null) {
+				LogMessage ($"   Did not find {DesignerAssemblyNamespace}.Resource type. It was probably linked out.");
+				return;
+			}
+			lookup = BuildResourceDesignerPropertyLookup (designerType);
+			return;
+		}
+
+		internal override bool ProcessAssemblyDesigner (AssemblyDefinition assembly)
+		{
+			if (designerAssembly == null || designerType == null) {
+				LogMessage ($"   Not using {DesignerAssemblyName}");
+				return false;
+			}
+
+			if (!FindResourceDesigner (assembly, mainApplication: false, out TypeDefinition designer, out CustomAttribute designerAttribute)) {
+				LogMessage ($"   {assembly.Name.Name} has no designer. ");
+				return false;
+			}
+
+			LogMessage ($"   {assembly.Name.Name} has a designer. ");
+			LogMessage ($"   BaseType: {designer.BaseType.FullName}. ");
+			if (designer.BaseType.FullName == $"{DesignerAssemblyNamespace}.Resource") {
+				LogMessage ($"   {assembly.Name.Name} has already been processed. ");
+				return false;
+			}
+
+			LogMessage ($"    Adding reference {designerAssembly.Name.Name}.");
+			assembly.MainModule.AssemblyReferences.Add (designerAssembly.Name);
+			var importedDesignerType = assembly.MainModule.ImportReference (designerType.Resolve ());
+
+			LogMessage ($"    FixupAssemblyTypes {assembly.Name.Name}.");
+			// now replace all ldsfld with a call to the property get_ method.
+			FixupAssemblyTypes (assembly, designer);
+
+			LogMessage ($"    ClearDesignerClass {assembly.Name.Name}.");
+			// then clean out the designer.
+			ClearDesignerClass (designer, completely: true);
+			designer.BaseType = importedDesignerType;
+			return true;
+		}
+
+		Dictionary<string, MethodDefinition> BuildResourceDesignerPropertyLookup (TypeDefinition type)
+		{
+			LogMessage ($"     Building Designer Lookups for {type.FullName}");
+			var output = new Dictionary<string, MethodDefinition> (StringComparer.Ordinal);
+			foreach (TypeDefinition definition in type.NestedTypes)
+			{
+				foreach (PropertyDefinition property in definition.Properties)
+				{
+					string key = $"{definition.Name}::{property.Name}";
+					if (!output.ContainsKey (key)) {
+						LogMessage ($"          Adding {key}");
+						output.Add(key, property.GetMethod);
+					}
+				}
+			}
+			return output;
+		}
+
+		protected override void FixBody (MethodBody body, TypeDefinition designer)
+		{
+			// replace
+			// IL_0068: ldsfld int32 Xamarin.Forms.Platform.Android.Resource/Layout::Toolbar
+			// with
+			// call int32 Xamarin.Forms.Platform.Android.Resource/Layout::get_Toolbar()
+			string designerFullName = $"{designer.FullName}/";
+			var processor = body.GetILProcessor ();
+			Dictionary<Instruction, Instruction> instructions = new Dictionary<Instruction, Instruction>();
+			foreach (var i in body.Instructions)
+			{
+				if (i.OpCode != OpCodes.Ldsfld)
+					continue;
+				string line = i.ToString ();
+				int idx = line.IndexOf (designerFullName, StringComparison.Ordinal);
+				if (idx >= 0) {
+					string key = line.Substring (idx + designerFullName.Length);
+					LogMessage ($"Looking for {key}.");
+					if (lookup.TryGetValue (key, out MethodDefinition method)) {
+						var importedMethod = designer.Module.ImportReference (method);
+						var newIn = Instruction.Create (OpCodes.Call, importedMethod);
+						instructions.Add (i, newIn);
+					} else {
+						LogMessage ($"DEBUG! Failed to find {key}!");
+					}
+				}
+			}
+			if (instructions.Count > 0)
+				LogMessage ($"    Fixing up {body.Method.FullName}");
+			foreach (var i in instructions)
+			{
+				LogMessage ($"      Replacing {i.Key}");
+				LogMessage ($"      With {i.Value}");
+				processor.Replace(i.Key, i.Value);
+			}
+		}
+	}
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs
index 928fdfd6e4f..f03fa12d0fc 100644
--- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs
+++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs
@@ -67,20 +67,24 @@ protected bool FindResourceDesigner (AssemblyDefinition assembly, bool mainAppli
 			return false;
 		}
 
-		protected void ClearDesignerClass (TypeDefinition designer)
+		protected void ClearDesignerClass (TypeDefinition designer, bool completely = false)
 		{
 			LogMessage ($"    TryRemoving {designer.FullName}");
 			// for each of the nested types clear all but the
 			// int[] fields.
-			for (int i = designer.NestedTypes.Count -1; i >= 0; i--) {
-				var nestedType = designer.NestedTypes [i];
-				RemoveFieldsFromType (nestedType, designer.Module);
-				if (nestedType.Fields.Count == 0) {
-					// no fields we do not need this class at all.
-					designer.NestedTypes.RemoveAt (i);
+			if (!completely) {
+				for (int i = designer.NestedTypes.Count -1; i >= 0; i--) {
+					var nestedType = designer.NestedTypes [i];
+					RemoveFieldsFromType (nestedType, designer.Module);
+					if (nestedType.Fields.Count == 0) {
+						// no fields we do not need this class at all.
+						designer.NestedTypes.RemoveAt (i);
+					}
 				}
+				RemoveUpdateIdValues (designer);
+			} else {
+				designer.NestedTypes.Clear ();
 			}
-			RemoveUpdateIdValues (designer);
 			designer.Fields.Clear ();
 			designer.Properties.Clear ();
 			designer.CustomAttributes.Clear ();
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/Linker.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/Linker.cs
index cca2056cf35..45c3a3feeb3 100644
--- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/Linker.cs
+++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/Linker.cs
@@ -111,6 +111,8 @@ static Pipeline CreatePipeline (LinkerOptions options)
 			pipeline.AppendStep (new RemoveResources (options.I18nAssemblies)); // remove collation tables
 			// end monodroid specific
 
+			if (options.UseDesignerAssembly)
+				pipeline.AppendStep (new FixLegacyResourceDesignerStep (cache));
 			pipeline.AppendStep (new FixAbstractMethodsStep (cache));
 			pipeline.AppendStep (new MonoDroidMarkStep (cache));
 			pipeline.AppendStep (new SweepStep ());
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkerOptions.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkerOptions.cs
index 0cd81bb8641..1886d50915e 100644
--- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkerOptions.cs
+++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkerOptions.cs
@@ -26,5 +26,6 @@ class LinkerOptions
 		public bool PreserveJniMarshalMethods { get; set; }
 		public bool DeterministicOutput { get; set; }
 		public bool LinkResources { get; set; }
+		public bool UseDesignerAssembly { get; set; }
 	}
 }
diff --git a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Aapt2.targets b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Aapt2.targets
index 8827e1ceb51..d1bfde205de 100644
--- a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Aapt2.targets
+++ b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Aapt2.targets
@@ -154,7 +154,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
     <AndroidAapt2LinkExtraArgs Condition=" $(AndroidResgenExtraArgs.Contains('--no-version-vectors')) And !($(AndroidAapt2LinkExtraArgs.Contains('--no-version-vectors'))) ">--no-version-vectors $(AndroidAapt2LinkExtraArgs) </AndroidAapt2LinkExtraArgs>
   </PropertyGroup>
   <Aapt2Link
-      Condition=" '$(_AndroidResourceDesignerFile)' != '' "
+      Condition=" '$(_AndroidResourceDesignerFile)' != '' Or '$(AndroidUseDesignerAssembly)' == 'True' "
       ContinueOnError="$(DesignTimeBuild)"
       DaemonMaxInstanceCount="$(Aapt2DaemonMaxInstanceCount)"
       DaemonKeepInDomain="$(_Aapt2DaemonKeepInDomain)"
diff --git a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Designer.targets b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Designer.targets
index 4b8f8388493..e3192db607f 100644
--- a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Designer.targets
+++ b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Designer.targets
@@ -145,7 +145,7 @@ Copyright (C) 2016 Xamarin. All rights reserved.
 </Target>
 
 <Target Name="SetupDependenciesForDesigner"
-    DependsOnTargets="UpdateAndroidResources;_AdjustJavacVersionArguments;_GeneratePackageManagerJavaForDesigner;_GetMonoPlatformJarPath;_DetermineJavaLibrariesToCompile"
+    DependsOnTargets="_ResolveMonoAndroidSdks;UpdateAndroidResources;_AdjustJavacVersionArguments;_GeneratePackageManagerJavaForDesigner;_GetMonoPlatformJarPath;_DetermineJavaLibrariesToCompile"
     Inputs="@(_AndroidMSBuildAllProjects);$(MonoPlatformJarPath);@(_JavaStubFiles);@(AndroidJavaSource)"
     Outputs="$(_AndroidStampDirectory)SetupDependenciesForDesigner.stamp">
   <Javac
diff --git a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets
new file mode 100644
index 00000000000..95e7d80efd3
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets
@@ -0,0 +1,217 @@
+<!--
+***********************************************************************************************
+Xamarin.Android.Resource.Designer.targets
+
+WARNING:  DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
+  created a backup copy.  Incorrect changes to this file will make it
+  impossible to load or build your projects from the command-line or the IDE.
+
+This file imports the version- and platform-specific targets for the project importing
+this file. This file also defines targets to produce an error if the specified targets
+file does not exist, but the project is built anyway (command-line or IDE build).
+
+Copyright (C) 2016 Xamarin. All rights reserved.
+***********************************************************************************************
+-->
+
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+<UsingTask TaskName="Xamarin.Android.Tasks.GenerateResourceDesignerIntermediateClass" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
+<UsingTask TaskName="Xamarin.Android.Tasks.GenerateResourceDesignerAssembly" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
+<UsingTask TaskName="Xamarin.Android.Tasks.GenerateResourceCaseMap" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
+<UsingTask TaskName="Xamarin.Android.Tasks.GenerateRtxt" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
+
+<PropertyGroup>
+  <AndroidUseDesignerAssembly Condition=" '$(AndroidUseDesignerAssembly)' == '' ">False</AndroidUseDesignerAssembly>
+</PropertyGroup>
+
+<Target Name="_SetupDesignerProperties">
+  <PropertyGroup>
+    <_DesignerAssemblyName>_Microsoft.Android.Resource.Designer</_DesignerAssemblyName>
+    <!--
+      Handle the case where ResolveProjectReferences is running.
+      `ResolveProjectReferences` runs after a project has build, but
+      during the referencing project build system.
+
+      Unfortunately it gets passed the referencing projects `IntermediateOutputPath`
+      value, this can cause it to look for files which do not exist.
+    -->
+    <_DesignerIntermediateOutputPath Condition=" '$(_DesignerIntermediateOutputPath)' == '' And Exists ('$(IntermediateOutputPath)$(_DesignerAssemblyName).dll') ">$(IntermediateOutputPath)</_DesignerIntermediateOutputPath>
+    <_DesignerIntermediateOutputPath Condition=" '$(_DesignerIntermediateOutputPath)' == '' And '$(_OuterIntermediateOutputPath)' != '' And Exists ('$(_OuterIntermediateOutputPath)$(_DesignerAssemblyName).dll') ">$(_OuterIntermediateOutputPath)</_DesignerIntermediateOutputPath>
+    <!-- If we have not already built an assembly in either location, prefer the
+    `_OuterIntermediateOutputPath` if possible over the `IntermediateOutputPath`.
+    This will mean only one copy of the assembly will be created. Rather than one
+    per TargetFramework.
+    -->
+    <_DesignerIntermediateOutputPath Condition=" '$(_DesignerIntermediateOutputPath)' == '' And '$(_OuterIntermediateOutputPath)' != '' ">$(_OuterIntermediateOutputPath)</_DesignerIntermediateOutputPath>
+    <_DesignerIntermediateOutputPath Condition=" '$(_DesignerIntermediateOutputPath)' == '' ">$(IntermediateOutputPath)</_DesignerIntermediateOutputPath>
+    <_GenerateResourceDesignerAssemblyOutput>$(_DesignerIntermediateOutputPath)$(_DesignerAssemblyName).dll</_GenerateResourceDesignerAssemblyOutput>
+    <_GenerateResourceDesignerClassFile Condition=" '$(Language)' == 'F#' ">$(_DesignerIntermediateOutputPath)_$(_DesignerAssemblyName).fs</_GenerateResourceDesignerClassFile>
+    <_GenerateResourceDesignerClassFile Condition=" '$(_GenerateResourceDesignerClassFile)' == '' ">$(_DesignerIntermediateOutputPath)_$(_DesignerAssemblyName).cs</_GenerateResourceDesignerClassFile>
+    <_GenerateResourceCaseMapFile>$(_DesignerIntermediateOutputPath)case_map.txt</_GenerateResourceCaseMapFile>
+  </PropertyGroup>
+  <Message Text="_OuterIntermediateOutputPath: $(_OuterIntermediateOutputPath)" />
+  <Message Text="IntermediateOutputPath: $(IntermediateOutputPath)" />
+</Target>
+
+<Target Name="_GenerateRtxt"
+    Condition="'$(AndroidUseDesignerAssembly)' == 'True' And '$(DesignTimeBuild)' == 'True' "
+    DependsOnTargets="_CreatePropertiesCache;_ResolveSdks;_ResolveAndroidTooling;_GetJavaPlatformJar;_GenerateAndroidResourceDir;_SetupDesignerProperties"
+    Inputs="$(_AndroidResFlagFile);@(_AndroidResourceDest);@(LibraryResourceDirectories->'%(StampFile)')"
+    Outputs="$(_DesignerIntermediateOutputPath)R.txt"
+  >
+    <!-- Generate an R.txt file using the Managed Parser -->
+    <GenerateRtxt
+        AdditionalResourceDirectories="@(LibraryResourceDirectories)"
+        CaseMapFile="$(_GenerateResourceCaseMapFile)"
+        JavaPlatformJarPath="$(JavaPlatformJarPath)"
+        ResourceDirectory="$(MonoAndroidResDirIntermediate)"
+        ResourceFlagFile="$(_AndroidResFlagFile)"
+        RTxtFile="$(_DesignerIntermediateOutputPath)R.txt"
+    >
+    </GenerateRtxt>
+</Target>
+
+<Target Name="_GenerateResourceCaseMap"
+    DependsOnTargets="_ComputeAndroidResourcePaths;_SetupDesignerProperties;_GetLibraryImports"
+    Inputs="@(_AndroidResourceDest);@(LibraryResourceDirectories->'%(StampFile)')"
+    Outputs="$(_GenerateResourceCaseMapFile)"
+  >
+    <!-- Generate a ResourceMap file for the project and its resources -->
+    <GenerateResourceCaseMap
+        AdditionalResourceDirectories="@(LibraryResourceDirectories)"
+        OutputFile="$(_GenerateResourceCaseMapFile)"
+        ProjectDir="$(ProjectDir)"
+        ResourceDirectory="$(MonoAndroidResDirIntermediate)"
+        Resources="@(_AndroidResourceDest)"
+    />
+    <Touch Files="$(_GenerateResourceCaseMapFile)" />
+    <ItemGroup>
+      <FileWrites Include="$(_GenerateResourceCaseMapFile)" />
+    </ItemGroup>
+</Target>
+
+<!--
+    We only want to do this for non application projects unless the user has
+    specifically opted into the new system. This can be done by either
+    1. using `dotnet new android` and building a new project.
+    2. Add <AndroidUseDesignerAssembly>true</AndroidUseDesignerAssembly> to
+       the project.
+ -->
+<Target Name="_GenerateResourceDesignerIntermediateClass"
+    Condition=" '$(AndroidUseDesignerAssembly)' == 'True' "
+    Inputs="$(MSBuildProjectFullPath)"
+    Outputs="$(_GenerateResourceDesignerClassFile)"
+  >
+  <!-- Creates a Resource.designer.cs file in the Intermediate output path which derives from the
+       Designer Assembly, for backward compatability.
+   -->
+    <GenerateResourceDesignerIntermediateClass
+        IsApplication="$(AndroidApplication)"
+        Namespace="$(AndroidResgenNamespace)"
+        OutputFile="$(_GenerateResourceDesignerClassFile)"
+    >
+    </GenerateResourceDesignerIntermediateClass>
+    <Touch Files="$(_GenerateResourceDesignerClassFile)" />
+    <ItemGroup>
+      <FileWrites Include="$(_GenerateResourceDesignerClassFile)" />
+    </ItemGroup>
+</Target>
+
+<Target Name="_GenerateResourceDesignerAssembly"
+    Condition=" '$(AndroidUseDesignerAssembly)' == 'True' And '$(DesignTimeBuild)' == 'True' "
+    DependsOnTargets="_GenerateResourceCaseMap"
+    Inputs="$(_DesignerIntermediateOutputPath)R.txt"
+    Outputs="$(_GenerateResourceDesignerAssemblyOutput)">
+    <GenerateResourceDesignerAssembly
+        ContinueOnError="$(DesignTimeBuild)"
+        AdditionalResourceDirectories="@(LibraryResourceDirectories)"
+        AssemblyName="$(AssemblyName)"
+        CaseMapFile="$(_GenerateResourceCaseMapFile)"
+        DesignTimeBuild="$(DesignTimeBuild)"
+        Deterministic="$(Deterministic)"
+        FrameworkDirectories="$(_XATargetFrameworkDirectories);$(_XATargetFrameworkDirectories)Facades"
+        IsApplication="$(AndroidApplication)"
+        OutputFile="$(_GenerateResourceDesignerAssemblyOutput)"
+        ProjectDir="$(ProjectDir)"
+        Resources="@(AndroidResource);@(AndroidBoundLayout)"
+        ResourceDirectory="$(MonoAndroidResourcePrefix)"
+        RTxtFile="$(_DesignerIntermediateOutputPath)R.txt"
+        TargetFrameworkIdentifier="$(TargetFrameworkIdentifier)"
+        TargetFrameworkVersion="$(TargetFrameworkVersion)"
+    >
+    </GenerateResourceDesignerAssembly>
+    <ItemGroup>
+      <FileWrites Include="$(_GenerateResourceDesignerAssemblyOutput)" />
+    </ItemGroup>
+</Target>
+
+<Target Name="_CheckForInvalidDesignerConfig"
+    Condition=" '$(AndroidUseDesignerAssembly)' != 'True' "
+    DependsOnTargets="_AddAndroidCustomMetaData">
+    <ItemGroup>
+      <_ErrorItems Include="@(_MonoAndroidReferencePath)" Condition=" '%(_MonoAndroidReferencePath.HasResourceDesignerAssemblyReference)' == 'True' "/>
+      <_ErrorItems Include="@(_MonoAndroidReferenceDependencyPaths)"  Condition=" '%(_MonoAndroidReferenceDependencyPaths.HasResourceDesignerAssemblyReference)' == 'True' "/>
+    </ItemGroup>
+    <AndroidError Code="XA1031"
+        ResourceName="XA1031"
+        FormatArguments="%(_ErrorItems.FullPath)"
+        Condition=" '@(_ErrorItems->Count())' != '0' "
+    />
+</Target>
+
+<PropertyGroup>
+  <_BuildResourceDesignerDependsOn>
+    _SetupDesignerProperties;
+    _GenerateResourceCaseMap;
+    _GenerateRtxt;
+    _GenerateResourceDesignerIntermediateClass;
+    _GenerateResourceDesignerAssembly;
+    _AddResourceDesignerFiles;
+  </_BuildResourceDesignerDependsOn>
+</PropertyGroup>
+
+<Target Name="_AddResourceDesignerFiles"
+    Condition=" '$(AndroidUseDesignerAssembly)' == 'True' "
+    DependsOnTargets="_SetupDesignerProperties"
+    AfterTargets="GenerateGlobalUsings">
+    <ItemGroup>
+      <ReferencePath Include="$(_GenerateResourceDesignerAssemblyOutput)">
+        <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
+      </ReferencePath>
+      <Compile Remove="$(_AndroidResourceDesignerFile)" />
+      <Compile Include="$(_GenerateResourceDesignerClassFile)" Condition=" '$(Language)' != 'F#' "/>
+      <!-- For F# we need to use the CompileBefore ItemGroup so that our type is processed
+            before all the other types in the build. Otherwise we get weird compiler errors.
+        -->
+      <CompileBefore Include="$(_GenerateResourceDesignerClassFile)" Condition=" '$(Language)' == 'F#' "/>
+    </ItemGroup>
+</Target>
+
+<!--
+    We need to inject the designer assembly into the `ResolvedFileToPublish` item group in
+    order for it to be included in the final application package.
+
+    In additon we MUST set the `PostprocessAssembly` metadata to `true` so that the file
+    is processed by the ILLink step. If we do not do this then the reference to
+    `netstandard.dll` is not replaced with `System.Private.CoreLib` and the app crashes.
+-->
+<Target Name="_AddResourceDesignerToPublishFiles"
+    Condition=" '$(AndroidUseDesignerAssembly)' == 'True' "
+    AfterTargets="ComputeResolvedFilesToPublishList"
+    DependsOnTargets="_SetupDesignerProperties">
+    <ItemGroup>
+      <ResolvedFileToPublish Include="$(_GenerateResourceDesignerAssemblyOutput)">
+        <RelativePath>$(_DesignerAssemblyName).dll</RelativePath>
+        <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
+        <PostprocessAssembly>true</PostprocessAssembly>
+        <IsTrimmable>true</IsTrimmable>
+      </ResolvedFileToPublish>
+    </ItemGroup>
+</Target>
+
+<Target Name="_BuildResourceDesigner"
+    Condition=" '$(AndroidUseDesignerAssembly)' == 'True' "
+    DependsOnTargets="$(_BuildResourceDesignerDependsOn)" />
+
+</Project>
\ No newline at end of file
diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets
index e15b10a264f..c4a7a91b861 100644
--- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets
+++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets
@@ -67,6 +67,14 @@ _ResolveAssemblies MSBuild target.
       <IntermediateAssembly Remove="@(IntermediateAssembly)" />
       <IntermediateAssembly Include="$(_OuterIntermediateAssembly)" />
     </ItemGroup>
+    <ItemGroup Condition=" '$(AndroidUseDesignerAssembly)' == 'True' ">
+      <ReferenceCopyLocalPaths Include="$(_GenerateResourceDesignerAssemblyOutput)">
+        <PostprocessAssembly>True</PostprocessAssembly>
+        <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
+        <IsTrimmable>false</IsTrimmable>
+        <RuntimeIdentifier>android</RuntimeIdentifier>
+      </ReferenceCopyLocalPaths>
+    </ItemGroup>
     <ItemGroup Condition=" '@(_DebugSymbolsIntermediatePath->Count())' != '0' ">
       <_DebugSymbolsIntermediatePath Remove="@(_DebugSymbolsIntermediatePath)" />
       <_DebugSymbolsIntermediatePath Include="$([System.IO.Path]::ChangeExtension ($(_OuterIntermediateAssembly), '.pdb'))" />
diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets
index b9305f91637..fa15917a912 100644
--- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets
+++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets
@@ -107,6 +107,7 @@ projects, these properties are set in Xamarin.Android.Legacy.targets.
 
   <PropertyGroup>
     <CoreResolveReferencesDependsOn>
+      _CreatePropertiesCache;
       _SeparateAppExtensionReferences;
       $(ResolveReferencesDependsOn);
       _ConvertAndroidMamMappingFileToXml;
@@ -116,17 +117,25 @@ projects, these properties are set in Xamarin.Android.Legacy.targets.
     </CoreResolveReferencesDependsOn>
     <ResolveReferencesDependsOn>
       $(CoreResolveReferencesDependsOn);
-      UpdateAndroidInterfaceProxies;
       UpdateAndroidResources;
+      _BuildResourceDesigner;
+      UpdateAndroidInterfaceProxies;
       _SetAndroidGenerateManagedBindings;
       AddBindingsToCompile;
+      _CheckForInvalidDesignerConfig;
     </ResolveReferencesDependsOn>
+    <DesignTimeResolveAssemblyReferencesDependsOn>
+      $(DesignTimeResolveAssemblyReferencesDependsOn);
+      _BuildResourceDesigner;
+    </DesignTimeResolveAssemblyReferencesDependsOn>
     <_UpdateAndroidResourcesDependsOn>
       $(CoreResolveReferencesDependsOn);
       _CreatePropertiesCache;
       _CheckForDeletedResourceFile;
       _ComputeAndroidResourcePaths;
       _UpdateAndroidResgen;
+      _CreateAar;
+      _BuildResourceDesigner;
     </_UpdateAndroidResourcesDependsOn>
     <CompileDependsOn>
       _SetupMSBuildAllProjects;
@@ -134,6 +143,8 @@ projects, these properties are set in Xamarin.Android.Legacy.targets.
       _AddAndroidDefines;
       _IncludeLayoutBindingSources;
       AddLibraryJarsToBind;
+      _BuildResourceDesigner;
+      _AddResourceDesignerFiles;
       $(CompileDependsOn);
       _CheckAndroidHttpClientHandlerType;
     </CompileDependsOn>
@@ -170,6 +181,7 @@ projects, these properties are set in Xamarin.Android.Legacy.targets.
       _BeforeGetAndroidDependencies;
       _SetLatestTargetFrameworkVersion;
       _ResolveSdks;
+      _ResolveMonoAndroidSdks;
       _ResolveAndroidTooling;
       $(GetAndroidDependenciesDependsOn);
     </GetAndroidDependenciesDependsOn>
diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets
index 687dc79e266..43ed246a334 100644
--- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets
+++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets
@@ -10,6 +10,8 @@
     <AndroidEnableSGenConcurrent Condition=" '$(AndroidEnableSGenConcurrent)' == '' ">true</AndroidEnableSGenConcurrent>
     <AndroidHttpClientHandlerType Condition=" '$(AndroidHttpClientHandlerType)' == '' and '$(UsingAndroidNETSdk)' == 'true' ">Xamarin.Android.Net.AndroidMessageHandler</AndroidHttpClientHandlerType>
     <AndroidHttpClientHandlerType Condition=" '$(AndroidHttpClientHandlerType)' == '' and '$(UsingAndroidNETSdk)' != 'true' ">Xamarin.Android.Net.AndroidClientHandler</AndroidHttpClientHandlerType>
+    <AndroidUseDesignerAssembly Condition=" '$(AndroidUseDesignerAssembly)' == '' ">true</AndroidUseDesignerAssembly>
+    <AndroidGenerateResourceDesigner Condition=" '$(AndroidUseDesignerAssembly)' == 'True' ">false</AndroidGenerateResourceDesigner>
     <AndroidGenerateResourceDesigner Condition=" '$(AndroidGenerateResourceDesigner)' == '' ">true</AndroidGenerateResourceDesigner>
     <AndroidUseIntermediateDesignerFile Condition=" '$(AndroidUseIntermediateDesignerFile)' == '' ">$(AndroidGenerateResourceDesigner)</AndroidUseIntermediateDesignerFile>
     <GenerateDependencyFile Condition=" '$(GenerateDependencyFile)' == '' ">false</GenerateDependencyFile>
diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets
index f28c5b6d9d5..7400de192ff 100644
--- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets
+++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets
@@ -88,7 +88,12 @@ This file contains the .NET 5-specific targets to customize ILLink
           AfterStep="CleanStep"
           Type="MonoDroid.Tuner.GetAssembliesStep"
       />
-
+      <_TrimmerCustomSteps
+          Condition=" '$(AndroidUseDesignerAssembly)' == 'true' "
+          Include="$(_AndroidLinkerCustomStepAssembly)"
+          BeforeStep="MarkStep"
+          Type="MonoDroid.Tuner.FixLegacyResourceDesignerStep"
+      />
       <_PreserveLists Include="$(MSBuildThisFileDirectory)..\PreserveLists\*.xml" />
       <TrimmerRootDescriptor
           Condition=" '@(ResolvedFileToPublish->Count())' != '0' and '%(Filename)' != '' "
diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.Publish.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.Publish.targets
index 4d20974eb23..95dc9575032 100644
--- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.Publish.targets
+++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.Publish.targets
@@ -25,6 +25,7 @@ This file contains the implementation for 'dotnet publish'.
       <_AndroidPackageFormats Include="@(_AllPackageFormats->Distinct())" />
       <_AndroidFilesToPublish Include="$(OutputPath)*.%(_AndroidPackageFormats.Identity)" />
       <_AndroidFilesToPublish Include="$(AndroidProguardMappingFile)" Condition="Exists ('$(AndroidProguardMappingFile)')" />
+      <_AndroidFilesToPublish Include="$(_GenerateResourceDesignerAssemblyOutput)" Condition="Exists('$(_GenerateResourceDesignerAssemblyOutput)')" />
       <ResolvedFileToPublish Remove="@(ResolvedFileToPublish)" />
       <ResolvedFileToPublish Include="@(_AndroidFilesToPublish)" RelativePath="%(FileName)%(Extension)" />
     </ItemGroup>
diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs b/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs
index b2a969da7cc..05f4c4e0c4c 100644
--- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs
+++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs
@@ -728,6 +728,15 @@ public static string XA1028 {
             }
         }
 
+        /// <summary>
+        ///   Looks up a localized string similar to The &apos;AndroidEnableProguard&apos; MSBuild property is set to &apos;true&apos; and the &apos;AndroidLinkTool&apos; MSBuild property is empty, so &apos;AndroidLinkTool&apos; will default to &apos;proguard&apos;..
+        /// </summary>
+        public static string XA1031 {
+            get {
+                return ResourceManager.GetString("XA1031", resourceCulture);
+            }
+        }
+
         /// <summary>
         ///   Looks up a localized string similar to Use of AppDomain.CreateDomain() detected in assembly: {0}. .NET 6 and higher will only support a single AppDomain, so this API will no longer be available in Xamarin.Android once .NET 6 is released..
         /// </summary>
diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx
index ac48bbe6967..a526aa6c63b 100644
--- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx
+++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx
@@ -487,6 +487,10 @@ Please change the value to an assembly-qualifed type name which inherits from '{
     <value>Could not resolve '{0}'. Please check your `AndroidHttpClientHandlerType` setting.</value>
     <comment>The following are literal names and should not be translated: 'AndroidHttpClientHandlerType',
 {0} - The value of the property.</comment>
+  <data name="XA1034" xml:space="preserve">
+    <value>Your project references '{0}' which uses the `_Microsoft.Android.Resource.Designer` assembly, but you do not have this feature enabled. Please set the `AndroidUseDesignerAssembly` MSBuild property to `true` in your project file.</value>
+    <comment>The following are literal names and should not be translated: '_Microsoft.Android.Resource.Desinger', 'AndroidUseDesignerAssembly', 'true'
+{0} - The name of the assembly</comment>
   </data>
   <data name="XA2000" xml:space="preserve">
     <value>Use of AppDomain.CreateDomain() detected in assembly: {0}. .NET 6 and higher will only support a single AppDomain, so this API will no longer be available in Xamarin.Android once .NET 6 is released.</value>
diff --git a/src/Xamarin.Android.Build.Tasks/Resources/Resource.Designer.snk b/src/Xamarin.Android.Build.Tasks/Resources/Resource.Designer.snk
new file mode 100644
index 0000000000000000000000000000000000000000..7f3d225c9d23ae363ae3378adb74e2b0c860d59e
GIT binary patch
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/Aapt2Link.cs b/src/Xamarin.Android.Build.Tasks/Tasks/Aapt2Link.cs
index c70cfb09fb7..4dd27c19321 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/Aapt2Link.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/Aapt2Link.cs
@@ -82,6 +82,7 @@ public class Aapt2Link : Aapt2 {
 		List<string> tempFiles = new List<string> ();
 		SortedSet<string> rulesFiles = new SortedSet<string> ();
 		Dictionary<string, long> apks = new Dictionary<string, long> ();
+		string resourceSymbolsTextFileTemp;
 
 		protected override int GetRequiredDaemonInstances ()
 		{
@@ -93,6 +94,8 @@ public async override System.Threading.Tasks.Task RunTaskAsync ()
 			try {
 				assemblyMap.Load (Path.Combine (WorkingDirectory, AssemblyIdentityMapFile));
 
+				resourceSymbolsTextFileTemp = GetTempFile ();
+
 				await this.WhenAll (ManifestFiles, ProcessManifest);
 
 				ProcessOutput ();
@@ -132,6 +135,8 @@ public async override System.Threading.Tasks.Task RunTaskAsync ()
 					}
 					Files.CopyIfStringChanged (sb.ToString (), ProguardRuleOutput);
 				}
+				if (!string.IsNullOrEmpty (ResourceSymbolsTextFile))
+					Files.CopyIfChanged (resourceSymbolsTextFileTemp, GetFullPath (ResourceSymbolsTextFile));
 			} finally {
 				lock (tempFiles) {
 					foreach (var temp in tempFiles) {
@@ -253,7 +258,7 @@ string [] GenerateCommandLineCommands (string ManifestFile, string currentAbi, s
 
 			if (!string.IsNullOrEmpty (ResourceSymbolsTextFile)) {
 				cmd.Add ("--output-text-symbols");
-				cmd.Add (GetFullPath (ResourceSymbolsTextFile));
+				cmd.Add (GetFullPath (resourceSymbolsTextFileTemp));
 			}
 
 			if (ProtobufFormat)
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/AppendCustomMetadataToItemGroup.cs b/src/Xamarin.Android.Build.Tasks/Tasks/AppendCustomMetadataToItemGroup.cs
index ffd28e90201..9ab1d323596 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/AppendCustomMetadataToItemGroup.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/AppendCustomMetadataToItemGroup.cs
@@ -35,6 +35,11 @@ public override bool RunTask ()
 			foreach (var item in Inputs) {
 				var fn = Path.GetFileNameWithoutExtension (item.ItemSpec);
 				output.Add (item);
+				var md = item.GetMetadata ("HasResourceDesignerAssemblyReference");
+				if (string.IsNullOrEmpty (md)) {
+					var b = MonoAndroidHelper.HasResourceDesignerAssemblyReference (item);
+					item.SetMetadata ("HasResourceDesignerAssemblyReference", MonoAndroidHelper.HasResourceDesignerAssemblyReference (item).ToString ());
+				}
 				List<ITaskItem> metaDataList;
 				if (!metaData.TryGetValue (fn, out metaDataList))
 					continue;
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/ConvertCustomView.cs b/src/Xamarin.Android.Build.Tasks/Tasks/ConvertCustomView.cs
index ea7a65b7a57..9e88ff78d2f 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/ConvertCustomView.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/ConvertCustomView.cs
@@ -31,7 +31,7 @@ public class ConvertCustomView : AndroidTask {
 
 		public override bool RunTask ()
 		{
-			var acw_map = MonoAndroidHelper.LoadAcwMapFile (AcwMapFile);
+			var acw_map = MonoAndroidHelper.LoadMapFile (BuildEngine4, AcwMapFile, StringComparer.Ordinal);
 			var customViewMap = MonoAndroidHelper.LoadCustomViewMapFile (BuildEngine4, CustomViewMapFile);
 			var processed = new HashSet<string> ();
 
@@ -119,8 +119,8 @@ bool TryFixCustomClassAttribute (XAttribute attr, Dictionary<string, string> acw
 
 		bool TryFixFragment (XAttribute attr, Dictionary<string, string> acwMap)
 		{
-			// Looks for any: 
-			//   <fragment class="My.DotNet.Class" 
+			// Looks for any:
+			//   <fragment class="My.DotNet.Class"
 			//   <fragment android:name="My.DotNet.Class" ...
 			// and tries to change it to the ACW name
 			if (attr.Parent.Name != "fragment")
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/FilterAssemblies.cs b/src/Xamarin.Android.Build.Tasks/Tasks/FilterAssemblies.cs
index cf783c038d8..6abce912aef 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/FilterAssemblies.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/FilterAssemblies.cs
@@ -24,6 +24,8 @@ public class FilterAssemblies : AndroidTask
 
 		public ITaskItem [] InputAssemblies { get; set; }
 
+		public bool UseDesignerAssembly { get; set; }
+
 		[Output]
 		public ITaskItem [] OutputAssemblies { get; set; }
 
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateLibraryResources.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateLibraryResources.cs
index b29c6d6fc44..9b898c5e45f 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateLibraryResources.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateLibraryResources.cs
@@ -165,7 +165,8 @@ IEnumerable<string []> ParseFile (StreamReader reader)
 			while (!reader.EndOfStream) {
 				var line = reader.ReadLine ();
 				var items = line.Split (Delimiter, 4);
-				yield return items;
+				if (items.Length == 4)
+					yield return items;
 			}
 		}
 	}
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs
index e8638b29761..a87f24a5832 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs
@@ -471,7 +471,7 @@ void GetRequiredTokens (string assemblyFilePath, out int android_runtime_jnienv_
 			}
 
 			if (android_runtime_jnienv_class_token == -1 || jnienv_initialize_method_token == -1 || jnienv_registerjninatives_method_token == -1) {
-				throw new InvalidOperationException ($"Unable to find the required Android.Runtime.JNIEnvInit method tokens");
+				throw new InvalidOperationException ($"Unable to find the required Android.Runtime.JNIEnvInit method tokens for {assemblyFilePath}");
 			}
 		}
 
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceCaseMap.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceCaseMap.cs
new file mode 100644
index 00000000000..9717be99f74
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceCaseMap.cs
@@ -0,0 +1,121 @@
+// Copyright (C) 2021 Microsoft, Inc. All rights reserved.
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using Microsoft.Android.Build.Tasks;
+
+namespace Xamarin.Android.Tasks
+{
+	public class GenerateResourceCaseMap : AndroidTask
+	{
+		public override string TaskPrefix => "GRCM";
+		public ITaskItem[] Resources { get; set; }
+
+		[Required]
+		public string ResourceDirectory { get; set; }
+
+		[Required]
+		public string ProjectDir { get; set; }
+
+		public ITaskItem[] AdditionalResourceDirectories { get; set; }
+
+		[Required]
+		public ITaskItem OutputFile { get; set; }
+
+		private Dictionary<string, string> resource_fixup = new Dictionary<string, string> (StringComparer.OrdinalIgnoreCase);
+
+		public override bool RunTask ()
+		{
+			// ResourceDirectory may be a relative path, and
+			// we need to compare it to absolute paths
+			ResourceDirectory = Path.GetFullPath (ResourceDirectory);
+
+			// Create our capitalization maps so we can support mixed case resources
+			foreach (var item in Resources) {
+				var path = Path.GetFullPath (item.ItemSpec);
+				if (!path.StartsWith (ResourceDirectory, StringComparison.OrdinalIgnoreCase)) {
+					Log.LogDebugMessage ($"Skipping {item}. Path is not include the '{ResourceDirectory}'");
+					continue;
+				}
+
+				var name = path.Substring (ResourceDirectory.Length).TrimStart ('/', '\\');
+				var logical_name = item.GetMetadata ("LogicalName").Replace ('\\', '/');
+				if (string.IsNullOrEmpty (logical_name))
+					logical_name = Path.GetFileName (path);
+
+				AddRename (name.Replace ('/', Path.DirectorySeparatorChar), logical_name.Replace ('/', Path.DirectorySeparatorChar));
+			}
+			foreach (var additionalDir in AdditionalResourceDirectories ?? Array.Empty<ITaskItem>()) {
+				var dir = Path.Combine (ProjectDir, Path.GetDirectoryName (additionalDir.ItemSpec));
+				var file = Path.Combine (dir, "__res_name_case_map.txt");
+				if (!File.Exists (file)) {
+					// .NET 6 .aar files place the file in a sub-directory
+					file = Path.Combine (dir, ".net", "__res_name_case_map.txt");
+					if (!File.Exists (file))
+						continue;
+				}
+				foreach (var line in File.ReadLines (file)) {
+					if (string.IsNullOrEmpty (line))
+						continue;
+					string [] tok = line.Split (';');
+					AddRename (tok [1].Replace ('/', Path.DirectorySeparatorChar), tok [0].Replace ('/', Path.DirectorySeparatorChar));
+				}
+			}
+
+			if (MonoAndroidHelper.SaveMapFile (BuildEngine4, Path.GetFullPath (OutputFile.ItemSpec), resource_fixup)) {
+				Log.LogDebugMessage ($"Writing to: {OutputFile.ItemSpec}");
+			} else {
+				Log.LogDebugMessage ($"Up to date: {OutputFile.ItemSpec}");
+			}
+
+			return !Log.HasLoggedErrors;
+		}
+
+		private void AddRename (string android, string user)
+		{
+			var from = android;
+			var to = user;
+
+			if (from.Contains ('.'))
+				from = from.Substring (0, from.LastIndexOf ('.'));
+			if (to.Contains ('.'))
+				to = to.Substring (0, to.LastIndexOf ('.'));
+
+			from = NormalizeAlternative (from);
+			to = NormalizeAlternative (to);
+
+			string curTo;
+
+			if (resource_fixup.TryGetValue (from, out curTo)) {
+				if (string.Compare (to, curTo, StringComparison.OrdinalIgnoreCase) != 0) {
+					var ext = Path.GetExtension (android);
+					var dir = Path.GetDirectoryName (user);
+
+					Log.LogDebugMessage ("Resource target names differ; got '{0}', expected '{1}'.",
+						Path.Combine (dir, Path.GetFileName (to) + ext),
+						Path.Combine (dir, Path.GetFileName (curTo) + ext));
+				}
+				return;
+			}
+			Log.LogDebugMessage ($"Adding map from '{from}' to '{to}'.");
+			resource_fixup.Add (from, to);
+		}
+
+		static string NormalizeAlternative (string value)
+		{
+			int s = value.IndexOfAny (new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar });
+
+			if (s < 0)
+				return value;
+
+			int a = value.IndexOf ('-');
+
+			return
+				ResourceParser.GetNestedTypeName (value.Substring (0, (a < 0 || a >= s) ? s : a)).ToLowerInvariant () +
+				value.Substring (s);
+		}
+	}
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesigner.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesigner.cs
index ba7fbe053a3..efb8fa465f5 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesigner.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesigner.cs
@@ -53,6 +53,8 @@ public class GenerateResourceDesigner : AndroidTask
 
 		public string ResourceFlagFile { get; set; }
 
+		public string CaseMapFile { get; set; }
+
 		private Dictionary<string, string> resource_fixup = new Dictionary<string, string> (StringComparer.OrdinalIgnoreCase);
 
 		public override bool RunTask ()
@@ -73,35 +75,7 @@ public override bool RunTask ()
 
 			var javaPlatformDirectory = Path.GetDirectoryName (JavaPlatformJarPath);
 
-			// Create our capitalization maps so we can support mixed case resources
-			foreach (var item in Resources) {
-				var path = Path.GetFullPath (item.ItemSpec);
-				if (!path.StartsWith (ResourceDirectory, StringComparison.OrdinalIgnoreCase))
-					continue;
-
-				var name = path.Substring (ResourceDirectory.Length).TrimStart ('/', '\\');
-				var logical_name = item.GetMetadata ("LogicalName").Replace ('\\', '/');
-				if (string.IsNullOrEmpty (logical_name))
-					logical_name = Path.GetFileName (path);
-
-				AddRename (name.Replace ('/', Path.DirectorySeparatorChar), logical_name.Replace ('/', Path.DirectorySeparatorChar));
-			}
-			if (AdditionalResourceDirectories != null) {
-				foreach (var additionalDir in AdditionalResourceDirectories) {
-					var dir = Path.Combine (ProjectDir, Path.GetDirectoryName (additionalDir.ItemSpec));
-					var file = Path.Combine (dir, "__res_name_case_map.txt");
-					if (!File.Exists (file)) {
-						// .NET 6 .aar files place the file in a sub-directory
-						file = Path.Combine (dir, ".net", "__res_name_case_map.txt");
-						if (!File.Exists (file))
-							continue;
-					}
-					foreach (var line in File.ReadAllLines (file).Where (l => !string.IsNullOrEmpty (l))) {
-						string [] tok = line.Split (';');
-						AddRename (tok [1].Replace ('/', Path.DirectorySeparatorChar), tok [0].Replace ('/', Path.DirectorySeparatorChar));
-					}
-				}
-			}
+			resource_fixup = MonoAndroidHelper.LoadMapFile (BuildEngine4, CaseMapFile, StringComparer.OrdinalIgnoreCase);
 
 			// Parse out the resources from the R.java file
 			CodeTypeDeclaration resources;
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerAssembly.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerAssembly.cs
new file mode 100644
index 00000000000..4ca7ea3f0f1
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerAssembly.cs
@@ -0,0 +1,350 @@
+// Copyright (C) 2011 Xamarin, Inc. All rights reserved.
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.Runtime.Versioning;
+using System.IO;
+using System.Linq;
+using System.Text;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using Microsoft.Android.Build.Tasks;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+using Java.Interop.Tools.Cecil;
+using Brutal.Dev.StrongNameSigner;
+using MonoDroid.Tuner;
+
+namespace Xamarin.Android.Tasks
+{
+	public class GenerateResourceDesignerAssembly : AndroidTask
+	{
+		public override string TaskPrefix => "GRDA";
+
+		[Required]
+		public ITaskItem RTxtFile { get; set; }
+
+		public ITaskItem ResourceMap { get; set; }
+
+		[Required]
+		public bool IsApplication { get; set; }
+
+		[Required]
+		public bool DesignTimeBuild { get; set; }
+
+		[Required]
+		public ITaskItem OutputFile { get; set; }
+
+		[Required]
+		public string TargetFrameworkVersion { get; set; }
+
+		[Required]
+		public string TargetFrameworkIdentifier { get; set; }
+
+		[Required]
+		public string ProjectDir { get; set; }
+
+		[Required]
+		public ITaskItem[] Resources { get; set; }
+
+		[Required]
+		public string ResourceDirectory { get; set; }
+		public string CaseMapFile { get; set; }
+		public ITaskItem[] AdditionalResourceDirectories { get; set; }
+		public ITaskItem[] FrameworkDirectories { get; set; }
+		public bool Deterministic { get; set; }
+		public string AssemblyName { get; set; }
+		TypeReference intArray;
+		TypeReference intRef;
+		TypeReference objectRef;
+		Dictionary<string, string> resource_fixup = new Dictionary<string, string> (StringComparer.OrdinalIgnoreCase);
+
+		public override bool RunTask ()
+		{
+			using (var res = new DirectoryAssemblyResolver (this.CreateTaskLogger (), loadDebugSymbols: false)) {
+				Run(res);
+			}
+			return !Log.HasLoggedErrors;
+		}
+
+		bool Run(DirectoryAssemblyResolver res)
+		{
+			foreach (var dir in FrameworkDirectories) {
+				if (Directory.Exists (dir.ItemSpec))
+					res.SearchDirectories.Add (dir.ItemSpec);
+			}
+			// ResourceDirectory may be a relative path, and
+			// we need to compare it to absolute paths
+			ResourceDirectory = Path.GetFullPath (ResourceDirectory);
+
+			string assemblyName = Path.GetFileNameWithoutExtension (OutputFile.ItemSpec);
+
+			resource_fixup = MonoAndroidHelper.LoadMapFile (BuildEngine4, CaseMapFile, StringComparer.OrdinalIgnoreCase);
+			// Generate an assembly which contains all the values in the provided
+			// R.txt file.
+			var mp = new ModuleParameters ();
+			mp.AssemblyResolver = res;
+			mp.Kind = ModuleKind.Dll;
+			var assembly = AssemblyDefinition.CreateAssembly (
+				new AssemblyNameDefinition (assemblyName, new Version (1, 0)),
+				assemblyName,
+				mp);
+
+			var module = assembly.MainModule;
+
+			module.AssemblyReferences.Clear ();
+			var netstandardAsm = AssemblyNameReference.Parse ("netstandard, Version=2.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51");
+			module.AssemblyReferences.Add(netstandardAsm);
+			var netstandardDef = module.AssemblyResolver.Resolve(netstandardAsm);
+
+			if (!IsApplication) {
+				MethodReference referenceAssemblyConstructor = ImportCustomAttributeConstructor ("System.Runtime.CompilerServices.ReferenceAssemblyAttribute", module, netstandardDef.MainModule);
+				module.Assembly.CustomAttributes.Add (new CustomAttribute (referenceAssemblyConstructor));
+			} else {
+				// Add the InternalsVisibleToAttribute so the app can access ResourceConstant
+				if (!string.IsNullOrEmpty (AssemblyName)) {
+					MethodReference internalsVisibleToAttributeConstructor = ImportCustomAttributeConstructor ("System.Runtime.CompilerServices.InternalsVisibleToAttribute", module, netstandardDef.MainModule);
+					var ar = new CustomAttribute (internalsVisibleToAttributeConstructor);
+					ar.ConstructorArguments.Add (new CustomAttributeArgument (module.TypeSystem.String, AssemblyName));
+					module.Assembly.CustomAttributes.Add (ar);
+				}
+			}
+
+			MethodReference targetFrameworkConstructor = ImportCustomAttributeConstructor ("System.Runtime.Versioning.TargetFrameworkAttribute", module, netstandardDef.MainModule);
+
+			var attr = new CustomAttribute (targetFrameworkConstructor);
+			attr.ConstructorArguments.Add (new CustomAttributeArgument (module.TypeSystem.String, $".NETStandard,Version=v2.1"));
+			attr.Properties.Add (new CustomAttributeNamedArgument ("FrameworkDisplayName", new CustomAttributeArgument (module.TypeSystem.String, "")));
+			module.Assembly.CustomAttributes.Add (attr);
+
+			var att = TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.Public | TypeAttributes.BeforeFieldInit;
+
+			intArray = new ArrayType (module.TypeSystem.Int32);
+			intRef = module.TypeSystem.Int32;
+			objectRef = module.TypeSystem.Object;
+
+			// The Property Based class.
+			var resourceDesigner = new TypeDefinition (
+				FixLegacyResourceDesignerStep.DesignerAssemblyNamespace,
+				"Resource",
+				att,
+				objectRef
+			);
+			CreateCtor (resourceDesigner, module);
+			module.Types.Add (resourceDesigner);
+			TypeDefinition constDesigner = null;
+			if (IsApplication) {
+				// The Constant based class
+				TypeAttributes attrib = string.IsNullOrEmpty (AssemblyName) ? TypeAttributes.Public : TypeAttributes.Public;
+				constDesigner = new TypeDefinition (
+					FixLegacyResourceDesignerStep.DesignerAssemblyNamespace,
+					"ResourceConstant",
+					attrib | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit,
+					objectRef
+				);
+				CreateCtor (constDesigner, module);
+				module.Types.Add (constDesigner);
+			}
+
+			DateTime lastWriteTimeUtc = DateTime.MinValue;
+			if (File.Exists (OutputFile.ItemSpec))
+				lastWriteTimeUtc = File.GetLastWriteTimeUtc (OutputFile.ItemSpec);
+
+			if (File.Exists (RTxtFile.ItemSpec)) {
+				if (File.GetLastWriteTimeUtc (RTxtFile.ItemSpec) < lastWriteTimeUtc) {
+					Log.LogDebugMessage ($"{RTxtFile.ItemSpec} has not changed since {OutputFile.ItemSpec} was generated.");
+					return !Log.HasLoggedErrors;
+				}
+				var parser = new RtxtParser ();
+				var resources = parser.Parse (RTxtFile.ItemSpec, Log, resource_fixup);
+				foreach (var r in resources) {
+					switch (r.Type) {
+						case RType.Integer:
+							if (IsApplication)
+								CreateIntField (r.ResourceTypeName, r.Identifier, r.Id, constDesigner, module);
+							CreateIntProperty (r.ResourceTypeName, r.Identifier, r.Id, resourceDesigner, module);
+							break;
+						case RType.Array:
+							if (IsApplication)
+								CreateIntArrayField (r.ResourceTypeName, r.Identifier, r.Ids, constDesigner, module);
+							CreateIntArrayProperty (r.ResourceTypeName, r.Identifier, r.Ids, resourceDesigner, module);
+							break;
+					}
+				}
+			}
+			// Add a return to each of the static constructor
+			foreach(var c in staticConstructors) {
+				var il = c.Value.Body.GetILProcessor ();
+				il.Emit(OpCodes.Ret);
+			}
+			StrongNameAssembly (assembly.Name);
+			var wp = new WriterParameters () {
+				DeterministicMvid = Deterministic,
+			};
+			var s = MemoryStreamPool.Shared.Rent ();
+			try {
+				assembly.Write (s, wp);
+				s.Position = 0;
+				if (Files.CopyIfStreamChanged (s, OutputFile.ItemSpec)) {
+					Log.LogDebugMessage ($"Updated '{OutputFile.ItemSpec}'.");
+				} else {
+					Log.LogDebugMessage ($"'{OutputFile.ItemSpec}' was up to date.");
+				}
+			} finally {
+				MemoryStreamPool.Shared.Return (s);
+			}
+			return !Log.HasLoggedErrors;
+		}
+
+		MethodReference ImportCustomAttributeConstructor (string type, ModuleDefinition module, ModuleDefinition sourceModule = null)
+		{
+			var tr = module.ImportReference ((sourceModule ?? module).ExportedTypes.First(x => x.FullName == type).Resolve ());
+			var tv = tr.Resolve();
+			return module.ImportReference (tv.Methods.First(x => x.IsConstructor));
+		}
+
+		void CreateIntProperty (string resourceClass, string propertyName, int value, TypeDefinition resourceDesigner, ModuleDefinition module,
+			MethodAttributes attributes = MethodAttributes.Public, TypeAttributes typeAttributes = TypeAttributes.NestedPublic)
+		{
+			TypeDefinition nestedType = CreateResourceClass (resourceDesigner, resourceClass, module, typeAttributes);
+			PropertyDefinition p = CreateProperty (propertyName, value, module, attributes);
+			nestedType.Properties.Add (p);
+			nestedType.Methods.Insert (Math.Max(0, nestedType.Methods.Count () -1), p.GetMethod);
+		}
+
+		void CreateIntField (string resourceClass, string fieldName, int value, TypeDefinition resourceDesigner, ModuleDefinition module,
+			FieldAttributes attributes = FieldAttributes.Public, TypeAttributes typeAttributes = TypeAttributes.NestedPublic)
+		{
+			TypeDefinition nestedType = CreateResourceClass (resourceDesigner, resourceClass, module, typeAttributes);
+			FieldDefinition p = CreateField (fieldName, value, module, attributes);
+			nestedType.Fields.Add (p);
+		}
+
+		void CreateIntArrayProperty (string resourceClass, string propertyName, int[] values, TypeDefinition resourceDesigner, ModuleDefinition module,
+			MethodAttributes attributes = MethodAttributes.Public, TypeAttributes typeAttributes = TypeAttributes.NestedPublic)
+		{
+			TypeDefinition nestedType = CreateResourceClass (resourceDesigner, resourceClass, module, typeAttributes);
+			PropertyDefinition p = CreateArrayProperty (propertyName, values, module, attributes);
+			nestedType.Properties.Add (p);
+			nestedType.Methods.Insert (Math.Max(0, nestedType.Methods.Count () -1), p.GetMethod);
+		}
+
+		void CreateIntArrayField (string resourceClass, string fieldName, int[] values, TypeDefinition resourceDesigner, ModuleDefinition module,
+			FieldAttributes attributes = FieldAttributes.Public, TypeAttributes typeAttributes = TypeAttributes.NestedPublic)
+		{
+			TypeDefinition nestedType = CreateResourceClass (resourceDesigner, resourceClass, module, typeAttributes);
+			FieldDefinition p = CreateArrayField (fieldName, values, module, attributes);
+			nestedType.Fields.Add (p);
+			MethodDefinition ctor = GetOrCreateStaticCtor (nestedType, module);
+			ILProcessor il = ctor.Body.GetILProcessor ();
+			il.Emit (OpCodes.Ldc_I4, values.Length); // store array size
+			il.Emit (OpCodes.Newarr, intRef); //create a new  array
+			il.Emit (OpCodes.Stsfld, p);
+			int index = 0;
+			foreach (int value in values) {
+				il.Emit (OpCodes.Ldsfld, p);
+				il.Emit (OpCodes.Ldc_I4, index++); // index
+				il.Emit (OpCodes.Ldc_I4, value); // value
+				il.Emit (OpCodes.Stelem_I4);
+			}
+		}
+
+		Dictionary<string, TypeDefinition> resourceClasses = new Dictionary<string, TypeDefinition> (StringComparer.OrdinalIgnoreCase);
+		Dictionary<string, MethodDefinition> staticConstructors = new Dictionary<string, MethodDefinition> ();
+
+		void CreateCtor (TypeDefinition type, ModuleDefinition module)
+		{
+			var ctor = new MethodDefinition (".ctor", MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig | MethodAttributes.Public, module.TypeSystem.Void);
+			var ctoril = ctor.Body.GetILProcessor ();
+			ctoril.Emit (OpCodes.Ldarg_0);
+			var o = module.TypeSystem.Object.Resolve ();
+			ctoril.Emit (OpCodes.Call, module.ImportReference (o.Methods.First (x => x.IsConstructor)));
+			ctoril.Emit (OpCodes.Ret);
+			type.Methods.Add (ctor);
+		}
+
+		MethodDefinition GetOrCreateStaticCtor (TypeDefinition type, ModuleDefinition module)
+		{
+			string key = type.FullName + ".cctor";
+			if (staticConstructors.ContainsKey (key))
+				return staticConstructors[key];
+			var ctor = new MethodDefinition (".cctor", MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig | MethodAttributes.Static, module.TypeSystem.Void);
+			type.Methods.Add (ctor);
+			type.IsBeforeFieldInit = false;
+			staticConstructors.Add (key, ctor);
+			return ctor;
+		}
+
+		TypeDefinition CreateResourceClass (TypeDefinition resourceDesigner, string className, ModuleDefinition module, TypeAttributes attributes = TypeAttributes.NestedPublic)
+		{
+			string name = ResourceParser.GetNestedTypeName (className);
+			string key = resourceDesigner.Name + name;
+			if (resourceClasses.ContainsKey (key)) {
+				return resourceClasses[key];
+			}
+			var resourceClass = new TypeDefinition (string.Empty, name, attributes | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.Sealed, objectRef);
+			CreateCtor (resourceClass, module);
+			resourceDesigner.NestedTypes.Add (resourceClass);
+			resourceClasses[key] = resourceClass;
+			return resourceClass;
+		}
+
+		PropertyDefinition CreateProperty (string propertyName, int value, ModuleDefinition module, MethodAttributes attributes = MethodAttributes.Public)
+		{
+			var p = new PropertyDefinition (propertyName, PropertyAttributes.None, intRef);
+			var getter = new MethodDefinition ($"get_{propertyName}", attributes | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Static, intRef);
+			p.GetMethod = getter;
+			p.SetMethod = null;
+			var il = p.GetMethod.Body.GetILProcessor ();
+			il.Emit (OpCodes.Ldc_I4, value);
+			il.Emit (OpCodes.Ret);
+			return p;
+		}
+
+		FieldDefinition CreateField (string fieldName, int value, ModuleDefinition module, FieldAttributes attributes = FieldAttributes.Public)
+		{
+			var f = new FieldDefinition (fieldName, attributes | FieldAttributes.Literal | FieldAttributes.Static | FieldAttributes.HasDefault, intRef);
+			f.Constant = value;
+			return f;
+		}
+
+		FieldDefinition CreateArrayField (string fieldName, int[] values, ModuleDefinition module, FieldAttributes attributes = FieldAttributes.Public)
+		{
+			var f = new FieldDefinition (fieldName, attributes | FieldAttributes.Static | FieldAttributes.HasDefault, intArray);
+			f.Constant = values;
+			return f;
+		}
+
+		PropertyDefinition CreateArrayProperty (string propertyName, int[] values, ModuleDefinition module, MethodAttributes attributes = MethodAttributes.Public)
+		{
+			var p = new PropertyDefinition (propertyName, PropertyAttributes.None, intArray);
+			var getter = new MethodDefinition ($"get_{propertyName}", attributes | MethodAttributes.Static, intArray);
+			p.GetMethod = getter;
+			p.SetMethod = null;
+			var il = p.GetMethod.Body.GetILProcessor ();
+			il.Emit (OpCodes.Ldc_I4, values.Length);
+			il.Emit (OpCodes.Newarr, intRef);
+			int index = 0;
+			foreach (int value in values) {
+				il.Emit (OpCodes.Dup);
+				il.Emit (OpCodes.Ldc_I4, index++);
+				il.Emit (OpCodes.Ldc_I4, value);
+				il.Emit (OpCodes.Stelem_I4);
+			}
+			il.Emit (OpCodes.Ret);
+			return p;
+		}
+
+		void StrongNameAssembly (AssemblyNameDefinition name)
+		{
+			using (Stream stream = typeof (GenerateResourceDesignerAssembly).Assembly.GetManifestResourceStream ("Resource.Designer.snk")) {
+				byte[] publicKey = new byte[stream.Length];
+				stream.Read (publicKey, 0, publicKey.Length);
+				name.HashAlgorithm = AssemblyHashAlgorithm.SHA1;
+				name.PublicKey = SigningHelper.GetPublicKey (publicKey);
+				name.HasPublicKey = true;
+				name.Attributes |= AssemblyAttributes.PublicKey;
+			}
+		}
+	}
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerIntermediateClass.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerIntermediateClass.cs
new file mode 100644
index 00000000000..9247993a554
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerIntermediateClass.cs
@@ -0,0 +1,53 @@
+using System;
+using System.IO;
+using System.CodeDom.Compiler;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using Microsoft.Android.Build.Tasks;
+using MonoDroid.Tuner;
+
+namespace Xamarin.Android.Tasks
+{
+	public class GenerateResourceDesignerIntermediateClass : AndroidTask
+	{
+		public override string TaskPrefix => "GRDIC";
+
+		private const string ResourceDesigner = $"{FixLegacyResourceDesignerStep.DesignerAssemblyNamespace}.Resource";
+		private const string ResourceDesignerConstants = $"{FixLegacyResourceDesignerStep.DesignerAssemblyNamespace}.ResourceConstant";
+
+		private const string CSharpTemplate = @"// This is an Auto Generated file DO NOT EDIT
+using System;
+
+namespace %NAMESPACE% {
+	public partial class Resource : %BASECLASS% {
+	}
+}
+";
+		private const string FSharpTemplate = @"// This is an Auto Generated file DO NOT EDIT
+namespace %NAMESPACE%
+
+type Resource = %BASECLASS%
+";
+
+		public string Namespace { get; set; }
+		public bool IsApplication { get; set; } = false;
+		public ITaskItem OutputFile { get; set; }
+		public override bool RunTask ()
+		{
+			string ns = IsApplication ? ResourceDesignerConstants : ResourceDesigner;
+			var extension = Path.GetExtension (OutputFile.ItemSpec);
+			var language = string.Compare (extension, ".fs", StringComparison.OrdinalIgnoreCase) == 0 ? "F#" : CodeDomProvider.GetLanguageFromExtension (extension);
+			//bool isVB = string.Equals (extension, ".vb", StringComparison.OrdinalIgnoreCase);
+			bool isFSharp = string.Equals (language, "F#", StringComparison.OrdinalIgnoreCase);
+			bool isCSharp = string.Equals (language, "C#", StringComparison.OrdinalIgnoreCase);
+			string template = "";
+			if (isCSharp)
+				template = CSharpTemplate.Replace ("%NAMESPACE%", Namespace).Replace ("%BASECLASS%", ns);
+			else if (isFSharp)
+				template = FSharpTemplate.Replace ("%NAMESPACE%", Namespace).Replace ("%BASECLASS%", ns);
+
+			Files.CopyIfStringChanged (template, OutputFile.ItemSpec);
+			return !Log.HasLoggedErrors;
+		}
+	}
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateRtxt.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateRtxt.cs
new file mode 100644
index 00000000000..a9927347626
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateRtxt.cs
@@ -0,0 +1,48 @@
+// Copyright (C) 2022 Microsoft Ltd, Inc. All rights reserved.
+using System;
+using System.CodeDom;
+using System.CodeDom.Compiler;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using Microsoft.Android.Build.Tasks;
+
+namespace Xamarin.Android.Tasks
+{
+	public class GenerateRtxt : AndroidTask
+	{
+		public override string TaskPrefix => "GR";
+
+		[Required]
+		public string RTxtFile { get; set; }
+
+		[Required]
+		public string ResourceDirectory { get; set; }
+		public string[] AdditionalResourceDirectories { get; set; }
+
+		[Required]
+		public string JavaPlatformJarPath { get; set; }
+
+		public string ResourceFlagFile { get; set; }
+		public string CaseMapFile { get; set; }
+
+		public override bool RunTask ()
+		{
+			// Parse the Resource files and then generate an R.txt file
+			var writer = new RtxtWriter ();
+
+			var resource_fixup = MonoAndroidHelper.LoadMapFile (BuildEngine4, CaseMapFile, StringComparer.OrdinalIgnoreCase);
+
+			var javaPlatformDirectory = Path.GetDirectoryName (JavaPlatformJarPath);
+			var parser = new FileResourceParser () { Log = Log, JavaPlatformDirectory = javaPlatformDirectory, ResourceFlagFile = ResourceFlagFile};
+			var resources = parser.Parse (ResourceDirectory, AdditionalResourceDirectories, resource_fixup);
+
+			// only update if it changed.
+			writer.Write (RTxtFile, resources);
+
+			return !Log.HasLoggedErrors;
+		}
+	}
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/LinkAssemblies.cs b/src/Xamarin.Android.Build.Tasks/Tasks/LinkAssemblies.cs
index 55c7bf7d804..67c72c382da 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/LinkAssemblies.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/LinkAssemblies.cs
@@ -58,6 +58,8 @@ public class LinkAssemblies : AndroidTask, ML.ILogger
 
 		public bool LinkResources { get; set; }
 
+		public bool UseDesignerAssembly { get; set; }
+
 		IEnumerable<AssemblyDefinition> GetRetainAssemblies (DirectoryAssemblyResolver res)
 		{
 			List<AssemblyDefinition> retainList = null;
@@ -109,6 +111,7 @@ bool Execute (DirectoryAssemblyResolver res)
 			options.PreserveJniMarshalMethods = PreserveJniMarshalMethods;
 			options.DeterministicOutput = Deterministic;
 			options.LinkResources = LinkResources;
+			options.UseDesignerAssembly = UseDesignerAssembly;
 
 			var skiplist = new List<string> ();
 
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/LinkAssembliesNoShrink.cs b/src/Xamarin.Android.Build.Tasks/Tasks/LinkAssembliesNoShrink.cs
index 25da6cbde08..5d4c65c8509 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/LinkAssembliesNoShrink.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/LinkAssembliesNoShrink.cs
@@ -38,6 +38,8 @@ public class LinkAssembliesNoShrink : AndroidTask
 
 		public bool AddKeepAlives { get; set; }
 
+		public bool UseDesignerAssembly { get; set; }
+
 		public bool Deterministic { get; set; }
 
 		public override bool RunTask ()
@@ -64,6 +66,9 @@ public override bool RunTask ()
 				var cache = new TypeDefinitionCache ();
 				var fixAbstractMethodsStep = new FixAbstractMethodsStep (resolver, cache, Log);
 				var addKeepAliveStep = new AddKeepAlivesStep (resolver, cache, Log, UsingAndroidNETSdk);
+				var fixLegacyResourceDesignerStep = new FixLegacyResourceDesignerStep (resolver, cache, Log);
+				if (UseDesignerAssembly)
+					fixLegacyResourceDesignerStep.Load ();
 				for (int i = 0; i < SourceFiles.Length; i++) {
 					var source = SourceFiles [i];
 					var destination = DestinationFiles [i];
@@ -91,8 +96,12 @@ public override bool RunTask ()
 						if (assemblyDefinition == null)
 							assemblyDefinition = resolver.GetAssembly (source.ItemSpec);
 
-						if (fixAbstractMethodsStep.FixAbstractMethods (assemblyDefinition) ||
-						    (AddKeepAlives && addKeepAliveStep.AddKeepAlives (assemblyDefinition))) {
+						bool save = fixAbstractMethodsStep.FixAbstractMethods (assemblyDefinition);
+						if (UseDesignerAssembly)
+							save |= fixLegacyResourceDesignerStep.ProcessAssemblyDesigner (assemblyDefinition);
+						if (AddKeepAlives)
+							save |= addKeepAliveStep.AddKeepAlives (assemblyDefinition);
+						if (save) {
 							Log.LogDebugMessage ($"Saving modified assembly: {destination.ItemSpec}");
 							writerParameters.WriteSymbols = assemblyDefinition.MainModule.HasSymbols;
 							assemblyDefinition.Write (destination.ItemSpec, writerParameters);
@@ -119,6 +128,33 @@ void CopyIfChanged (ITaskItem source, ITaskItem destination)
 			}
 		}
 
+		class FixLegacyResourceDesignerStep : MonoDroid.Tuner.FixLegacyResourceDesignerStep
+		{
+			readonly DirectoryAssemblyResolver resolver;
+			readonly TaskLoggingHelper logger;
+
+			public FixLegacyResourceDesignerStep (DirectoryAssemblyResolver resolver, TypeDefinitionCache cache, TaskLoggingHelper logger)
+				: base (cache)
+			{
+				this.resolver = resolver;
+				this.logger = logger;
+			}
+
+			public void Load () {
+				LoadDesigner ();
+			}
+
+			public override void LogMessage (string message)
+			{
+				logger.LogDebugMessage ("{0}", message);
+			}
+
+			public override AssemblyDefinition Resolve (AssemblyNameReference name)
+			{
+				return resolver.Resolve (name);
+			}
+		}
+
 		class FixAbstractMethodsStep : MonoDroid.Tuner.FixAbstractMethodsStep
 		{
 			readonly DirectoryAssemblyResolver resolver;
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/ResolveLibraryProjectImports.cs b/src/Xamarin.Android.Build.Tasks/Tasks/ResolveLibraryProjectImports.cs
index f675f9f1bc9..f55838abac1 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/ResolveLibraryProjectImports.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/ResolveLibraryProjectImports.cs
@@ -352,6 +352,7 @@ void Extract (
 				string importsDir = Path.Combine (outDirForDll, ImportsDirectory);
 				string resDir = Path.Combine (importsDir, "res");
 				string resDirArchive = Path.Combine (resDir, "..", "res.zip");
+				string rTxt = Path.Combine (importsDir, "R.txt");
 				string assetsDir = Path.Combine (importsDir, "assets");
 				string proguardFile = Path.Combine (importsDir, "proguard.txt");
 
@@ -367,7 +368,7 @@ void Extract (
 							AddJar (jars, Path.GetFullPath (file));
 						}
 					}
-					if (Directory.Exists (resDir)) {
+					if (Directory.Exists (resDir) || File.Exists (rTxt)) {
 						var skipProcessing = aarFile.GetMetadata (AndroidSkipResourceProcessing);
 						if (string.IsNullOrEmpty (skipProcessing)) {
 							skipProcessing = "True";
@@ -424,8 +425,9 @@ void Extract (
 						Log.LogErrorFromException (new PathTooLongException ($"Error extracting resources from \"{aarFile.ItemSpec}\"", ex));
 					}
 				}
-				if (Directory.Exists (resDir)) {
-					CreateResourceArchive (resDir, resDirArchive);
+				if (Directory.Exists (resDir) || File.Exists (rTxt)) {
+					if (Directory.Exists (resDir))
+						CreateResourceArchive (resDir, resDirArchive);
 					var skipProcessing = aarFile.GetMetadata (AndroidSkipResourceProcessing);
 					if (string.IsNullOrEmpty (skipProcessing)) {
 						skipProcessing = "True";
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs
index 6858b962cae..00add1baf48 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs
@@ -18,8 +18,11 @@ namespace Xamarin.Android.Build.Tests
 	public class AndroidUpdateResourcesTest : BaseTest
 	{
 		[Test]
-		public void CheckMultipleLibraryProjectReferenceAlias ([Values (true, false)] bool withGlobal)
+		public void CheckMultipleLibraryProjectReferenceAlias ([Values (true, false)] bool withGlobal, [Values (true, false)] bool useDesignerAssembly)
 		{
+			if (useDesignerAssembly && !Builder.UseDotNet) {
+				Assert.Ignore ($"Skipping, {useDesignerAssembly} not supported in Legacy.");
+			}
 			var path = Path.Combine (Root, "temp", TestName);
 			var library1 = new XamarinAndroidLibraryProject () {
 				ProjectName = "Library1",
@@ -38,6 +41,9 @@ public void CheckMultipleLibraryProjectReferenceAlias ([Values (true, false)] bo
 					},
 				},
 			};
+			library1.SetProperty ("AndroidUseDesignerAssembly", "false");
+			library2.SetProperty ("AndroidUseDesignerAssembly", useDesignerAssembly.ToString ());
+			proj.SetProperty ("AndroidUseDesignerAssembly", useDesignerAssembly.ToString ());
 			using (var builder1 = CreateDllBuilder (Path.Combine (path, library1.ProjectName), cleanupAfterSuccessfulBuild: false, cleanupOnDispose: false)) {
 				builder1.ThrowOnBuildFailure = false;
 				Assert.IsTrue (builder1.Build (library1), "Library should have built.");
@@ -47,10 +53,12 @@ public void CheckMultipleLibraryProjectReferenceAlias ([Values (true, false)] bo
 					using (var b = CreateApkBuilder (Path.Combine (path, proj.ProjectName), cleanupAfterSuccessfulBuild: false, cleanupOnDispose: false)) {
 						b.ThrowOnBuildFailure = false;
 						Assert.IsTrue (b.Build (proj), "Project should have built.");
-						string resource_designer_cs = GetResourceDesignerPath (b, proj);
-						string [] text = File.ReadAllLines (resource_designer_cs);
-						Assert.IsTrue (text.Count (x => x.Contains ("Library1.Resource.String.library_name")) == 2, "library_name resource should be present exactly once for each library");
-						Assert.IsTrue (text.Count (x => x == "extern alias Lib1A;" || x == "extern alias Lib1B;") <= 1, "No more than one extern alias should be present for each library.");
+						if (!useDesignerAssembly) {
+							string resource_designer_cs = GetResourceDesignerPath (b, proj);
+							string [] text = GetResourceDesignerLines (proj, resource_designer_cs);
+							Assert.IsTrue (text.Count (x => x.Contains ("Library1.Resource.String.library_name")) == 2, "library_name resource should be present exactly once for each library");
+							Assert.IsTrue (text.Count (x => x == "extern alias Lib1A;" || x == "extern alias Lib1B;") <= 1, "No more than one extern alias should be present for each library.");
+						}
 					}
 				}
 			}
@@ -92,6 +100,7 @@ public void DesignTimeBuild ([Values(false, true)] bool isRelease, [Values (fals
 				IsRelease = isRelease,
 			};
 			lib.SetProperty ("AndroidUseManagedDesignTimeResourceGenerator", useManagedParser.ToString ());
+			lib.SetProperty ("AndroidUseDesignerAssembly", "false");
 			lib.AndroidUseAapt2 = useAapt2;
 			var proj = new XamarinAndroidApplicationProject () {
 				IsRelease = isRelease,
@@ -101,6 +110,7 @@ public void DesignTimeBuild ([Values(false, true)] bool isRelease, [Values (fals
 			};
 			var intermediateOutputPath = Path.Combine (path, proj.ProjectName, proj.IntermediateOutputPath);
 			proj.SetProperty ("AndroidUseManagedDesignTimeResourceGenerator", useManagedParser.ToString ());
+			proj.SetProperty ("AndroidUseDesignerAssembly", "false");
 			proj.AndroidUseAapt2 = useAapt2;
 			using (var l = CreateDllBuilder (Path.Combine (path, lib.ProjectName), false, false)) {
 				using (var b = CreateApkBuilder (Path.Combine (path, proj.ProjectName), false, false)) {
@@ -528,13 +538,20 @@ public void CheckResourceDesignerIsCreated (bool isRelease, ProjectLanguage lang
 			using (var b = CreateApkBuilder ()) {
 				Assert.IsTrue (b.Build (proj), "Build should have succeeded.");
 				// Intermediate designer file support is not compatible with F# projects using Xamarin.Android.FSharp.ResourceProvider.
-				var outputFile = isFSharp ? Path.Combine (Root, b.ProjectDirectory, "Resources", "Resource.designer" + proj.Language.DefaultDesignerExtension)
-					: Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "Resource.designer" + proj.Language.DefaultDesignerExtension);
-				Assert.IsTrue (File.Exists (outputFile), "Resource.designer{1} should have been created in {0}",
-					isFSharp ? Path.Combine (Root, b.ProjectDirectory, "Resources") : proj.IntermediateOutputPath,
-					proj.Language.DefaultDesignerExtension);
+				string outputFile;
+				if (Builder.UseDotNet) {
+					outputFile = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "__Microsoft.Android.Resource.Designer" + proj.Language.DefaultDesignerExtension);
+					Assert.IsTrue (File.Exists (outputFile), $"{outputFile} should have been created in {proj.IntermediateOutputPath}");
+				} else {
+					outputFile = isFSharp ? Path.Combine (Root, b.ProjectDirectory, "Resources", "Resource.designer" + proj.Language.DefaultDesignerExtension)
+						: Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "Resource.designer" + proj.Language.DefaultDesignerExtension);
+					Assert.IsTrue (File.Exists (outputFile), "Resource.designer{1} should have been created in {0}",
+						isFSharp ? Path.Combine (Root, b.ProjectDirectory, "Resources") : proj.IntermediateOutputPath,
+						proj.Language.DefaultDesignerExtension);
+				}
+
 				Assert.IsTrue (b.Clean (proj), "Clean should have succeeded.");
-				if (!isFSharp) {
+				if (!isFSharp || Builder.UseDotNet) {
 					Assert.IsFalse (File.Exists (outputFile), "Resource.designer{1} should have been cleaned in {0}",
 						proj.IntermediateOutputPath, proj.Language.DefaultDesignerExtension);
 				}
@@ -597,13 +614,12 @@ public void CheckOldResourceDesignerIsNotUsed ([Values (true, false)] bool isRel
 				var fi = new FileInfo (Path.Combine (Root, b.ProjectDirectory, designer));
 				Assert.IsFalse (fi.Length > new [] { 0xef, 0xbb, 0xbf, 0x0d, 0x0a }.Length,
 					"{0} should not contain anything.", designer);
+				var designerFile = Builder.UseDotNet ? "__Microsoft.Android.Resource.Designer" : "Resource.designer" ;
 				var outputFile = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath,
-					"Resource.designer"  + proj.Language.DefaultDesignerExtension);
-				Assert.IsTrue (File.Exists (outputFile), "Resource.designer{1} should have been created in {0}",
-					proj.IntermediateOutputPath, proj.Language.DefaultDesignerExtension);
+					designerFile + proj.Language.DefaultDesignerExtension);
+				Assert.IsTrue (File.Exists (outputFile), $"{designerFile}{proj.Language.DefaultDesignerExtension} should have been created in {proj.IntermediateOutputPath}");
 				Assert.IsTrue (b.Clean (proj), "Clean should have succeeded.");
-				Assert.IsFalse (File.Exists (outputFile), "Resource.designer{1} should have been cleaned in {0}",
-					proj.IntermediateOutputPath, proj.Language.DefaultDesignerExtension);
+				Assert.IsFalse (File.Exists (outputFile), $"{designerFile}{proj.Language.DefaultDesignerExtension} should have been cleaned in {proj.IntermediateOutputPath}");
 			}
 		}
 
@@ -625,13 +641,56 @@ public void CheckOldResourceDesignerWithWrongCasingIsRemoved ([Values (true, fal
 				Assert.IsFalse (File.Exists (Path.Combine (Root, b.ProjectDirectory, "Resources",
 					"Resource.designer"  + proj.Language.DefaultDesignerExtension)),
 					"{0} should not exists", designer.Include ());
+				var designerFile = Builder.UseDotNet ? "__Microsoft.Android.Resource.Designer" : "Resource.designer" ;
 				var outputFile = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath,
-					"Resource.designer"  + proj.Language.DefaultDesignerExtension);
-				Assert.IsTrue (File.Exists (outputFile), "Resource.designer{1} should have been created in {0}",
-					proj.IntermediateOutputPath, proj.Language.DefaultDesignerExtension);
+					designerFile  + proj.Language.DefaultDesignerExtension);
+				Assert.IsTrue (File.Exists (outputFile), $"{designerFile}{proj.Language.DefaultDesignerExtension} should have been created in {proj.IntermediateOutputPath}");
 				Assert.IsTrue (b.Clean (proj), "Clean should have succeeded.");
-				Assert.IsFalse (File.Exists (outputFile), "Resource.designer{1} should have been cleaned in {0}",
-					proj.IntermediateOutputPath, proj.Language.DefaultDesignerExtension);
+				Assert.IsFalse (File.Exists (outputFile), $"{designerFile}{proj.Language.DefaultDesignerExtension} should have been cleaned in {proj.IntermediateOutputPath}");
+			}
+		}
+
+		[Test]
+		public void CheckThatXA1031IsRaisedForInvalidConfiguration ([Values (true, false)] bool isRelease)
+		{
+			if (!Builder.UseDotNet)
+				Assert.Ignore ("Test uses designer assembly which does not work on Legacy projects.");
+			string path = Path.Combine (Root, "temp", TestName);
+			var foo = new BuildItem.Source ("Foo.cs") {
+				TextContent = () => @"using System;
+namespace Lib1 {
+	public class Foo {
+		public static string GetFoo () {
+			return ""Foo"";
+		}
+	}
+}"
+			};
+			var library = new XamarinAndroidLibraryProject () {
+				IsRelease = isRelease,
+				ProjectName = "Lib1",
+				Sources = { foo },
+			};
+			library.SetProperty ("AndroidUseDesignerAssembly", "True");
+
+			var proj = new XamarinAndroidApplicationProject () {
+				IsRelease = isRelease,
+				ProjectName = "App1",
+				References = {
+					new BuildItem.ProjectReference ($"..\\{library.ProjectName}\\{library.ProjectName}.csproj", library.ProjectName, library.ProjectGuid),
+				},
+			};
+			proj.SetProperty ("AndroidUseDesignerAssembly", "False");
+			proj.MainActivity = proj.DefaultMainActivity.Replace ("//${AFTER_ONCREATE}", "Console.WriteLine (Lib1.Foo.GetFoo ());");
+			using (var lb = CreateDllBuilder (Path.Combine (path, library.ProjectName))) {
+				lb.ThrowOnBuildFailure = false;
+				Assert.IsTrue (lb.Build (library), "Library project should have built.");
+				using (var pb = CreateApkBuilder (Path.Combine (path, proj.ProjectName))) {
+					pb.ThrowOnBuildFailure = false;
+					Assert.IsFalse (pb.Build (proj), "Application project build should have failed.");
+					StringAssertEx.ContainsText (pb.LastBuildOutput, "XA1031: ");
+					StringAssertEx.ContainsText (pb.LastBuildOutput, "1 Error(s)");
+				}
 			}
 		}
 
@@ -785,8 +844,10 @@ public void CheckFilesAreRemoved () {
 		}
 
 		[Test]
-		public void CheckDontUpdateResourceIfNotNeeded ()
+		public void CheckDontUpdateResourceIfNotNeeded ([Values (true, false)] bool useDesignerAssembly)
 		{
+			if (!Builder.UseDotNet && useDesignerAssembly)
+				Assert.Ignore ("Test uses designer assembly which does not work on Legacy projects.");
 			var path = Path.Combine ("temp", TestName);
 			var target = Builder.UseDotNet ? "_CreateAar" : "_CreateManagedLibraryResourceArchive";
 			var foo = new BuildItem.Source ("Foo.cs") {
@@ -824,6 +885,7 @@ public string GetFoo () {
 				},
 			};
 			libProj.SetProperty ("Deterministic", "true");
+			libProj.SetProperty ("AndroidUseDesignerAssembly", useDesignerAssembly.ToString ());
 			var appProj = new XamarinAndroidApplicationProject () {
 				IsRelease = true,
 				ProjectName = "App1",
@@ -831,6 +893,7 @@ public string GetFoo () {
 					new BuildItem.ProjectReference (@"..\Lib1\Lib1.csproj", libProj.ProjectName, libProj.ProjectGuid),
 				},
 			};
+			appProj.SetProperty ("AndroidUseDesignerAssembly", useDesignerAssembly.ToString ());
 			using (var libBuilder = CreateDllBuilder (Path.Combine (path, libProj.ProjectName), false, false)) {
 				Assert.IsTrue (libBuilder.Build (libProj), "Library project should have built");
 				using (var appBuilder = CreateApkBuilder (Path.Combine (path, appProj.ProjectName), false, false)) {
@@ -864,7 +927,7 @@ public string GetFoo () {
 					appBuilder.BuildLogFile = "build2.log";
 					Assert.IsTrue (appBuilder.Build (appProj, doNotCleanupOnUpdate: true, saveProject: false), "Application Build should have succeeded.");
 					string resource_designer_cs = GetResourceDesignerPath (appBuilder, appProj);
-					string text = File.ReadAllText (resource_designer_cs);
+					string text = GetResourceDesignerText (appProj, resource_designer_cs);
 					StringAssert.Contains ("theme_devicedefault_background2", text, "Resource.designer.cs was not updated.");
 					appBuilder.Output.AssertTargetIsNotSkipped ("_UpdateAndroidResgen");
 					appBuilder.Output.AssertTargetIsNotSkipped ("_CreateBaseApk");
@@ -904,6 +967,7 @@ public void BuildAppWithManagedResourceParser()
 				ProjectName = "App1",
 			};
 			appProj.SetProperty ("AndroidUseManagedDesignTimeResourceGenerator", "True");
+			appProj.SetProperty ("AndroidUseDesignerAssembly", "false");
 			using (var appBuilder = CreateApkBuilder (Path.Combine (path, appProj.ProjectName))) {
 				Assert.IsTrue (appBuilder.DesignTimeBuild (appProj), "DesignTime Application Build should have succeeded.");
 				Assert.IsFalse (appProj.CreateBuildOutput (appBuilder).IsTargetSkipped ("_ManagedUpdateAndroidResgen"),
@@ -961,6 +1025,7 @@ public void BuildAppWithManagedResourceParserAndLibraries ()
 				},
 			};
 			libProj.SetProperty ("AndroidUseManagedDesignTimeResourceGenerator", "True");
+			libProj.SetProperty ("AndroidUseDesignerAssembly", "false");
 			var appProj = new XamarinAndroidApplicationProject () {
 				IsRelease = true,
 				ProjectName = "App1",
@@ -978,6 +1043,7 @@ public void BuildAppWithManagedResourceParserAndLibraries ()
 				},
 			};
 			appProj.SetProperty ("AndroidUseManagedDesignTimeResourceGenerator", "True");
+			appProj.SetProperty ("AndroidUseDesignerAssembly", "false");
 			using (var libBuilder = CreateDllBuilder (Path.Combine (path, libProj.ProjectName), false, false)) {
 				libBuilder.AutomaticNuGetRestore = false;
 				Assert.IsTrue (libBuilder.RunTarget (libProj, "Restore"), "Library project should have restored.");
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AotTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AotTests.cs
index f9641bff999..6a8ccadba77 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AotTests.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AotTests.cs
@@ -276,6 +276,13 @@ public void BuildAMassiveApp ()
 				AotAssemblies = true,
 				IsRelease = true,
 			};
+			if (Builder.UseDotNet) {
+				app1.PackageReferences.Clear ();
+				app1.PackageReferences.Add (KnownPackages.XamarinForms_5_0_0_2515);
+				app1.PackageReferences.Add (KnownPackages.XamarinFormsMaps_5_0_0_2515);
+				app1.PackageReferences.Add (KnownPackages.Xamarin_Build_Download_0_11_3);
+
+			}
 			//NOTE: BuildingInsideVisualStudio prevents the projects from being built as dependencies
 			sb.BuildingInsideVisualStudio = false;
 			app1.Imports.Add (new Import ("foo.targets") {
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs
index 3e777babfde..e5a7d05a09c 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs
@@ -477,8 +477,11 @@ public void CheckItemMetadata ([Values (true, false)] bool isRelease)
 
 		// Context https://bugzilla.xamarin.com/show_bug.cgi?id=29706
 		[Test]
-		public void CheckLogicalNamePathSeperators ([Values (false, true)] bool isRelease)
+		public void CheckLogicalNamePathSeperators ([Values (false, true)] bool isRelease, [Values (false, true)] bool useDesignerAssembly)
 		{
+			if (useDesignerAssembly && !Builder.UseDotNet) {
+				Assert.Ignore ($"Skipping, {useDesignerAssembly} not supported in Legacy.");
+			}
 			var illegalSeperator = IsWindows ? "/" : @"\";
 			var dll = new XamarinAndroidLibraryProject () {
 				ProjectName = "Library1",
@@ -503,20 +506,18 @@ public void CheckLogicalNamePathSeperators ([Values (false, true)] bool isReleas
 					new BuildItem ("ProjectReference","..\\Library1\\Library1.csproj"),
 				},
 			};
+			if (!useDesignerAssembly)
+				dll.SetProperty ("AndroidUseDesignerAssembly", useDesignerAssembly.ToString ());
+			proj.SetProperty ("AndroidUseDesignerAssembly", useDesignerAssembly.ToString ());
 			var path = Path.Combine ("temp", TestName);
 			using (var b = CreateDllBuilder (Path.Combine (path, dll.ProjectName))) {
 				Assert.IsTrue (b.Build (dll), "Build should have succeeded.");
 				using (var builder = CreateApkBuilder (Path.Combine (path, proj.ProjectName), isRelease)) {
 					Assert.IsTrue (builder.Build (proj), "Build should have succeeded");
-					string resource_designer_cs;
-					if (Builder.UseDotNet) {
-						resource_designer_cs = Path.Combine (Root, builder.ProjectDirectory, proj.IntermediateOutputPath, "Resource.designer.cs");
-					} else {
-						resource_designer_cs = Path.Combine (Root, builder.ProjectDirectory, "Resources", "Resource.designer.cs");
-					}
-					var contents = File.ReadAllText (resource_designer_cs);
-					StringAssert.Contains ("public const int foo = ", contents);
-					StringAssert.Contains ("public const int foo2 = ", contents);
+					string resource_designer_cs = GetResourceDesignerPath (builder, proj);
+					var contents = GetResourceDesignerText (proj, resource_designer_cs);
+					StringAssert.Contains ("public const int foo =", contents);
+					StringAssert.Contains ("public const int foo2 =", contents);
 				}
 			}
 		}
@@ -2020,8 +2021,11 @@ public void LibraryReferenceWithHigherTFVShouldDisplayWarning ([Values (true, fa
 		}
 
 		[Test]
-		public void AllResourcesInClassLibrary ([Values (true, false)] bool useAapt2)
+		public void AllResourcesInClassLibrary ([Values (true, false)] bool useAapt2, [Values (false, true)] bool useDesignerAssembly)
 		{
+			if (useDesignerAssembly && !Builder.UseDotNet) {
+				Assert.Ignore ($"Skipping, {useDesignerAssembly} not supported in Legacy.");
+			}
 			AssertAaptSupported (useAapt2);
 			var path = Path.Combine ("temp", TestName);
 
@@ -2035,6 +2039,7 @@ public void AllResourcesInClassLibrary ([Values (true, false)] bool useAapt2)
 				}
 			};
 			lib.SetProperty ("AndroidApplication", "False");
+			lib.SetProperty ("AndroidUseDesignerAssembly", useDesignerAssembly.ToString ());
 			lib.AndroidUseAapt2 = useAapt2;
 			if (Builder.UseDotNet) {
 				lib.RemoveProperty ("OutputType");
@@ -2054,6 +2059,7 @@ public void AllResourcesInClassLibrary ([Values (true, false)] bool useAapt2)
 					},
 				}
 			};
+			app.SetProperty ("AndroidUseDesignerAssembly", useDesignerAssembly.ToString ());
 			app.AndroidResources.Clear (); // No Resources
 			if (Builder.UseDotNet) {
 				app.SetProperty (KnownProperties.OutputType, "Exe");
@@ -2075,7 +2081,7 @@ public void AllResourcesInClassLibrary ([Values (true, false)] bool useAapt2)
 
 				var resource_designer_cs = GetResourceDesignerPath (appBuilder, app);
 				FileAssert.Exists (resource_designer_cs);
-				var contents = File.ReadAllText (resource_designer_cs);
+				var contents = GetResourceDesignerText (app, resource_designer_cs);
 				Assert.AreNotEqual ("", contents);
 			}
 		}
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/DesignerTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/DesignerTests.cs
index 925e80472c4..63c6603fed7 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/DesignerTests.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/DesignerTests.cs
@@ -93,10 +93,14 @@ public CustomTextView(Context context, IAttributeSet attributes) : base(context,
 </LinearLayout>"
 			});
 
+			lib.SetProperty ("AndroidUseDesignerAssembly", "False");
+			proj.SetProperty ("AndroidUseDesignerAssembly", "False");
+
 			using (var libb = CreateDllBuilder (Path.Combine (path, lib.ProjectName), false, false))
 			using (var appb = CreateApkBuilder (Path.Combine (path, proj.ProjectName), false, false)) {
 				// Save the library project, but don't build it yet
 				libb.Save (lib);
+				appb.BuildLogFile = "build1.log";
 				appb.Target = target;
 				Assert.IsTrue (appb.Build (proj, parameters: DesignerParameters), $"build should have succeeded for target `{target}`");
 				Assert.IsTrue (appb.Output.AreTargetsAllBuilt ("_UpdateAndroidResgen"), "_UpdateAndroidResgen should have run completely.");
@@ -111,6 +115,7 @@ public CustomTextView(Context context, IAttributeSet attributes) : base(context,
 				// Build the library project now
 				Assert.IsTrue (libb.Build (lib, doNotCleanupOnUpdate: true), "library build should have succeeded.");
 				appb.Target = "Build";
+				appb.BuildLogFile = "build2.log";
 				Assert.IsTrue (appb.Build (proj, doNotCleanupOnUpdate: true), "app build should have succeeded.");
 				Assert.IsTrue (appb.Output.AreTargetsAllBuilt ("_UpdateAndroidResgen"), "_UpdateAndroidResgen should have run completely.");
 				Assert.IsTrue (appb.Output.AreTargetsAllBuilt ("_Foo"), "_Foo should have run completely");
@@ -120,6 +125,7 @@ public CustomTextView(Context context, IAttributeSet attributes) : base(context,
 				Assert.IsNull (doc.Element ("LinearLayout").Element ("unnamedproject.CustomTextView"),
 					"unnamedproject.CustomTextView should have been replaced with a $(Hash).CustomTextView");
 				appb.Target = target;
+				appb.BuildLogFile = "build3.log";
 				Assert.IsTrue (appb.Build (proj, parameters: DesignerParameters, doNotCleanupOnUpdate: true), $"build should have succeeded for target `{target}`");
 				Assert.IsTrue (appb.Output.AreTargetsAllSkipped ("_UpdateAndroidResgen"), "_UpdateAndroidResgen should have been skipped.");
 				Assert.IsTrue (appb.Output.AreTargetsAllBuilt ("_Foo"), "_Foo should have run completely");
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs
index 3aa68042cdd..24fe06606b7 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs
@@ -156,6 +156,7 @@ public void IncrementalCleanDuringClean ()
 				IsRelease = true,
 			};
 			proj.SetProperty ("AndroidUseManagedDesignTimeResourceGenerator", "True");
+			proj.SetProperty ("AndroidUseDesignerAssembly", "False");
 			using (var b = CreateApkBuilder (path)) {
 				b.Target = "Compile";
 				Assert.IsTrue(b.Build (proj), "DesignTime Build should have succeeded");
@@ -830,6 +831,7 @@ public void ResolveLibraryProjectImports ([Values (true, false)] bool useAapt2)
 				FileAssert.Exists (stamp);
 				File.Delete (stamp);
 
+				b.BuildLogFile = "build2.log";
 				Assert.IsTrue (b.Build (proj), "second build should have succeeded.");
 				var actual = ReadCache (cacheFile);
 				CollectionAssert.AreEqual (actual.Jars.Select (j => j.ItemSpec),
@@ -843,6 +845,7 @@ public void ResolveLibraryProjectImports ([Values (true, false)] bool useAapt2)
 				};
 				proj.OtherBuildItems.Add (aar);
 
+				b.BuildLogFile = "build3.log";
 				Assert.IsTrue (b.Build (proj), "third build should have succeeded.");
 				actual = ReadCache (cacheFile);
 				Assert.AreEqual (expected.Jars.Length + 1, actual.Jars.Length,
@@ -856,6 +859,7 @@ public void ResolveLibraryProjectImports ([Values (true, false)] bool useAapt2)
 				}
 
 				// Build with no changes, checking we are skipping targets appropriately
+				b.BuildLogFile = "build4.log";
 				Assert.IsTrue (b.Build (proj), "fourth build should have succeeded.");
 				var targets = new List<string> {
 					"_UpdateAndroidResgen",
@@ -1274,6 +1278,7 @@ public void AndroidResourceChange ()
 				// AndroidResource change
 				proj.LayoutMain += $"{Environment.NewLine}<!--comment-->";
 				proj.Touch ("Resources\\layout\\Main.axml");
+				builder.BuildLogFile = "build2.log";
 				Assert.IsTrue (builder.Build (proj), "second build should succeed");
 
 				builder.Output.AssertTargetIsSkipped ("_ResolveLibraryProjectImports");
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs
index 3601da8a073..f69eeb8b5c1 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs
@@ -95,6 +95,7 @@ public void CheckIncludedAssemblies ([Values (false, true)] bool usesAssemblySto
 					"System.Runtime.InteropServices.dll",
 					"System.Linq.dll",
 					"UnnamedProject.dll",
+					"_Microsoft.Android.Resource.Designer.dll",
 				} :
 				new [] {
 					"Java.Interop.dll",
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GenerateResourceCaseMapTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GenerateResourceCaseMapTests.cs
new file mode 100644
index 00000000000..8cfd159b009
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GenerateResourceCaseMapTests.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using Microsoft.Build.Utilities;
+using NUnit.Framework;
+using Xamarin.Android.Tasks;
+using Xamarin.ProjectTools;
+
+namespace Xamarin.Android.Build.Tests {
+	[TestFixture]
+	[Category ("Node-5")]
+	[Parallelizable (ParallelScope.Children)]
+	public class GenerateResourceCaseMapTests : BaseTest {
+
+		public void CreateResourceDirectory (string path)
+		{
+			Directory.CreateDirectory (Path.Combine (Root, path));
+			Directory.CreateDirectory (Path.Combine (Root, path, "res", "drawable"));
+			Directory.CreateDirectory (Path.Combine (Root, path, "res", "values"));
+			using (var stream = typeof (XamarinAndroidCommonProject).Assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Base.Icon.png")) {
+				var icon_binary_mdpi = new byte [stream.Length];
+				stream.Read (icon_binary_mdpi, 0, (int)stream.Length);
+				File.WriteAllBytes (Path.Combine (Root, path, "res", "drawable", "IMALLCAPS.png"), icon_binary_mdpi);
+			}
+		}
+
+		[Test]
+		public void CaseMapAllCapsWorks ()
+		{
+			var path = Path.Combine ("temp", TestName + " Some Space");
+			CreateResourceDirectory (path);
+			var task = new GenerateResourceCaseMap () {
+				BuildEngine = new MockBuildEngine (TestContext.Out)
+			};
+			task.ProjectDir = Path.Combine (Root, path);
+			task.ResourceDirectory = Path.Combine (Root, path, "res") + Path.DirectorySeparatorChar;
+			task.Resources = new TaskItem [] {
+				new TaskItem (Path.Combine (Root, path, "res", "values", "strings.xml"), new Dictionary<string, string> () {
+					{ "LogicalName", "values\\strings.xml" },
+				}),
+				new TaskItem (Path.Combine (Root, path, "res", "drawable", "IMALLCAPS.png")),
+			};
+			task.OutputFile = new TaskItem (Path.Combine (Root, path, "case_map.txt"));
+
+			Assert.IsTrue (task.Execute (), "Task should have run successfully.");
+			FileAssert.Exists (task.OutputFile.ItemSpec, $"'{task.OutputFile}' should have been created.");
+			var content1 = File.ReadAllText (task.OutputFile.ItemSpec);
+			StringAssert.Contains ($"drawable{Path.DirectorySeparatorChar}IMALLCAPS;IMALLCAPS", content1, "File should contain 'IMALLCAPS'");
+		}
+	}
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/ManagedResourceParserTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/ManagedResourceParserTests.cs
index 55737bd0610..7a6f89c90b2 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/ManagedResourceParserTests.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/ManagedResourceParserTests.cs
@@ -230,7 +230,7 @@ int string app_name 0x7f110000
 int string foo 0x7f110002
 int string hello 0x7f110003
 int string menu_settings 0x7f110004
-int[] styleable CustomFonts { 0x10100D2, 0x7F040000, 0x7F040000, 0x7F040001 }
+int[] styleable CustomFonts { 0x010100d2, 0x7f040000, 0x7f040000, 0x7f040001 }
 int styleable CustomFonts_android_scrollX 0
 int styleable CustomFonts_customFont 1
 int styleable CustomFonts_customFont 2
@@ -309,6 +309,7 @@ void BuildLibraryWithResources (string path)
 
 			var libraryStrings = library.AndroidResources.FirstOrDefault (r => r.Include () == @"Resources\values\Strings.xml");
 
+			library.SetProperty ("AndroidUseDesignerAssembly", "false");
 			library.AndroidResources.Clear ();
 			library.AndroidResources.Add (libraryStrings);
 			library.AndroidResources.Add (new AndroidItem.AndroidResource (Path.Combine ("Resources", "animator", "slide_in_bottom.xml")) { TextContent = () => Animator });
@@ -355,6 +356,25 @@ void CompareFilesIgnoreRuntimeInfoString (string file1, string file2)
 			}
 		}
 
+		GenerateResourceCaseMap CreateCaseMapTask (string path)
+		{
+			var task = new GenerateResourceCaseMap () {
+				BuildEngine = new MockBuildEngine (TestContext.Out)
+			};
+			task.ProjectDir = Path.Combine (Root, path);
+			task.ResourceDirectory = Path.Combine (Root, path, "res") + Path.DirectorySeparatorChar;
+			task.Resources = new TaskItem [] {
+				new TaskItem (Path.Combine (Root, path, "res", "values", "strings.xml"), new Dictionary<string, string> () {
+					{ "LogicalName", "values\\strings.xml" },
+				}),
+			};
+			task.AdditionalResourceDirectories = new TaskItem [] {
+				new TaskItem (Path.Combine (Root, path, "lp", "res")),
+			};
+			task.OutputFile = new TaskItem (Path.Combine (Root, path, "case_map.txt"));
+			return task;
+		}
+
 		GenerateResourceDesigner CreateTask (string path)
 		{
 			var task = new GenerateResourceDesigner {
@@ -375,6 +395,7 @@ GenerateResourceDesigner CreateTask (string path)
 			task.AdditionalResourceDirectories = new TaskItem [] {
 				new TaskItem (Path.Combine (Root, path, "lp", "res")),
 			};
+			task.CaseMapFile = Path.Combine (Root, path, "case_map.txt");
 			task.IsApplication = true;
 			task.JavaPlatformJarPath = Path.Combine (AndroidSdkDirectory, "platforms", "android-27", "android.jar");
 			return task;
@@ -400,6 +421,8 @@ public void GenerateDesignerFileWithÜmläüts ()
 		{
 			var path = Path.Combine ("temp", TestName + " Some Space");
 			CreateResourceDirectory (path);
+			var mapTask = CreateCaseMapTask (path);
+			Assert.IsTrue (mapTask.Execute (), "Map Task should have executed successfully.");
 			var task = CreateTask (path);
 			Assert.IsTrue (task.Execute (), "Task should have executed successfully.");
 			AssertResourceDesigner (task, "GenerateDesignerFileExpected.cs");
@@ -411,6 +434,8 @@ public void GenerateDesignerFileFromRtxt ([Values (false, true)] bool withLibrar
 		{
 			var path = Path.Combine ("temp", TestName + " Some Space");
 			CreateResourceDirectory (path);
+			var mapTask = CreateCaseMapTask (path);
+			Assert.IsTrue (mapTask.Execute (), "Map Task should have executed successfully.");
 			var task = CreateTask (path);
 			task.RTxtFile = Path.Combine (Root, path, "R.txt");
 			File.WriteAllText (task.RTxtFile, Rtxt);
@@ -444,6 +469,8 @@ public void UpdateLayoutIdIsIncludedInDesigner ([Values(true, false)] bool useRt
 		{
 			var path = Path.Combine ("temp", TestName + " Some Space");
 			CreateResourceDirectory (path);
+			var mapTask = CreateCaseMapTask (path);
+			Assert.IsTrue (mapTask.Execute (), "Map Task should have executed successfully.");
 			if (useRtxt)
 			    File.WriteAllText (Path.Combine (Root, path, "R.txt"), Rtxt);
 			IBuildEngine engine = new MockBuildEngine (TestContext.Out);
@@ -465,6 +492,7 @@ public void UpdateLayoutIdIsIncludedInDesigner ([Values(true, false)] bool useRt
 				new TaskItem (Path.Combine (Root, path, "lp", "res")),
 			};
 			task.ResourceFlagFile = Path.Combine (Root, path, "AndroidResgen.flag");
+			task.CaseMapFile = Path.Combine (Root, path, "case_map.txt");
 			File.WriteAllText (task.ResourceFlagFile, string.Empty);
 			task.IsApplication = true;
 			task.JavaPlatformJarPath = Path.Combine (AndroidSdkDirectory, "platforms", "android-27", "android.jar");
@@ -484,6 +512,38 @@ public void UpdateLayoutIdIsIncludedInDesigner ([Values(true, false)] bool useRt
 			Directory.Delete (Path.Combine (Root, path), recursive: true);
 		}
 
+		[Test]
+		[Category ("SmokeTests")]
+		public void RtxtGeneratorOutput ()
+		{
+			var path = Path.Combine ("temp", TestName);
+			int platform = AndroidSdkResolver.GetMaxInstalledPlatform ();
+			string resPath = Path.Combine (Root, path, "res");
+			string rTxt = Path.Combine (Root, path, "R.txt");
+			string expectedrTxt = Path.Combine (Root, path, "expectedR.txt");
+			CreateResourceDirectory (path);
+			File.WriteAllText (expectedrTxt, Rtxt);
+			List<BuildErrorEventArgs> errors = new List<BuildErrorEventArgs> ();
+			List<BuildMessageEventArgs> messages = new List<BuildMessageEventArgs> ();
+			IBuildEngine engine = new MockBuildEngine (TestContext.Out, errors: errors, messages: messages);
+			var generateRtxt = new GenerateRtxt () {
+				BuildEngine = engine,
+				RTxtFile = rTxt,
+				ResourceDirectory = resPath,
+				JavaPlatformJarPath = Path.Combine (AndroidSdkDirectory, "platforms", $"android-{platform}", "android.jar"),
+				ResourceFlagFile = Path.Combine (Root, path, "res.flag"),
+				AdditionalResourceDirectories = new string[] {
+					Path.Combine (Root, path, "lp", "res"),
+				},
+			};
+			Assert.IsTrue (generateRtxt.Execute (), "Task should have succeeded.");
+			FileAssert.Exists (rTxt, $"{rTxt} should have been created.");
+
+			CompareFilesIgnoreRuntimeInfoString (rTxt, expectedrTxt);
+
+			Directory.Delete (Path.Combine (Root, path), recursive: true);
+		}
+
 		[Test]
 		[Category ("SmokeTests")]
 		public void CompareAapt2AndManagedParserOutput ()
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs
index d773e523ceb..a8f678a4d9a 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs
@@ -12,6 +12,8 @@
 using Xamarin.ProjectTools;
 using Microsoft.Android.Build.Tasks;
 using System.Runtime.CompilerServices;
+using ICSharpCode.Decompiler;
+using ICSharpCode.Decompiler.CSharp;
 
 namespace Xamarin.Android.Build.Tests
 {
@@ -556,12 +558,37 @@ protected string GetResourceDesignerPath (ProjectBuilder builder, XamarinAndroid
 			string path;
 			if (Builder.UseDotNet) {
 				path = Path.Combine (Root, builder.ProjectDirectory, project.IntermediateOutputPath);
+				if (string.Compare (project.GetProperty ("AndroidUseDesignerAssembly"), "True", ignoreCase: true) == 0) {
+					return Path.Combine (path, "_Microsoft.Android.Resource.Designer.dll");
+				}
 			} else {
 				path = Path.Combine (Root, builder.ProjectDirectory, "Resources");
 			}
 			return Path.Combine (path, "Resource.designer" + project.Language.DefaultDesignerExtension);
 		}
 
+		protected string GetResourceDesignerText (XamarinAndroidProject project, string path)
+		{
+			if (Builder.UseDotNet) {
+				if (string.Compare (project.GetProperty ("AndroidUseDesignerAssembly"), "True", ignoreCase: true) == 0) {
+					var decompiler = new CSharpDecompiler (path, new DecompilerSettings () { });
+					return decompiler.DecompileWholeModuleAsString ();
+				}
+			}
+			return File.ReadAllText (path);
+		}
+
+		protected string[] GetResourceDesignerLines (XamarinAndroidProject project, string path)
+		{
+			if (Builder.UseDotNet) {
+				if (string.Compare (project.GetProperty ("AndroidUseDesignerAssembly"), "True", ignoreCase: true) == 0) {
+					var decompiler = new CSharpDecompiler (path, new DecompilerSettings () { });
+					return decompiler.DecompileWholeModuleAsString ().Split (Environment.NewLine[0]);
+				}
+			}
+			return File.ReadAllLines (path);
+		}
+
 		/// <summary>
 		/// Asserts that a AndroidManifest.xml file contains the expected //application/@android:extractNativeLibs value.
 		/// </summary>
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs
index 81f094ee126..462dcc7228b 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs
@@ -28,23 +28,41 @@ public class XASdkTests : BaseTest
 
 		static readonly object [] DotNetBuildLibrarySource = new object [] {
 			new object [] {
-				/* isRelease */    false,
-				/* duplicateAar */ false,
+				/* isRelease */           false,
+				/* duplicateAar */        false,
+				/* useDesignerAssembly */ false,
 			},
 			new object [] {
-				/* isRelease */    false,
-				/* duplicateAar */ true,
+				/* isRelease */           false,
+				/* duplicateAar */        true,
+				/* useDesignerAssembly */ false,
 			},
 			new object [] {
-				/* isRelease */    true,
-				/* duplicateAar */ false,
+				/* isRelease */           true,
+				/* duplicateAar */        false,
+				/* useDesignerAssembly */ false,
+			},
+			new object [] {
+				/* isRelease */           false,
+				/* duplicateAar */        false,
+				/* useDesignerAssembly */ true,
+			},
+			new object [] {
+				/* isRelease */           false,
+				/* duplicateAar */        true,
+				/* useDesignerAssembly */ true,
+			},
+			new object [] {
+				/* isRelease */           true,
+				/* duplicateAar */        false,
+				/* useDesignerAssembly */ true,
 			},
 		};
 
 		[Test]
 		[Category ("SmokeTests")]
 		[TestCaseSource (nameof (DotNetBuildLibrarySource))]
-		public void DotNetBuildLibrary (bool isRelease, bool duplicateAar)
+		public void DotNetBuildLibrary (bool isRelease, bool duplicateAar, bool useDesignerAssembly)
 		{
 			var path = Path.Combine ("temp", TestName);
 			var env_var = "MY_ENVIRONMENT_VAR";
@@ -70,6 +88,7 @@ public void DotNetBuildLibrary (bool isRelease, bool duplicateAar)
 			libC.OtherBuildItems.Add (new AndroidItem.AndroidAsset ("Assets\\bar\\bar.txt") {
 				BinaryContent = () => Array.Empty<byte> (),
 			});
+			libC.SetProperty ("AndroidUseDesignerAssembly", useDesignerAssembly.ToString ());
 			var activity = libC.Sources.FirstOrDefault (s => s.Include () == "MainActivity.cs");
 			if (activity != null)
 				libC.Sources.Remove (activity);
@@ -141,6 +160,7 @@ public Foo ()
 				BinaryContent = () => Array.Empty<byte> (),
 			});
 			libB.AddReference (libC);
+			libB.SetProperty ("AndroidUseDesignerAssembly", useDesignerAssembly.ToString ());
 
 			activity = libB.Sources.FirstOrDefault (s => s.Include () == "MainActivity.cs");
 			if (activity != null)
@@ -190,6 +210,7 @@ public Foo ()
 				// Test a duplicate @(AndroidLibrary) item with the same path of LibraryB.aar
 				appA.OtherBuildItems.Add (new AndroidItem.AndroidLibrary (aarPath));
 			}
+			appA.SetProperty ("AndroidUseDesignerAssembly", useDesignerAssembly.ToString ());
 			var appBuilder = CreateDotNetBuilder (appA, Path.Combine (path, appA.ProjectName));
 			Assert.IsTrue (appBuilder.Build (), $"{appA.ProjectName} should succeed");
 
@@ -223,11 +244,13 @@ public Foo ()
 			Assert.AreEqual (env_val, actual, $"{env_var} should be {env_val}");
 
 			// Check Resource.designer.cs
-			var resource_designer_cs = Path.Combine (intermediate, "Resource.designer.cs");
-			FileAssert.Exists (resource_designer_cs);
-			var resource_designer_text = File.ReadAllText (resource_designer_cs);
-			StringAssert.Contains ("public const int MyLayout", resource_designer_text);
-			StringAssert.Contains ("global::LibraryB.Resource.Drawable.IMALLCAPS = global::AppA.Resource.Drawable.IMALLCAPS", resource_designer_text);
+			if (!useDesignerAssembly) {
+				var resource_designer_cs = Path.Combine (intermediate, "Resource.designer.cs");
+				FileAssert.Exists (resource_designer_cs);
+				var resource_designer_text = File.ReadAllText (resource_designer_cs);
+				StringAssert.Contains ("public const int MyLayout", resource_designer_text);
+				StringAssert.Contains ("global::LibraryB.Resource.Drawable.IMALLCAPS = global::AppA.Resource.Drawable.IMALLCAPS", resource_designer_text);
+			}
 		}
 
 		[Test]
@@ -443,6 +466,7 @@ public void GenerateResourceDesigner_false()
 			};
 			// Turn off Resource.designer.cs and remove usage of it
 			proj.SetProperty ("AndroidGenerateResourceDesigner", "false");
+			proj.SetProperty ("AndroidUseDesignerAssembly", "false");
 			proj.MainActivity = proj.DefaultMainActivity
 				.Replace ("Resource.Layout.Main", "0")
 				.Replace ("Resource.Id.myButton", "0");
@@ -1037,16 +1061,18 @@ public void DotNetIncremental ([Values (true, false)] bool isRelease, [Values ("
 			};
 			appA.AddReference (libB);
 			var appBuilder = CreateDotNetBuilder (appA, Path.Combine (path, appA.ProjectName));
+			appBuilder.BuildLogFile = Path.Combine (Root, path, appA.ProjectName, "build1.log");
 			Assert.IsTrue (appBuilder.Build (runtimeIdentifier: runtimeIdentifier), $"{appA.ProjectName} should succeed");
-			appBuilder.AssertTargetIsNotSkipped ("CoreCompile");
+			appBuilder.AssertTargetIsNotSkipped ("CoreCompile", occurrence: 1);
 			if (isRelease) {
 				appBuilder.AssertTargetIsNotSkipped ("_RemoveRegisterAttribute");
 				appBuilder.AssertTargetIsNotSkipped ("_AndroidAot");
 			}
 
 			// Build again, no changes
+			appBuilder.BuildLogFile = Path.Combine (Root, path, appA.ProjectName, "build2.log");
 			Assert.IsTrue (appBuilder.Build (runtimeIdentifier: runtimeIdentifier), $"{appA.ProjectName} should succeed");
-			appBuilder.AssertTargetIsSkipped ("CoreCompile");
+			appBuilder.AssertTargetIsSkipped ("CoreCompile", occurrence: 2);
 			if (isRelease) {
 				appBuilder.AssertTargetIsSkipped ("_RemoveRegisterAttribute");
 				appBuilder.AssertTargetIsSkipped ("_AndroidAotCompilation");
@@ -1114,6 +1140,34 @@ public Foo () {
 			helper.AssertContainsEntry ($"assemblies/{libC.ProjectName}.dll");
 		}
 
+		[Test]
+		public void DotNetDesignTimeBuild ()
+		{
+			var proj = new XASdkProject ();
+			proj.SetProperty ("AndroidUseDesignerAssembly", "true");
+			var builder = CreateDotNetBuilder (proj);
+			var parameters = new [] { "BuildingInsideVisualStudio=true"};
+			builder.BuildLogFile = "update.log";
+			Assert.IsTrue (builder.Build ("Compile", parameters: parameters), $"{proj.ProjectName} should succeed");
+			builder.AssertTargetIsNotSkipped ("_GenerateResourceCaseMap", occurrence: 1);
+			builder.AssertTargetIsNotSkipped ("_GenerateRtxt");
+			builder.AssertTargetIsNotSkipped ("_GenerateResourceDesignerIntermediateClass");
+			builder.AssertTargetIsNotSkipped ("_GenerateResourceDesignerAssembly", occurrence: 1);
+			parameters = new [] { "BuildingInsideVisualStudio=true" };
+			builder.BuildLogFile = "build1.log";
+			Assert.IsTrue (builder.Build ("SignAndroidPackage", parameters: parameters), $"{proj.ProjectName} should succeed");
+			builder.AssertTargetIsNotSkipped ("_GenerateResourceCaseMap", occurrence: 2);
+			builder.AssertTargetIsSkipped ("_GenerateRtxt", occurrence: 1);
+			builder.AssertTargetIsSkipped ("_GenerateResourceDesignerIntermediateClass", occurrence: 1);
+			builder.AssertTargetIsSkipped ("_GenerateResourceDesignerAssembly", occurrence: 2);
+			builder.BuildLogFile = "build2.log";
+			Assert.IsTrue (builder.Build ("SignAndroidPackage", parameters: parameters), $"{proj.ProjectName} should succeed 2");
+			builder.AssertTargetIsNotSkipped ("_GenerateResourceCaseMap", occurrence: 3);
+			builder.AssertTargetIsSkipped ("_GenerateRtxt", occurrence: 2);
+			builder.AssertTargetIsSkipped ("_GenerateResourceDesignerIntermediateClass", occurrence: 2);
+			builder.AssertTargetIsSkipped ("_GenerateResourceDesignerAssembly");
+		}
+
 		[Test]
 		public void SignAndroidPackage ()
 		{
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Xamarin.Android.Build.Tests.csproj b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Xamarin.Android.Build.Tests.csproj
index be74e205c2d..8fab24d3966 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Xamarin.Android.Build.Tests.csproj
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Xamarin.Android.Build.Tests.csproj
@@ -59,6 +59,7 @@
 
   <ItemGroup>
     <PackageReference Include="ELFSharp" Version="$(ELFSharpVersion)" />
+    <PackageReference Include="ICSharpCode.Decompiler" Version="7.2.1.6856" />
   </ItemGroup>
 
   <ItemGroup>
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/KnownPackages.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/KnownPackages.cs
index 3cac7b400be..6fb9b090e2e 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/KnownPackages.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/KnownPackages.cs
@@ -203,11 +203,21 @@ public static class KnownPackages
 			Version = "4.7.0.1142",
 			TargetFramework = "MonoAndroid10.0",
 		};
+		public static Package XamarinForms_5_0_0_2515 = new Package {
+			Id = "Xamarin.Forms",
+			Version = "5.0.0.2515",
+			TargetFramework = "MonoAndroid10.0",
+		};
 		public static Package XamarinFormsMaps_4_7_0_1142 = new Package {
 			Id = "Xamarin.Forms.Maps",
 			Version = "4.7.0.1142",
 			TargetFramework = "MonoAndroid10.0",
 		};
+		public static Package XamarinFormsMaps_5_0_0_2515 = new Package {
+			Id = "Xamarin.Forms.Maps",
+			Version = "5.0.0.2515",
+			TargetFramework = "MonoAndroid10.0",
+		};
 		public static Package XamarinFormsMaps_4_0_0_425677 = new Package {
 			Id = "Xamarin.Forms.Maps",
 			Version = "4.0.0.425677",
@@ -474,6 +484,11 @@ public static class KnownPackages
 			Id = "Xamarin.Build.Download",
 			Version = "0.11.2",
 		};
+
+		public static Package Xamarin_Build_Download_0_11_3 = new Package {
+			Id = "Xamarin.Build.Download",
+			Version = "0.11.3",
+		};
 		// NOTE: old version required for some tests
 		public static Package Xamarin_Build_Download_0_4_11 = new Package {
 			Id = "Xamarin.Build.Download",
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidCommonProject.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidCommonProject.cs
index cb964c0963b..51a4772a395 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidCommonProject.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidCommonProject.cs
@@ -54,8 +54,12 @@ protected XamarinAndroidCommonProject (string debugConfigurationName = "Debug",
 			AndroidResources.Add (new AndroidItem.AndroidResource ("Resources\\drawable-xxhdpi\\Icon.png") { BinaryContent = () => icon_binary_xxhdpi });
 			AndroidResources.Add (new AndroidItem.AndroidResource ("Resources\\drawable-xxxhdpi\\Icon.png") { BinaryContent = () => icon_binary_xxxhdpi });
 			//AndroidResources.Add (new AndroidItem.AndroidResource ("Resources\\drawable-nodpi\\Icon.png") { BinaryContent = () => icon_binary });
+			if (Builder.UseDotNet) {
+				// set our default
+				SetProperty ("AndroidUseDesignerAssembly", "True");
+			}
 		}
-		
+
 		public override string ProjectTypeGuid {
 			get { return "FAE04EC0-301F-11D3-BF4B-00C04F79EFBC"; }
 		}
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidProjectLanguage.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidProjectLanguage.cs
index 7c77da35bbc..4365ce6bab1 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidProjectLanguage.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidProjectLanguage.cs
@@ -34,7 +34,7 @@ public override string DefaultExtension {
 				get { return ".fs"; }
 			}
 			public override string DefaultDesignerExtension {
-				get { return ".cs"; }
+				get { return Builder.UseDotNet ? ".fs" : ".cs"; }
 			}
 			public override string DefaultProjectExtension {
 				get { return ".fsproj"; }
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetCLI.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetCLI.cs
index b2f383bcedd..9b64f3d7922 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetCLI.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetCLI.cs
@@ -147,13 +147,15 @@ List<string> GetDefaultCommandLineArgs (string verb, string target = null, strin
 			if (string.IsNullOrEmpty (BuildLogFile))
 				BuildLogFile = Path.Combine (testDir, "build.log");
 
-			var binlog = string.IsNullOrEmpty (target) ? "msbuild" : target;
+			var binlog = string.IsNullOrEmpty (target) ? Path.GetFileNameWithoutExtension (string.IsNullOrEmpty (BuildLogFile) ? "msbuild" : BuildLogFile) : target;
 			var arguments = new List<string> {
 				verb,
 				$"\"{projectOrSolution}\"",
 				"/noconsolelogger",
 				$"/flp1:LogFile=\"{BuildLogFile}\";Encoding=UTF-8;Verbosity={Verbosity}",
 				$"/bl:\"{Path.Combine (testDir, $"{binlog}.binlog")}\"",
+				"-m:1",
+				"-nr:false",
 				"/p:_DisableParallelAot=true",
 			};
 			if (!string.IsNullOrEmpty (target)) {
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc
index 7ca259a29f0..d747a184fe7 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc
@@ -4,6 +4,9 @@
     "AndroidManifest.xml": {
       "Size": 3032
     },
+    "assemblies/_Microsoft.Android.Resource.Designer.dll": {
+      "Size": 1028
+    },
     "assemblies/Java.Interop.dll": {
       "Size": 58924
     },
@@ -35,7 +38,7 @@
       "Size": 3628
     },
     "classes.dex": {
-      "Size": 18968
+      "Size": 19020
     },
     "lib/arm64-v8a/libmono-component-marshal-ilgen.so": {
       "Size": 93552
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleLegacy.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleLegacy.apkdesc
index cb7562922f1..a881ffe9a94 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleLegacy.apkdesc
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleLegacy.apkdesc
@@ -5,22 +5,22 @@
       "Size": 2604
     },
     "assemblies/Java.Interop.dll": {
-      "Size": 68913
+      "Size": 68923
     },
     "assemblies/Mono.Android.dll": {
-      "Size": 265169
+      "Size": 265142
     },
     "assemblies/mscorlib.dll": {
-      "Size": 769018
+      "Size": 769035
     },
     "assemblies/System.Core.dll": {
-      "Size": 28199
+      "Size": 28216
     },
     "assemblies/System.dll": {
-      "Size": 9180
+      "Size": 9191
     },
     "assemblies/UnnamedProject.dll": {
-      "Size": 2882
+      "Size": 2896
     },
     "classes.dex": {
       "Size": 370828
@@ -32,7 +32,7 @@
       "Size": 750976
     },
     "lib/arm64-v8a/libmonodroid.so": {
-      "Size": 332936
+      "Size": 333128
     },
     "lib/arm64-v8a/libmonosgen-2.0.so": {
       "Size": 4039176
@@ -41,7 +41,7 @@
       "Size": 66184
     },
     "lib/arm64-v8a/libxamarin-app.so": {
-      "Size": 21256
+      "Size": 21248
     },
     "META-INF/ANDROIDD.RSA": {
       "Size": 1213
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc
index 87875ce958d..6ae5c9740f2 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc
@@ -4,6 +4,9 @@
     "AndroidManifest.xml": {
       "Size": 3568
     },
+    "assemblies/_Microsoft.Android.Resource.Designer.dll": {
+      "Size": 1945
+    },
     "assemblies/FormsViewGroup.dll": {
       "Size": 7314
     },
@@ -185,10 +188,10 @@
       "Size": 528450
     },
     "assemblies/Xamarin.Forms.Platform.Android.dll": {
-      "Size": 384799
+      "Size": 337827
     },
     "assemblies/Xamarin.Forms.Platform.dll": {
-      "Size": 56878
+      "Size": 11087
     },
     "assemblies/Xamarin.Forms.Xaml.dll": {
       "Size": 60774
@@ -197,7 +200,7 @@
       "Size": 40159
     },
     "classes.dex": {
-      "Size": 3090508
+      "Size": 3141008
     },
     "lib/arm64-v8a/libmono-component-marshal-ilgen.so": {
       "Size": 93552
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsLegacy.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsLegacy.apkdesc
index ac496de717d..6e7516a240e 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsLegacy.apkdesc
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsLegacy.apkdesc
@@ -4,116 +4,119 @@
     "AndroidManifest.xml": {
       "Size": 3140
     },
+    "assemblies/_Microsoft.Android.Resource.Designer.dll": {
+      "Size": 133020
+    },
     "assemblies/FormsViewGroup.dll": {
-      "Size": 7215
+      "Size": 7230
     },
     "assemblies/Java.Interop.dll": {
-      "Size": 69956
+      "Size": 69966
     },
     "assemblies/Mono.Android.dll": {
-      "Size": 572709
+      "Size": 572672
     },
     "assemblies/Mono.Security.dll": {
-      "Size": 68432
+      "Size": 68450
     },
     "assemblies/mscorlib.dll": {
-      "Size": 915408
+      "Size": 915425
     },
     "assemblies/System.Core.dll": {
-      "Size": 164046
+      "Size": 164059
     },
     "assemblies/System.dll": {
-      "Size": 388864
+      "Size": 388883
     },
     "assemblies/System.Drawing.Common.dll": {
-      "Size": 12365
+      "Size": 12370
     },
     "assemblies/System.Net.Http.dll": {
-      "Size": 110693
+      "Size": 110718
     },
     "assemblies/System.Numerics.dll": {
-      "Size": 15683
+      "Size": 15705
     },
     "assemblies/System.Runtime.Serialization.dll": {
-      "Size": 186660
+      "Size": 186683
     },
     "assemblies/System.ServiceModel.Internals.dll": {
-      "Size": 26594
+      "Size": 26604
     },
     "assemblies/System.Xml.dll": {
-      "Size": 395656
+      "Size": 395668
     },
     "assemblies/UnnamedProject.dll": {
-      "Size": 116899
+      "Size": 116994
     },
     "assemblies/Xamarin.AndroidX.Activity.dll": {
-      "Size": 7697
+      "Size": 7711
     },
     "assemblies/Xamarin.AndroidX.AppCompat.AppCompatResources.dll": {
-      "Size": 6648
+      "Size": 6664
     },
     "assemblies/Xamarin.AndroidX.AppCompat.dll": {
-      "Size": 125328
+      "Size": 125346
     },
     "assemblies/Xamarin.AndroidX.CardView.dll": {
-      "Size": 7367
+      "Size": 7380
     },
     "assemblies/Xamarin.AndroidX.CoordinatorLayout.dll": {
-      "Size": 18272
+      "Size": 18289
     },
     "assemblies/Xamarin.AndroidX.Core.dll": {
-      "Size": 131930
+      "Size": 131944
     },
     "assemblies/Xamarin.AndroidX.DrawerLayout.dll": {
-      "Size": 15426
+      "Size": 15444
     },
     "assemblies/Xamarin.AndroidX.Fragment.dll": {
-      "Size": 43135
+      "Size": 43150
     },
     "assemblies/Xamarin.AndroidX.Legacy.Support.Core.UI.dll": {
-      "Size": 6715
+      "Size": 6728
     },
     "assemblies/Xamarin.AndroidX.Lifecycle.Common.dll": {
-      "Size": 7062
+      "Size": 7078
     },
     "assemblies/Xamarin.AndroidX.Lifecycle.LiveData.Core.dll": {
-      "Size": 7193
+      "Size": 7207
     },
     "assemblies/Xamarin.AndroidX.Lifecycle.ViewModel.dll": {
-      "Size": 4873
+      "Size": 4886
     },
     "assemblies/Xamarin.AndroidX.Loader.dll": {
-      "Size": 13585
+      "Size": 13596
     },
     "assemblies/Xamarin.AndroidX.RecyclerView.dll": {
-      "Size": 102327
+      "Size": 102349
     },
     "assemblies/Xamarin.AndroidX.SavedState.dll": {
-      "Size": 6268
+      "Size": 6294
     },
     "assemblies/Xamarin.AndroidX.SwipeRefreshLayout.dll": {
-      "Size": 11271
+      "Size": 11284
     },
     "assemblies/Xamarin.AndroidX.ViewPager.dll": {
-      "Size": 19424
+      "Size": 19438
     },
     "assemblies/Xamarin.Forms.Core.dll": {
-      "Size": 524736
+      "Size": 524743
     },
     "assemblies/Xamarin.Forms.Platform.Android.dll": {
-      "Size": 384872
+      "Size": 384885
     },
     "assemblies/Xamarin.Forms.Platform.dll": {
       "Size": 56878
     },
     "assemblies/Xamarin.Forms.Xaml.dll": {
-      "Size": 55801
+      "Size": 55807
     },
     "assemblies/Xamarin.Google.Android.Material.dll": {
-      "Size": 43497
+      "Size": 43514
     },
     "classes.dex": {
-      "Size": 3482812
+      "Size": 3533300
     },
     "lib/arm64-v8a/libmono-btls-shared.so": {
       "Size": 1613872
@@ -122,7 +125,7 @@
       "Size": 750976
     },
     "lib/arm64-v8a/libmonodroid.so": {
-      "Size": 332936
+      "Size": 333128
     },
     "lib/arm64-v8a/libmonosgen-2.0.so": {
       "Size": 4039176
@@ -131,7 +134,7 @@
       "Size": 66184
     },
     "lib/arm64-v8a/libxamarin-app.so": {
-      "Size": 107024
+      "Size": 107144
     },
     "META-INF/android.support.design_material.version": {
       "Size": 12
@@ -140,7 +143,7 @@
       "Size": 1213
     },
     "META-INF/ANDROIDD.SF": {
-      "Size": 75858
+      "Size": 75981
     },
     "META-INF/androidx.activity_activity.version": {
       "Size": 6
@@ -251,7 +254,7 @@
       "Size": 10
     },
     "META-INF/MANIFEST.MF": {
-      "Size": 75731
+      "Size": 75854
     },
     "META-INF/proguard/androidx-annotations.pro": {
       "Size": 339
@@ -1883,5 +1886,5 @@
       "Size": 341040
     }
   },
-  "PackageSize": 9521310
+  "PackageSize": 9672959
 }
\ No newline at end of file
diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/FileResourceParser.cs b/src/Xamarin.Android.Build.Tasks/Utilities/FileResourceParser.cs
new file mode 100644
index 00000000000..73168a69c01
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/FileResourceParser.cs
@@ -0,0 +1,389 @@
+using System;
+using System.CodeDom;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Xml;
+using System.Xml.Linq;
+using System.Xml.XPath;
+using System.Text;
+using System.Text.RegularExpressions;
+using Microsoft.Build.Utilities;
+using Microsoft.Android.Build.Tasks;
+
+namespace Xamarin.Android.Tasks
+{
+	class FileResourceParser : ResourceParser
+	{
+		public string JavaPlatformDirectory { get; set; }
+
+		public string ResourceFlagFile { get; set; }
+
+		Dictionary<R, R []> arrayMapping = new Dictionary<R, R []> ();
+		Dictionary<string, List<string>> foofoo = new Dictionary<string, List<string>> ();
+		List<string> custom_types = new List<string> ();
+		XDocument publicXml;
+
+		string[] publicXmlFiles = new string[] {
+			"public.xml",
+			"public-final.xml",
+			"public-staging.xml",
+		};
+
+		protected XDocument LoadPublicXml () {
+			string publicXmlPath = Path.Combine (JavaPlatformDirectory, "data", "res", "values");
+			foreach (var file in publicXmlFiles) {
+				if (File.Exists (Path.Combine (publicXmlPath, file))) {
+					return XDocument.Load (Path.Combine (publicXmlPath, file));
+				}
+			}
+			return null;
+		}
+
+		public IList<R> Parse (string resourceDirectory, IEnumerable<string> additionalResourceDirectories, Dictionary<string, string> resourceMap)
+		{
+			Log.LogDebugMessage ($"Parsing Directory {resourceDirectory}");
+			string publicXmlPath = Path.Combine (JavaPlatformDirectory, "data", "res", "values");
+			publicXml = LoadPublicXml ();
+			var result = new List<R> ();
+			Dictionary<string, ICollection<R>> resources = new Dictionary<string, ICollection<R>> ();
+			foreach (var knownType in RtxtParser.knownTypes) {
+				if (knownType == "styleable") {
+					resources.Add (knownType, new List<R> ());
+					continue;
+				}
+				resources.Add (knownType, new SortedSet<R> (new RComparer ()));
+			}
+			foreach (var dir in Directory.EnumerateDirectories (resourceDirectory, "*", SearchOption.TopDirectoryOnly)) {
+				foreach (var file in Directory.EnumerateFiles (dir, "*.*", SearchOption.AllDirectories)) {
+					ProcessResourceFile (file, resources);
+				}
+			}
+			foreach (var dir in additionalResourceDirectories ?? Array.Empty<string>()) {
+				Log.LogDebugMessage ($"Processing Directory {dir}");
+				if (Directory.Exists (dir)) {
+					foreach (var file in Directory.EnumerateFiles (dir, "*.*", SearchOption.AllDirectories)) {
+						ProcessResourceFile (file, resources);
+					}
+				} else {
+					Log.LogDebugMessage ($"Skipping non-existent directory: {dir}");
+				}
+			}
+
+			// now generate the Id's we need in a specific order
+			List<string> declarationIds = new List<string> ();
+			declarationIds.Add ("attr");
+			declarationIds.Add ("drawable");
+			declarationIds.Add ("mipmap");
+			declarationIds.Add ("font");
+			declarationIds.Add ("layout");
+			declarationIds.Add ("anim");
+			declarationIds.Add ("animator");
+			declarationIds.Add ("transition");
+			declarationIds.Add ("xml");
+			declarationIds.Add ("raw");
+			declarationIds.Add ("dimen");
+			declarationIds.Add ("string");
+			declarationIds.Add ("array");
+			declarationIds.Add ("plurals");
+			declarationIds.Add ("bool");
+			declarationIds.Add ("color");
+			declarationIds.Add ("integer");
+			declarationIds.Add ("menu");
+			declarationIds.Add ("id");
+			// custom types
+			foreach (var customClass in custom_types) {
+				declarationIds.Add (customClass);
+			}
+
+			declarationIds.Add ("interpolator");
+			declarationIds.Add ("style");
+			declarationIds.Add ("styleable");
+
+			declarationIds.Sort ((a, b) => {
+				return string.Compare (a, b, StringComparison.OrdinalIgnoreCase);
+			});
+
+			string itemPackageId = "0x7f";
+			int typeid = 1;
+
+			foreach (var t in declarationIds) {
+				int itemid = 0;
+				if (!resources.ContainsKey(t)) {
+					continue;
+				}
+				if (resources[t].Count () == 0) {
+					continue;
+				}
+				foreach (R r in resources[t].OrderBy(x => x.ToSortedString(), StringComparer.Ordinal)) {
+
+					int id = Convert.ToInt32 (itemPackageId + typeid.ToString ("X2") + itemid.ToString ("X4"), fromBase: 16);
+					if (r.Type == RType.Integer && r.Id == -1) {
+						itemid++;
+						r.UpdateId (id);
+					} else {
+						if (foofoo.ContainsKey (r.Identifier)) {
+							var items = foofoo[r.Identifier];
+							if (r.Ids != null) {
+								// do something special cos its an array we need to replace *some* its.
+								int[] newIds = new int[r.Ids.Length];
+								for (int i = 0; i < r.Ids.Length; i++) {
+									// we need to lookup the ID's for these from the ones generated.
+									newIds[i] = r.Ids[i];
+									if (r.Ids[i] == -1)
+										newIds[i] = GetId (result, items[i]);
+								}
+								r.UpdateIds (newIds);
+							}
+						}
+					}
+					result.Add (r);
+				}
+				typeid++;
+			}
+
+			result.Sort (new RComparer ());
+
+			return result;
+		}
+
+		class RComparer : IComparer<R> {
+			public int Compare(R a, R b) {
+				return string.Compare (a.ToSortedString (), b.ToSortedString (), StringComparison.Ordinal);
+			}
+		}
+
+		HashSet<string> resourceNamesToUseDirectly = new HashSet<string> () {
+			"integer-array",
+			"string-array",
+			"declare-styleable",
+			"add-resource",
+		};
+
+		int GetId (ICollection<R> resources, string identifier)
+		{
+			foreach (R r in resources) {
+				if (r.Identifier == identifier) {
+					return r.Id;
+				}
+			}
+			return -1;
+		}
+
+		void ProcessResourceFile (string file, Dictionary<string, ICollection<R>> resources)
+		{
+			Log.LogDebugMessage ($"{nameof(ProcessResourceFile)} {file}");
+			var fileName = Path.GetFileNameWithoutExtension (file);
+			if (string.IsNullOrEmpty (fileName))
+				return;
+			if (fileName.EndsWith (".9", StringComparison.OrdinalIgnoreCase))
+				fileName = Path.GetFileNameWithoutExtension (fileName);
+			var path = Directory.GetParent (file).Name;
+			var ext = Path.GetExtension (file);
+			switch (ext) {
+				case ".xml":
+				case ".axml":
+					if (string.Compare (path, "raw", StringComparison.OrdinalIgnoreCase) == 0)
+						goto default;
+					try {
+						ProcessXmlFile (file, resources);
+					} catch (XmlException ex) {
+						Log.LogCodedWarning ("XA1000", Properties.Resources.XA1000, file, ex);
+					}
+					break;
+				default:
+					break;
+			}
+			CreateResourceField (path, fileName, resources);
+		}
+
+		void CreateResourceField (string root, string id, Dictionary<string, ICollection<R>> resources) {
+			var i = root.IndexOf ('-');
+			var item = i < 0 ? root : root.Substring (0, i);
+			item = resourceNamesToUseDirectly.Contains (root) ? root : item;
+			switch (item.ToLowerInvariant ()) {
+				case "animation":
+					item = "anim";
+					break;
+				case "array":
+				case "string-array":
+				case "integer-array":
+					item = "array";
+					break;
+				case "enum":
+				case "flag":
+					item = "id";
+					break;
+			}
+			var r = new R () {
+				ResourceTypeName = item,
+				Identifier = id,
+				Id = -1,
+			};
+			if (!resources.ContainsKey (item)) {
+				Log.LogDebugMessage ($"Ignoring path:{item}");
+				return;
+			}
+			resources[item].Add (r);
+		}
+
+		void ProcessStyleable (XmlReader reader, Dictionary<string, ICollection<R>> resources)
+		{
+			Log.LogDebugMessage ($"{nameof(ProcessStyleable)}");
+			string topName = null;
+			int fieldCount = 0;
+			List<R> fields = new List<R> ();
+			List<string> attribs = new List<string> ();
+			if (reader.HasAttributes) {
+				while (reader.MoveToNextAttribute ()) {
+					if (reader.Name.Replace ("android:", "") == "name")
+						topName = reader.Value;
+				}
+			}
+			while (reader.Read ()) {
+				if (reader.NodeType == XmlNodeType.Whitespace || reader.NodeType == XmlNodeType.Comment)
+					continue;
+				string name = null;
+				if (string.IsNullOrEmpty (topName)) {
+					if (reader.HasAttributes) {
+						while (reader.MoveToNextAttribute ()) {
+							if (reader.Name.Replace ("android:", "") == "name")
+								topName = reader.Value;
+						}
+					}
+				}
+				if (!reader.IsStartElement ())
+					continue;
+				if (reader.HasAttributes) {
+					while (reader.MoveToNextAttribute ()) {
+						if (reader.Name.Replace ("android:", "") == "name")
+							name = reader.Value;
+					}
+				}
+				reader.MoveToElement ();
+				if (reader.LocalName == "attr") {
+					attribs.Add (name);
+				}
+			}
+			var field = new R () {
+				ResourceTypeName = "styleable",
+				Identifier = topName,
+				Type = RType.Array,
+			};
+			if (!arrayMapping.ContainsKey (field)) {
+				foofoo.Add (field.Identifier, new List<string> ());
+				attribs.Sort (StringComparer.OrdinalIgnoreCase);
+				for (int i = 0; i < attribs.Count; i++) {
+					string name = attribs [i];
+					if (!name.StartsWith ("android:", StringComparison.OrdinalIgnoreCase)) {
+						var r = new R () {
+							ResourceTypeName = "attr",
+							Identifier = $"{name}",
+							Id = -1,
+						};
+						resources [r.ResourceTypeName].Add (r);
+						fields.Add (r);
+					} else {
+						// this is an android:xxx resource, we should not calculate the id
+						// we should get it from "somewhere" maybe the pubic.xml
+						name = name.Replace ("android:", string.Empty);
+						var element = publicXml?.XPathSelectElement ($"/resources/public[@name='{name}']") ?? null;
+						int value = Convert.ToInt32 (element?.Attribute ("id")?.Value ?? "0x0", fromBase: 16);
+						var r = new R () {
+							ResourceTypeName = "attr",
+							Identifier = $"{name}",
+							Id = value,
+						};
+						fields.Add (r);
+					}
+				}
+				if (field.Type != RType.Array)
+					return;
+				arrayMapping.Add (field, fields.ToArray ());
+
+				field.Ids = new int [attribs.Count];
+				for (int idx =0; idx < field.Ids.Length; idx++)
+					field.Ids[idx] = fields[idx].Id;
+				resources [field.ResourceTypeName].Add (field);
+				int id = 0;
+				foreach (string r in attribs) {
+					foofoo[field.Identifier].Add (r.Replace (":", "_"));
+					resources [field.ResourceTypeName].Add (new R () {
+						ResourceTypeName = field.ResourceTypeName,
+						Identifier = $"{field.Identifier}_{r.Replace (":", "_")}",
+						Id = id++,
+					});
+				}
+			}
+		}
+
+		void ProcessXmlFile (string file, Dictionary<string, ICollection<R>> resources)
+		{
+			Log.LogDebugMessage ($"{nameof(ProcessXmlFile)}");
+			using (var reader = XmlReader.Create (file)) {
+				while (reader.Read ()) {
+					if (reader.NodeType == XmlNodeType.Whitespace || reader.NodeType == XmlNodeType.Comment)
+						continue;
+					if (reader.IsStartElement ()) {
+						var elementName = reader.Name;
+						if (elementName == "declare-styleable" || elementName == "configVarying" || elementName == "add-resource") {
+							ProcessStyleable (reader.ReadSubtree (), resources);
+							continue;
+						}
+						if (reader.HasAttributes) {
+							string name = null;
+							string type = null;
+							string id = null;
+							string custom_id = null;
+							while (reader.MoveToNextAttribute ()) {
+								if (reader.LocalName == "name")
+									name = reader.Value;
+								if (reader.LocalName == "type")
+									type = reader.Value;
+								if (reader.LocalName == "id") {
+									string[] values = reader.Value.Split ('/');
+									if (values.Length != 2) {
+										id = reader.Value.Replace ("@+id/", "").Replace ("@id/", "");
+									} else {
+										if (values [0] != "@+id" && values [0] != "@id" && !values [0].Contains ("android:")) {
+											custom_id = values [0].Replace ("@", "").Replace ("+", "");
+										}
+										id = values [1];
+									}
+
+								}
+								if (reader.LocalName == "inflatedId") {
+									string inflateId = reader.Value.Replace ("@+id/", "").Replace ("@id/", "");
+									var r = new R () {
+										ResourceTypeName = "id",
+										Identifier = inflateId,
+										Id = -1,
+									};
+									Log.LogDebugMessage ($"Adding 1 {r}");
+									resources[r.ResourceTypeName].Add (r);
+								}
+							}
+							if (name?.Contains ("android:") ?? false)
+								continue;
+							if (id?.Contains ("android:") ?? false)
+								continue;
+							// Move the reader back to the element node.
+							reader.MoveToElement ();
+							if (!string.IsNullOrEmpty (name)) {
+								CreateResourceField (type ?? elementName, name, resources);
+							}
+							if (!string.IsNullOrEmpty (custom_id) && !resources.ContainsKey (custom_id)) {
+								resources.Add (custom_id, new SortedSet<R> (new RComparer ()));
+								custom_types.Add (custom_id);
+							}
+							if (!string.IsNullOrEmpty (id)) {
+								CreateResourceField (custom_id ?? "id", id.Replace ("-", "_").Replace (".", "_"), resources);
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ManagedResourceParser.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ManagedResourceParser.cs
index fa735737a36..bcb01245334 100644
--- a/src/Xamarin.Android.Build.Tasks/Utilities/ManagedResourceParser.cs
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/ManagedResourceParser.cs
@@ -14,7 +14,7 @@
 
 namespace Xamarin.Android.Tasks
 {
-	class ManagedResourceParser : ResourceParser
+	class ManagedResourceParser : FileResourceParser
 	{
 		class CompareTuple : IComparer<(int Key, CodeMemberField Value)>
 		{
@@ -37,10 +37,6 @@ public int Compare((int Key, CodeMemberField Value) x, (int Key, CodeMemberField
 
 		XDocument publicXml;
 
-		public string JavaPlatformDirectory { get; set; }
-
-		public string ResourceFlagFile { get; set; }
-
 		void SortMembers (CodeTypeDeclaration decl, StringComparison stringComparison = StringComparison.OrdinalIgnoreCase)
 		{
 			CodeTypeMember [] members = new CodeTypeMember [decl.Members.Count];
@@ -87,10 +83,7 @@ public CodeTypeDeclaration Parse (string resourceDirectory, string rTxtFile, IEn
 			transition = CreateClass ("Transition");
 			xml = CreateClass ("Xml");
 
-			string publicXmlPath = Path.Combine (JavaPlatformDirectory, "data", "res", "values", "public.xml");
-			if (File.Exists (publicXmlPath)) {
-				publicXml = XDocument.Load (publicXmlPath);
-			}
+			publicXml = LoadPublicXml ();
 
 			var resModifiedDate = !string.IsNullOrEmpty (ResourceFlagFile) && File.Exists (ResourceFlagFile)
 				? File.GetLastWriteTimeUtc (ResourceFlagFile)
@@ -296,104 +289,17 @@ public CodeTypeDeclaration Parse (string resourceDirectory, string rTxtFile, IEn
 
 		void ProcessRtxtFile (string file)
 		{
-			var lines = System.IO.File.ReadLines (file);
-			int lineNumber = 0;
-			foreach (var line in lines) {
-				lineNumber++;
-				var items = line.Split (new char [] { ' ' }, 4);
-				if (items.Length < 4) {
-					Log.LogDebugMessage ($"'{file}:{lineNumber}' ignoring contents '{line}', it does not have the correct number of elements.");
-					continue;
-				}
-				int value = items [1] != "styleable" ? Convert.ToInt32 (items [3], 16) : -1;
-				string itemName = items [2];
-				switch (items [1]) {
-				case "anim":
-					CreateIntField (animation, itemName, value);
-					break;
-				case "animator":
-					CreateIntField (animator, itemName, value);
-					break;
-				case "attr":
-					CreateIntField (attrib, itemName, value);
-					break;
-				case "array":
-					CreateIntField (arrays, itemName, value);
-					break;
-				case "bool":
-					CreateIntField (boolean, itemName, value);
-					break;
-				case "color":
-					CreateIntField (colors, itemName, value);
-					break;
-				case "dimen":
-					CreateIntField (dimension, itemName, value);
-					break;
-				case "drawable":
-					CreateIntField (drawable, itemName, value);
-					break;
-				case "font":
-					CreateIntField (font, itemName, value);
-					break;
-				case "id":
-					CreateIntField (ids, itemName, value);
-					break;
-				case "integer":
-					CreateIntField (ints, itemName, value);
-					break;
-				case "interpolator":
-					CreateIntField (interpolators, itemName, value);
-					break;
-				case "layout":
-					CreateIntField (layout, itemName, value);
-					break;
-				case "menu":
-					CreateIntField (menu, itemName, value);
-					break;
-				case "mipmap":
-					CreateIntField (mipmaps, itemName, value);
-					break;
-				case "plurals":
-					CreateIntField (plurals, itemName, value);
-					break;
-				case "raw":
-					CreateIntField (raw, itemName, value);
-					break;
-				case "string":
-					CreateIntField (strings, itemName, value);
-					break;
-				case "style":
-					CreateIntField (style, itemName, value);
-					break;
-				case "styleable":
-					switch (items [0]) {
-					case "int":
-						CreateIntField (styleable, itemName, Convert.ToInt32 (items [3], 10));
+			var parser = new RtxtParser ();
+			var resources = parser.Parse (file, Log, map);
+			foreach (var r in resources) {
+				var cl = CreateClass (r.ResourceTypeName);
+				switch (r.Type) {
+					case RType.Integer:
+						CreateIntField (cl, r.Identifier, r.Id);
 						break;
-					case "int[]":
-						var arrayValues = items [3].Trim (new char [] { '{', '}' })
-							.Replace (" ", "")
-							.Split (new char [] { ',' });
-						CreateIntArrayField (styleable, itemName, arrayValues.Length,
-							arrayValues.Select (x => string.IsNullOrEmpty (x) ? -1 : Convert.ToInt32 (x, 16)).ToArray ());
+					case RType.Array:
+						CreateIntArrayField (cl, r.Identifier, r.Ids.Length, r.Ids);
 						break;
-					}
-					break;
-				case "transition":
-					CreateIntField (transition, itemName, value);
-					break;
-				case "xml":
-					CreateIntField (xml, itemName, value);
-					break;
-				// for custom views
-				default:
-					CodeTypeDeclaration customClass;
-					if (!custom_types.TryGetValue (items [1], out customClass)) {
-							customClass = CreateClass (items [1]);
-							custom_types.Add (items [1], customClass);
-					}
-					CreateIntField (customClass, itemName, value);
-					break;
 				}
 			}
 		}
@@ -441,15 +347,22 @@ CodeTypeDeclaration CreateResourceClass ()
 			return decl;
 		}
 
+		Dictionary<string, CodeTypeDeclaration> classMapping = new Dictionary<string, CodeTypeDeclaration> (StringComparer.OrdinalIgnoreCase);
+
 		CodeTypeDeclaration CreateClass (string type)
 		{
-			var t = new CodeTypeDeclaration (ResourceParser.GetNestedTypeName (type)) {
+			var typeName = ResourceParser.GetNestedTypeName (type);
+			if (classMapping.ContainsKey (typeName)) {
+				return classMapping [typeName];
+			}
+			var t = new CodeTypeDeclaration (typeName) {
 				IsPartial = true,
 				TypeAttributes = TypeAttributes.Public,
 			};
 			t.Members.Add (new CodeConstructor () {
 				Attributes = MemberAttributes.Private,
 			});
+			classMapping.Add (typeName, t);
 			return t;
 		}
 
@@ -608,7 +521,6 @@ void CreateResourceField (string root, string fieldName, XmlReader element = nul
 		void ProcessStyleable (XmlReader reader)
 		{
 			string topName = null;
-			int fieldCount = 0;
 			List<CodeMemberField> fields = new List<CodeMemberField> ();
 			List<string> attribs = new List<string> ();
 			while (reader.Read ()) {
diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs b/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs
index 5e41b62be37..19088a10f6b 100644
--- a/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs
@@ -325,6 +325,28 @@ public static bool HasMonoAndroidReference (MetadataReader reader)
 			return false;
 		}
 
+		public static bool HasResourceDesignerAssemblyReference (ITaskItem assembly)
+		{
+			if (!File.Exists (assembly.ItemSpec)) {
+				return false;
+			}
+			using var pe = new PEReader (File.OpenRead (assembly.ItemSpec));
+			var reader = pe.GetMetadataReader ();
+			return HasResourceDesignerAssemblyReference (reader);
+		}
+
+		public static bool HasResourceDesignerAssemblyReference (MetadataReader reader)
+		{
+			foreach (var handle in reader.AssemblyReferences) {
+				var reference = reader.GetAssemblyReference (handle);
+				var name = reader.GetString (reference.Name);
+				if (string.CompareOrdinal (name, "_Microsoft.Android.Resource.Designer") == 0) {
+					return true;
+				}
+			}
+			return false;
+		}
+
 		public static bool IsReferenceAssembly (string assembly)
 		{
 			using (var stream = File.OpenRead (assembly))
@@ -388,12 +410,26 @@ internal static IEnumerable<ITaskItem> GetFrameworkAssembliesToTreatAsUserAssemb
 		}
 #endif
 
-		public static Dictionary<string, string> LoadAcwMapFile (string acwPath)
+		public static bool SaveMapFile (IBuildEngine4 engine, string mapFile, Dictionary<string, string> map)
 		{
-			var acw_map = new Dictionary<string, string> ();
-			if (!File.Exists (acwPath))
+			engine?.RegisterTaskObjectAssemblyLocal (mapFile, map, RegisteredTaskObjectLifetime.Build);
+			using (var writer = MemoryStreamPool.Shared.CreateStreamWriter ()) {
+				foreach (var i in map.OrderBy (x => x.Key)) {
+					writer.WriteLine ($"{i.Key};{i.Value}");
+				}
+				writer.Flush ();
+				return Files.CopyIfStreamChanged (writer.BaseStream, mapFile);
+			}
+		}
+		public static Dictionary<string, string> LoadMapFile (IBuildEngine4 engine, string mapFile, StringComparer comparer)
+		{
+			var cachedMap = engine?.GetRegisteredTaskObjectAssemblyLocal<Dictionary<string, string>> (mapFile, RegisteredTaskObjectLifetime.Build);
+			if (cachedMap != null)
+				return cachedMap;
+			var acw_map = new Dictionary<string, string> (comparer);
+			if (!File.Exists (mapFile))
 				return acw_map;
-			foreach (var s in File.ReadLines (acwPath)) {
+			foreach (var s in File.ReadLines (mapFile)) {
 				var items = s.Split (new char[] { ';' }, count: 2);
 				if (!acw_map.ContainsKey (items [0]))
 					acw_map.Add (items [0], items [1]);
diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ResourceDesignerImportGenerator.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ResourceDesignerImportGenerator.cs
index 8e7ddacfd3e..d9bcf2ecf69 100644
--- a/src/Xamarin.Android.Build.Tasks/Utilities/ResourceDesignerImportGenerator.cs
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/ResourceDesignerImportGenerator.cs
@@ -47,6 +47,7 @@ public void CreateImportMethods (IEnumerable<ITaskItem> libraries)
 					var reader = pe.GetMetadataReader ();
 					var resourceDesignerName = GetResourceDesignerClass (reader);
 					if (string.IsNullOrEmpty (resourceDesignerName)) {
+						Log.LogDebugMessage ($"Could not find 'ResourceDesignerAttribute' in {assemblyPath}");
 						continue;
 					}
 					string aliasMetaData = assemblyPath.GetMetadata ("Aliases");
diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ResourceIdentifier.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ResourceIdentifier.cs
index eb96d4f5aa0..7edfc38faf5 100644
--- a/src/Xamarin.Android.Build.Tasks/Utilities/ResourceIdentifier.cs
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/ResourceIdentifier.cs
@@ -6,6 +6,7 @@
 using System.Linq;
 using System.Reflection;
 using System.Text.RegularExpressions;
+using Microsoft.Android.Build.Tasks;
 using Microsoft.Build.Utilities;
 
 namespace Xamarin.Android.Tasks
@@ -42,5 +43,20 @@ public static string CreateValidIdentifier (string identifier)
 
 			return result;
 		}
+
+		internal static string GetResourceName (string type, string name, Dictionary<string, string> map, TaskLoggingHelper log)
+		{
+			string mappedValue;
+			string key = string.Format ("{0}{1}{2}", type, Path.DirectorySeparatorChar, name).ToLowerInvariant ();
+
+			if (map.TryGetValue (key, out mappedValue)) {
+				log.LogDebugMessage ("  - Remapping resource: {0}.{1} -> {2}", type, name, mappedValue);
+				return ResourceIdentifier.CreateValidIdentifier (mappedValue.Substring (mappedValue.LastIndexOf (Path.DirectorySeparatorChar) + 1));
+			}
+
+			log.LogDebugMessage ("  - Not remapping resource: {0}.{1}", type, name);
+
+			return ResourceIdentifier.CreateValidIdentifier (name);
+		}
 	}
-}
\ No newline at end of file
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ResourceParser.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ResourceParser.cs
index d85b97299e9..64cedf71129 100644
--- a/src/Xamarin.Android.Build.Tasks/Utilities/ResourceParser.cs
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/ResourceParser.cs
@@ -40,17 +40,7 @@ internal static string GetNestedTypeName (string name)
 
 		internal string GetResourceName (string type, string name, Dictionary<string, string> map)
 		{
-			string mappedValue;
-			string key = string.Format ("{0}{1}{2}", type, Path.DirectorySeparatorChar, name).ToLowerInvariant ();
-
-			if (map.TryGetValue (key, out mappedValue)) {
-				Log.LogDebugMessage ("  - Remapping resource: {0}.{1} -> {2}", type, name, mappedValue);
-				return ResourceIdentifier.CreateValidIdentifier (mappedValue.Substring (mappedValue.LastIndexOf (Path.DirectorySeparatorChar) + 1));
-			}
-
-			Log.LogDebugMessage ("  - Not remapping resource: {0}.{1}", type, name);
-
-			return ResourceIdentifier.CreateValidIdentifier (name);
+			return ResourceIdentifier.GetResourceName (type, name, map, Log);
 		}
 
 	}
diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/RtxtParser.cs b/src/Xamarin.Android.Build.Tasks/Utilities/RtxtParser.cs
new file mode 100644
index 00000000000..4584601c1b5
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/RtxtParser.cs
@@ -0,0 +1,156 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Microsoft.Android.Build.Tasks;
+using Microsoft.Build.Utilities;
+
+namespace Xamarin.Android.Tasks
+{
+	public enum RType {
+		Integer,
+		Array,
+	}
+	public enum ResourceType {
+		System,
+		Custom,
+	}
+	public struct R : IComparable<R> {
+		public RType Type;
+		public int Id;
+		public int [] Ids;
+		public string Identifier;
+		public string ResourceTypeName;
+		public ResourceType ResourceType;
+
+		public string Key => $"{ResourceTypeName}:{Identifier}";
+
+		public override string ToString ()
+		{
+			if (Type == RType.Integer) {
+				if (ResourceTypeName == "styleable")
+					return $"int {ResourceTypeName} {Identifier} {Id}";
+				return $"int {ResourceTypeName} {Identifier} 0x{Id.ToString ("x8")}";
+			}
+			return $"int[] {ResourceTypeName} {Identifier} {{ {String.Join (", ", Ids.Select (x => $"0x{x.ToString ("x8")}"))} }}";
+		}
+
+		public string ToSortedString ()
+		{
+			return $"{ResourceTypeName}_{Identifier}";
+		}
+
+		public int CompareTo(R other)
+		{
+			return String.Compare (ToSortedString (), other.ToSortedString (), StringComparison.OrdinalIgnoreCase);
+		}
+
+		public void UpdateId (int newId)
+		{
+			Id = newId;
+		}
+
+		public void UpdateIds (int [] newIds)
+		{
+			Ids = newIds;
+		}
+	}
+
+	public class RtxtParser {
+
+		static readonly char[] EmptyChar = new char [] { ' ' };
+		static readonly char[] CurlyBracketsChar = new char [] { '{', '}' };
+		static readonly char[] CommaChar = new char [] { ',' };
+
+		TaskLoggingHelper log;
+		Dictionary<string, string> map;
+
+		public static HashSet<string> knownTypes = new HashSet<string> () {
+			"anim",
+			"animator",
+			"attr",
+			"array",
+			"bool",
+			"color",
+			"dimen",
+			"drawable",
+			"font",
+			"id",
+			"integer",
+			"interpolator",
+			"layout",
+			"menu",
+			"mipmap",
+			"plurals",
+			"raw",
+			"string",
+			"style",
+			"styleable",
+			"transition",
+			"xml",
+		};
+
+		public IEnumerable<R> Parse (string file, TaskLoggingHelper logger, Dictionary<string, string> mapping)
+		{
+			log = logger;
+			map = mapping;
+			var result = new List<R> ();
+			if (File.Exists (file))
+				ProcessRtxtFile (file, result);
+			return result;
+		}
+
+		void ProcessRtxtFile (string file, IList<R> result)
+		{
+			int lineNumber = 0;
+			foreach (var line in File.ReadLines (file)) {
+				lineNumber++;
+				var items = line.Split (EmptyChar, 4);
+				if (items.Length < 4) {
+					log.LogDebugMessage ($"'{file}:{lineNumber}' ignoring contents '{line}', it does not have the correct number of elements.");
+					continue;
+				}
+				int value = items [1] != "styleable" ? Convert.ToInt32 (items [3], 16) : -1;
+				string itemName = ResourceIdentifier.GetResourceName(items [1], items [2], map, log);
+				if (knownTypes.Contains (items [1])) {
+					if (items [1] != "styleable") {
+						result.Add (new R () {
+							ResourceTypeName = items [1],
+							Identifier = itemName,
+							Id = value,
+						});
+						continue;
+					}
+					switch (items [0]) {
+						case "int":
+							result.Add (new R () {
+								ResourceTypeName = items [1],
+								Identifier = itemName,
+								Id = Convert.ToInt32 (items [3], 10),
+							});
+							break;
+						case "int[]":
+							var arrayValues = items [3].Trim (CurlyBracketsChar)
+								.Replace (" ", "")
+								.Split (CommaChar);
+
+							result.Add (new R () {
+								ResourceTypeName = items [1],
+								Type = RType.Array,
+								Identifier = itemName,
+								Ids = arrayValues.Select (x => string.IsNullOrEmpty (x) ? -1 : Convert.ToInt32 (x, 16)).ToArray (),
+							});
+							break;
+					}
+
+				}
+				result.Add (new R () {
+					ResourceTypeName = items[1],
+					ResourceType = ResourceType.Custom,
+					Identifier = itemName,
+					Id = value,
+				});
+			}
+		}
+	}
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/RtxtWriter.cs b/src/Xamarin.Android.Build.Tasks/Utilities/RtxtWriter.cs
new file mode 100644
index 00000000000..cc2e7a70991
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/RtxtWriter.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Linq;
+using Microsoft.Android.Build.Tasks;
+using Microsoft.Build.Utilities;
+
+namespace Xamarin.Android.Tasks
+{
+	/// Write a list of Item to a file
+	///
+	public class RtxtWriter {
+		public void Write (string file, IList<R> items)
+		{
+			var sb = new StringBuilder ();
+			foreach (var item in items) {
+				sb.AppendLine (item.ToString ());
+			}
+			Files.CopyIfStringChanged (sb.ToString (), file);
+		}
+	}
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj
index ee9e29a5c39..dd902240461 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj
@@ -348,6 +348,12 @@
     <Compile Include="..\..\src-ThirdParty\android-platform-tools-base\SymbolWriter.cs">
       <Link>Utilities\%(Filename)%(Extension)</Link>
     </Compile>
+    <Compile Include="..\..\src-ThirdParty\Mono.Security.Cryptography\CryptoConvert.cs">
+      <Link>Utilities\%(Filename)%(Extension)</Link>
+    </Compile>
+    <Compile Include="..\..\src-ThirdParty\StrongNameSigner\SigningHelper.cs">
+      <Link>Utilities\%(Filename)%(Extension)</Link>
+    </Compile>
   </ItemGroup>
 
   <ItemGroup>
@@ -407,6 +413,9 @@
     <EmbeddedResource Include="..\Mono.Android\java\mono\android\TypeManager.java">
       <LogicalName>JavaInteropTypeManager.java</LogicalName>
     </EmbeddedResource>
+    <EmbeddedResource Include="Resources\Resource.Designer.snk">
+      <LogicalName>Resource.Designer.snk</LogicalName>
+    </EmbeddedResource>
   </ItemGroup>
 
   <ItemGroup>
diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets
index 7cb21493b26..cd4782e7bba 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets
@@ -88,6 +88,10 @@
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
       <Link>Xamarin.Android.Designer.targets</Link>
     </None>
+    <None Include="MSBuild\Xamarin\Android\Xamarin.Android.Resource.Designer.targets">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+      <Link>Xamarin.Android.Resource.Designer.targets</Link>
+    </None>
     <None Include="MSBuild\Xamarin\Android\Xamarin.Android.Aapt.targets">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
       <Link>Xamarin.Android.Aapt.targets</Link>
diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
index af4d1456749..8be69cc1c2c 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
@@ -57,6 +57,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
 <UsingTask TaskName="Xamarin.Android.Tasks.GenerateLibraryResources" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
 <UsingTask TaskName="Xamarin.Android.Tasks.GenerateManagedAidlProxies" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
 <UsingTask TaskName="Xamarin.Android.Tasks.GenerateResourceDesigner" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
+<UsingTask TaskName="Xamarin.Android.Tasks.GenerateResourceDesignerAssembly" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
 <UsingTask TaskName="Xamarin.Android.Tasks.GenerateJavaStubs" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
 <UsingTask TaskName="Xamarin.Android.Tasks.GeneratePackageManagerJava" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
 <UsingTask TaskName="Xamarin.Android.Tasks.GetAndroidDefineConstants" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
@@ -375,6 +376,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
 <Import Project="$(MSBuildThisFileDirectory)Xamarin.Android.DesignTime.targets" />
 <Import Project="$(MSBuildThisFileDirectory)Xamarin.Android.EmbeddedResource.targets" />
 <Import Project="$(MSBuildThisFileDirectory)Xamarin.Android.Javac.targets" />
+<Import Project="$(MSBuildThisFileDirectory)Xamarin.Android.Resource.Designer.targets" />
 <Import Project="$(MSBuildThisFileDirectory)Xamarin.Android.SkipCases.projitems" />
 <Import Project="$(MSBuildThisFileDirectory)Xamarin.Android.Tooling.targets" />
 <Import Project="$(MSBuildThisFileDirectory)Xamarin.Android.Legacy.targets" Condition=" '$(UsingAndroidNETSdk)' != 'True' " />
@@ -574,11 +576,11 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
 </Target>
 
 <Target Name="_RemoveLegacyDesigner"
-		Condition=" '$(Language)' == 'C#' and '$(AndroidUseIntermediateDesignerFile)' == 'true' and '$(ManagedDesignTimeBuild)' != 'true' ">
+		Condition=" '$(Language)' == 'C#' and '$(ManagedDesignTimeBuild)' != 'true' ">
 	<ItemGroup>
 		<CorrectCasedItem Include="%(Compile.Identity)" Condition="'%(Compile.Identity)' == '$(AndroidResgenFile)'"/>
 		<Compile Remove="@(CorrectCasedItem)" Condition=" '$(AndroidResgenFile)' != '' "/>
-		<Compile Include="$(_AndroidResourceDesignerFile)" />
+		<Compile Include="$(_AndroidResourceDesignerFile)" Condition=" '$(AndroidUseDesignerAssembly)' != 'true' " />
 	</ItemGroup>
 </Target>
 
@@ -998,6 +1000,7 @@ because xbuild doesn't support framework reference assemblies.
 		<_PropertyCacheItems Include="AndroidSupportedAbis=$(AndroidSupportedAbis)" />
 		<_PropertyCacheItems Include="AndroidManifestPlaceholders=$(AndroidManifestPlaceholders)" />
 		<_PropertyCacheItems Include="ProjectFullPath=$(MSBuildProjectFullPath)" />
+		<_PropertyCacheItems Include="AndroidUseDesignerAssembly=$(AndroidUseDesignerAssembly)" />
 	</ItemGroup>
 	<WriteLinesToFile
 			File="$(_AndroidBuildPropertiesCache)"
@@ -1038,10 +1041,10 @@ because xbuild doesn't support framework reference assemblies.
 </Target>
 
 <!-- Managed DesignTime Resource Generation -->
-<Target Name="_ManagedUpdateAndroidResgen" Condition=" '$(ManagedDesignTimeBuild)' == 'True' "
+<Target Name="_ManagedUpdateAndroidResgen" Condition=" '$(ManagedDesignTimeBuild)' == 'True' And  '$(AndroidUseDesignerAssembly)' != 'True' "
 		Inputs="$(_ManagedUpdateAndroidResgenInputs)"
 		Outputs="$(_AndroidManagedResourceDesignerFile)"
-		DependsOnTargets="_CreatePropertiesCache;_ExtractLibraryProjectImports;_ValidateAndroidPackageProperties;_BeforeManagedUpdateAndroidResgen">
+		DependsOnTargets="_CreatePropertiesCache;_ExtractLibraryProjectImports;_ValidateAndroidPackageProperties;_GenerateResourceCaseMap;_BeforeManagedUpdateAndroidResgen">
 	<MakeDir Directories="$(_AndroidIntermediateDesignTimeBuildDirectory)" />
 	<!-- Parse primary R.java and create Resources.Designer.cs -->
 	<GenerateResourceDesigner
@@ -1060,6 +1063,7 @@ because xbuild doesn't support framework reference assemblies.
 		DesignTimeBuild="$(DesignTimeBuild)"
 		JavaPlatformJarPath="$(JavaPlatformJarPath)"
 		ResourceFlagFile="$(_AndroidResFlagFile)"
+		CaseMapFile="$(_GenerateResourceCaseMapFile)"
 		Condition="Exists ('$(MonoAndroidResourcePrefix)')"
 	/>
 	<Touch Condition="Exists ('$(_AndroidManagedResourceDesignerFile)')" Files="$(_AndroidManagedResourceDesignerFile)" />
@@ -1080,11 +1084,11 @@ because xbuild doesn't support framework reference assemblies.
 
 <Target Name="UpdateAndroidResources"
     Condition=" '$(DesignTimeBuild)' != 'True' Or '$(DeferredBuildSupported)' != 'True' Or '$(DeferredBuild)' == 'True' "
-    DependsOnTargets="_SetupDesignTimeBuildForCompile;_ManagedUpdateAndroidResgen;_UpdateAndroidResources"
+    DependsOnTargets="_SetupDesignTimeBuildForCompile;_ManagedUpdateAndroidResgen;_BuildResourceDesigner;_UpdateAndroidResources"
 />
 
 <!-- Handle a case where the designer file has been deleted, but the flag file still exists -->
-<Target Name="_CheckForDeletedResourceFile">
+<Target Name="_CheckForDeletedResourceFile" Condition=" '$(AndroidUseDesignerAssembly)' != 'True' ">
 	<Delete Files="$(_AndroidResgenFlagFile)"
 		Condition="Exists ('$(_AndroidResgenFlagFile)') AND '$(_AndroidResourceDesignerFile)' != '' AND !Exists('$(_AndroidResourceDesignerFile)')" />
 </Target>
@@ -1244,6 +1248,7 @@ because xbuild doesn't support framework reference assemblies.
 		_GenerateAndroidResourceDir;
 		_IncludeLayoutBindingSources;
 		_DefineBuildTargetAbis;
+		_GenerateResourceCaseMap;
 	</_UpdateAndroidResgenDependsOnTargets>
 	<_UpdateAndroidResgenInputs>
 		@(_AndroidMSBuildAllProjects);
@@ -1265,7 +1270,7 @@ because xbuild doesn't support framework reference assemblies.
 	<CallTarget Targets="_UpdateAndroidResgenAapt2" Condition=" '$(AndroidUseAapt2)' == 'true' " />
 
 	<GenerateLibraryResources
-		Condition=" '$(_AndroidResourceDesignerFile)' != '' And Exists('$(IntermediateOutputPath)R.txt') "
+		Condition=" ('$(_AndroidResourceDesignerFile)' != '' Or '$(AndroidUseDesignerAssembly)' == 'True') And Exists('$(IntermediateOutputPath)R.txt') "
 		ResourceSymbolsTextFile="$(IntermediateOutputPath)R.txt"
 		OutputDirectory="$(_AndroidIntermediateJavaSourceDirectory)"
 		LibraryTextFiles="@(LibraryResourceDirectories->'%(Identity)\..\R.txt')"
@@ -1288,7 +1293,7 @@ because xbuild doesn't support framework reference assemblies.
 
   <!-- Parse primary R.java and create Resources.Designer.cs -->
 	<GenerateResourceDesigner
-		Condition="'$(_AndroidResourceDesignerFile)' != ''"
+		Condition="'$(_AndroidResourceDesignerFile)' != '' And '$(AndroidUseDesignerAssembly)' != 'True' "
 		ContinueOnError="$(DesignTimeBuild)"
 		NetResgenOutputFile="$(_AndroidResourceDesignerFile)"
 		DesignTimeOutputFile="$(_AndroidManagedResourceDesignerFile)"
@@ -1304,18 +1309,42 @@ because xbuild doesn't support framework reference assemblies.
 		UseManagedResourceGenerator="$(_UseManagedResourceGenerator)"
 		DesignTimeBuild="$(DesignTimeBuild)"
 		JavaPlatformJarPath="$(JavaPlatformJarPath)"
+		CaseMapFile="$(_GenerateResourceCaseMapFile)"
 	/>
+	<!-- Generate the final Resource Assembly if we need to. -->
+	<GenerateResourceDesignerAssembly
+			Condition="'$(AndroidUseDesignerAssembly)' == 'True' "
+			ContinueOnError="$(DesignTimeBuild)"
+			RTxtFile="$(IntermediateOutputPath)R.txt"
+			IsApplication="$(AndroidApplication)"
+			DesignTimeBuild="$(DesignTimeBuild)"
+			Deterministic="$(Deterministic)"
+			OutputFile="$(_GenerateResourceDesignerAssemblyOutput)"
+			TargetFrameworkIdentifier="$(TargetFrameworkIdentifier)"
+			TargetFrameworkVersion="$(TargetFrameworkVersion)"
+			ProjectDir="$(ProjectDir)"
+			Resources="@(AndroidResource);@(AndroidBoundLayout)"
+			ResourceDirectory="$(MonoAndroidResourcePrefix)"
+			CaseMapFile="$(_GenerateResourceCaseMapFile)"
+			FrameworkDirectories="$(_XATargetFrameworkDirectories);$(_XATargetFrameworkDirectories)Facades"
+			AdditionalResourceDirectories="@(LibraryResourceDirectories)"
+			AssemblyName="$(AssemblyName)"
+	>
+	</GenerateResourceDesignerAssembly>
+	<ItemGroup>
+		<FileWrites Include="$(_GenerateResourceDesignerAssemblyOutput)" />
+	</ItemGroup>
 
-  <!-- Delete our temporary directory -->
-  <RemoveDirFixed
-      Directories="$(ResgenTemporaryDirectory)"
-      ContinueOnError="WarnAndContinue"
-  />
+	<!-- Delete our temporary directory -->
+	<RemoveDirFixed
+			Directories="$(ResgenTemporaryDirectory)"
+			ContinueOnError="WarnAndContinue"
+	/>
 
-  <Touch Files="$(_AndroidResgenFlagFile)" AlwaysCreate="True" />
-  <ItemGroup>
-    <FileWrites Include="$(_AndroidResgenFlagFile)" />
-  </ItemGroup>
+	<Touch Files="$(_AndroidResgenFlagFile)" AlwaysCreate="True" />
+	<ItemGroup>
+		<FileWrites Include="$(_AndroidResgenFlagFile)" />
+	</ItemGroup>
 </Target>
 
 <!-- AIDL Build -->
@@ -1460,6 +1489,7 @@ because xbuild doesn't support framework reference assemblies.
       DestinationFiles="@(ResolvedAssemblies->'$(MonoAndroidIntermediateAssemblyDir)%(DestinationSubPath)')"
       TargetName="$(TargetName)"
       AddKeepAlives="$(AndroidAddKeepAlives)"
+      UseDesignerAssembly="$(AndroidUseDesignerAssembly)"
       Deterministic="$(Deterministic)"
       UsingAndroidNETSdk="$(UsingAndroidNETSdk)"
   />
diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.DesignTime.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.DesignTime.targets
index 2102d915d28..00f3f2cfdd5 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.DesignTime.targets
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.DesignTime.targets
@@ -42,6 +42,7 @@ This file is used by all project types, including binding projects.
     <PropertyGroup>
       <DesignTimeBuild Condition=" '$(DesignTimeBuild)' == '' ">true</DesignTimeBuild>
       <ManagedDesignTimeBuild Condition=" '$(AndroidGenerateResourceDesigner)' == 'True' And '$(AndroidUseManagedDesignTimeResourceGenerator)' == 'true' And '$(DesignTimeBuild)' == 'true' And '$(BuildingInsideVisualStudio)' == 'true' ">true</ManagedDesignTimeBuild>
+      <ManagedDesignTimeBuild Condition=" '$(ManagedDesignTimeBuild)' == '' And '$(DesignTimeBuild)' == 'True' And '$(AndroidUseDesignerAssembly)' == 'True' " >True</ManagedDesignTimeBuild>
       <ManagedDesignTimeBuild Condition=" '$(ManagedDesignTimeBuild)' == '' ">False</ManagedDesignTimeBuild>
       <_AndroidLibraryImportsCache Condition=" '$(DesignTimeBuild)' == 'true' And !Exists ('$(_AndroidLibraryImportsCache)') ">$(_AndroidLibraryImportsDesignTimeCache)</_AndroidLibraryImportsCache>
       <_AndroidLibraryProjectImportsCache Condition=" '$(DesignTimeBuild)' == 'true' And !Exists ('$(_AndroidLibraryProjectImportsCache)') ">$(_AndroidLibraryProjectImportsDesignTimeCache)</_AndroidLibraryProjectImportsCache>
diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Legacy.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Legacy.targets
index b08a0d94736..800cabe865b 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Legacy.targets
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Legacy.targets
@@ -108,8 +108,8 @@ projects. .NET 5 projects will not import this file.
     </CoreResolveReferencesDependsOn>
     <ResolveReferencesDependsOn>
       $(CoreResolveReferencesDependsOn);
-      UpdateAndroidInterfaceProxies;
       UpdateAndroidResources;
+      UpdateAndroidInterfaceProxies;
     </ResolveReferencesDependsOn>
     <DeferredBuildDependsOn>
       $(DeferredBuildDependsOn);
@@ -300,6 +300,10 @@ projects. .NET 5 projects will not import this file.
           Include="$(OutDir)$(TargetFileName)"
           Condition="Exists ('$(OutDir)$(TargetFileName)')"
       />
+      <FilteredAssemblies
+          Include="$(_GenerateResourceDesignerAssemblyOutput)"
+          Condition="Exists ('$(_GenerateResourceDesignerAssemblyOutput)')"
+      />
       <FilteredAssemblies
           Include="@(ReferenceCopyLocalPaths)"
           Condition="'%(ReferenceCopyLocalPaths.ResolvedFrom)' != 'ImplicitlyExpandDesignTimeFacades' And '%(ReferenceCopyLocalPaths.Extension)' == '.dll' And '%(ReferenceCopyLocalPaths.RelativeDir)' == '' And Exists('%(ReferenceCopyLocalPaths.Identity)') "
@@ -656,6 +660,7 @@ projects. .NET 5 projects will not import this file.
         ProguardConfiguration="$(_ProguardProjectConfiguration)"
         AddKeepAlives="$(AndroidAddKeepAlives)"
         LinkResources="$(AndroidLinkResources)"
+        UseDesignerAssembly="$(AndroidUseDesignerAssembly)"
         PreserveJniMarshalMethods="$(AndroidGenerateJniMarshalMethods)"
         EnableProguard="$(AndroidEnableProguard)"
         Deterministic="$(Deterministic)"
diff --git a/tests/MSBuildDeviceIntegration/MSBuildDeviceIntegration.csproj b/tests/MSBuildDeviceIntegration/MSBuildDeviceIntegration.csproj
index 2aebfdb3f47..d6bb578c27b 100644
--- a/tests/MSBuildDeviceIntegration/MSBuildDeviceIntegration.csproj
+++ b/tests/MSBuildDeviceIntegration/MSBuildDeviceIntegration.csproj
@@ -36,6 +36,7 @@
   <ItemGroup>
     <PackageReference Include="NodaTime" Version="2.4.5" />
     <PackageReference Include="MSBuild.StructuredLogger" Version="2.1.758" />
+    <PackageReference Include="ICSharpCode.Decompiler" Version="7.2.1.6856" />
   </ItemGroup>
 
   <ItemGroup>
diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs
index f79b85b3222..53188b11db7 100644
--- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs
+++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs
@@ -706,6 +706,67 @@ public void RunWithLLVMEnabled ()
 				Path.Combine (Root, builder.ProjectDirectory, "startup-logcat.log")));
 		}
 
+		[Test]
+		public void ResourceDesignerWithNuGetReference ([Values ("net6.0-android32.0", "net7.0-android33.0")] string dotnetTargetFramework)
+		{
+			AssertHasDevices ();
+
+			string path = Path.Combine (Root, "temp", TestName);
+
+			if (!Builder.UseDotNet) {
+				Assert.Ignore ("Skipping. Test not relevant under Classic.");
+			}
+			// Build a NuGet Package
+			var nuget = new XASdkProject (outputType: "Library") {
+				Sdk = "Xamarin.Legacy.Sdk/0.2.0-alpha2",
+				ProjectName = "Test.Nuget.Package",
+				IsRelease = true,
+				ExtraNuGetConfigSources = {
+					// Projects targeting net6.0 require ref/runtime packs on NuGet.org
+					"https://api.nuget.org/v3/index.json",
+					"https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6/nuget/v3/index.json",
+				},
+			};
+			nuget.Sources.Clear ();
+			nuget.Sources.Add (new AndroidItem.AndroidResource ("Resources/values/Strings.xml") {
+						TextContent = () => @"<resources>
+    <string name='library_resouce_from_nuget'>Library Resource From Nuget</string>
+</resources>",
+			});
+			nuget.SetProperty ("PackageName", "Test.Nuget.Package");
+			var legacyTargetFrameworkVersion = "13.0";
+			var legacyTargetFramework = $"monoandroid{legacyTargetFrameworkVersion}";
+			nuget.SetProperty ("TargetFramework",  value: "");
+			nuget.SetProperty ("TargetFrameworks", value: $"{dotnetTargetFramework};{legacyTargetFramework}");
+
+			string directory = Path.Combine ("temp", TestName, "Test.Nuget.Package");
+			var dotnet = CreateDotNetBuilder (nuget, directory);
+			Assert.IsTrue (dotnet.Pack (), "`dotnet pack` should succeed");
+
+			// Build an app which references it.
+			var proj = new XamarinAndroidApplicationProject () {
+				IsRelease = true,
+			};
+			proj.SetAndroidSupportedAbis ("armeabi-v7a", "x86", "x86_64");
+			proj.OtherBuildItems.Add (new BuildItem ("None", "NuGet.config") {
+				TextContent = () => @"<?xml version='1.0' encoding='utf-8'?>
+<configuration>
+  <packageSources>
+	<add key='local' value='" + Path.Combine (Root, directory, "bin", "Release") + @"' />
+  </packageSources>
+</configuration>",
+			});
+			proj.PackageReferences.Add (new Package {
+					Id = "Test.Nuget.Package",
+					Version = "1.0.0",
+				});
+			builder = CreateApkBuilder (Path.Combine (path, proj.ProjectName));
+			Assert.IsTrue (builder.Install (proj, doNotCleanupOnUpdate: true), "Install should have succeeded.");
+			string resource_designer = GetResourceDesignerPath (builder, proj);
+			var contents = GetResourceDesignerText (proj, resource_designer);
+			StringAssert.Contains ("public const int library_resouce_from_nuget =", contents);
+		}
+
 		[Test]
 		public void SingleProject_ApplicationId ()
 		{
@@ -841,5 +902,30 @@ public MyLayout (Android.Content.Context context, Android.Util.IAttributeSet att
 				Path.Combine (Root, builder.ProjectDirectory, "startup-logcat.log"));
 			Assert.IsTrue (didStart, "Activity should have started.");
 		}
+
+		DotNetCLI CreateDotNetBuilder (string relativeProjectDir = null)
+		{
+			if (string.IsNullOrEmpty (relativeProjectDir)) {
+				relativeProjectDir = Path.Combine ("temp", TestName);
+			}
+			string fullProjectDirectory = Path.Combine (Root, relativeProjectDir);
+			TestOutputDirectories [TestContext.CurrentContext.Test.ID] = fullProjectDirectory;
+
+			new XASdkProject ().CopyNuGetConfig (relativeProjectDir);
+			return new DotNetCLI (Path.Combine (fullProjectDirectory, $"{TestName}.csproj"));
+		}
+
+		DotNetCLI CreateDotNetBuilder (XASdkProject project, string relativeProjectDir = null)
+		{
+			if (string.IsNullOrEmpty (relativeProjectDir)) {
+				relativeProjectDir = Path.Combine ("temp", TestName);
+			}
+			string fullProjectDirectory = Path.Combine (Root, relativeProjectDir);
+			TestOutputDirectories [TestContext.CurrentContext.Test.ID] = fullProjectDirectory;
+			var files = project.Save ();
+			project.Populate (relativeProjectDir, files);
+			project.CopyNuGetConfig (relativeProjectDir);
+			return new DotNetCLI (project, Path.Combine (fullProjectDirectory, project.ProjectFilePath));
+		}
 	}
 }
diff --git a/tests/MSBuildDeviceIntegration/Tests/InstantRunTest.cs b/tests/MSBuildDeviceIntegration/Tests/InstantRunTest.cs
index d3ff4f02248..6605cba3a8d 100644
--- a/tests/MSBuildDeviceIntegration/Tests/InstantRunTest.cs
+++ b/tests/MSBuildDeviceIntegration/Tests/InstantRunTest.cs
@@ -56,6 +56,7 @@ public void TargetsSkipped ([Values(false, true)] bool useManagedResourceGenerat
 				UseLatestPlatformSdk = true,
 			};
 			proj.SetProperty ("AndroidUseManagedDesignTimeResourceGenerator", useManagedResourceGenerator.ToString ());
+			proj.SetProperty ("AndroidUseDesignerAssembly", "False");
 			var b = CreateApkBuilder ($"temp/InstantRunTargetsSkipped_{useManagedResourceGenerator}", cleanupOnDispose: false);
 			Assert.IsTrue (b.Build (proj), "1 build should have succeeded.");
 
diff --git a/tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.csproj b/tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.csproj
index 84fbd2ae182..80c5cb93874 100644
--- a/tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.csproj
+++ b/tests/Mono.Android-Tests/Java.Interop-Tests/Java.Interop-Tests.csproj
@@ -59,6 +59,7 @@
   </ItemGroup>
   <ItemGroup>
     <Compile Include="$(MSBuildThisFileDirectory)..\..\..\external\Java.Interop\tests\Java.Interop-Tests\**\*.cs" />
+    <Compile Remove="$(MSBuildThisFileDirectory)..\..\..\external\Java.Interop\tests\Java.Interop-Tests\obj\*.cs" />
     <Compile Remove="$(MSBuildThisFileDirectory)..\..\..\external\Java.Interop\tests\Java.Interop-Tests\Java.Interop\JavaVMFixture.cs" />
     <Compile Remove="$(MSBuildThisFileDirectory)..\..\..\external\Java.Interop\tests\Java.Interop-Tests\Java.Interop\JniReferenceSafeHandleTest.cs" />
   </ItemGroup>
diff --git a/tests/Mono.Android-Tests/Mono.Android-Test.Shared.projitems b/tests/Mono.Android-Tests/Mono.Android-Test.Shared.projitems
index 16b42acd14b..185f6e9fe7c 100644
--- a/tests/Mono.Android-Tests/Mono.Android-Test.Shared.projitems
+++ b/tests/Mono.Android-Tests/Mono.Android-Test.Shared.projitems
@@ -13,7 +13,6 @@
   </ItemGroup>
   <ItemGroup>
     <Compile Include="$(MSBuildThisFileDirectory)System.Linq\LinqExpressionTest.cs" />
-    <Compile Include="$(MSBuildThisFileDirectory)Resources\Resource.designer.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Properties\AssemblyInfo.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Android.App\ApplicationTest.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Android.Content.Res\AssetManagerTest.cs" />
diff --git a/tests/Mono.Android-Tests/Mono.Android-Tests.csproj b/tests/Mono.Android-Tests/Mono.Android-Tests.csproj
index 1d4a287f573..f976680d4e3 100644
--- a/tests/Mono.Android-Tests/Mono.Android-Tests.csproj
+++ b/tests/Mono.Android-Tests/Mono.Android-Tests.csproj
@@ -29,6 +29,7 @@
     <_ASANScript>..\..\build-tools\wrap.sh\asan.sh</_ASANScript>
     <_UBSANScript>..\..\build-tools\wrap.sh\ubsan.sh</_UBSANScript>
     <_MonoAndroidTestPackage>Mono.Android_Tests</_MonoAndroidTestPackage>
+    <AndroidUseIntermediateDesignerFile>True</AndroidUseIntermediateDesignerFile>
   </PropertyGroup>
   <Import Project="Mono.Android-Test.Shared.projitems" Label="Shared" Condition="Exists('Mono.Android-Test.Shared.projitems')" />
   <Import Project="..\..\Configuration.props" />
diff --git a/tests/Mono.Android-Tests/Runtime-MultiDex/Mono.Android-TestsMultiDex.csproj b/tests/Mono.Android-Tests/Runtime-MultiDex/Mono.Android-TestsMultiDex.csproj
index 848607e2899..b7146ae1ca7 100644
--- a/tests/Mono.Android-Tests/Runtime-MultiDex/Mono.Android-TestsMultiDex.csproj
+++ b/tests/Mono.Android-Tests/Runtime-MultiDex/Mono.Android-TestsMultiDex.csproj
@@ -24,6 +24,7 @@
     <_SkipJniAddNativeMethodRegistrationAttributeScan>True</_SkipJniAddNativeMethodRegistrationAttributeScan>
     <_MonoAndroidTestPackage>Mono.Android_TestsMultiDex</_MonoAndroidTestPackage>
     <PlotDataLabelSuffix>-MultiDex</PlotDataLabelSuffix>
+    <AndroidUseIntermediateDesignerFile>True</AndroidUseIntermediateDesignerFile>
   </PropertyGroup>
   <Import Project="..\Mono.Android-Test.Shared.projitems" Label="Shared" Condition="Exists('..\Mono.Android-Test.Shared.projitems')" />
   <Import Project="..\..\..\Configuration.props" />
@@ -67,7 +68,6 @@
     <None Include="Resources\AboutResources.txt" />
     <None Include="Assets\AboutAssets.txt" />
     <Compile Remove="..\Resources\Resource.designer.cs" />
-    <Compile Include="Resources\Resource.designer.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
   <ItemGroup>

From 1d11baee2313c2620d61722698add29dd1ff8875 Mon Sep 17 00:00:00 2001
From: Dean Ellis <dellis1972@googlemail.com>
Date: Wed, 7 Dec 2022 17:05:07 +0000
Subject: [PATCH 02/18] Fix test failures

---
 src/Xamarin.Android.Build.Tasks/Utilities/RtxtParser.cs     | 2 +-
 .../Xamarin.Android.Common.targets                          | 6 ++++--
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/RtxtParser.cs b/src/Xamarin.Android.Build.Tasks/Utilities/RtxtParser.cs
index 4584601c1b5..6b3d1fd9470 100644
--- a/src/Xamarin.Android.Build.Tasks/Utilities/RtxtParser.cs
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/RtxtParser.cs
@@ -142,7 +142,7 @@ void ProcessRtxtFile (string file, IList<R> result)
 							});
 							break;
 					}
-
+					continue;
 				}
 				result.Add (new R () {
 					ResourceTypeName = items[1],
diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
index 8be69cc1c2c..717ecc87fb2 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
@@ -578,8 +578,10 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
 <Target Name="_RemoveLegacyDesigner"
 		Condition=" '$(Language)' == 'C#' and '$(ManagedDesignTimeBuild)' != 'true' ">
 	<ItemGroup>
-		<CorrectCasedItem Include="%(Compile.Identity)" Condition="'%(Compile.Identity)' == '$(AndroidResgenFile)'"/>
-		<Compile Remove="@(CorrectCasedItem)" Condition=" '$(AndroidResgenFile)' != '' "/>
+		<CorrectCasedItem Include="%(Compile.Identity)" Condition=" '$(AndroidResgenFile)' != '' And '%(Compile.Identity)' == '$(AndroidResgenFile)'"/>
+		<!-- Forcably Remove the old Resource.designer.cs even if the AndroidResgenFile is not set.-->
+		<CorrectCasedItem Include="%(Compile.Identity)" Condition=" '$(AndroidUseDesignerAssembly)' == 'True' And '%(Compile.Filename)%(Compile.Extension)' == '$(_AndroidResourceDesigner)' "/>
+		<Compile Remove="@(CorrectCasedItem)" />
 		<Compile Include="$(_AndroidResourceDesignerFile)" Condition=" '$(AndroidUseDesignerAssembly)' != 'true' " />
 	</ItemGroup>
 </Target>

From 66b433a8ea5a07a52fbe309c36aa02dac706886f Mon Sep 17 00:00:00 2001
From: Dean Ellis <dellis1972@googlemail.com>
Date: Thu, 8 Dec 2022 11:02:41 +0000
Subject: [PATCH 03/18] Fix failing test

---
 src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
index 717ecc87fb2..4a07b87e4b4 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
@@ -582,7 +582,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
 		<!-- Forcably Remove the old Resource.designer.cs even if the AndroidResgenFile is not set.-->
 		<CorrectCasedItem Include="%(Compile.Identity)" Condition=" '$(AndroidUseDesignerAssembly)' == 'True' And '%(Compile.Filename)%(Compile.Extension)' == '$(_AndroidResourceDesigner)' "/>
 		<Compile Remove="@(CorrectCasedItem)" />
-		<Compile Include="$(_AndroidResourceDesignerFile)" Condition=" '$(AndroidUseDesignerAssembly)' != 'true' " />
+		<Compile Include="$(_AndroidResourceDesignerFile)" Condition=" '$(AndroidUseIntermediateDesignerFile)' == 'true' And '$(AndroidUseDesignerAssembly)' != 'true' " />
 	</ItemGroup>
 </Target>
 

From a3077557ac80c5acc335e2965436e2af80127d12 Mon Sep 17 00:00:00 2001
From: Dean Ellis <dellis1972@googlemail.com>
Date: Thu, 8 Dec 2022 13:20:16 +0000
Subject: [PATCH 04/18] Fix make all-tests

---
 src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
index 4a07b87e4b4..14418bb0e23 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
@@ -578,7 +578,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
 <Target Name="_RemoveLegacyDesigner"
 		Condition=" '$(Language)' == 'C#' and '$(ManagedDesignTimeBuild)' != 'true' ">
 	<ItemGroup>
-		<CorrectCasedItem Include="%(Compile.Identity)" Condition=" '$(AndroidResgenFile)' != '' And '%(Compile.Identity)' == '$(AndroidResgenFile)'"/>
+		<CorrectCasedItem Include="%(Compile.Identity)" Condition=" '$(AndroidUseIntermediateDesignerFile)' == 'true' And '$(AndroidResgenFile)' != '' And '%(Compile.Identity)' == '$(AndroidResgenFile)'"/>
 		<!-- Forcably Remove the old Resource.designer.cs even if the AndroidResgenFile is not set.-->
 		<CorrectCasedItem Include="%(Compile.Identity)" Condition=" '$(AndroidUseDesignerAssembly)' == 'True' And '%(Compile.Filename)%(Compile.Extension)' == '$(_AndroidResourceDesigner)' "/>
 		<Compile Remove="@(CorrectCasedItem)" />

From fb0bccfb767918619a1ddd80442b09455562972b Mon Sep 17 00:00:00 2001
From: Dean Ellis <dellis1972@googlemail.com>
Date: Thu, 8 Dec 2022 16:59:06 +0000
Subject: [PATCH 05/18] Fix apkdesc files

---
 .../BuildReleaseArm64SimpleLegacy.apkdesc     |  8 +++---
 .../BuildReleaseArm64XFormsLegacy.apkdesc     | 25 ++++++++-----------
 2 files changed, 15 insertions(+), 18 deletions(-)

diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleLegacy.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleLegacy.apkdesc
index a881ffe9a94..ff98f67fb80 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleLegacy.apkdesc
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleLegacy.apkdesc
@@ -8,13 +8,13 @@
       "Size": 68923
     },
     "assemblies/Mono.Android.dll": {
-      "Size": 265142
+      "Size": 265140
     },
     "assemblies/mscorlib.dll": {
-      "Size": 769035
+      "Size": 769036
     },
     "assemblies/System.Core.dll": {
-      "Size": 28216
+      "Size": 28215
     },
     "assemblies/System.dll": {
       "Size": 9191
@@ -41,7 +41,7 @@
       "Size": 66184
     },
     "lib/arm64-v8a/libxamarin-app.so": {
-      "Size": 21248
+      "Size": 21264
     },
     "META-INF/ANDROIDD.RSA": {
       "Size": 1213
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsLegacy.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsLegacy.apkdesc
index 6e7516a240e..4a37d89eac4 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsLegacy.apkdesc
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsLegacy.apkdesc
@@ -4,9 +4,6 @@
     "AndroidManifest.xml": {
       "Size": 3140
     },
-    "assemblies/_Microsoft.Android.Resource.Designer.dll": {
-      "Size": 133020
-    },
     "assemblies/FormsViewGroup.dll": {
       "Size": 7230
     },
@@ -14,10 +11,10 @@
       "Size": 69966
     },
     "assemblies/Mono.Android.dll": {
-      "Size": 572672
+      "Size": 572670
     },
     "assemblies/Mono.Security.dll": {
-      "Size": 68450
+      "Size": 68449
     },
     "assemblies/mscorlib.dll": {
       "Size": 915425
@@ -35,7 +32,7 @@
       "Size": 110718
     },
     "assemblies/System.Numerics.dll": {
-      "Size": 15705
+      "Size": 15706
     },
     "assemblies/System.Runtime.Serialization.dll": {
       "Size": 186683
@@ -59,7 +56,7 @@
       "Size": 125346
     },
     "assemblies/Xamarin.AndroidX.CardView.dll": {
-      "Size": 7380
+      "Size": 7381
     },
     "assemblies/Xamarin.AndroidX.CoordinatorLayout.dll": {
       "Size": 18289
@@ -89,7 +86,7 @@
       "Size": 13596
     },
     "assemblies/Xamarin.AndroidX.RecyclerView.dll": {
-      "Size": 102349
+      "Size": 102348
     },
     "assemblies/Xamarin.AndroidX.SavedState.dll": {
       "Size": 6294
@@ -113,10 +110,10 @@
       "Size": 55807
     },
     "assemblies/Xamarin.Google.Android.Material.dll": {
-      "Size": 43514
+      "Size": 43513
     },
     "classes.dex": {
-      "Size": 3533300
+      "Size": 3533252
     },
     "lib/arm64-v8a/libmono-btls-shared.so": {
       "Size": 1613872
@@ -134,7 +131,7 @@
       "Size": 66184
     },
     "lib/arm64-v8a/libxamarin-app.so": {
-      "Size": 107144
+      "Size": 107032
     },
     "META-INF/android.support.design_material.version": {
       "Size": 12
@@ -143,7 +140,7 @@
       "Size": 1213
     },
     "META-INF/ANDROIDD.SF": {
-      "Size": 75981
+      "Size": 75858
     },
     "META-INF/androidx.activity_activity.version": {
       "Size": 6
@@ -254,7 +251,7 @@
       "Size": 10
     },
     "META-INF/MANIFEST.MF": {
-      "Size": 75854
+      "Size": 75731
     },
     "META-INF/proguard/androidx-annotations.pro": {
       "Size": 339
@@ -1886,5 +1883,5 @@
       "Size": 341040
     }
   },
-  "PackageSize": 9672959
+  "PackageSize": 9537694
 }
\ No newline at end of file

From b0f76b6b09492ff879a3020b76f1c51ddc1076ed Mon Sep 17 00:00:00 2001
From: Dean Ellis <dellis1972@googlemail.com>
Date: Fri, 9 Dec 2022 13:03:18 +0000
Subject: [PATCH 06/18] Update Unit Test feed

---
 tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs
index 53188b11db7..a6d6b3e3513 100644
--- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs
+++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs
@@ -707,7 +707,7 @@ public void RunWithLLVMEnabled ()
 		}
 
 		[Test]
-		public void ResourceDesignerWithNuGetReference ([Values ("net6.0-android32.0", "net7.0-android33.0")] string dotnetTargetFramework)
+		public void ResourceDesignerWithNuGetReference ([Values ("net6.0-android32.0", "net7.0-android33.0", "net8.0-android33.0")] string dotnetTargetFramework)
 		{
 			AssertHasDevices ();
 
@@ -725,6 +725,7 @@ public void ResourceDesignerWithNuGetReference ([Values ("net6.0-android32.0", "
 					// Projects targeting net6.0 require ref/runtime packs on NuGet.org
 					"https://api.nuget.org/v3/index.json",
 					"https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6/nuget/v3/index.json",
+					"https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet7/nuget/v3/index.json",
 				},
 			};
 			nuget.Sources.Clear ();

From ab03d41d94866cfb4acd81a44efb1a77f375255f Mon Sep 17 00:00:00 2001
From: Dean Ellis <dellis1972@googlemail.com>
Date: Fri, 9 Dec 2022 14:53:50 +0000
Subject: [PATCH 07/18] use AddNuGetSourcesForOlderTargetFrameworks

---
 tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs
index a6d6b3e3513..956edc36bdf 100644
--- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs
+++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs
@@ -721,13 +721,8 @@ public void ResourceDesignerWithNuGetReference ([Values ("net6.0-android32.0", "
 				Sdk = "Xamarin.Legacy.Sdk/0.2.0-alpha2",
 				ProjectName = "Test.Nuget.Package",
 				IsRelease = true,
-				ExtraNuGetConfigSources = {
-					// Projects targeting net6.0 require ref/runtime packs on NuGet.org
-					"https://api.nuget.org/v3/index.json",
-					"https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6/nuget/v3/index.json",
-					"https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet7/nuget/v3/index.json",
-				},
 			};
+			nuget.AddNuGetSourcesForOlderTargetFrameworks ();
 			nuget.Sources.Clear ();
 			nuget.Sources.Add (new AndroidItem.AndroidResource ("Resources/values/Strings.xml") {
 						TextContent = () => @"<resources>

From 817016e16948fe554f6a7f31afba5e58c9377e3e Mon Sep 17 00:00:00 2001
From: Dean Ellis <dellis1972@googlemail.com>
Date: Fri, 9 Dec 2022 17:08:15 +0000
Subject: [PATCH 08/18] Test .net8

---
 tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs
index 956edc36bdf..7f780147517 100644
--- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs
+++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs
@@ -707,7 +707,7 @@ public void RunWithLLVMEnabled ()
 		}
 
 		[Test]
-		public void ResourceDesignerWithNuGetReference ([Values ("net6.0-android32.0", "net7.0-android33.0", "net8.0-android33.0")] string dotnetTargetFramework)
+		public void ResourceDesignerWithNuGetReference ([Values ("net8.0-android33.0")] string dotnetTargetFramework)
 		{
 			AssertHasDevices ();
 

From 5e2d6bbe022eb4fb57597875c31f19649af0631b Mon Sep 17 00:00:00 2001
From: Dean Ellis <dellis1972@googlemail.com>
Date: Wed, 14 Dec 2022 20:26:23 +0000
Subject: [PATCH 09/18] fix merge conflicts

---
 .../Properties/Resources.Designer.cs           | 18 +++++++++---------
 .../Properties/Resources.resx                  |  1 +
 2 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs b/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs
index 05f4c4e0c4c..c87254b93ce 100644
--- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs
+++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs
@@ -728,15 +728,6 @@ public static string XA1028 {
             }
         }
 
-        /// <summary>
-        ///   Looks up a localized string similar to The &apos;AndroidEnableProguard&apos; MSBuild property is set to &apos;true&apos; and the &apos;AndroidLinkTool&apos; MSBuild property is empty, so &apos;AndroidLinkTool&apos; will default to &apos;proguard&apos;..
-        /// </summary>
-        public static string XA1031 {
-            get {
-                return ResourceManager.GetString("XA1031", resourceCulture);
-            }
-        }
-
         /// <summary>
         ///   Looks up a localized string similar to Use of AppDomain.CreateDomain() detected in assembly: {0}. .NET 6 and higher will only support a single AppDomain, so this API will no longer be available in Xamarin.Android once .NET 6 is released..
         /// </summary>
@@ -1476,5 +1467,14 @@ public static string XA1033 {
                 return ResourceManager.GetString("XA1033", resourceCulture);
             }
         }
+
+        /// <summary>
+        ///   Looks up a localized string similar to Your project references '{0}' which uses the `_Microsoft.Android.Resource.Designer` assembly, but you do not have this feature enabled. Please set the `AndroidUseDesignerAssembly` MSBuild property to `true` in your project file.
+        /// </summary>
+        public static string XA1034 {
+            get {
+                return ResourceManager.GetString("XA1034", resourceCulture);
+            }
+        }
     }
 }
diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx
index a526aa6c63b..c36b272704b 100644
--- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx
+++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx
@@ -487,6 +487,7 @@ Please change the value to an assembly-qualifed type name which inherits from '{
     <value>Could not resolve '{0}'. Please check your `AndroidHttpClientHandlerType` setting.</value>
     <comment>The following are literal names and should not be translated: 'AndroidHttpClientHandlerType',
 {0} - The value of the property.</comment>
+  </data>
   <data name="XA1034" xml:space="preserve">
     <value>Your project references '{0}' which uses the `_Microsoft.Android.Resource.Designer` assembly, but you do not have this feature enabled. Please set the `AndroidUseDesignerAssembly` MSBuild property to `true` in your project file.</value>
     <comment>The following are literal names and should not be translated: '_Microsoft.Android.Resource.Desinger', 'AndroidUseDesignerAssembly', 'true'

From b080be042136d7ab80f265635f18bf1cb167fb17 Mon Sep 17 00:00:00 2001
From: Dean Ellis <dellis1972@googlemail.com>
Date: Wed, 14 Dec 2022 23:48:05 +0000
Subject: [PATCH 10/18] Change to XA1034

---
 .../guides/building-apps/build-properties.md     |  2 +-
 Documentation/guides/messages/xa1034.md          | 16 ++++++++++++++++
 .../Xamarin.Android.Resource.Designer.targets    |  4 ++--
 .../AndroidUpdateResourcesTest.cs                |  4 ++--
 4 files changed, 21 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/guides/messages/xa1034.md

diff --git a/Documentation/guides/building-apps/build-properties.md b/Documentation/guides/building-apps/build-properties.md
index 72b17d2806d..1cfab5a9e06 100644
--- a/Documentation/guides/building-apps/build-properties.md
+++ b/Documentation/guides/building-apps/build-properties.md
@@ -1388,7 +1388,7 @@ net7.0-android have been deprecated.
 .NET 8 Projects which choose to turn this setting off will not be able to
 consume references which do use it. If you try to use an assembly
 which does have this feature enabled in a project that does not, you will
-get a `XA1031` build error.
+get a `XA1034` build error.
 
 Added in .NET 8.  Unsupported in Classic Xamarin.Android.
 
diff --git a/Documentation/guides/messages/xa1034.md b/Documentation/guides/messages/xa1034.md
new file mode 100644
index 00000000000..be1bffd43e7
--- /dev/null
+++ b/Documentation/guides/messages/xa1034.md
@@ -0,0 +1,16 @@
+---
+title: Xamarin.Android error XA1034
+description: XA1034 error code
+ms.date: 13/12/2022
+---
+# Xamarin.Android error XA1034
+
+## Example messages
+
+```
+Your project references 'Foo.dll' which uses the `_Microsoft.Android.Resource.Designer` assembly, but you do not have this feature enabled. Please set the `AndroidUseDesignerAssembly` MSBuild property to `true` in your project file.
+```
+
+## Solution
+
+Edit your csproj directly and change the 'AndroidUseDesignerAssembly' to `True`.
\ No newline at end of file
diff --git a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets
index 95e7d80efd3..8530f437915 100644
--- a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets
+++ b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets
@@ -153,8 +153,8 @@ Copyright (C) 2016 Xamarin. All rights reserved.
       <_ErrorItems Include="@(_MonoAndroidReferencePath)" Condition=" '%(_MonoAndroidReferencePath.HasResourceDesignerAssemblyReference)' == 'True' "/>
       <_ErrorItems Include="@(_MonoAndroidReferenceDependencyPaths)"  Condition=" '%(_MonoAndroidReferenceDependencyPaths.HasResourceDesignerAssemblyReference)' == 'True' "/>
     </ItemGroup>
-    <AndroidError Code="XA1031"
-        ResourceName="XA1031"
+    <AndroidError Code="XA1034"
+        ResourceName="XA1034"
         FormatArguments="%(_ErrorItems.FullPath)"
         Condition=" '@(_ErrorItems->Count())' != '0' "
     />
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs
index 00add1baf48..35b5bf82aed 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs
@@ -651,7 +651,7 @@ public void CheckOldResourceDesignerWithWrongCasingIsRemoved ([Values (true, fal
 		}
 
 		[Test]
-		public void CheckThatXA1031IsRaisedForInvalidConfiguration ([Values (true, false)] bool isRelease)
+		public void CheckThatXA1034IsRaisedForInvalidConfiguration ([Values (true, false)] bool isRelease)
 		{
 			if (!Builder.UseDotNet)
 				Assert.Ignore ("Test uses designer assembly which does not work on Legacy projects.");
@@ -688,7 +688,7 @@ public static string GetFoo () {
 				using (var pb = CreateApkBuilder (Path.Combine (path, proj.ProjectName))) {
 					pb.ThrowOnBuildFailure = false;
 					Assert.IsFalse (pb.Build (proj), "Application project build should have failed.");
-					StringAssertEx.ContainsText (pb.LastBuildOutput, "XA1031: ");
+					StringAssertEx.ContainsText (pb.LastBuildOutput, "XA1034: ");
 					StringAssertEx.ContainsText (pb.LastBuildOutput, "1 Error(s)");
 				}
 			}

From d669fd66d016c6d7ce1cfa21d0c1c4e2397a65d8 Mon Sep 17 00:00:00 2001
From: Dean Ellis <dellis1972@googlemail.com>
Date: Fri, 16 Dec 2022 16:51:04 +0000
Subject: [PATCH 11/18] Update based on feedback

---
 Documentation/guides/building-apps/build-properties.md     | 3 ++-
 .../Android/Xamarin.Android.Resource.Designer.targets      | 7 -------
 src/Xamarin.Android.Build.Tasks/Tasks/FilterAssemblies.cs  | 4 +---
 .../Tasks/GenerateResourceDesignerAssembly.cs              | 4 ++--
 .../Utilities/FileResourceParser.cs                        | 2 +-
 .../Utilities/ManagedResourceParser.cs                     | 4 ++--
 .../Utilities/ResourceParser.cs                            | 6 ------
 src/Xamarin.Android.Build.Tasks/Utilities/RtxtParser.cs    | 2 ++
 src/Xamarin.Android.Build.Tasks/Utilities/RtxtWriter.cs    | 6 +++---
 9 files changed, 13 insertions(+), 25 deletions(-)

diff --git a/Documentation/guides/building-apps/build-properties.md b/Documentation/guides/building-apps/build-properties.md
index 1cfab5a9e06..113c87c3635 100644
--- a/Documentation/guides/building-apps/build-properties.md
+++ b/Documentation/guides/building-apps/build-properties.md
@@ -1376,7 +1376,8 @@ This setting is not backward compatible with Classic Xamarin.Android.
 As a Nuget Author it is recommended that you ship three versions of
 the assembly if you want to maintain backward compatibility.
 One for MonoAndroid, one for net6.0-android and
-one for net8.0-android. You can do this by using [Xamarin.Legacy.Sdk](https://www.nuget.org/packages/Xamarin.Legacy.Sdk).
+one for net8.0-android. You can do this by using [Xamarin.Legacy.Sdk](https://www.nuget.org/packages/Xamarin.Legacy.Sdk). This is only required if your Nuget Library
+project makes use of `AndroidResource` items in the project or via a dependency.
 
 ```
 <TargetFrameworks>monoandroid90;net6.0-android;net8.0-android</TargetFrameworks>
diff --git a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets
index 8530f437915..de36c90ea4b 100644
--- a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets
+++ b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets
@@ -91,13 +91,6 @@ Copyright (C) 2016 Xamarin. All rights reserved.
     </ItemGroup>
 </Target>
 
-<!--
-    We only want to do this for non application projects unless the user has
-    specifically opted into the new system. This can be done by either
-    1. using `dotnet new android` and building a new project.
-    2. Add <AndroidUseDesignerAssembly>true</AndroidUseDesignerAssembly> to
-       the project.
- -->
 <Target Name="_GenerateResourceDesignerIntermediateClass"
     Condition=" '$(AndroidUseDesignerAssembly)' == 'True' "
     Inputs="$(MSBuildProjectFullPath)"
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/FilterAssemblies.cs b/src/Xamarin.Android.Build.Tasks/Tasks/FilterAssemblies.cs
index 6abce912aef..13645c84ca9 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/FilterAssemblies.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/FilterAssemblies.cs
@@ -24,8 +24,6 @@ public class FilterAssemblies : AndroidTask
 
 		public ITaskItem [] InputAssemblies { get; set; }
 
-		public bool UseDesignerAssembly { get; set; }
-
 		[Output]
 		public ITaskItem [] OutputAssemblies { get; set; }
 
@@ -53,7 +51,7 @@ public override bool RunTask ()
 				} catch (Exception e) when (e is FileNotFoundException || e is DirectoryNotFoundException) {
 					Log.LogDebugMessage ($"Skipping non-existent dependency '{assemblyItem.ItemSpec}'.");
 				}
-				
+
 			}
 			OutputAssemblies = output.ToArray ();
 
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerAssembly.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerAssembly.cs
index 4ca7ea3f0f1..ba009724f7b 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerAssembly.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerAssembly.cs
@@ -209,7 +209,7 @@ void CreateIntProperty (string resourceClass, string propertyName, int value, Ty
 			TypeDefinition nestedType = CreateResourceClass (resourceDesigner, resourceClass, module, typeAttributes);
 			PropertyDefinition p = CreateProperty (propertyName, value, module, attributes);
 			nestedType.Properties.Add (p);
-			nestedType.Methods.Insert (Math.Max(0, nestedType.Methods.Count () -1), p.GetMethod);
+			nestedType.Methods.Insert (Math.Max(0, nestedType.Methods.Count () - 1), p.GetMethod);
 		}
 
 		void CreateIntField (string resourceClass, string fieldName, int value, TypeDefinition resourceDesigner, ModuleDefinition module,
@@ -226,7 +226,7 @@ void CreateIntArrayProperty (string resourceClass, string propertyName, int[] va
 			TypeDefinition nestedType = CreateResourceClass (resourceDesigner, resourceClass, module, typeAttributes);
 			PropertyDefinition p = CreateArrayProperty (propertyName, values, module, attributes);
 			nestedType.Properties.Add (p);
-			nestedType.Methods.Insert (Math.Max(0, nestedType.Methods.Count () -1), p.GetMethod);
+			nestedType.Methods.Insert (Math.Max(0, nestedType.Methods.Count () - 1), p.GetMethod);
 		}
 
 		void CreateIntArrayField (string resourceClass, string fieldName, int[] values, TypeDefinition resourceDesigner, ModuleDefinition module,
diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/FileResourceParser.cs b/src/Xamarin.Android.Build.Tasks/Utilities/FileResourceParser.cs
index 73168a69c01..96f48253931 100644
--- a/src/Xamarin.Android.Build.Tasks/Utilities/FileResourceParser.cs
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/FileResourceParser.cs
@@ -113,7 +113,7 @@ public IList<R> Parse (string resourceDirectory, IEnumerable<string> additionalR
 				if (!resources.ContainsKey(t)) {
 					continue;
 				}
-				if (resources[t].Count () == 0) {
+				if (resources[t].Count == 0) {
 					continue;
 				}
 				foreach (R r in resources[t].OrderBy(x => x.ToSortedString(), StringComparer.Ordinal)) {
diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ManagedResourceParser.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ManagedResourceParser.cs
index bcb01245334..07c4b1537c5 100644
--- a/src/Xamarin.Android.Build.Tasks/Utilities/ManagedResourceParser.cs
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/ManagedResourceParser.cs
@@ -377,7 +377,7 @@ void CreateField (CodeTypeDeclaration parentType, string name, Type type)
 
 		CodeMemberField CreateIntField (CodeTypeDeclaration parentType, string name, int value = -1)
 		{
-			string mappedName = GetResourceName (parentType.Name, name, map);
+			string mappedName = ResourceIdentifier.GetResourceName (parentType.Name, name, map, Log);
 			CodeMemberField f = (CodeMemberField)parentType.Members.OfType<CodeTypeMember> ().FirstOrDefault (x => string.Compare (x.Name, mappedName, StringComparison.Ordinal) == 0);
 			if (f != null)
 				return f;
@@ -397,7 +397,7 @@ CodeMemberField CreateIntField (CodeTypeDeclaration parentType, string name, int
 
 		CodeMemberField CreateIntArrayField (CodeTypeDeclaration parentType, string name, int count, params int[] values)
 		{
-			string mappedName = GetResourceName (parentType.Name, name, map);
+			string mappedName = ResourceIdentifier.GetResourceName (parentType.Name, name, map, Log);
 			CodeMemberField f = (CodeMemberField)parentType.Members.OfType<CodeTypeMember> ().FirstOrDefault (x => string.Compare (x.Name, mappedName, StringComparison.Ordinal) == 0);
 			if (f != null)
 				return f;
diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ResourceParser.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ResourceParser.cs
index 64cedf71129..3becd20d1ec 100644
--- a/src/Xamarin.Android.Build.Tasks/Utilities/ResourceParser.cs
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/ResourceParser.cs
@@ -37,11 +37,5 @@ internal static string GetNestedTypeName (string name)
 				default: return char.ToUpperInvariant (name[0]) + name.Substring (1);
 			}
 		}
-
-		internal string GetResourceName (string type, string name, Dictionary<string, string> map)
-		{
-			return ResourceIdentifier.GetResourceName (type, name, map, Log);
-		}
-
 	}
 }
diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/RtxtParser.cs b/src/Xamarin.Android.Build.Tasks/Utilities/RtxtParser.cs
index 6b3d1fd9470..644df0e2e31 100644
--- a/src/Xamarin.Android.Build.Tasks/Utilities/RtxtParser.cs
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/RtxtParser.cs
@@ -11,10 +11,12 @@ public enum RType {
 		Integer,
 		Array,
 	}
+
 	public enum ResourceType {
 		System,
 		Custom,
 	}
+
 	public struct R : IComparable<R> {
 		public RType Type;
 		public int Id;
diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/RtxtWriter.cs b/src/Xamarin.Android.Build.Tasks/Utilities/RtxtWriter.cs
index cc2e7a70991..5682af04139 100644
--- a/src/Xamarin.Android.Build.Tasks/Utilities/RtxtWriter.cs
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/RtxtWriter.cs
@@ -13,11 +13,11 @@ namespace Xamarin.Android.Tasks
 	public class RtxtWriter {
 		public void Write (string file, IList<R> items)
 		{
-			var sb = new StringBuilder ();
+			using var sw = MemoryStreamPool.Shared.CreateStreamWriter ();
 			foreach (var item in items) {
-				sb.AppendLine (item.ToString ());
+				sw .WriteLine (item.ToString ());
 			}
-			Files.CopyIfStringChanged (sb.ToString (), file);
+			Files.CopyIfStreamChanged (sw.BaseStream, file);
 		}
 	}
 }

From 6837c90a34b0ac1a99b10765d467d36f7467fc99 Mon Sep 17 00:00:00 2001
From: Dean Ellis <dellis1972@googlemail.com>
Date: Fri, 16 Dec 2022 16:51:34 +0000
Subject: [PATCH 12/18] Back out some unit test changes

---
 .../Tests/Xamarin.Android.Build.Tests/AotTests.cs        | 9 +++++----
 .../Mono.Android-Test.Shared.projitems                   | 1 +
 tests/Mono.Android-Tests/Mono.Android-Tests.csproj       | 1 -
 3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AotTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AotTests.cs
index 6a8ccadba77..3f2ee58ed3a 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AotTests.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AotTests.cs
@@ -277,10 +277,11 @@ public void BuildAMassiveApp ()
 				IsRelease = true,
 			};
 			if (Builder.UseDotNet) {
-				app1.PackageReferences.Clear ();
-				app1.PackageReferences.Add (KnownPackages.XamarinForms_5_0_0_2515);
-				app1.PackageReferences.Add (KnownPackages.XamarinFormsMaps_5_0_0_2515);
-				app1.PackageReferences.Add (KnownPackages.Xamarin_Build_Download_0_11_3);
+				//TODO Re-enable if this test fails.
+				// app1.PackageReferences.Clear ();
+				// app1.PackageReferences.Add (KnownPackages.XamarinForms_5_0_0_2515);
+				// app1.PackageReferences.Add (KnownPackages.XamarinFormsMaps_5_0_0_2515);
+				// app1.PackageReferences.Add (KnownPackages.Xamarin_Build_Download_0_11_3);
 
 			}
 			//NOTE: BuildingInsideVisualStudio prevents the projects from being built as dependencies
diff --git a/tests/Mono.Android-Tests/Mono.Android-Test.Shared.projitems b/tests/Mono.Android-Tests/Mono.Android-Test.Shared.projitems
index 185f6e9fe7c..052219da8fc 100644
--- a/tests/Mono.Android-Tests/Mono.Android-Test.Shared.projitems
+++ b/tests/Mono.Android-Tests/Mono.Android-Test.Shared.projitems
@@ -14,6 +14,7 @@
   <ItemGroup>
     <Compile Include="$(MSBuildThisFileDirectory)System.Linq\LinqExpressionTest.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Properties\AssemblyInfo.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Resources\Resource.designer.cs" Condition=" '$(AndroidUseDesignerAssembly)' == 'False' And '$(AndroidUseIntermediateDesignerFile)' == 'False' "/>
     <Compile Include="$(MSBuildThisFileDirectory)Android.App\ApplicationTest.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Android.Content.Res\AssetManagerTest.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Android.Content\IntentTest.cs" />
diff --git a/tests/Mono.Android-Tests/Mono.Android-Tests.csproj b/tests/Mono.Android-Tests/Mono.Android-Tests.csproj
index f976680d4e3..1d4a287f573 100644
--- a/tests/Mono.Android-Tests/Mono.Android-Tests.csproj
+++ b/tests/Mono.Android-Tests/Mono.Android-Tests.csproj
@@ -29,7 +29,6 @@
     <_ASANScript>..\..\build-tools\wrap.sh\asan.sh</_ASANScript>
     <_UBSANScript>..\..\build-tools\wrap.sh\ubsan.sh</_UBSANScript>
     <_MonoAndroidTestPackage>Mono.Android_Tests</_MonoAndroidTestPackage>
-    <AndroidUseIntermediateDesignerFile>True</AndroidUseIntermediateDesignerFile>
   </PropertyGroup>
   <Import Project="Mono.Android-Test.Shared.projitems" Label="Shared" Condition="Exists('Mono.Android-Test.Shared.projitems')" />
   <Import Project="..\..\Configuration.props" />

From c9441127bde9d8d2a88590296b3114f11a9bfc46 Mon Sep 17 00:00:00 2001
From: Dean Ellis <dellis1972@googlemail.com>
Date: Fri, 16 Dec 2022 17:10:45 +0000
Subject: [PATCH 13/18] Fix build error

---
 .../Utilities/JavaResourceParser.cs                         | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/JavaResourceParser.cs b/src/Xamarin.Android.Build.Tasks/Utilities/JavaResourceParser.cs
index bb705dfbcdd..bf92442a733 100644
--- a/src/Xamarin.Android.Build.Tasks/Utilities/JavaResourceParser.cs
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/JavaResourceParser.cs
@@ -23,7 +23,7 @@ public CodeTypeDeclaration Parse (string file, bool isApp, Dictionary<string, st
 
 				while ((line = reader.ReadLine ()) != null) {
 					var info = Parser.Select (p => new { Match = p.Key.Match (line), Handler = p.Value }).FirstOrDefault (x => x.Match.Success);
-					
+
 					if (info == null)
 						continue;
 
@@ -84,7 +84,7 @@ public JavaResourceParser ()
 			Parse (@"^        public static final int ([^ =]+)\s*=\s*([^;]+);$",
 					(m, app, g, map) => {
 						var name = ((CodeTypeDeclaration) g.Members [g.Members.Count-1]).Name;
-						var f = new CodeMemberField (typeof (int), GetResourceName (name, m.Groups[1].Value, map)) {
+						var f = new CodeMemberField (typeof (int), ResourceIdentifier.GetResourceName (name, m.Groups[1].Value, map, Log)) {
 								Attributes      = app ? MemberAttributes.Const | MemberAttributes.Public : MemberAttributes.Static | MemberAttributes.Public,
 								InitExpression  = new CodePrimitiveExpression (ToInt32 (m.Groups [2].Value, m.Groups [2].Value.IndexOf ("0x", StringComparison.Ordinal) == 0 ? 16 : 10)),
 								Comments = {
@@ -97,7 +97,7 @@ public JavaResourceParser ()
 			Parse (@"^        public static final int\[\] ([^ =]+) = {",
 					(m, app, g, map) => {
 						var name = ((CodeTypeDeclaration) g.Members [g.Members.Count-1]).Name;
-						var f = new CodeMemberField (typeof (int[]), GetResourceName (name, m.Groups[1].Value, map)) {
+						var f = new CodeMemberField (typeof (int[]), ResourceIdentifier.GetResourceName (name, m.Groups[1].Value, map, Log)) {
 								// pity I can't make the member readonly...
 								Attributes      = MemberAttributes.Public | MemberAttributes.Static,
 						};

From f48c1f582302d98a3b5131656267d61046ac013b Mon Sep 17 00:00:00 2001
From: Dean Ellis <dellis1972@googlemail.com>
Date: Sat, 17 Dec 2022 17:09:55 +0000
Subject: [PATCH 14/18] Use Flush to make sure we have data in the stream

---
 .../Utilities/RtxtWriter.cs                            | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/RtxtWriter.cs b/src/Xamarin.Android.Build.Tasks/Utilities/RtxtWriter.cs
index 5682af04139..eb3a8abf038 100644
--- a/src/Xamarin.Android.Build.Tasks/Utilities/RtxtWriter.cs
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/RtxtWriter.cs
@@ -13,11 +13,13 @@ namespace Xamarin.Android.Tasks
 	public class RtxtWriter {
 		public void Write (string file, IList<R> items)
 		{
-			using var sw = MemoryStreamPool.Shared.CreateStreamWriter ();
-			foreach (var item in items) {
-				sw .WriteLine (item.ToString ());
+			using (var sw = MemoryStreamPool.Shared.CreateStreamWriter ()) {
+				foreach (var item in items) {
+					sw.WriteLine (item.ToString ());
+				}
+				sw.Flush ();
+				Files.CopyIfStreamChanged (sw.BaseStream, file);
 			}
-			Files.CopyIfStreamChanged (sw.BaseStream, file);
 		}
 	}
 }

From ae51be4eec44ff034408ac83b3c1a3f3c28e479f Mon Sep 17 00:00:00 2001
From: Dean Ellis <dellis1972@googlemail.com>
Date: Sun, 18 Dec 2022 23:42:16 +0000
Subject: [PATCH 15/18] Fix apkdesc

---
 .../BuildReleaseArm64SimpleDotNet.apkdesc     | 20 +++++++--------
 .../BuildReleaseArm64SimpleLegacy.apkdesc     |  6 ++---
 .../BuildReleaseArm64XFormsDotNet.apkdesc     | 18 ++++++-------
 .../BuildReleaseArm64XFormsLegacy.apkdesc     | 25 +++++++++++--------
 4 files changed, 36 insertions(+), 33 deletions(-)

diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc
index d747a184fe7..a0af2696b00 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc
@@ -8,13 +8,13 @@
       "Size": 1028
     },
     "assemblies/Java.Interop.dll": {
-      "Size": 58924
+      "Size": 58926
     },
     "assemblies/Mono.Android.dll": {
-      "Size": 87710
+      "Size": 87074
     },
     "assemblies/Mono.Android.Runtime.dll": {
-      "Size": 5924
+      "Size": 5832
     },
     "assemblies/rc.bin": {
       "Size": 1182
@@ -26,16 +26,16 @@
       "Size": 9253
     },
     "assemblies/System.Private.CoreLib.dll": {
-      "Size": 484001
+      "Size": 483854
     },
     "assemblies/System.Runtime.dll": {
-      "Size": 2629
+      "Size": 2608
     },
     "assemblies/System.Runtime.InteropServices.dll": {
       "Size": 2269
     },
     "assemblies/UnnamedProject.dll": {
-      "Size": 3628
+      "Size": 3275
     },
     "classes.dex": {
       "Size": 19020
@@ -59,16 +59,16 @@
       "Size": 150584
     },
     "lib/arm64-v8a/libxamarin-app.so": {
-      "Size": 16632
+      "Size": 16728
     },
     "META-INF/BNDLTOOL.RSA": {
       "Size": 1213
     },
     "META-INF/BNDLTOOL.SF": {
-      "Size": 2914
+      "Size": 3037
     },
     "META-INF/MANIFEST.MF": {
-      "Size": 2787
+      "Size": 2910
     },
     "res/drawable-hdpi-v4/icon.png": {
       "Size": 2178
@@ -95,5 +95,5 @@
       "Size": 1904
     }
   },
-  "PackageSize": 2603241
+  "PackageSize": 2603338
 }
\ No newline at end of file
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleLegacy.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleLegacy.apkdesc
index ff98f67fb80..4eb6fa09ccf 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleLegacy.apkdesc
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleLegacy.apkdesc
@@ -14,13 +14,13 @@
       "Size": 769036
     },
     "assemblies/System.Core.dll": {
-      "Size": 28215
+      "Size": 28216
     },
     "assemblies/System.dll": {
-      "Size": 9191
+      "Size": 9192
     },
     "assemblies/UnnamedProject.dll": {
-      "Size": 2896
+      "Size": 2894
     },
     "classes.dex": {
       "Size": 370828
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc
index 6ae5c9740f2..8134fd88f91 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc
@@ -11,13 +11,13 @@
       "Size": 7314
     },
     "assemblies/Java.Interop.dll": {
-      "Size": 66797
+      "Size": 66801
     },
     "assemblies/Mono.Android.dll": {
-      "Size": 444767
+      "Size": 444662
     },
     "assemblies/Mono.Android.Runtime.dll": {
-      "Size": 5924
+      "Size": 5832
     },
     "assemblies/mscorlib.dll": {
       "Size": 3856
@@ -104,7 +104,7 @@
       "Size": 16805
     },
     "assemblies/System.Runtime.dll": {
-      "Size": 2791
+      "Size": 2756
     },
     "assemblies/System.Runtime.InteropServices.dll": {
       "Size": 2269
@@ -131,7 +131,7 @@
       "Size": 1858
     },
     "assemblies/UnnamedProject.dll": {
-      "Size": 117399
+      "Size": 5347
     },
     "assemblies/Xamarin.AndroidX.Activity.dll": {
       "Size": 5872
@@ -221,7 +221,7 @@
       "Size": 150584
     },
     "lib/arm64-v8a/libxamarin-app.so": {
-      "Size": 333632
+      "Size": 333728
     },
     "META-INF/android.support.design_material.version": {
       "Size": 12
@@ -335,13 +335,13 @@
       "Size": 1213
     },
     "META-INF/BNDLTOOL.SF": {
-      "Size": 79203
+      "Size": 79326
     },
     "META-INF/com.google.android.material_material.version": {
       "Size": 10
     },
     "META-INF/MANIFEST.MF": {
-      "Size": 79076
+      "Size": 79199
     },
     "META-INF/proguard/androidx-annotations.pro": {
       "Size": 339
@@ -1976,5 +1976,5 @@
       "Size": 341228
     }
   },
-  "PackageSize": 7991971
+  "PackageSize": 7803652
 }
\ No newline at end of file
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsLegacy.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsLegacy.apkdesc
index 4a37d89eac4..0d28c81d989 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsLegacy.apkdesc
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsLegacy.apkdesc
@@ -4,6 +4,9 @@
     "AndroidManifest.xml": {
       "Size": 3140
     },
+    "assemblies/_Microsoft.Android.Resource.Designer.dll": {
+      "Size": 119643
+    },
     "assemblies/FormsViewGroup.dll": {
       "Size": 7230
     },
@@ -14,7 +17,7 @@
       "Size": 572670
     },
     "assemblies/Mono.Security.dll": {
-      "Size": 68449
+      "Size": 68450
     },
     "assemblies/mscorlib.dll": {
       "Size": 915425
@@ -44,7 +47,7 @@
       "Size": 395668
     },
     "assemblies/UnnamedProject.dll": {
-      "Size": 116994
+      "Size": 116997
     },
     "assemblies/Xamarin.AndroidX.Activity.dll": {
       "Size": 7711
@@ -56,7 +59,7 @@
       "Size": 125346
     },
     "assemblies/Xamarin.AndroidX.CardView.dll": {
-      "Size": 7381
+      "Size": 7380
     },
     "assemblies/Xamarin.AndroidX.CoordinatorLayout.dll": {
       "Size": 18289
@@ -65,7 +68,7 @@
       "Size": 131944
     },
     "assemblies/Xamarin.AndroidX.DrawerLayout.dll": {
-      "Size": 15444
+      "Size": 15443
     },
     "assemblies/Xamarin.AndroidX.Fragment.dll": {
       "Size": 43150
@@ -86,7 +89,7 @@
       "Size": 13596
     },
     "assemblies/Xamarin.AndroidX.RecyclerView.dll": {
-      "Size": 102348
+      "Size": 102349
     },
     "assemblies/Xamarin.AndroidX.SavedState.dll": {
       "Size": 6294
@@ -110,10 +113,10 @@
       "Size": 55807
     },
     "assemblies/Xamarin.Google.Android.Material.dll": {
-      "Size": 43513
+      "Size": 43514
     },
     "classes.dex": {
-      "Size": 3533252
+      "Size": 3533300
     },
     "lib/arm64-v8a/libmono-btls-shared.so": {
       "Size": 1613872
@@ -131,7 +134,7 @@
       "Size": 66184
     },
     "lib/arm64-v8a/libxamarin-app.so": {
-      "Size": 107032
+      "Size": 107160
     },
     "META-INF/android.support.design_material.version": {
       "Size": 12
@@ -140,7 +143,7 @@
       "Size": 1213
     },
     "META-INF/ANDROIDD.SF": {
-      "Size": 75858
+      "Size": 75981
     },
     "META-INF/androidx.activity_activity.version": {
       "Size": 6
@@ -251,7 +254,7 @@
       "Size": 10
     },
     "META-INF/MANIFEST.MF": {
-      "Size": 75731
+      "Size": 75854
     },
     "META-INF/proguard/androidx-annotations.pro": {
       "Size": 339
@@ -1883,5 +1886,5 @@
       "Size": 341040
     }
   },
-  "PackageSize": 9537694
+  "PackageSize": 9656575
 }
\ No newline at end of file

From 94f399a9f644f0a6aa4231afc94adb2f1e9af757 Mon Sep 17 00:00:00 2001
From: Dean Ellis <dellis1972@googlemail.com>
Date: Sun, 18 Dec 2022 23:46:45 +0000
Subject: [PATCH 16/18] update apkdesc

---
 .../Base/BuildReleaseArm64SimpleDotNet.apkdesc         |  2 +-
 .../Base/BuildReleaseArm64XFormsLegacy.apkdesc         | 10 +++++-----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc
index a0af2696b00..fd5dea2cee2 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc
@@ -35,7 +35,7 @@
       "Size": 2269
     },
     "assemblies/UnnamedProject.dll": {
-      "Size": 3275
+      "Size": 3273
     },
     "classes.dex": {
       "Size": 19020
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsLegacy.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsLegacy.apkdesc
index 0d28c81d989..d2314748565 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsLegacy.apkdesc
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsLegacy.apkdesc
@@ -17,7 +17,7 @@
       "Size": 572670
     },
     "assemblies/Mono.Security.dll": {
-      "Size": 68450
+      "Size": 68449
     },
     "assemblies/mscorlib.dll": {
       "Size": 915425
@@ -32,7 +32,7 @@
       "Size": 12370
     },
     "assemblies/System.Net.Http.dll": {
-      "Size": 110718
+      "Size": 110717
     },
     "assemblies/System.Numerics.dll": {
       "Size": 15706
@@ -44,7 +44,7 @@
       "Size": 26604
     },
     "assemblies/System.Xml.dll": {
-      "Size": 395668
+      "Size": 395667
     },
     "assemblies/UnnamedProject.dll": {
       "Size": 116997
@@ -59,7 +59,7 @@
       "Size": 125346
     },
     "assemblies/Xamarin.AndroidX.CardView.dll": {
-      "Size": 7380
+      "Size": 7381
     },
     "assemblies/Xamarin.AndroidX.CoordinatorLayout.dll": {
       "Size": 18289
@@ -80,7 +80,7 @@
       "Size": 7078
     },
     "assemblies/Xamarin.AndroidX.Lifecycle.LiveData.Core.dll": {
-      "Size": 7207
+      "Size": 7208
     },
     "assemblies/Xamarin.AndroidX.Lifecycle.ViewModel.dll": {
       "Size": 4886

From ae8764cde37281fd93175060b85ff382ea47fb9a Mon Sep 17 00:00:00 2001
From: Dean Ellis <dellis1972@googlemail.com>
Date: Mon, 19 Dec 2022 21:46:41 +0000
Subject: [PATCH 17/18] ff

---
 .../BuildReleaseArm64SimpleDotNet.apkdesc     |  4 ++--
 .../BuildReleaseArm64SimpleLegacy.apkdesc     |  2 +-
 .../BuildReleaseArm64XFormsDotNet.apkdesc     |  2 +-
 .../BuildReleaseArm64XFormsLegacy.apkdesc     | 21 ++++++++-----------
 4 files changed, 13 insertions(+), 16 deletions(-)

diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc
index fd5dea2cee2..f5a8ad55bfe 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc
@@ -14,7 +14,7 @@
       "Size": 87074
     },
     "assemblies/Mono.Android.Runtime.dll": {
-      "Size": 5832
+      "Size": 5833
     },
     "assemblies/rc.bin": {
       "Size": 1182
@@ -35,7 +35,7 @@
       "Size": 2269
     },
     "assemblies/UnnamedProject.dll": {
-      "Size": 3273
+      "Size": 3276
     },
     "classes.dex": {
       "Size": 19020
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleLegacy.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleLegacy.apkdesc
index 4eb6fa09ccf..adfe30f0e3b 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleLegacy.apkdesc
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleLegacy.apkdesc
@@ -20,7 +20,7 @@
       "Size": 9192
     },
     "assemblies/UnnamedProject.dll": {
-      "Size": 2894
+      "Size": 2897
     },
     "classes.dex": {
       "Size": 370828
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc
index 8134fd88f91..efc6347e949 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc
@@ -17,7 +17,7 @@
       "Size": 444662
     },
     "assemblies/Mono.Android.Runtime.dll": {
-      "Size": 5832
+      "Size": 5833
     },
     "assemblies/mscorlib.dll": {
       "Size": 3856
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsLegacy.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsLegacy.apkdesc
index d2314748565..00393868d67 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsLegacy.apkdesc
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsLegacy.apkdesc
@@ -4,9 +4,6 @@
     "AndroidManifest.xml": {
       "Size": 3140
     },
-    "assemblies/_Microsoft.Android.Resource.Designer.dll": {
-      "Size": 119643
-    },
     "assemblies/FormsViewGroup.dll": {
       "Size": 7230
     },
@@ -32,7 +29,7 @@
       "Size": 12370
     },
     "assemblies/System.Net.Http.dll": {
-      "Size": 110717
+      "Size": 110718
     },
     "assemblies/System.Numerics.dll": {
       "Size": 15706
@@ -44,7 +41,7 @@
       "Size": 26604
     },
     "assemblies/System.Xml.dll": {
-      "Size": 395667
+      "Size": 395668
     },
     "assemblies/UnnamedProject.dll": {
       "Size": 116997
@@ -59,7 +56,7 @@
       "Size": 125346
     },
     "assemblies/Xamarin.AndroidX.CardView.dll": {
-      "Size": 7381
+      "Size": 7380
     },
     "assemblies/Xamarin.AndroidX.CoordinatorLayout.dll": {
       "Size": 18289
@@ -74,7 +71,7 @@
       "Size": 43150
     },
     "assemblies/Xamarin.AndroidX.Legacy.Support.Core.UI.dll": {
-      "Size": 6728
+      "Size": 6727
     },
     "assemblies/Xamarin.AndroidX.Lifecycle.Common.dll": {
       "Size": 7078
@@ -116,7 +113,7 @@
       "Size": 43514
     },
     "classes.dex": {
-      "Size": 3533300
+      "Size": 3533252
     },
     "lib/arm64-v8a/libmono-btls-shared.so": {
       "Size": 1613872
@@ -134,7 +131,7 @@
       "Size": 66184
     },
     "lib/arm64-v8a/libxamarin-app.so": {
-      "Size": 107160
+      "Size": 107032
     },
     "META-INF/android.support.design_material.version": {
       "Size": 12
@@ -143,7 +140,7 @@
       "Size": 1213
     },
     "META-INF/ANDROIDD.SF": {
-      "Size": 75981
+      "Size": 75858
     },
     "META-INF/androidx.activity_activity.version": {
       "Size": 6
@@ -254,7 +251,7 @@
       "Size": 10
     },
     "META-INF/MANIFEST.MF": {
-      "Size": 75854
+      "Size": 75731
     },
     "META-INF/proguard/androidx-annotations.pro": {
       "Size": 339
@@ -1886,5 +1883,5 @@
       "Size": 341040
     }
   },
-  "PackageSize": 9656575
+  "PackageSize": 9537694
 }
\ No newline at end of file

From a765beacc6c9f29597d75ed9dbe56529a9cdc478 Mon Sep 17 00:00:00 2001
From: Jonathan Pryor <jonpryor@vt.edu>
Date: Wed, 4 Jan 2023 19:55:30 -0500
Subject: [PATCH 18/18] Fix indentation formatting

---
 .../Xamarin.Android.Resource.Designer.targets | 164 +++++++++---------
 1 file changed, 82 insertions(+), 82 deletions(-)

diff --git a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets
index de36c90ea4b..8d19b2128da 100644
--- a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets
+++ b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets
@@ -60,16 +60,16 @@ Copyright (C) 2016 Xamarin. All rights reserved.
     Inputs="$(_AndroidResFlagFile);@(_AndroidResourceDest);@(LibraryResourceDirectories->'%(StampFile)')"
     Outputs="$(_DesignerIntermediateOutputPath)R.txt"
   >
-    <!-- Generate an R.txt file using the Managed Parser -->
-    <GenerateRtxt
-        AdditionalResourceDirectories="@(LibraryResourceDirectories)"
-        CaseMapFile="$(_GenerateResourceCaseMapFile)"
-        JavaPlatformJarPath="$(JavaPlatformJarPath)"
-        ResourceDirectory="$(MonoAndroidResDirIntermediate)"
-        ResourceFlagFile="$(_AndroidResFlagFile)"
-        RTxtFile="$(_DesignerIntermediateOutputPath)R.txt"
-    >
-    </GenerateRtxt>
+  <!-- Generate an R.txt file using the Managed Parser -->
+  <GenerateRtxt
+      AdditionalResourceDirectories="@(LibraryResourceDirectories)"
+      CaseMapFile="$(_GenerateResourceCaseMapFile)"
+      JavaPlatformJarPath="$(JavaPlatformJarPath)"
+      ResourceDirectory="$(MonoAndroidResDirIntermediate)"
+      ResourceFlagFile="$(_AndroidResFlagFile)"
+      RTxtFile="$(_DesignerIntermediateOutputPath)R.txt"
+  >
+  </GenerateRtxt>
 </Target>
 
 <Target Name="_GenerateResourceCaseMap"
@@ -77,18 +77,18 @@ Copyright (C) 2016 Xamarin. All rights reserved.
     Inputs="@(_AndroidResourceDest);@(LibraryResourceDirectories->'%(StampFile)')"
     Outputs="$(_GenerateResourceCaseMapFile)"
   >
-    <!-- Generate a ResourceMap file for the project and its resources -->
-    <GenerateResourceCaseMap
-        AdditionalResourceDirectories="@(LibraryResourceDirectories)"
-        OutputFile="$(_GenerateResourceCaseMapFile)"
-        ProjectDir="$(ProjectDir)"
-        ResourceDirectory="$(MonoAndroidResDirIntermediate)"
-        Resources="@(_AndroidResourceDest)"
-    />
-    <Touch Files="$(_GenerateResourceCaseMapFile)" />
-    <ItemGroup>
-      <FileWrites Include="$(_GenerateResourceCaseMapFile)" />
-    </ItemGroup>
+  <!-- Generate a ResourceMap file for the project and its resources -->
+  <GenerateResourceCaseMap
+      AdditionalResourceDirectories="@(LibraryResourceDirectories)"
+      OutputFile="$(_GenerateResourceCaseMapFile)"
+      ProjectDir="$(ProjectDir)"
+      ResourceDirectory="$(MonoAndroidResDirIntermediate)"
+      Resources="@(_AndroidResourceDest)"
+  />
+  <Touch Files="$(_GenerateResourceCaseMapFile)" />
+  <ItemGroup>
+    <FileWrites Include="$(_GenerateResourceCaseMapFile)" />
+  </ItemGroup>
 </Target>
 
 <Target Name="_GenerateResourceDesignerIntermediateClass"
@@ -99,16 +99,16 @@ Copyright (C) 2016 Xamarin. All rights reserved.
   <!-- Creates a Resource.designer.cs file in the Intermediate output path which derives from the
        Designer Assembly, for backward compatability.
    -->
-    <GenerateResourceDesignerIntermediateClass
-        IsApplication="$(AndroidApplication)"
-        Namespace="$(AndroidResgenNamespace)"
-        OutputFile="$(_GenerateResourceDesignerClassFile)"
-    >
-    </GenerateResourceDesignerIntermediateClass>
-    <Touch Files="$(_GenerateResourceDesignerClassFile)" />
-    <ItemGroup>
-      <FileWrites Include="$(_GenerateResourceDesignerClassFile)" />
-    </ItemGroup>
+  <GenerateResourceDesignerIntermediateClass
+      IsApplication="$(AndroidApplication)"
+      Namespace="$(AndroidResgenNamespace)"
+      OutputFile="$(_GenerateResourceDesignerClassFile)"
+  >
+  </GenerateResourceDesignerIntermediateClass>
+  <Touch Files="$(_GenerateResourceDesignerClassFile)" />
+  <ItemGroup>
+    <FileWrites Include="$(_GenerateResourceDesignerClassFile)" />
+  </ItemGroup>
 </Target>
 
 <Target Name="_GenerateResourceDesignerAssembly"
@@ -116,41 +116,41 @@ Copyright (C) 2016 Xamarin. All rights reserved.
     DependsOnTargets="_GenerateResourceCaseMap"
     Inputs="$(_DesignerIntermediateOutputPath)R.txt"
     Outputs="$(_GenerateResourceDesignerAssemblyOutput)">
-    <GenerateResourceDesignerAssembly
-        ContinueOnError="$(DesignTimeBuild)"
-        AdditionalResourceDirectories="@(LibraryResourceDirectories)"
-        AssemblyName="$(AssemblyName)"
-        CaseMapFile="$(_GenerateResourceCaseMapFile)"
-        DesignTimeBuild="$(DesignTimeBuild)"
-        Deterministic="$(Deterministic)"
-        FrameworkDirectories="$(_XATargetFrameworkDirectories);$(_XATargetFrameworkDirectories)Facades"
-        IsApplication="$(AndroidApplication)"
-        OutputFile="$(_GenerateResourceDesignerAssemblyOutput)"
-        ProjectDir="$(ProjectDir)"
-        Resources="@(AndroidResource);@(AndroidBoundLayout)"
-        ResourceDirectory="$(MonoAndroidResourcePrefix)"
-        RTxtFile="$(_DesignerIntermediateOutputPath)R.txt"
-        TargetFrameworkIdentifier="$(TargetFrameworkIdentifier)"
-        TargetFrameworkVersion="$(TargetFrameworkVersion)"
-    >
-    </GenerateResourceDesignerAssembly>
-    <ItemGroup>
-      <FileWrites Include="$(_GenerateResourceDesignerAssemblyOutput)" />
-    </ItemGroup>
+  <GenerateResourceDesignerAssembly
+      ContinueOnError="$(DesignTimeBuild)"
+      AdditionalResourceDirectories="@(LibraryResourceDirectories)"
+      AssemblyName="$(AssemblyName)"
+      CaseMapFile="$(_GenerateResourceCaseMapFile)"
+      DesignTimeBuild="$(DesignTimeBuild)"
+      Deterministic="$(Deterministic)"
+      FrameworkDirectories="$(_XATargetFrameworkDirectories);$(_XATargetFrameworkDirectories)Facades"
+      IsApplication="$(AndroidApplication)"
+      OutputFile="$(_GenerateResourceDesignerAssemblyOutput)"
+      ProjectDir="$(ProjectDir)"
+      Resources="@(AndroidResource);@(AndroidBoundLayout)"
+      ResourceDirectory="$(MonoAndroidResourcePrefix)"
+      RTxtFile="$(_DesignerIntermediateOutputPath)R.txt"
+      TargetFrameworkIdentifier="$(TargetFrameworkIdentifier)"
+      TargetFrameworkVersion="$(TargetFrameworkVersion)"
+  >
+  </GenerateResourceDesignerAssembly>
+  <ItemGroup>
+    <FileWrites Include="$(_GenerateResourceDesignerAssemblyOutput)" />
+  </ItemGroup>
 </Target>
 
 <Target Name="_CheckForInvalidDesignerConfig"
     Condition=" '$(AndroidUseDesignerAssembly)' != 'True' "
     DependsOnTargets="_AddAndroidCustomMetaData">
-    <ItemGroup>
-      <_ErrorItems Include="@(_MonoAndroidReferencePath)" Condition=" '%(_MonoAndroidReferencePath.HasResourceDesignerAssemblyReference)' == 'True' "/>
-      <_ErrorItems Include="@(_MonoAndroidReferenceDependencyPaths)"  Condition=" '%(_MonoAndroidReferenceDependencyPaths.HasResourceDesignerAssemblyReference)' == 'True' "/>
-    </ItemGroup>
-    <AndroidError Code="XA1034"
-        ResourceName="XA1034"
-        FormatArguments="%(_ErrorItems.FullPath)"
-        Condition=" '@(_ErrorItems->Count())' != '0' "
-    />
+  <ItemGroup>
+    <_ErrorItems Include="@(_MonoAndroidReferencePath)" Condition=" '%(_MonoAndroidReferencePath.HasResourceDesignerAssemblyReference)' == 'True' "/>
+    <_ErrorItems Include="@(_MonoAndroidReferenceDependencyPaths)"  Condition=" '%(_MonoAndroidReferenceDependencyPaths.HasResourceDesignerAssemblyReference)' == 'True' "/>
+  </ItemGroup>
+  <AndroidError Code="XA1034"
+      ResourceName="XA1034"
+      FormatArguments="%(_ErrorItems.FullPath)"
+      Condition=" '@(_ErrorItems->Count())' != '0' "
+  />
 </Target>
 
 <PropertyGroup>
@@ -168,17 +168,17 @@ Copyright (C) 2016 Xamarin. All rights reserved.
     Condition=" '$(AndroidUseDesignerAssembly)' == 'True' "
     DependsOnTargets="_SetupDesignerProperties"
     AfterTargets="GenerateGlobalUsings">
-    <ItemGroup>
-      <ReferencePath Include="$(_GenerateResourceDesignerAssemblyOutput)">
-        <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
-      </ReferencePath>
-      <Compile Remove="$(_AndroidResourceDesignerFile)" />
-      <Compile Include="$(_GenerateResourceDesignerClassFile)" Condition=" '$(Language)' != 'F#' "/>
-      <!-- For F# we need to use the CompileBefore ItemGroup so that our type is processed
-            before all the other types in the build. Otherwise we get weird compiler errors.
-        -->
-      <CompileBefore Include="$(_GenerateResourceDesignerClassFile)" Condition=" '$(Language)' == 'F#' "/>
-    </ItemGroup>
+  <ItemGroup>
+    <ReferencePath Include="$(_GenerateResourceDesignerAssemblyOutput)">
+      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
+    </ReferencePath>
+    <Compile Remove="$(_AndroidResourceDesignerFile)" />
+    <Compile Include="$(_GenerateResourceDesignerClassFile)" Condition=" '$(Language)' != 'F#' "/>
+    <!-- For F# we need to use the CompileBefore ItemGroup so that our type is processed
+          before all the other types in the build. Otherwise we get weird compiler errors.
+      -->
+    <CompileBefore Include="$(_GenerateResourceDesignerClassFile)" Condition=" '$(Language)' == 'F#' "/>
+  </ItemGroup>
 </Target>
 
 <!--
@@ -193,18 +193,18 @@ Copyright (C) 2016 Xamarin. All rights reserved.
     Condition=" '$(AndroidUseDesignerAssembly)' == 'True' "
     AfterTargets="ComputeResolvedFilesToPublishList"
     DependsOnTargets="_SetupDesignerProperties">
-    <ItemGroup>
-      <ResolvedFileToPublish Include="$(_GenerateResourceDesignerAssemblyOutput)">
-        <RelativePath>$(_DesignerAssemblyName).dll</RelativePath>
-        <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
-        <PostprocessAssembly>true</PostprocessAssembly>
-        <IsTrimmable>true</IsTrimmable>
-      </ResolvedFileToPublish>
-    </ItemGroup>
+  <ItemGroup>
+    <ResolvedFileToPublish Include="$(_GenerateResourceDesignerAssemblyOutput)">
+      <RelativePath>$(_DesignerAssemblyName).dll</RelativePath>
+      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
+      <PostprocessAssembly>true</PostprocessAssembly>
+      <IsTrimmable>true</IsTrimmable>
+    </ResolvedFileToPublish>
+  </ItemGroup>
 </Target>
 
 <Target Name="_BuildResourceDesigner"
     Condition=" '$(AndroidUseDesignerAssembly)' == 'True' "
     DependsOnTargets="$(_BuildResourceDesignerDependsOn)" />
 
-</Project>
\ No newline at end of file
+</Project>
