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 5d4506284cd..ca499db4505 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 @@ -45,6 +45,15 @@ false + + + <_AndroidZipAlignment Condition=" '$(_AndroidZipAlignment)' == '' ">4 diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/AndroidZipAlign.cs b/src/Xamarin.Android.Build.Tasks/Tasks/AndroidZipAlign.cs index 262c7af4db1..c0508250737 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/AndroidZipAlign.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/AndroidZipAlign.cs @@ -7,6 +7,10 @@ namespace Xamarin.Android.Tasks { public class AndroidZipAlign : AndroidRunToolTask { + // Sometime next year the default value should be changed to 16 since it's going to be a Google Play store requirement for + // application submissions + internal const int DefaultZipAlignment = 4; + public override string TaskPrefix => "AZA"; [Required] @@ -15,7 +19,7 @@ public class AndroidZipAlign : AndroidRunToolTask [Required] public ITaskItem DestinationDirectory { get; set; } - int alignment = 4; + int alignment = DefaultZipAlignment; public int Alignment { get {return alignment;} set {alignment = value;} @@ -53,4 +57,3 @@ protected override void LogEventsFromTextOutput (string singleLine, MessageImpor } } } - diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs index 29a2118a86f..6340419ca9d 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs @@ -80,6 +80,7 @@ public class GeneratePackageManagerJava : AndroidTask public string AndroidSequencePointsMode { get; set; } public bool EnableSGenConcurrent { get; set; } public string? CustomBundleConfigFile { get; set; } + public int ZipAlignmentPages { get; set; } = AndroidZipAlign.DefaultZipAlignment; [Output] public string BuildId { get; set; } @@ -334,6 +335,7 @@ void AddEnvironment () bool haveRuntimeConfigBlob = !String.IsNullOrEmpty (RuntimeConfigBinFilePath) && File.Exists (RuntimeConfigBinFilePath); var jniRemappingNativeCodeInfo = BuildEngine4.GetRegisteredTaskObjectAssemblyLocal (ProjectSpecificTaskObjectKey (GenerateJniRemappingNativeCode.JniRemappingNativeCodeInfoKey), RegisteredTaskObjectLifetime.Build); + uint zipAlignmentMask = MonoAndroidHelper.ZipAlignmentToMask (ZipAlignmentPages); var appConfigAsmGen = new ApplicationConfigNativeAssemblyGenerator (environmentVariables, systemProperties, Log) { UsesMonoAOT = usesMonoAOT, UsesMonoLLVM = EnableLLVM, @@ -357,6 +359,7 @@ void AddEnvironment () JNIEnvRegisterJniNativesToken = jnienv_registerjninatives_method_token, JniRemappingReplacementTypeCount = jniRemappingNativeCodeInfo == null ? 0 : jniRemappingNativeCodeInfo.ReplacementTypeCount, JniRemappingReplacementMethodIndexEntryCount = jniRemappingNativeCodeInfo == null ? 0 : jniRemappingNativeCodeInfo.ReplacementMethodIndexEntryCount, + ZipAlignmentMask = zipAlignmentMask, MarshalMethodsEnabled = EnableMarshalMethods, IgnoreSplitConfigs = ShouldIgnoreSplitConfigs (), }; diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/LinkApplicationSharedLibraries.cs b/src/Xamarin.Android.Build.Tasks/Tasks/LinkApplicationSharedLibraries.cs index cc021dbae71..617ade907a4 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/LinkApplicationSharedLibraries.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/LinkApplicationSharedLibraries.cs @@ -44,6 +44,8 @@ sealed class InputFiles [Required] public string AndroidBinUtilsDirectory { get; set; } + public int ZipAlignmentPages { get; set; } = AndroidZipAlign.DefaultZipAlignment; + public override System.Threading.Tasks.Task RunTaskAsync () { return this.WhenAll (GetLinkerConfigs (), RunLinker); @@ -129,7 +131,6 @@ IEnumerable GetLinkerConfigs () "-soname libxamarin-app.so " + "-z relro " + "-z noexecstack " + - "-z max-page-size=4096 " + "--enable-new-dtags " + "--build-id " + "--warn-shared-textrel " + @@ -186,6 +187,10 @@ IEnumerable GetLinkerConfigs () } } + uint maxPageSize = MonoAndroidHelper.ZipAlignmentToPageSize (ZipAlignmentPages); + targetLinkerArgs.Add ("-z"); + targetLinkerArgs.Add ($"max-page-size={maxPageSize}"); + string targetArgs = String.Join (" ", targetLinkerArgs); yield return new Config { LinkerPath = ld, diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/EnvironmentHelper.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/EnvironmentHelper.cs index 9cd8d26ffc0..9f93faf206e 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/EnvironmentHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/EnvironmentHelper.cs @@ -63,11 +63,12 @@ public sealed class ApplicationConfig public uint jnienv_registerjninatives_method_token; public uint jni_remapping_replacement_type_count; public uint jni_remapping_replacement_method_index_entry_count; + public uint zip_alignment_mask; public uint mono_components_mask; public string android_package_name = String.Empty; } - const uint ApplicationConfigFieldCount = 26; + const uint ApplicationConfigFieldCount = 27; const string ApplicationConfigSymbolName = "application_config"; const string AppEnvironmentVariablesSymbolName = "app_environment_variables"; @@ -326,12 +327,17 @@ static ApplicationConfig ReadApplicationConfig (EnvironmentFile envFile) ret.jni_remapping_replacement_method_index_entry_count = ConvertFieldToUInt32 ("jni_remapping_replacement_method_index_entry_count", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); break; - case 24: // mono_components_mask: uint32_t / .word | .long + case 24: // zip_alignment_mask: uint32_t / .word | .long + Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); + ret.zip_alignment_mask = ConvertFieldToUInt32 ("zip_alignment_mask", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); + break; + + case 25: // mono_components_mask: uint32_t / .word | .long Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); ret.mono_components_mask = ConvertFieldToUInt32 ("mono_components_mask", envFile.Path, parser.SourceFilePath, item.LineNumber, field [1]); break; - case 25: // android_package_name: string / [pointer type] + case 26: // android_package_name: string / [pointer type] Assert.IsTrue (expectedPointerTypes.Contains (field [0]), $"Unexpected pointer field type in '{envFile.Path}:{item.LineNumber}': {field [0]}"); pointers.Add (field [1].Trim ()); break; diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfig.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfig.cs index 96fa8af6f5a..2b24f2d0347 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfig.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfig.cs @@ -55,6 +55,9 @@ sealed class ApplicationConfig public uint jni_remapping_replacement_type_count; public uint jni_remapping_replacement_method_index_entry_count; + // 3, for 4-byte alignment (4k memory pages); 15, for 16-byte alignment (16k memory pages) + public uint zip_alignment_mask; + [NativeAssembler (NumberFormat = LLVMIR.LlvmIrVariableNumberFormat.Hexadecimal)] public uint mono_components_mask; public string android_package_name = String.Empty; diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs index 53140f8cf70..642f5183573 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs @@ -183,6 +183,7 @@ sealed class XamarinAndroidBundledAssembly public int JNIEnvRegisterJniNativesToken { get; set; } public int JniRemappingReplacementTypeCount { get; set; } public int JniRemappingReplacementMethodIndexEntryCount { get; set; } + public uint ZipAlignmentMask { get; set; } public MonoComponent MonoComponents { get; set; } public PackageNamingPolicy PackageNamingPolicy { get; set; } public List NativeLibraries { get; set; } @@ -244,6 +245,7 @@ protected override void Construct (LlvmIrModule module) jnienv_registerjninatives_method_token = (uint)JNIEnvRegisterJniNativesToken, jni_remapping_replacement_type_count = (uint)JniRemappingReplacementTypeCount, jni_remapping_replacement_method_index_entry_count = (uint)JniRemappingReplacementMethodIndexEntryCount, + zip_alignment_mask = ZipAlignmentMask, mono_components_mask = (uint)MonoComponents, android_package_name = AndroidPackageName, }; diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs b/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs index bfd3c67eb48..54c1303c1f8 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs @@ -712,5 +712,22 @@ internal static void DumpMarshalMethodsToConsole (string heading, IDictionary ZipAlignmentToMaskOrPageSize (alignment, needMask: true); + public static uint ZipAlignmentToPageSize (int alignment) => ZipAlignmentToMaskOrPageSize (alignment, needMask: false); + + static uint ZipAlignmentToMaskOrPageSize (int alignment, bool needMask) + { + const uint pageSize4k = 4096; + const uint pageMask4k = 3; + const uint pageSize16k = 16384; + const uint pageMask16k = 15; + + return alignment switch { + 4 => needMask ? pageMask4k : pageSize4k, + 16 => needMask ? pageMask16k : pageSize16k, + _ => throw new InvalidOperationException ($"Internal error: unsupported zip page alignment value {alignment}") + }; + } } } diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 915441086a8..a919417c349 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -1724,6 +1724,7 @@ because xbuild doesn't support framework reference assemblies. UseAssemblyStore="$(AndroidUseAssemblyStore)" EnableMarshalMethods="$(_AndroidUseMarshalMethods)" CustomBundleConfigFile="$(AndroidBundleConfigurationFile)" + ZipAlignmentPages="$(_AndroidZipAlignment)" > @@ -2010,6 +2011,7 @@ because xbuild doesn't support framework reference assemblies. ApplicationSharedLibraries="@(_ApplicationSharedLibrary)" DebugBuild="$(AndroidIncludeDebugSymbols)" AndroidBinUtilsDirectory="$(AndroidBinUtilsDirectory)" + ZipAlignmentPages="$(_AndroidZipAlignment)" /> @@ -2354,6 +2356,7 @@ because xbuild doesn't support framework reference assemblies.