diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs index 2ad1e0f1a0f..dba71a8b077 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs @@ -269,10 +269,38 @@ void AddEnvironment () throw new InvalidOperationException ($"Unsupported BoundExceptionType value '{BoundExceptionType}'"); } + int assemblyNameWidth = 0; int assemblyCount = ResolvedAssemblies.Length; + Encoding assemblyNameEncoding = Encoding.UTF8; + + Action updateNameWidth = (ITaskItem assembly) => { + string assemblyName = Path.GetFileName (assembly.ItemSpec); + int nameBytes = assemblyNameEncoding.GetBytes (assemblyName).Length; + if (nameBytes > assemblyNameWidth) { + assemblyNameWidth = nameBytes; + } + }; + if (SatelliteAssemblies != null) { assemblyCount += SatelliteAssemblies.Length; + + foreach (ITaskItem assembly in SatelliteAssemblies) { + updateNameWidth (assembly); + } + } + + foreach (var assembly in ResolvedAssemblies) { + updateNameWidth (assembly); + } + + int abiNameLength = 0; + foreach (string abi in SupportedAbis) { + if (abi.Length <= abiNameLength) { + continue; + } + abiNameLength = abi.Length; } + assemblyNameWidth += abiNameLength + 1; // room for '/' bool haveRuntimeConfigBlob = !String.IsNullOrEmpty (RuntimeConfigBinFilePath) && File.Exists (RuntimeConfigBinFilePath); var appConfState = BuildEngine4.GetRegisteredTaskObjectAssemblyLocal (ApplicationConfigTaskState.RegisterTaskObjectKey, RegisteredTaskObjectLifetime.Build); @@ -295,6 +323,7 @@ void AddEnvironment () JniAddNativeMethodRegistrationAttributePresent = appConfState != null ? appConfState.JniAddNativeMethodRegistrationAttributePresent : false, HaveRuntimeConfigBlob = haveRuntimeConfigBlob, NumberOfAssembliesInApk = assemblyCount, + BundledAssemblyNameWidth = assemblyNameWidth + 1, }; using (var sw = MemoryStreamPool.Shared.CreateStreamWriter ()) { 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 0dd769eacc7..e539ecb9731 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 @@ -31,9 +31,10 @@ public sealed class ApplicationConfig public uint environment_variable_count; public uint system_property_count; public uint number_of_assemblies_in_apk; + public uint bundled_assembly_name_width; public string android_package_name; }; - const uint ApplicationConfigFieldCount = 14; + const uint ApplicationConfigFieldCount = 15; static readonly object ndkInitLock = new object (); static readonly char[] readElfFieldSeparator = new [] { ' ', '\t' }; @@ -182,7 +183,12 @@ static ApplicationConfig ReadApplicationConfig (string envFile) ret.number_of_assemblies_in_apk = ConvertFieldToUInt32 ("number_of_assemblies_in_apk", envFile, i, field [1]); break; - case 13: // android_package_name: string / [pointer type] + case 13: // bundled_assembly_name_width: uint32_t / .word | .long + Assert.IsTrue (expectedUInt32Types.Contains (field [0]), $"Unexpected uint32_t field type in '{envFile}:{i}': {field [0]}"); + ret.bundled_assembly_name_width = ConvertFieldToUInt32 ("bundled_assembly_name_width", envFile, i, field [1]); + break; + + case 14: // android_package_name: string / [pointer type] Assert.IsTrue (expectedPointerTypes.Contains (field [0]), $"Unexpected pointer field type in '{envFile}:{i}': {field [0]}"); pointers.Add (field [1].Trim ()); break; 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 b11610478ad..6377ed0b0f2 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 @@ -8,166 +8,166 @@ "Size": 7236 }, "assemblies/Java.Interop.dll": { - "Size": 64941 + "Size": 64940 }, "assemblies/Microsoft.Win32.Primitives.dll": { - "Size": 4856 + "Size": 4869 }, "assemblies/Mono.Android.dll": { - "Size": 453236 + "Size": 453210 }, "assemblies/mscorlib.dll": { - "Size": 4216 + "Size": 4223 }, "assemblies/netstandard.dll": { - "Size": 5923 + "Size": 5931 }, "assemblies/rc.bin": { "Size": 946 }, "assemblies/System.Collections.Concurrent.dll": { - "Size": 12647 + "Size": 12657 }, "assemblies/System.Collections.dll": { - "Size": 20436 + "Size": 20542 }, "assemblies/System.Collections.NonGeneric.dll": { - "Size": 9490 + "Size": 9513 }, "assemblies/System.ComponentModel.dll": { - "Size": 2907 + "Size": 2916 }, "assemblies/System.ComponentModel.Primitives.dll": { - "Size": 3500 + "Size": 3509 }, "assemblies/System.ComponentModel.TypeConverter.dll": { - "Size": 7237 + "Size": 7245 }, "assemblies/System.Console.dll": { - "Size": 6854 + "Size": 6865 }, "assemblies/System.Core.dll": { - "Size": 2409 + "Size": 2416 }, "assemblies/System.Diagnostics.DiagnosticSource.dll": { - "Size": 4029 + "Size": 4039 }, "assemblies/System.Diagnostics.TraceSource.dll": { - "Size": 7708 + "Size": 7718 }, "assemblies/System.dll": { - "Size": 2772 + "Size": 2779 }, "assemblies/System.Drawing.dll": { - "Size": 2462 + "Size": 2471 }, "assemblies/System.Drawing.Primitives.dll": { - "Size": 13157 + "Size": 13166 }, "assemblies/System.Formats.Asn1.dll": { - "Size": 28056 + "Size": 28064 }, "assemblies/System.IO.Compression.Brotli.dll": { - "Size": 12614 + "Size": 12625 }, "assemblies/System.IO.Compression.dll": { - "Size": 20019 + "Size": 20029 }, "assemblies/System.IO.IsolatedStorage.dll": { - "Size": 12048 + "Size": 12056 }, "assemblies/System.Linq.dll": { - "Size": 21047 + "Size": 21059 }, "assemblies/System.Linq.Expressions.dll": { - "Size": 186847 + "Size": 187198 }, "assemblies/System.Net.Http.dll": { - "Size": 219177 + "Size": 219143 }, "assemblies/System.Net.NameResolution.dll": { - "Size": 14139 + "Size": 14148 }, "assemblies/System.Net.NetworkInformation.dll": { - "Size": 18709 + "Size": 18719 }, "assemblies/System.Net.Primitives.dll": { - "Size": 43138 + "Size": 43113 }, "assemblies/System.Net.Quic.dll": { - "Size": 47303 + "Size": 47792 }, "assemblies/System.Net.Requests.dll": { - "Size": 4372 + "Size": 4382 }, "assemblies/System.Net.Security.dll": { - "Size": 59085 + "Size": 59106 }, "assemblies/System.Net.Sockets.dll": { - "Size": 56023 + "Size": 56026 }, "assemblies/System.ObjectModel.dll": { - "Size": 13202 + "Size": 13222 }, "assemblies/System.Private.CoreLib.dll": { - "Size": 807464 + "Size": 807755 }, "assemblies/System.Private.DataContractSerialization.dll": { - "Size": 198721 + "Size": 198766 }, "assemblies/System.Private.Uri.dll": { - "Size": 45114 + "Size": 45147 }, "assemblies/System.Private.Xml.dll": { - "Size": 256175 + "Size": 256185 }, "assemblies/System.Private.Xml.Linq.dll": { - "Size": 18743 + "Size": 18752 }, "assemblies/System.Runtime.CompilerServices.Unsafe.dll": { "Size": 1844 }, "assemblies/System.Runtime.dll": { - "Size": 2868 + "Size": 2877 }, "assemblies/System.Runtime.InteropServices.RuntimeInformation.dll": { - "Size": 3934 + "Size": 3945 }, "assemblies/System.Runtime.Numerics.dll": { - "Size": 25308 + "Size": 25253 }, "assemblies/System.Runtime.Serialization.dll": { - "Size": 2384 + "Size": 2392 }, "assemblies/System.Runtime.Serialization.Formatters.dll": { - "Size": 3791 + "Size": 3802 }, "assemblies/System.Runtime.Serialization.Primitives.dll": { - "Size": 4804 + "Size": 4813 }, "assemblies/System.Security.Cryptography.Algorithms.dll": { - "Size": 44515 + "Size": 44388 }, "assemblies/System.Security.Cryptography.Encoding.dll": { - "Size": 15178 + "Size": 15181 }, "assemblies/System.Security.Cryptography.Primitives.dll": { - "Size": 10308 + "Size": 10319 }, "assemblies/System.Security.Cryptography.X509Certificates.dll": { - "Size": 78809 + "Size": 78796 }, "assemblies/System.Text.RegularExpressions.dll": { - "Size": 78319 + "Size": 78340 }, "assemblies/System.Threading.Channels.dll": { - "Size": 17982 + "Size": 18006 }, "assemblies/System.Xml.dll": { - "Size": 2278 + "Size": 2285 }, "assemblies/UnnamedProject.dll": { - "Size": 117076 + "Size": 117083 }, "assemblies/Xamarin.AndroidX.Activity.dll": { "Size": 6374 @@ -239,10 +239,10 @@ "Size": 3455384 }, "lib/arm64-v8a/libmonodroid.so": { - "Size": 338784 + "Size": 342824 }, "lib/arm64-v8a/libmonosgen-2.0.so": { - "Size": 3155488 + "Size": 3159584 }, "lib/arm64-v8a/libSystem.IO.Compression.Native.so": { "Size": 776216 @@ -254,7 +254,7 @@ "Size": 150024 }, "lib/arm64-v8a/libxamarin-app.so": { - "Size": 126816 + "Size": 134032 }, "META-INF/android.support.design_material.version": { "Size": 12 @@ -2006,5 +2006,5 @@ "Size": 341040 } }, - "PackageSize": 8672957 + "PackageSize": 8677053 } \ 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 98a085a8248..21a794dffef 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,264 @@ "AndroidManifest.xml": { "Size": 3120 }, + "assemblies/FormsViewGroup.dll": { + "Size": 7200 + }, + "assemblies/Java.Interop.dll": { + "Size": 68711 + }, + "assemblies/Mono.Android.dll": { + "Size": 557367 + }, + "assemblies/Mono.Security.dll": { + "Size": 68420 + }, + "assemblies/mscorlib.dll": { + "Size": 915407 + }, + "assemblies/System.Core.dll": { + "Size": 164038 + }, + "assemblies/System.dll": { + "Size": 388853 + }, + "assemblies/System.Drawing.Common.dll": { + "Size": 12354 + }, + "assemblies/System.Net.Http.dll": { + "Size": 110631 + }, + "assemblies/System.Numerics.dll": { + "Size": 15680 + }, + "assemblies/System.Runtime.Serialization.dll": { + "Size": 186652 + }, + "assemblies/System.ServiceModel.Internals.dll": { + "Size": 26578 + }, + "assemblies/System.Xml.dll": { + "Size": 395644 + }, + "assemblies/UnnamedProject.dll": { + "Size": 116882 + }, + "assemblies/Xamarin.AndroidX.Activity.dll": { + "Size": 7686 + }, + "assemblies/Xamarin.AndroidX.AppCompat.AppCompatResources.dll": { + "Size": 6635 + }, + "assemblies/Xamarin.AndroidX.AppCompat.dll": { + "Size": 125317 + }, + "assemblies/Xamarin.AndroidX.CardView.dll": { + "Size": 7354 + }, + "assemblies/Xamarin.AndroidX.CoordinatorLayout.dll": { + "Size": 18259 + }, + "assemblies/Xamarin.AndroidX.Core.dll": { + "Size": 131919 + }, + "assemblies/Xamarin.AndroidX.DrawerLayout.dll": { + "Size": 15417 + }, + "assemblies/Xamarin.AndroidX.Fragment.dll": { + "Size": 43119 + }, + "assemblies/Xamarin.AndroidX.Legacy.Support.Core.UI.dll": { + "Size": 6704 + }, + "assemblies/Xamarin.AndroidX.Lifecycle.Common.dll": { + "Size": 7050 + }, + "assemblies/Xamarin.AndroidX.Lifecycle.LiveData.Core.dll": { + "Size": 7179 + }, + "assemblies/Xamarin.AndroidX.Lifecycle.ViewModel.dll": { + "Size": 4859 + }, + "assemblies/Xamarin.AndroidX.Loader.dll": { + "Size": 13574 + }, + "assemblies/Xamarin.AndroidX.RecyclerView.dll": { + "Size": 102317 + }, + "assemblies/Xamarin.AndroidX.SavedState.dll": { + "Size": 6262 + }, + "assemblies/Xamarin.AndroidX.SwipeRefreshLayout.dll": { + "Size": 11261 + }, + "assemblies/Xamarin.AndroidX.ViewPager.dll": { + "Size": 19409 + }, + "assemblies/Xamarin.Forms.Core.dll": { + "Size": 524723 + }, + "assemblies/Xamarin.Forms.Platform.Android.dll": { + "Size": 384855 + }, + "assemblies/Xamarin.Forms.Platform.dll": { + "Size": 56878 + }, + "assemblies/Xamarin.Forms.Xaml.dll": { + "Size": 55786 + }, + "assemblies/Xamarin.Google.Android.Material.dll": { + "Size": 43488 + }, + "classes.dex": { + "Size": 3455228 + }, + "lib/arm64-v8a/libmono-btls-shared.so": { + "Size": 1613872 + }, + "lib/arm64-v8a/libmono-native.so": { + "Size": 707024 + }, + "lib/arm64-v8a/libmonodroid.so": { + "Size": 283112 + }, + "lib/arm64-v8a/libmonosgen-2.0.so": { + "Size": 4037584 + }, + "lib/arm64-v8a/libxa-internal-api.so": { + "Size": 65496 + }, + "lib/arm64-v8a/libxamarin-app.so": { + "Size": 142104 + }, + "META-INF/android.support.design_material.version": { + "Size": 12 + }, + "META-INF/ANDROIDD.RSA": { + "Size": 1213 + }, + "META-INF/ANDROIDD.SF": { + "Size": 75858 + }, + "META-INF/androidx.activity_activity.version": { + "Size": 6 + }, + "META-INF/androidx.appcompat_appcompat-resources.version": { + "Size": 6 + }, + "META-INF/androidx.appcompat_appcompat.version": { + "Size": 6 + }, + "META-INF/androidx.arch.core_core-runtime.version": { + "Size": 6 + }, + "META-INF/androidx.asynclayoutinflater_asynclayoutinflater.version": { + "Size": 6 + }, + "META-INF/androidx.browser_browser.version": { + "Size": 6 + }, + "META-INF/androidx.cardview_cardview.version": { + "Size": 6 + }, + "META-INF/androidx.coordinatorlayout_coordinatorlayout.version": { + "Size": 6 + }, + "META-INF/androidx.core_core.version": { + "Size": 6 + }, + "META-INF/androidx.cursoradapter_cursoradapter.version": { + "Size": 6 + }, + "META-INF/androidx.customview_customview.version": { + "Size": 6 + }, + "META-INF/androidx.documentfile_documentfile.version": { + "Size": 6 + }, + "META-INF/androidx.drawerlayout_drawerlayout.version": { + "Size": 6 + }, + "META-INF/androidx.fragment_fragment.version": { + "Size": 6 + }, + "META-INF/androidx.interpolator_interpolator.version": { + "Size": 6 + }, + "META-INF/androidx.legacy_legacy-support-core-ui.version": { + "Size": 6 + }, + "META-INF/androidx.legacy_legacy-support-core-utils.version": { + "Size": 6 + }, + "META-INF/androidx.legacy_legacy-support-v4.version": { + "Size": 6 + }, + "META-INF/androidx.lifecycle_lifecycle-livedata-core.version": { + "Size": 6 + }, + "META-INF/androidx.lifecycle_lifecycle-livedata.version": { + "Size": 6 + }, + "META-INF/androidx.lifecycle_lifecycle-runtime.version": { + "Size": 6 + }, + "META-INF/androidx.lifecycle_lifecycle-viewmodel.version": { + "Size": 6 + }, + "META-INF/androidx.loader_loader.version": { + "Size": 6 + }, + "META-INF/androidx.localbroadcastmanager_localbroadcastmanager.version": { + "Size": 6 + }, + "META-INF/androidx.media_media.version": { + "Size": 6 + }, + "META-INF/androidx.print_print.version": { + "Size": 6 + }, + "META-INF/androidx.recyclerview_recyclerview.version": { + "Size": 6 + }, + "META-INF/androidx.savedstate_savedstate.version": { + "Size": 6 + }, + "META-INF/androidx.slidingpanelayout_slidingpanelayout.version": { + "Size": 6 + }, + "META-INF/androidx.swiperefreshlayout_swiperefreshlayout.version": { + "Size": 6 + }, + "META-INF/androidx.transition_transition.version": { + "Size": 6 + }, + "META-INF/androidx.vectordrawable_vectordrawable-animated.version": { + "Size": 6 + }, + "META-INF/androidx.vectordrawable_vectordrawable.version": { + "Size": 6 + }, + "META-INF/androidx.versionedparcelable_versionedparcelable.version": { + "Size": 6 + }, + "META-INF/androidx.viewpager_viewpager.version": { + "Size": 6 + }, + "META-INF/com.google.android.material_material.version": { + "Size": 10 + }, + "META-INF/MANIFEST.MF": { + "Size": 75731 + }, + "META-INF/proguard/androidx-annotations.pro": { + "Size": 339 + }, + "res/anim-v21/design_bottom_sheet_slide_in.xml": { + "Size": 616 + }, + "res/anim-v21/design_bottom_sheet_slide_out.xml": { + "Size": 616 + }, "res/anim/abc_fade_in.xml": { "Size": 388 }, @@ -100,11 +358,8 @@ "res/anim/exittoright.xml": { "Size": 468 }, - "res/anim-v21/design_bottom_sheet_slide_in.xml": { - "Size": 616 - }, - "res/anim-v21/design_bottom_sheet_slide_out.xml": { - "Size": 616 + "res/animator-v21/design_appbar_state_list_animator.xml": { + "Size": 1216 }, "res/animator/design_fab_hide_motion_spec.xml": { "Size": 796 @@ -133,29 +388,59 @@ "res/animator/mtrl_fab_transformation_sheet_expand_spec.xml": { "Size": 1888 }, - "res/animator-v21/design_appbar_state_list_animator.xml": { - "Size": 1216 - }, - "res/color/abc_background_cache_hint_selector_material_dark.xml": { - "Size": 468 + "res/color-v21/abc_btn_colored_borderless_text_material.xml": { + "Size": 464 }, - "res/color/abc_background_cache_hint_selector_material_light.xml": { - "Size": 468 + "res/color-v23/abc_btn_colored_borderless_text_material.xml": { + "Size": 500 }, - "res/color/abc_btn_colored_borderless_text_material.xml": { - "Size": 604 + "res/color-v23/abc_btn_colored_text_material.xml": { + "Size": 500 }, - "res/color/abc_btn_colored_text_material.xml": { - "Size": 604 + "res/color-v23/abc_color_highlight_material.xml": { + "Size": 544 }, - "res/color/abc_hint_foreground_material_dark.xml": { - "Size": 564 + "res/color-v23/abc_tint_btn_checkable.xml": { + "Size": 624 }, - "res/color/abc_hint_foreground_material_light.xml": { - "Size": 564 + "res/color-v23/abc_tint_default.xml": { + "Size": 1120 }, - "res/color/abc_primary_text_disable_only_material_dark.xml": { - "Size": 464 + "res/color-v23/abc_tint_edittext.xml": { + "Size": 668 + }, + "res/color-v23/abc_tint_seek_thumb.xml": { + "Size": 500 + }, + "res/color-v23/abc_tint_spinner.xml": { + "Size": 668 + }, + "res/color-v23/abc_tint_switch_track.xml": { + "Size": 664 + }, + "res/color-v23/design_tint_password_toggle.xml": { + "Size": 376 + }, + "res/color/abc_background_cache_hint_selector_material_dark.xml": { + "Size": 468 + }, + "res/color/abc_background_cache_hint_selector_material_light.xml": { + "Size": 468 + }, + "res/color/abc_btn_colored_borderless_text_material.xml": { + "Size": 604 + }, + "res/color/abc_btn_colored_text_material.xml": { + "Size": 604 + }, + "res/color/abc_hint_foreground_material_dark.xml": { + "Size": 564 + }, + "res/color/abc_hint_foreground_material_light.xml": { + "Size": 564 + }, + "res/color/abc_primary_text_disable_only_material_dark.xml": { + "Size": 464 }, "res/color/abc_primary_text_disable_only_material_light.xml": { "Size": 464 @@ -238,10 +523,10 @@ "res/color/mtrl_tabs_colored_ripple_color.xml": { "Size": 948 }, - "res/color/mtrl_tabs_icon_color_selector.xml": { + "res/color/mtrl_tabs_icon_color_selector_colored.xml": { "Size": 464 }, - "res/color/mtrl_tabs_icon_color_selector_colored.xml": { + "res/color/mtrl_tabs_icon_color_selector.xml": { "Size": 464 }, "res/color/mtrl_tabs_legacy_text_color_selector.xml": { @@ -259,284 +544,221 @@ "res/color/switch_thumb_material_light.xml": { "Size": 464 }, - "res/color-v21/abc_btn_colored_borderless_text_material.xml": { - "Size": 464 - }, - "res/color-v23/abc_btn_colored_borderless_text_material.xml": { - "Size": 500 + "res/drawable-anydpi-v21/design_ic_visibility_off.xml": { + "Size": 1144 }, - "res/color-v23/abc_btn_colored_text_material.xml": { - "Size": 500 + "res/drawable-anydpi-v21/design_ic_visibility.xml": { + "Size": 540 }, - "res/color-v23/abc_color_highlight_material.xml": { - "Size": 544 + "res/drawable-hdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png": { + "Size": 272 }, - "res/color-v23/abc_tint_btn_checkable.xml": { - "Size": 624 + "res/drawable-hdpi-v4/abc_btn_check_to_on_mtrl_000.png": { + "Size": 227 }, - "res/color-v23/abc_tint_default.xml": { - "Size": 1120 + "res/drawable-hdpi-v4/abc_btn_check_to_on_mtrl_015.png": { + "Size": 404 }, - "res/color-v23/abc_tint_edittext.xml": { - "Size": 668 + "res/drawable-hdpi-v4/abc_btn_radio_to_on_mtrl_000.png": { + "Size": 464 }, - "res/color-v23/abc_tint_seek_thumb.xml": { - "Size": 500 + "res/drawable-hdpi-v4/abc_btn_radio_to_on_mtrl_015.png": { + "Size": 563 }, - "res/color-v23/abc_tint_spinner.xml": { - "Size": 668 + "res/drawable-hdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png": { + "Size": 1096 }, - "res/color-v23/abc_tint_switch_track.xml": { - "Size": 664 + "res/drawable-hdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png": { + "Size": 1243 }, - "res/color-v23/design_tint_password_toggle.xml": { - "Size": 376 + "res/drawable-hdpi-v4/abc_cab_background_top_mtrl_alpha.9.png": { + "Size": 226 }, - "res/drawable/abc_btn_borderless_material.xml": { - "Size": 588 + "res/drawable-hdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png": { + "Size": 171 }, - "res/drawable/abc_btn_check_material.xml": { - "Size": 464 + "res/drawable-hdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png": { + "Size": 202 }, - "res/drawable/abc_btn_check_material_anim.xml": { - "Size": 816 + "res/drawable-hdpi-v4/abc_ic_menu_cut_mtrl_alpha.png": { + "Size": 404 }, - "res/drawable/abc_btn_colored_material.xml": { - "Size": 344 + "res/drawable-hdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png": { + "Size": 226 }, - "res/drawable/abc_btn_default_mtrl_shape.xml": { - "Size": 932 + "res/drawable-hdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png": { + "Size": 215 }, - "res/drawable/abc_btn_radio_material.xml": { - "Size": 464 + "res/drawable-hdpi-v4/abc_ic_menu_share_mtrl_alpha.png": { + "Size": 389 }, - "res/drawable/abc_btn_radio_material_anim.xml": { - "Size": 816 + "res/drawable-hdpi-v4/abc_ic_star_black_16dp.png": { + "Size": 263 }, - "res/drawable/abc_cab_background_internal_bg.xml": { - "Size": 372 + "res/drawable-hdpi-v4/abc_ic_star_black_36dp.png": { + "Size": 522 }, - "res/drawable/abc_cab_background_top_material.xml": { - "Size": 336 + "res/drawable-hdpi-v4/abc_ic_star_black_48dp.png": { + "Size": 668 }, - "res/drawable/abc_dialog_material_background.xml": { - "Size": 716 + "res/drawable-hdpi-v4/abc_ic_star_half_black_16dp.png": { + "Size": 197 }, - "res/drawable/abc_edit_text_material.xml": { - "Size": 868 + "res/drawable-hdpi-v4/abc_ic_star_half_black_36dp.png": { + "Size": 328 }, - "res/drawable/abc_ic_ab_back_material.xml": { - "Size": 692 + "res/drawable-hdpi-v4/abc_ic_star_half_black_48dp.png": { + "Size": 431 }, - "res/drawable/abc_ic_arrow_drop_right_black_24dp.xml": { - "Size": 1000 + "res/drawable-hdpi-v4/abc_list_divider_mtrl_alpha.9.png": { + "Size": 167 }, - "res/drawable/abc_ic_clear_material.xml": { - "Size": 684 + "res/drawable-hdpi-v4/abc_list_focused_holo.9.png": { + "Size": 244 }, - "res/drawable/abc_ic_go_search_api_material.xml": { - "Size": 640 + "res/drawable-hdpi-v4/abc_list_longpressed_holo.9.png": { + "Size": 212 }, - "res/drawable/abc_ic_menu_overflow_material.xml": { - "Size": 792 + "res/drawable-hdpi-v4/abc_list_pressed_holo_dark.9.png": { + "Size": 208 }, - "res/drawable/abc_ic_search_api_material.xml": { - "Size": 812 + "res/drawable-hdpi-v4/abc_list_pressed_holo_light.9.png": { + "Size": 208 }, - "res/drawable/abc_ic_voice_search_api_material.xml": { - "Size": 828 + "res/drawable-hdpi-v4/abc_list_selector_disabled_holo_dark.9.png": { + "Size": 228 }, - "res/drawable/abc_item_background_holo_dark.xml": { - "Size": 1012 + "res/drawable-hdpi-v4/abc_list_selector_disabled_holo_light.9.png": { + "Size": 229 }, - "res/drawable/abc_item_background_holo_light.xml": { - "Size": 1012 + "res/drawable-hdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png": { + "Size": 738 }, - "res/drawable/abc_list_divider_material.xml": { - "Size": 480 + "res/drawable-hdpi-v4/abc_popup_background_mtrl_mult.9.png": { + "Size": 1098 }, - "res/drawable/abc_list_selector_background_transition_holo_dark.xml": { - "Size": 424 + "res/drawable-hdpi-v4/abc_scrubber_control_off_mtrl_alpha.png": { + "Size": 201 }, - "res/drawable/abc_list_selector_background_transition_holo_light.xml": { - "Size": 424 + "res/drawable-hdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png": { + "Size": 196 }, - "res/drawable/abc_list_selector_holo_dark.xml": { - "Size": 1064 + "res/drawable-hdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png": { + "Size": 272 }, - "res/drawable/abc_list_selector_holo_light.xml": { - "Size": 1064 + "res/drawable-hdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png": { + "Size": 205 }, - "res/drawable/abc_ratingbar_indicator_material.xml": { - "Size": 664 + "res/drawable-hdpi-v4/abc_scrubber_track_mtrl_alpha.9.png": { + "Size": 196 }, - "res/drawable-v21/abc_ratingbar_indicator_material.xml": { - "Size": 704 + "res/drawable-hdpi-v4/abc_spinner_mtrl_am_alpha.9.png": { + "Size": 345 }, - "res/drawable/abc_ratingbar_material.xml": { - "Size": 664 + "res/drawable-hdpi-v4/abc_switch_track_mtrl_alpha.9.png": { + "Size": 484 }, - "res/drawable-v21/abc_ratingbar_material.xml": { - "Size": 704 + "res/drawable-hdpi-v4/abc_tab_indicator_mtrl_alpha.9.png": { + "Size": 190 }, - "res/drawable/abc_ratingbar_small_material.xml": { - "Size": 664 + "res/drawable-hdpi-v4/abc_text_select_handle_left_mtrl_dark.png": { + "Size": 278 }, - "res/drawable-v21/abc_ratingbar_small_material.xml": { - "Size": 704 + "res/drawable-hdpi-v4/abc_text_select_handle_left_mtrl_light.png": { + "Size": 278 }, - "res/drawable/abc_seekbar_thumb_material.xml": { - "Size": 1100 + "res/drawable-hdpi-v4/abc_text_select_handle_middle_mtrl_dark.png": { + "Size": 398 }, - "res/drawable/abc_seekbar_tick_mark_material.xml": { - "Size": 516 + "res/drawable-hdpi-v4/abc_text_select_handle_middle_mtrl_light.png": { + "Size": 396 }, - "res/drawable/abc_seekbar_track_material.xml": { - "Size": 1408 + "res/drawable-hdpi-v4/abc_text_select_handle_right_mtrl_dark.png": { + "Size": 263 }, - "res/drawable/abc_spinner_textfield_background_material.xml": { - "Size": 1160 + "res/drawable-hdpi-v4/abc_text_select_handle_right_mtrl_light.png": { + "Size": 262 }, - "res/drawable/abc_switch_thumb_material.xml": { - "Size": 464 + "res/drawable-hdpi-v4/abc_textfield_activated_mtrl_alpha.9.png": { + "Size": 186 }, - "res/drawable/abc_tab_indicator_material.xml": { - "Size": 468 + "res/drawable-hdpi-v4/abc_textfield_default_mtrl_alpha.9.png": { + "Size": 192 }, - "res/drawable/abc_text_cursor_material.xml": { - "Size": 516 + "res/drawable-hdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png": { + "Size": 178 }, - "res/drawable/abc_textfield_search_material.xml": { - "Size": 756 + "res/drawable-hdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png": { + "Size": 178 }, - "res/drawable/abc_vector_test.xml": { - "Size": 612 + "res/drawable-hdpi-v4/design_ic_visibility_off.png": { + "Size": 507 }, - "res/drawable/btn_checkbox_checked_mtrl.xml": { - "Size": 2688 + "res/drawable-hdpi-v4/design_ic_visibility.png": { + "Size": 470 }, - "res/drawable/btn_checkbox_checked_to_unchecked_mtrl_animation.xml": { - "Size": 688 + "res/drawable-hdpi-v4/icon.png": { + "Size": 4762 }, - "res/drawable/btn_checkbox_unchecked_mtrl.xml": { - "Size": 2660 + "res/drawable-hdpi-v4/notification_bg_low_normal.9.png": { + "Size": 212 }, - "res/drawable/btn_checkbox_unchecked_to_checked_mtrl_animation.xml": { - "Size": 688 + "res/drawable-hdpi-v4/notification_bg_low_pressed.9.png": { + "Size": 225 }, - "res/drawable/btn_radio_off_mtrl.xml": { - "Size": 1728 - }, - "res/drawable/btn_radio_off_to_on_mtrl_animation.xml": { - "Size": 680 - }, - "res/drawable/btn_radio_on_mtrl.xml": { - "Size": 1656 - }, - "res/drawable/btn_radio_on_to_off_mtrl_animation.xml": { - "Size": 680 - }, - "res/drawable/design_bottom_navigation_item_background.xml": { - "Size": 784 - }, - "res/drawable/design_fab_background.xml": { - "Size": 372 - }, - "res/drawable/design_password_eye.xml": { - "Size": 464 - }, - "res/drawable/design_snackbar_background.xml": { - "Size": 484 - }, - "res/drawable/ic_mtrl_chip_checked_black.xml": { - "Size": 600 - }, - "res/drawable/ic_mtrl_chip_checked_circle.xml": { - "Size": 940 - }, - "res/drawable/ic_mtrl_chip_close_circle.xml": { - "Size": 808 - }, - "res/drawable/mtrl_snackbar_background.xml": { - "Size": 484 - }, - "res/drawable/mtrl_tabs_default_indicator.xml": { - "Size": 628 - }, - "res/drawable/navigation_empty_icon.xml": { - "Size": 516 - }, - "res/drawable/notification_bg.xml": { - "Size": 532 - }, - "res/drawable/notification_bg_low.xml": { - "Size": 532 - }, - "res/drawable/notification_icon_background.xml": { - "Size": 372 - }, - "res/drawable/notification_tile_bg.xml": { - "Size": 304 - }, - "res/drawable/tooltip_frame_dark.xml": { - "Size": 484 - }, - "res/drawable/tooltip_frame_light.xml": { - "Size": 484 - }, - "res/drawable-watch-v20/abc_dialog_material_background.xml": { - "Size": 372 + "res/drawable-hdpi-v4/notification_bg_normal_pressed.9.png": { + "Size": 225 }, - "res/drawable-v21/$avd_hide_password__0.xml": { - "Size": 1176 + "res/drawable-hdpi-v4/notification_bg_normal.9.png": { + "Size": 212 }, - "res/drawable-v21/$avd_hide_password__1.xml": { - "Size": 592 + "res/drawable-hdpi-v4/notify_panel_notification_icon_bg.png": { + "Size": 107 }, - "res/drawable-v21/$avd_hide_password__2.xml": { - "Size": 556 + "res/drawable-ldrtl-hdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png": { + "Size": 199 }, - "res/drawable-v21/$avd_show_password__0.xml": { - "Size": 1136 + "res/drawable-ldrtl-hdpi-v17/abc_ic_menu_cut_mtrl_alpha.png": { + "Size": 400 }, - "res/drawable-v21/$avd_show_password__1.xml": { - "Size": 592 + "res/drawable-ldrtl-hdpi-v17/abc_spinner_mtrl_am_alpha.9.png": { + "Size": 345 }, - "res/drawable-v21/$avd_show_password__2.xml": { - "Size": 556 + "res/drawable-ldrtl-mdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png": { + "Size": 127 }, - "res/drawable-v21/abc_action_bar_item_background_material.xml": { - "Size": 264 + "res/drawable-ldrtl-mdpi-v17/abc_ic_menu_cut_mtrl_alpha.png": { + "Size": 253 }, - "res/drawable-v21/abc_btn_colored_material.xml": { - "Size": 1716 + "res/drawable-ldrtl-mdpi-v17/abc_spinner_mtrl_am_alpha.9.png": { + "Size": 318 }, - "res/drawable-v21/abc_dialog_material_background.xml": { - "Size": 716 + "res/drawable-ldrtl-xhdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png": { + "Size": 178 }, - "res/drawable-v21/abc_edit_text_material.xml": { - "Size": 1172 + "res/drawable-ldrtl-xhdpi-v17/abc_ic_menu_cut_mtrl_alpha.png": { + "Size": 494 }, - "res/drawable-v21/abc_list_divider_material.xml": { - "Size": 516 + "res/drawable-ldrtl-xhdpi-v17/abc_spinner_mtrl_am_alpha.9.png": { + "Size": 417 }, - "res/drawable-v21/avd_hide_password.xml": { - "Size": 660 + "res/drawable-ldrtl-xxhdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png": { + "Size": 260 }, - "res/drawable-v21/avd_show_password.xml": { - "Size": 660 + "res/drawable-ldrtl-xxhdpi-v17/abc_ic_menu_cut_mtrl_alpha.png": { + "Size": 705 }, - "res/drawable-v21/design_bottom_navigation_item_background.xml": { - "Size": 264 + "res/drawable-ldrtl-xxhdpi-v17/abc_spinner_mtrl_am_alpha.9.png": { + "Size": 525 }, - "res/drawable-v21/design_password_eye.xml": { - "Size": 816 + "res/drawable-ldrtl-xxxhdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png": { + "Size": 325 }, - "res/drawable-v21/notification_action_background.xml": { - "Size": 1180 + "res/drawable-ldrtl-xxxhdpi-v17/abc_ic_menu_cut_mtrl_alpha.png": { + "Size": 905 }, - "res/drawable-v23/abc_control_background_material.xml": { - "Size": 304 + "res/drawable-ldrtl-xxxhdpi-v17/abc_spinner_mtrl_am_alpha.9.png": { + "Size": 437 }, "res/drawable-mdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png": { "Size": 267 @@ -679,12 +901,12 @@ "res/drawable-mdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png": { "Size": 178 }, - "res/drawable-mdpi-v4/design_ic_visibility.png": { - "Size": 309 - }, "res/drawable-mdpi-v4/design_ic_visibility_off.png": { "Size": 351 }, + "res/drawable-mdpi-v4/design_ic_visibility.png": { + "Size": 309 + }, "res/drawable-mdpi-v4/icon.png": { "Size": 2200 }, @@ -694,218 +916,98 @@ "res/drawable-mdpi-v4/notification_bg_low_pressed.9.png": { "Size": 223 }, - "res/drawable-mdpi-v4/notification_bg_normal.9.png": { - "Size": 215 - }, "res/drawable-mdpi-v4/notification_bg_normal_pressed.9.png": { "Size": 223 }, + "res/drawable-mdpi-v4/notification_bg_normal.9.png": { + "Size": 215 + }, "res/drawable-mdpi-v4/notify_panel_notification_icon_bg.png": { "Size": 98 }, - "res/drawable-ldrtl-mdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png": { - "Size": 127 + "res/drawable-v21/$avd_hide_password__0.xml": { + "Size": 1176 }, - "res/drawable-ldrtl-mdpi-v17/abc_ic_menu_cut_mtrl_alpha.png": { - "Size": 253 + "res/drawable-v21/$avd_hide_password__1.xml": { + "Size": 592 }, - "res/drawable-ldrtl-mdpi-v17/abc_spinner_mtrl_am_alpha.9.png": { - "Size": 318 + "res/drawable-v21/$avd_hide_password__2.xml": { + "Size": 556 }, - "res/drawable-hdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png": { - "Size": 272 + "res/drawable-v21/$avd_show_password__0.xml": { + "Size": 1136 }, - "res/drawable-hdpi-v4/abc_btn_check_to_on_mtrl_000.png": { - "Size": 227 + "res/drawable-v21/$avd_show_password__1.xml": { + "Size": 592 }, - "res/drawable-hdpi-v4/abc_btn_check_to_on_mtrl_015.png": { - "Size": 404 + "res/drawable-v21/$avd_show_password__2.xml": { + "Size": 556 }, - "res/drawable-hdpi-v4/abc_btn_radio_to_on_mtrl_000.png": { - "Size": 464 + "res/drawable-v21/abc_action_bar_item_background_material.xml": { + "Size": 264 }, - "res/drawable-hdpi-v4/abc_btn_radio_to_on_mtrl_015.png": { - "Size": 563 + "res/drawable-v21/abc_btn_colored_material.xml": { + "Size": 1716 }, - "res/drawable-hdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png": { - "Size": 1096 + "res/drawable-v21/abc_dialog_material_background.xml": { + "Size": 716 }, - "res/drawable-hdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png": { - "Size": 1243 + "res/drawable-v21/abc_edit_text_material.xml": { + "Size": 1172 }, - "res/drawable-hdpi-v4/abc_cab_background_top_mtrl_alpha.9.png": { - "Size": 226 + "res/drawable-v21/abc_list_divider_material.xml": { + "Size": 516 }, - "res/drawable-hdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png": { - "Size": 171 + "res/drawable-v21/abc_ratingbar_indicator_material.xml": { + "Size": 704 }, - "res/drawable-hdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png": { - "Size": 202 + "res/drawable-v21/abc_ratingbar_material.xml": { + "Size": 704 }, - "res/drawable-hdpi-v4/abc_ic_menu_cut_mtrl_alpha.png": { - "Size": 404 + "res/drawable-v21/abc_ratingbar_small_material.xml": { + "Size": 704 }, - "res/drawable-hdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png": { - "Size": 226 + "res/drawable-v21/avd_hide_password.xml": { + "Size": 660 }, - "res/drawable-hdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png": { - "Size": 215 + "res/drawable-v21/avd_show_password.xml": { + "Size": 660 }, - "res/drawable-hdpi-v4/abc_ic_menu_share_mtrl_alpha.png": { - "Size": 389 + "res/drawable-v21/design_bottom_navigation_item_background.xml": { + "Size": 264 }, - "res/drawable-hdpi-v4/abc_ic_star_black_16dp.png": { - "Size": 263 + "res/drawable-v21/design_password_eye.xml": { + "Size": 816 }, - "res/drawable-hdpi-v4/abc_ic_star_black_36dp.png": { - "Size": 522 + "res/drawable-v21/notification_action_background.xml": { + "Size": 1180 }, - "res/drawable-hdpi-v4/abc_ic_star_black_48dp.png": { - "Size": 668 + "res/drawable-v23/abc_control_background_material.xml": { + "Size": 304 }, - "res/drawable-hdpi-v4/abc_ic_star_half_black_16dp.png": { - "Size": 197 + "res/drawable-watch-v20/abc_dialog_material_background.xml": { + "Size": 372 }, - "res/drawable-hdpi-v4/abc_ic_star_half_black_36dp.png": { - "Size": 328 + "res/drawable-xhdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png": { + "Size": 280 }, - "res/drawable-hdpi-v4/abc_ic_star_half_black_48dp.png": { - "Size": 431 + "res/drawable-xhdpi-v4/abc_btn_check_to_on_mtrl_000.png": { + "Size": 281 }, - "res/drawable-hdpi-v4/abc_list_divider_mtrl_alpha.9.png": { - "Size": 167 + "res/drawable-xhdpi-v4/abc_btn_check_to_on_mtrl_015.png": { + "Size": 432 }, - "res/drawable-hdpi-v4/abc_list_focused_holo.9.png": { - "Size": 244 + "res/drawable-xhdpi-v4/abc_btn_radio_to_on_mtrl_000.png": { + "Size": 651 }, - "res/drawable-hdpi-v4/abc_list_longpressed_holo.9.png": { - "Size": 212 + "res/drawable-xhdpi-v4/abc_btn_radio_to_on_mtrl_015.png": { + "Size": 785 }, - "res/drawable-hdpi-v4/abc_list_pressed_holo_dark.9.png": { - "Size": 208 + "res/drawable-xhdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png": { + "Size": 1526 }, - "res/drawable-hdpi-v4/abc_list_pressed_holo_light.9.png": { - "Size": 208 - }, - "res/drawable-hdpi-v4/abc_list_selector_disabled_holo_dark.9.png": { - "Size": 228 - }, - "res/drawable-hdpi-v4/abc_list_selector_disabled_holo_light.9.png": { - "Size": 229 - }, - "res/drawable-hdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png": { - "Size": 738 - }, - "res/drawable-hdpi-v4/abc_popup_background_mtrl_mult.9.png": { - "Size": 1098 - }, - "res/drawable-hdpi-v4/abc_scrubber_control_off_mtrl_alpha.png": { - "Size": 201 - }, - "res/drawable-hdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png": { - "Size": 196 - }, - "res/drawable-hdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png": { - "Size": 272 - }, - "res/drawable-hdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png": { - "Size": 205 - }, - "res/drawable-hdpi-v4/abc_scrubber_track_mtrl_alpha.9.png": { - "Size": 196 - }, - "res/drawable-hdpi-v4/abc_spinner_mtrl_am_alpha.9.png": { - "Size": 345 - }, - "res/drawable-hdpi-v4/abc_switch_track_mtrl_alpha.9.png": { - "Size": 484 - }, - "res/drawable-hdpi-v4/abc_tab_indicator_mtrl_alpha.9.png": { - "Size": 190 - }, - "res/drawable-hdpi-v4/abc_text_select_handle_left_mtrl_dark.png": { - "Size": 278 - }, - "res/drawable-hdpi-v4/abc_text_select_handle_left_mtrl_light.png": { - "Size": 278 - }, - "res/drawable-hdpi-v4/abc_text_select_handle_middle_mtrl_dark.png": { - "Size": 398 - }, - "res/drawable-hdpi-v4/abc_text_select_handle_middle_mtrl_light.png": { - "Size": 396 - }, - "res/drawable-hdpi-v4/abc_text_select_handle_right_mtrl_dark.png": { - "Size": 263 - }, - "res/drawable-hdpi-v4/abc_text_select_handle_right_mtrl_light.png": { - "Size": 262 - }, - "res/drawable-hdpi-v4/abc_textfield_activated_mtrl_alpha.9.png": { - "Size": 186 - }, - "res/drawable-hdpi-v4/abc_textfield_default_mtrl_alpha.9.png": { - "Size": 192 - }, - "res/drawable-hdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png": { - "Size": 178 - }, - "res/drawable-hdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png": { - "Size": 178 - }, - "res/drawable-hdpi-v4/design_ic_visibility.png": { - "Size": 470 - }, - "res/drawable-hdpi-v4/design_ic_visibility_off.png": { - "Size": 507 - }, - "res/drawable-hdpi-v4/icon.png": { - "Size": 4762 - }, - "res/drawable-hdpi-v4/notification_bg_low_normal.9.png": { - "Size": 212 - }, - "res/drawable-hdpi-v4/notification_bg_low_pressed.9.png": { - "Size": 225 - }, - "res/drawable-hdpi-v4/notification_bg_normal.9.png": { - "Size": 212 - }, - "res/drawable-hdpi-v4/notification_bg_normal_pressed.9.png": { - "Size": 225 - }, - "res/drawable-hdpi-v4/notify_panel_notification_icon_bg.png": { - "Size": 107 - }, - "res/drawable-ldrtl-hdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png": { - "Size": 199 - }, - "res/drawable-ldrtl-hdpi-v17/abc_ic_menu_cut_mtrl_alpha.png": { - "Size": 400 - }, - "res/drawable-ldrtl-hdpi-v17/abc_spinner_mtrl_am_alpha.9.png": { - "Size": 345 - }, - "res/drawable-xhdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png": { - "Size": 280 - }, - "res/drawable-xhdpi-v4/abc_btn_check_to_on_mtrl_000.png": { - "Size": 281 - }, - "res/drawable-xhdpi-v4/abc_btn_check_to_on_mtrl_015.png": { - "Size": 432 - }, - "res/drawable-xhdpi-v4/abc_btn_radio_to_on_mtrl_000.png": { - "Size": 651 - }, - "res/drawable-xhdpi-v4/abc_btn_radio_to_on_mtrl_015.png": { - "Size": 785 - }, - "res/drawable-xhdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png": { - "Size": 1526 - }, - "res/drawable-xhdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png": { - "Size": 1731 + "res/drawable-xhdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png": { + "Size": 1731 }, "res/drawable-xhdpi-v4/abc_cab_background_top_mtrl_alpha.9.png": { "Size": 229 @@ -1027,12 +1129,12 @@ "res/drawable-xhdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png": { "Size": 182 }, - "res/drawable-xhdpi-v4/design_ic_visibility.png": { - "Size": 593 - }, "res/drawable-xhdpi-v4/design_ic_visibility_off.png": { "Size": 629 }, + "res/drawable-xhdpi-v4/design_ic_visibility.png": { + "Size": 593 + }, "res/drawable-xhdpi-v4/icon.png": { "Size": 7462 }, @@ -1042,24 +1144,15 @@ "res/drawable-xhdpi-v4/notification_bg_low_pressed.9.png": { "Size": 252 }, - "res/drawable-xhdpi-v4/notification_bg_normal.9.png": { - "Size": 221 - }, "res/drawable-xhdpi-v4/notification_bg_normal_pressed.9.png": { "Size": 247 }, + "res/drawable-xhdpi-v4/notification_bg_normal.9.png": { + "Size": 221 + }, "res/drawable-xhdpi-v4/notify_panel_notification_icon_bg.png": { "Size": 138 }, - "res/drawable-ldrtl-xhdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png": { - "Size": 178 - }, - "res/drawable-ldrtl-xhdpi-v17/abc_ic_menu_cut_mtrl_alpha.png": { - "Size": 494 - }, - "res/drawable-ldrtl-xhdpi-v17/abc_spinner_mtrl_am_alpha.9.png": { - "Size": 417 - }, "res/drawable-xxhdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png": { "Size": 286 }, @@ -1201,24 +1294,15 @@ "res/drawable-xxhdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png": { "Size": 186 }, - "res/drawable-xxhdpi-v4/design_ic_visibility.png": { - "Size": 868 - }, "res/drawable-xxhdpi-v4/design_ic_visibility_off.png": { "Size": 884 }, + "res/drawable-xxhdpi-v4/design_ic_visibility.png": { + "Size": 868 + }, "res/drawable-xxhdpi-v4/icon.png": { "Size": 13092 }, - "res/drawable-ldrtl-xxhdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png": { - "Size": 260 - }, - "res/drawable-ldrtl-xxhdpi-v17/abc_ic_menu_cut_mtrl_alpha.png": { - "Size": 705 - }, - "res/drawable-ldrtl-xxhdpi-v17/abc_spinner_mtrl_am_alpha.9.png": { - "Size": 525 - }, "res/drawable-xxxhdpi-v4/abc_btn_check_to_on_mtrl_000.png": { "Size": 275 }, @@ -1297,102 +1381,309 @@ "res/drawable-xxxhdpi-v4/abc_text_select_handle_right_mtrl_light.png": { "Size": 513 }, - "res/drawable-xxxhdpi-v4/design_ic_visibility.png": { - "Size": 1155 - }, "res/drawable-xxxhdpi-v4/design_ic_visibility_off.png": { "Size": 1201 }, + "res/drawable-xxxhdpi-v4/design_ic_visibility.png": { + "Size": 1155 + }, "res/drawable-xxxhdpi-v4/icon.png": { "Size": 20118 }, - "res/drawable-ldrtl-xxxhdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png": { - "Size": 325 + "res/drawable/abc_btn_borderless_material.xml": { + "Size": 588 }, - "res/drawable-ldrtl-xxxhdpi-v17/abc_ic_menu_cut_mtrl_alpha.png": { - "Size": 905 + "res/drawable/abc_btn_check_material_anim.xml": { + "Size": 816 }, - "res/drawable-ldrtl-xxxhdpi-v17/abc_spinner_mtrl_am_alpha.9.png": { - "Size": 437 + "res/drawable/abc_btn_check_material.xml": { + "Size": 464 }, - "res/drawable-anydpi-v21/design_ic_visibility.xml": { - "Size": 540 + "res/drawable/abc_btn_colored_material.xml": { + "Size": 344 }, - "res/drawable-anydpi-v21/design_ic_visibility_off.xml": { - "Size": 1144 + "res/drawable/abc_btn_default_mtrl_shape.xml": { + "Size": 932 }, - "res/interpolator/btn_checkbox_checked_mtrl_animation_interpolator_0.xml": { - "Size": 316 + "res/drawable/abc_btn_radio_material_anim.xml": { + "Size": 816 }, - "res/interpolator/btn_checkbox_checked_mtrl_animation_interpolator_1.xml": { - "Size": 328 + "res/drawable/abc_btn_radio_material.xml": { + "Size": 464 }, - "res/interpolator/btn_checkbox_unchecked_mtrl_animation_interpolator_0.xml": { - "Size": 316 + "res/drawable/abc_cab_background_internal_bg.xml": { + "Size": 372 }, - "res/interpolator/btn_checkbox_unchecked_mtrl_animation_interpolator_1.xml": { - "Size": 328 + "res/drawable/abc_cab_background_top_material.xml": { + "Size": 336 }, - "res/interpolator/btn_radio_to_off_mtrl_animation_interpolator_0.xml": { - "Size": 320 + "res/drawable/abc_dialog_material_background.xml": { + "Size": 716 }, - "res/interpolator/btn_radio_to_on_mtrl_animation_interpolator_0.xml": { - "Size": 320 + "res/drawable/abc_edit_text_material.xml": { + "Size": 868 }, - "res/interpolator/fast_out_slow_in.xml": { - "Size": 400 + "res/drawable/abc_ic_ab_back_material.xml": { + "Size": 692 }, - "res/interpolator/mtrl_fast_out_linear_in.xml": { - "Size": 136 + "res/drawable/abc_ic_arrow_drop_right_black_24dp.xml": { + "Size": 1000 }, - "res/interpolator/mtrl_fast_out_slow_in.xml": { - "Size": 144 + "res/drawable/abc_ic_clear_material.xml": { + "Size": 684 }, - "res/interpolator/mtrl_linear.xml": { - "Size": 132 + "res/drawable/abc_ic_go_search_api_material.xml": { + "Size": 640 }, - "res/interpolator/mtrl_linear_out_slow_in.xml": { - "Size": 136 + "res/drawable/abc_ic_menu_overflow_material.xml": { + "Size": 792 }, - "res/interpolator-v21/mtrl_fast_out_linear_in.xml": { - "Size": 400 + "res/drawable/abc_ic_search_api_material.xml": { + "Size": 812 }, - "res/interpolator-v21/mtrl_fast_out_slow_in.xml": { - "Size": 400 + "res/drawable/abc_ic_voice_search_api_material.xml": { + "Size": 828 }, - "res/interpolator-v21/mtrl_linear_out_slow_in.xml": { - "Size": 400 + "res/drawable/abc_item_background_holo_dark.xml": { + "Size": 1012 }, - "res/layout/abc_action_bar_title_item.xml": { - "Size": 872 + "res/drawable/abc_item_background_holo_light.xml": { + "Size": 1012 }, - "res/layout/abc_action_bar_up_container.xml": { - "Size": 440 + "res/drawable/abc_list_divider_material.xml": { + "Size": 480 }, - "res/layout/abc_action_menu_item_layout.xml": { - "Size": 768 + "res/drawable/abc_list_selector_background_transition_holo_dark.xml": { + "Size": 424 }, - "res/layout/abc_action_menu_layout.xml": { - "Size": 576 + "res/drawable/abc_list_selector_background_transition_holo_light.xml": { + "Size": 424 }, - "res/layout/abc_action_mode_bar.xml": { - "Size": 464 + "res/drawable/abc_list_selector_holo_dark.xml": { + "Size": 1064 + }, + "res/drawable/abc_list_selector_holo_light.xml": { + "Size": 1064 + }, + "res/drawable/abc_ratingbar_indicator_material.xml": { + "Size": 664 + }, + "res/drawable/abc_ratingbar_material.xml": { + "Size": 664 + }, + "res/drawable/abc_ratingbar_small_material.xml": { + "Size": 664 + }, + "res/drawable/abc_seekbar_thumb_material.xml": { + "Size": 1100 + }, + "res/drawable/abc_seekbar_tick_mark_material.xml": { + "Size": 516 + }, + "res/drawable/abc_seekbar_track_material.xml": { + "Size": 1408 + }, + "res/drawable/abc_spinner_textfield_background_material.xml": { + "Size": 1160 + }, + "res/drawable/abc_switch_thumb_material.xml": { + "Size": 464 + }, + "res/drawable/abc_tab_indicator_material.xml": { + "Size": 468 + }, + "res/drawable/abc_text_cursor_material.xml": { + "Size": 516 + }, + "res/drawable/abc_textfield_search_material.xml": { + "Size": 756 + }, + "res/drawable/abc_vector_test.xml": { + "Size": 612 + }, + "res/drawable/btn_checkbox_checked_mtrl.xml": { + "Size": 2688 + }, + "res/drawable/btn_checkbox_checked_to_unchecked_mtrl_animation.xml": { + "Size": 688 + }, + "res/drawable/btn_checkbox_unchecked_mtrl.xml": { + "Size": 2660 + }, + "res/drawable/btn_checkbox_unchecked_to_checked_mtrl_animation.xml": { + "Size": 688 + }, + "res/drawable/btn_radio_off_mtrl.xml": { + "Size": 1728 + }, + "res/drawable/btn_radio_off_to_on_mtrl_animation.xml": { + "Size": 680 + }, + "res/drawable/btn_radio_on_mtrl.xml": { + "Size": 1656 + }, + "res/drawable/btn_radio_on_to_off_mtrl_animation.xml": { + "Size": 680 + }, + "res/drawable/design_bottom_navigation_item_background.xml": { + "Size": 784 + }, + "res/drawable/design_fab_background.xml": { + "Size": 372 + }, + "res/drawable/design_password_eye.xml": { + "Size": 464 + }, + "res/drawable/design_snackbar_background.xml": { + "Size": 484 + }, + "res/drawable/ic_mtrl_chip_checked_black.xml": { + "Size": 600 + }, + "res/drawable/ic_mtrl_chip_checked_circle.xml": { + "Size": 940 + }, + "res/drawable/ic_mtrl_chip_close_circle.xml": { + "Size": 808 + }, + "res/drawable/mtrl_snackbar_background.xml": { + "Size": 484 + }, + "res/drawable/mtrl_tabs_default_indicator.xml": { + "Size": 628 + }, + "res/drawable/navigation_empty_icon.xml": { + "Size": 516 + }, + "res/drawable/notification_bg_low.xml": { + "Size": 532 + }, + "res/drawable/notification_bg.xml": { + "Size": 532 + }, + "res/drawable/notification_icon_background.xml": { + "Size": 372 + }, + "res/drawable/notification_tile_bg.xml": { + "Size": 304 + }, + "res/drawable/tooltip_frame_dark.xml": { + "Size": 484 + }, + "res/drawable/tooltip_frame_light.xml": { + "Size": 484 + }, + "res/interpolator-v21/mtrl_fast_out_linear_in.xml": { + "Size": 400 + }, + "res/interpolator-v21/mtrl_fast_out_slow_in.xml": { + "Size": 400 + }, + "res/interpolator-v21/mtrl_linear_out_slow_in.xml": { + "Size": 400 + }, + "res/interpolator/btn_checkbox_checked_mtrl_animation_interpolator_0.xml": { + "Size": 316 + }, + "res/interpolator/btn_checkbox_checked_mtrl_animation_interpolator_1.xml": { + "Size": 328 + }, + "res/interpolator/btn_checkbox_unchecked_mtrl_animation_interpolator_0.xml": { + "Size": 316 + }, + "res/interpolator/btn_checkbox_unchecked_mtrl_animation_interpolator_1.xml": { + "Size": 328 + }, + "res/interpolator/btn_radio_to_off_mtrl_animation_interpolator_0.xml": { + "Size": 320 + }, + "res/interpolator/btn_radio_to_on_mtrl_animation_interpolator_0.xml": { + "Size": 320 + }, + "res/interpolator/fast_out_slow_in.xml": { + "Size": 400 + }, + "res/interpolator/mtrl_fast_out_linear_in.xml": { + "Size": 136 + }, + "res/interpolator/mtrl_fast_out_slow_in.xml": { + "Size": 144 + }, + "res/interpolator/mtrl_linear_out_slow_in.xml": { + "Size": 136 + }, + "res/interpolator/mtrl_linear.xml": { + "Size": 132 + }, + "res/layout-sw600dp-v13/design_layout_snackbar.xml": { + "Size": 528 + }, + "res/layout-sw600dp-v13/mtrl_layout_snackbar.xml": { + "Size": 528 + }, + "res/layout-v16/notification_template_custom_big.xml": { + "Size": 3208 + }, + "res/layout-v21/abc_screen_toolbar.xml": { + "Size": 1504 + }, + "res/layout-v21/fallbacktoolbardonotuse.xml": { + "Size": 496 + }, + "res/layout-v21/notification_action_tombstone.xml": { + "Size": 1228 + }, + "res/layout-v21/notification_action.xml": { + "Size": 1052 + }, + "res/layout-v21/notification_template_custom_big.xml": { + "Size": 2456 + }, + "res/layout-v21/notification_template_icon_group.xml": { + "Size": 988 + }, + "res/layout-v21/toolbar.xml": { + "Size": 496 + }, + "res/layout-v22/abc_alert_dialog_button_bar_material.xml": { + "Size": 1584 + }, + "res/layout-v26/abc_screen_toolbar.xml": { + "Size": 1560 + }, + "res/layout-watch-v20/abc_alert_dialog_button_bar_material.xml": { + "Size": 1208 + }, + "res/layout-watch-v20/abc_alert_dialog_title_material.xml": { + "Size": 1352 + }, + "res/layout/abc_action_bar_title_item.xml": { + "Size": 872 + }, + "res/layout/abc_action_bar_up_container.xml": { + "Size": 440 + }, + "res/layout/abc_action_menu_item_layout.xml": { + "Size": 768 + }, + "res/layout/abc_action_menu_layout.xml": { + "Size": 576 + }, + "res/layout/abc_action_mode_bar.xml": { + "Size": 464 }, "res/layout/abc_action_mode_close_item_material.xml": { "Size": 840 }, - "res/layout/abc_activity_chooser_view.xml": { - "Size": 1684 - }, "res/layout/abc_activity_chooser_view_list_item.xml": { "Size": 1304 }, + "res/layout/abc_activity_chooser_view.xml": { + "Size": 1684 + }, "res/layout/abc_alert_dialog_button_bar_material.xml": { "Size": 1536 }, - "res/layout-v22/abc_alert_dialog_button_bar_material.xml": { - "Size": 1584 - }, "res/layout/abc_alert_dialog_material.xml": { "Size": 2476 }, @@ -1429,18 +1720,15 @@ "res/layout/abc_screen_content_include.xml": { "Size": 548 }, - "res/layout/abc_screen_simple.xml": { - "Size": 832 - }, "res/layout/abc_screen_simple_overlay_action_mode.xml": { "Size": 792 }, + "res/layout/abc_screen_simple.xml": { + "Size": 832 + }, "res/layout/abc_screen_toolbar.xml": { "Size": 1452 }, - "res/layout-v21/abc_screen_toolbar.xml": { - "Size": 1504 - }, "res/layout/abc_search_dropdown_item_icons_2line.xml": { "Size": 1916 }, @@ -1471,12 +1759,12 @@ "res/layout/design_bottom_sheet_dialog.xml": { "Size": 1184 }, - "res/layout/design_layout_snackbar.xml": { - "Size": 528 - }, "res/layout/design_layout_snackbar_include.xml": { "Size": 1444 }, + "res/layout/design_layout_snackbar.xml": { + "Size": 528 + }, "res/layout/design_layout_tab_icon.xml": { "Size": 408 }, @@ -1486,9 +1774,6 @@ "res/layout/design_menu_item_action_area.xml": { "Size": 320 }, - "res/layout/design_navigation_item.xml": { - "Size": 536 - }, "res/layout/design_navigation_item_header.xml": { "Size": 440 }, @@ -1498,12 +1783,15 @@ "res/layout/design_navigation_item_subheader.xml": { "Size": 564 }, - "res/layout/design_navigation_menu.xml": { - "Size": 528 + "res/layout/design_navigation_item.xml": { + "Size": 536 }, "res/layout/design_navigation_menu_item.xml": { "Size": 856 }, + "res/layout/design_navigation_menu.xml": { + "Size": 528 + }, "res/layout/design_text_input_password_icon.xml": { "Size": 564 }, @@ -1513,47 +1801,41 @@ "res/layout/fallbacktoolbardonotuse.xml": { "Size": 452 }, - "res/layout-v21/fallbacktoolbardonotuse.xml": { - "Size": 496 - }, "res/layout/flyoutcontent.xml": { "Size": 944 }, "res/layout/main.xml": { "Size": 544 }, - "res/layout/mtrl_layout_snackbar.xml": { - "Size": 528 - }, "res/layout/mtrl_layout_snackbar_include.xml": { "Size": 1404 }, - "res/layout/notification_action.xml": { - "Size": 1156 + "res/layout/mtrl_layout_snackbar.xml": { + "Size": 528 }, "res/layout/notification_action_tombstone.xml": { "Size": 1332 }, + "res/layout/notification_action.xml": { + "Size": 1156 + }, "res/layout/notification_media_action.xml": { "Size": 564 }, "res/layout/notification_media_cancel_action.xml": { "Size": 744 }, - "res/layout/notification_template_big_media.xml": { - "Size": 1696 - }, "res/layout/notification_template_big_media_custom.xml": { "Size": 3044 }, - "res/layout/notification_template_big_media_narrow.xml": { - "Size": 1824 - }, "res/layout/notification_template_big_media_narrow_custom.xml": { "Size": 3216 }, - "res/layout-v16/notification_template_custom_big.xml": { - "Size": 3208 + "res/layout/notification_template_big_media_narrow.xml": { + "Size": 1824 + }, + "res/layout/notification_template_big_media.xml": { + "Size": 1696 }, "res/layout/notification_template_icon_group.xml": { "Size": 392 @@ -1561,12 +1843,12 @@ "res/layout/notification_template_lines_media.xml": { "Size": 2872 }, - "res/layout/notification_template_media.xml": { - "Size": 1292 - }, "res/layout/notification_template_media_custom.xml": { "Size": 2756 }, + "res/layout/notification_template_media.xml": { + "Size": 1292 + }, "res/layout/notification_template_part_chronometer.xml": { "Size": 440 }, @@ -1597,291 +1879,9 @@ "res/layout/toolbar.xml": { "Size": 452 }, - "res/layout-v21/toolbar.xml": { - "Size": 496 - }, - "res/layout-sw600dp-v13/design_layout_snackbar.xml": { - "Size": 528 - }, - "res/layout-sw600dp-v13/mtrl_layout_snackbar.xml": { - "Size": 528 - }, - "res/layout-watch-v20/abc_alert_dialog_button_bar_material.xml": { - "Size": 1208 - }, - "res/layout-watch-v20/abc_alert_dialog_title_material.xml": { - "Size": 1352 - }, - "res/layout-v21/notification_action.xml": { - "Size": 1052 - }, - "res/layout-v21/notification_action_tombstone.xml": { - "Size": 1228 - }, - "res/layout-v21/notification_template_custom_big.xml": { - "Size": 2456 - }, - "res/layout-v21/notification_template_icon_group.xml": { - "Size": 988 - }, - "res/layout-v26/abc_screen_toolbar.xml": { - "Size": 1560 - }, "resources.arsc": { "Size": 341040 - }, - "classes.dex": { - "Size": 3455100 - }, - "assemblies/UnnamedProject.dll": { - "Size": 116864 - }, - "assemblies/FormsViewGroup.dll": { - "Size": 7192 - }, - "assemblies/Xamarin.AndroidX.Activity.dll": { - "Size": 7673 - }, - "assemblies/Xamarin.AndroidX.AppCompat.AppCompatResources.dll": { - "Size": 6628 - }, - "assemblies/Xamarin.AndroidX.AppCompat.dll": { - "Size": 125310 - }, - "assemblies/Xamarin.AndroidX.CardView.dll": { - "Size": 7343 - }, - "assemblies/Xamarin.AndroidX.CoordinatorLayout.dll": { - "Size": 18247 - }, - "assemblies/Xamarin.AndroidX.Core.dll": { - "Size": 131908 - }, - "assemblies/Xamarin.AndroidX.DrawerLayout.dll": { - "Size": 15404 - }, - "assemblies/Xamarin.AndroidX.Fragment.dll": { - "Size": 43114 - }, - "assemblies/Xamarin.AndroidX.Legacy.Support.Core.UI.dll": { - "Size": 6692 - }, - "assemblies/Xamarin.AndroidX.Lifecycle.Common.dll": { - "Size": 7039 - }, - "assemblies/Xamarin.AndroidX.Lifecycle.LiveData.Core.dll": { - "Size": 7165 - }, - "assemblies/Xamarin.AndroidX.Lifecycle.ViewModel.dll": { - "Size": 4845 - }, - "assemblies/Xamarin.AndroidX.Loader.dll": { - "Size": 13563 - }, - "assemblies/Xamarin.AndroidX.RecyclerView.dll": { - "Size": 102309 - }, - "assemblies/Xamarin.AndroidX.SavedState.dll": { - "Size": 6253 - }, - "assemblies/Xamarin.AndroidX.SwipeRefreshLayout.dll": { - "Size": 11251 - }, - "assemblies/Xamarin.AndroidX.ViewPager.dll": { - "Size": 19400 - }, - "assemblies/Xamarin.Forms.Core.dll": { - "Size": 524712 - }, - "assemblies/Xamarin.Forms.Platform.Android.dll": { - "Size": 384845 - }, - "assemblies/Xamarin.Forms.Platform.dll": { - "Size": 56878 - }, - "assemblies/Xamarin.Forms.Xaml.dll": { - "Size": 55776 - }, - "assemblies/Xamarin.Google.Android.Material.dll": { - "Size": 43475 - }, - "assemblies/System.Net.Http.dll": { - "Size": 110617 - }, - "assemblies/System.Runtime.Serialization.dll": { - "Size": 186635 - }, - "assemblies/Java.Interop.dll": { - "Size": 68652 - }, - "assemblies/Mono.Android.dll": { - "Size": 557091 - }, - "assemblies/mscorlib.dll": { - "Size": 915344 - }, - "assemblies/System.Core.dll": { - "Size": 164026 - }, - "assemblies/System.dll": { - "Size": 388843 - }, - "assemblies/System.Xml.dll": { - "Size": 395637 - }, - "assemblies/System.Numerics.dll": { - "Size": 15666 - }, - "assemblies/System.Drawing.Common.dll": { - "Size": 12338 - }, - "assemblies/System.ServiceModel.Internals.dll": { - "Size": 26568 - }, - "assemblies/Mono.Security.dll": { - "Size": 68408 - }, - "lib/arm64-v8a/libxamarin-app.so": { - "Size": 140560 - }, - "lib/arm64-v8a/libmonodroid.so": { - "Size": 268792 - }, - "lib/arm64-v8a/libxa-internal-api.so": { - "Size": 65312 - }, - "lib/arm64-v8a/libmono-btls-shared.so": { - "Size": 1613872 - }, - "lib/arm64-v8a/libmonosgen-2.0.so": { - "Size": 4050176 - }, - "lib/arm64-v8a/libmono-native.so": { - "Size": 707024 - }, - "META-INF/androidx.versionedparcelable_versionedparcelable.version": { - "Size": 6 - }, - "META-INF/androidx.lifecycle_lifecycle-runtime.version": { - "Size": 6 - }, - "META-INF/androidx.core_core.version": { - "Size": 6 - }, - "META-INF/androidx.customview_customview.version": { - "Size": 6 - }, - "META-INF/androidx.viewpager_viewpager.version": { - "Size": 6 - }, - "META-INF/androidx.vectordrawable_vectordrawable.version": { - "Size": 6 - }, - "META-INF/androidx.interpolator_interpolator.version": { - "Size": 6 - }, - "META-INF/androidx.vectordrawable_vectordrawable-animated.version": { - "Size": 6 - }, - "META-INF/androidx.savedstate_savedstate.version": { - "Size": 6 - }, - "META-INF/androidx.lifecycle_lifecycle-viewmodel.version": { - "Size": 6 - }, - "META-INF/androidx.arch.core_core-runtime.version": { - "Size": 6 - }, - "META-INF/androidx.lifecycle_lifecycle-livedata-core.version": { - "Size": 6 - }, - "META-INF/androidx.loader_loader.version": { - "Size": 6 - }, - "META-INF/androidx.activity_activity.version": { - "Size": 6 - }, - "META-INF/androidx.fragment_fragment.version": { - "Size": 6 - }, - "META-INF/androidx.transition_transition.version": { - "Size": 6 - }, - "META-INF/androidx.swiperefreshlayout_swiperefreshlayout.version": { - "Size": 6 - }, - "META-INF/androidx.slidingpanelayout_slidingpanelayout.version": { - "Size": 6 - }, - "META-INF/androidx.recyclerview_recyclerview.version": { - "Size": 6 - }, - "META-INF/androidx.print_print.version": { - "Size": 6 - }, - "META-INF/androidx.localbroadcastmanager_localbroadcastmanager.version": { - "Size": 6 - }, - "META-INF/androidx.documentfile_documentfile.version": { - "Size": 6 - }, - "META-INF/androidx.legacy_legacy-support-core-utils.version": { - "Size": 6 - }, - "META-INF/androidx.drawerlayout_drawerlayout.version": { - "Size": 6 - }, - "META-INF/androidx.cursoradapter_cursoradapter.version": { - "Size": 6 - }, - "META-INF/androidx.coordinatorlayout_coordinatorlayout.version": { - "Size": 6 - }, - "META-INF/androidx.asynclayoutinflater_asynclayoutinflater.version": { - "Size": 6 - }, - "META-INF/androidx.legacy_legacy-support-core-ui.version": { - "Size": 6 - }, - "META-INF/androidx.cardview_cardview.version": { - "Size": 6 - }, - "META-INF/androidx.appcompat_appcompat-resources.version": { - "Size": 6 - }, - "META-INF/androidx.appcompat_appcompat.version": { - "Size": 6 - }, - "META-INF/android.support.design_material.version": { - "Size": 12 - }, - "META-INF/com.google.android.material_material.version": { - "Size": 10 - }, - "META-INF/androidx.media_media.version": { - "Size": 6 - }, - "META-INF/androidx.lifecycle_lifecycle-livedata.version": { - "Size": 6 - }, - "META-INF/androidx.legacy_legacy-support-v4.version": { - "Size": 6 - }, - "META-INF/androidx.browser_browser.version": { - "Size": 6 - }, - "META-INF/proguard/androidx-annotations.pro": { - "Size": 339 - }, - "META-INF/ANDROIDD.SF": { - "Size": 75858 - }, - "META-INF/ANDROIDD.RSA": { - "Size": 1213 - }, - "META-INF/MANIFEST.MF": { - "Size": 75731 } }, - "PackageSize": 9476254 + "PackageSize": 9484446 } \ No newline at end of file diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs index e1013bdb397..8f7f69aad12 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs @@ -11,6 +11,7 @@ class ApplicationConfigNativeAssemblyGenerator : NativeAssemblyGenerator SortedDictionary environmentVariables; SortedDictionary systemProperties; uint stringCounter = 0; + uint bufferCounter = 0; public bool IsBundledApp { get; set; } public bool UsesMonoAOT { get; set; } @@ -24,6 +25,7 @@ class ApplicationConfigNativeAssemblyGenerator : NativeAssemblyGenerator public bool JniAddNativeMethodRegistrationAttributePresent { get; set; } public bool HaveRuntimeConfigBlob { get; set; } public int NumberOfAssembliesInApk { get; set; } + public int BundledAssemblyNameWidth { get; set; } // including the trailing NUL public PackageNamingPolicy PackageNamingPolicy { get; set; } @@ -90,6 +92,9 @@ protected override void WriteSymbols (StreamWriter output) WriteCommentLine (output, "number_of_assemblies_in_apk"); size += WriteData (output, NumberOfAssembliesInApk); + WriteCommentLine (output, "bundled_assembly_name_width"); + size += WriteData (output, BundledAssemblyNameWidth); + WriteCommentLine (output, "android_package_name"); size += WritePointer (output, MakeLocalLabel (stringLabel)); @@ -103,6 +108,57 @@ protected override void WriteSymbols (StreamWriter output) WriteNameValueStringArray (output, "app_environment_variables", environmentVariables); WriteNameValueStringArray (output, "app_system_properties", systemProperties); + + WriteBundledAssemblies (output); + } + + void WriteBundledAssemblies (StreamWriter output) + { + WriteCommentLine (output, $"Bundled assembly name buffers, all {BundledAssemblyNameWidth} bytes long"); + WriteSection (output, ".bss.bundled_assembly_names", hasStrings: false, writable: true, nobits: true); + + var name_labels = new List (); + for (int i = 0; i < NumberOfAssembliesInApk; i++) { + string bufferLabel = GetBufferLabel (); + WriteBufferAllocation (output, bufferLabel, (uint)BundledAssemblyNameWidth); + name_labels.Add (bufferLabel); + } + + string label = "bundled_assemblies"; + WriteCommentLine (output, "Bundled assemblies data"); + WriteDataSection (output, label); + WriteStructureSymbol (output, label, alignBits: TargetProvider.MapModulesAlignBits, isGlobal: true); + + uint size = 0; + for (int i = 0; i < NumberOfAssembliesInApk; i++) { + size += WriteStructure (output, packed: false, structureWriter: () => WriteBundledAssembly (output, MakeLocalLabel (name_labels[i]))); + } + WriteStructureSize (output, label, size); + } + + uint WriteBundledAssembly (StreamWriter output, string nameLabel) + { + WriteCommentLine (output, "apk_fd"); + uint size = WriteData (output, (int)-1); + + WriteCommentLine (output, "data_offset"); + size += WriteData (output, (uint)0); + + WriteCommentLine (output, "data_size"); + size += WriteData (output, (uint)0); + + WriteCommentLine (output, "data"); + size += WritePointer (output); + + WriteCommentLine (output, "name_length"); + size += WriteData (output, (uint)0); + + WriteCommentLine (output, "name"); + size += WritePointer (output, nameLabel); + + output.WriteLine (); + + return size; } void WriteNameValueStringArray (StreamWriter output, string label, SortedDictionary entries) @@ -149,5 +205,11 @@ string GetStringLabel () stringCounter++; return $"env.str.{stringCounter}"; } + + string GetBufferLabel () + { + bufferCounter++; + return $"env.buf.{bufferCounter}"; + } }; } diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/NativeAssemblyGenerator.cs b/src/Xamarin.Android.Build.Tasks/Utilities/NativeAssemblyGenerator.cs index 77f37b1f7f3..c11e00fc2a1 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/NativeAssemblyGenerator.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/NativeAssemblyGenerator.cs @@ -83,7 +83,7 @@ protected virtual void WriteFileHeader (StreamWriter output) protected virtual void WriteFileFooter (StreamWriter output) {} - protected virtual void WriteSection (StreamWriter output, string sectionName, bool hasStrings, bool writable) + protected virtual void WriteSection (StreamWriter output, string sectionName, bool hasStrings, bool writable, bool nobits = false) { output.Write (Indent); output.Write (".section"); @@ -97,7 +97,11 @@ protected virtual void WriteSection (StreamWriter output, string sectionName, bo output.Write ("\","); output.Write (TargetProvider.TypePrefix); - output.Write ("progbits"); + if (nobits) { + output.Write ("nobits"); + } else { + output.Write ("progbits"); + } if (hasStrings) output.Write (",1"); output.WriteLine (); @@ -334,6 +338,28 @@ protected uint WriteAsciiData (StreamWriter output, string value, uint padToWidt return size; } + protected void WriteBufferAllocation (StreamWriter output, string label, uint bufferSize, bool isGlobal = false) + { + string symbolName; + if (isGlobal) { + output.Write (Indent); + output.Write (".global"); + output.Write (Indent); + output.WriteLine (label); + symbolName = label; + } else { + symbolName = MakeLocalLabel (label); + } + + output.Write (symbolName); + output.WriteLine (':'); + + output.Write (Indent); + output.Write (".zero"); + output.Write (Indent); + output.WriteLine (bufferSize); + } + protected string MakeLocalLabel (string label) { return $".L.{label}"; diff --git a/src/monodroid/jni/application_dso_stub.cc b/src/monodroid/jni/application_dso_stub.cc index 8b4a1cddba1..9ace9df52f6 100644 --- a/src/monodroid/jni/application_dso_stub.cc +++ b/src/monodroid/jni/application_dso_stub.cc @@ -54,3 +54,26 @@ ApplicationConfig application_config = { const char* mono_aot_mode_name = ""; const char* app_environment_variables[] = {}; const char* app_system_properties[] = {}; + +static constexpr size_t AssemblyNameWidth = 128; + +static char first_assembly_name[AssemblyNameWidth]; +static char second_assembly_name[AssemblyNameWidth]; + +XamarinAndroidBundledAssembly bundled_assemblies[] = { + { + .apk_fd = -1, + .data_offset = 0, + .data_size = 0, + .data = nullptr, + .name = first_assembly_name, + }, + + { + .apk_fd = -1, + .data_offset = 0, + .data_size = 0, + .data = nullptr, + .name = second_assembly_name, + }, +}; diff --git a/src/monodroid/jni/cpp-util.hh b/src/monodroid/jni/cpp-util.hh index 64b085d915f..75e570d0cb4 100644 --- a/src/monodroid/jni/cpp-util.hh +++ b/src/monodroid/jni/cpp-util.hh @@ -5,6 +5,8 @@ #include #include +#include + #if defined (ANDROID) #include #else @@ -52,5 +54,38 @@ namespace xamarin::android template using c_unique_ptr = std::unique_ptr>; + + class PosixSemaphoreGuard final + { + public: + explicit PosixSemaphoreGuard (sem_t &semaphore) + : _semaphore (semaphore) + { + ret = sem_wait (&semaphore); + } + + PosixSemaphoreGuard (PosixSemaphoreGuard const&) = delete; + PosixSemaphoreGuard (PosixSemaphoreGuard const&&) = delete; + + PosixSemaphoreGuard& operator= (PosixSemaphoreGuard const&) = delete; + + ~PosixSemaphoreGuard () + { + if (ret != 0) { + return; + } + + sem_post (&_semaphore); + } + + int result () const noexcept + { + return ret; + } + + private: + sem_t &_semaphore; + int ret; + }; } #endif // !def __CPP_UTIL_HH diff --git a/src/monodroid/jni/embedded-assemblies-zip.cc b/src/monodroid/jni/embedded-assemblies-zip.cc index 982d5b8201f..4c58d4ad545 100644 --- a/src/monodroid/jni/embedded-assemblies-zip.cc +++ b/src/monodroid/jni/embedded-assemblies-zip.cc @@ -9,6 +9,7 @@ #include "embedded-assemblies.hh" #include "cpp-util.hh" #include "globals.hh" +#include "xamarin-app.hh" using namespace xamarin::android::internal; @@ -23,8 +24,18 @@ using read_count_type = unsigned int; using read_count_type = size_t; #endif +force_inline bool +EmbeddedAssemblies::is_debug_file (dynamic_local_string const& name) noexcept +{ + return utils.ends_with (name, ".pdb") +#if !defined (NET6) + || utils.ends_with (name, ".mdb") +#endif + ; +} + void -EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, monodroid_should_register should_register) +EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unused]] monodroid_should_register should_register) { uint32_t cd_offset; uint32_t cd_size; @@ -47,7 +58,7 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, monodroid_sh std::vector buf (cd_size); const char *prefix = get_assemblies_prefix (); - size_t prefix_len = get_assemblies_prefix_length (); + uint32_t prefix_len = get_assemblies_prefix_length (); size_t buf_offset = 0; uint16_t compression_method; uint32_t local_header_offset; @@ -65,18 +76,8 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, monodroid_sh bool runtime_config_blob_found = false; #endif // def NET6 - bool bundled_assemblies_slow_path = false; - if (bundled_assemblies.empty ()) { - // We're called for the first time, let's allocate space for all the assemblies counted during build. resize() - // will allocate all the memory and zero it in one operation - bundled_assemblies.resize (application_config.number_of_assemblies_in_apk); - } else { - // We are probably registering some assemblies dynamically, possibly loading from another apk, we need to extend - // the storage instead of taking advantage of the pre-allocated slots. - bundled_assemblies_slow_path = true; - } - - int64_t assembly_count = application_config.number_of_assemblies_in_apk; + bool bundled_assemblies_slow_path = bundled_assembly_index >= application_config.number_of_assemblies_in_apk; + uint32_t max_assembly_name_size = application_config.bundled_assembly_name_width - 1; // clang-tidy claims we have a leak in the loop: // @@ -92,7 +93,7 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, monodroid_sh bool result = zip_read_entry_info (buf, buf_offset, compression_method, local_header_offset, file_size, entry_name); #ifdef DEBUG - log_warn (LOG_ASSEMBLY, "%s entry: %s", apk_name, entry_name.get () == nullptr ? "unknown" : entry_name.get ()); + log_info (LOG_ASSEMBLY, "%s entry: %s", apk_name, entry_name.get () == nullptr ? "unknown" : entry_name.get ()); #endif if (!result || entry_name.empty ()) { log_fatal (LOG_ASSEMBLY, "Failed to read Central Directory info for entry %u in APK file %s", i, apk_name); @@ -104,19 +105,19 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, monodroid_sh exit (FATAL_EXIT_NO_ASSEMBLIES); } #ifdef DEBUG - log_warn (LOG_ASSEMBLY, " ZIP: local header offset: %u; data offset: %u; file size: %u", local_header_offset, data_offset, file_size); + log_info (LOG_ASSEMBLY, " ZIP: local header offset: %u; data offset: %u; file size: %u", local_header_offset, data_offset, file_size); #endif if (compression_method != 0) continue; - if (strncmp (prefix, entry_name.get (), prefix_len) != 0) + if (entry_name.get ()[0] != prefix[0] || strncmp (prefix, entry_name.get (), prefix_len) != 0) continue; #if defined (NET6) if (application_config.have_runtime_config_blob && !runtime_config_blob_found) { if (utils.ends_with (entry_name, SharedConstants::RUNTIME_CONFIG_BLOB_NAME)) { runtime_config_blob_found = true; - runtime_config_blob_mmap = md_mmap_apk_file (fd, data_offset, file_size, entry_name.get (), apk_name); + runtime_config_blob_mmap = md_mmap_apk_file (fd, data_offset, file_size, entry_name.get ()); continue; } } @@ -129,25 +130,31 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, monodroid_sh exit (FATAL_EXIT_MISSING_ZIPALIGN); } +#if defined (DEBUG) const char *last_slash = utils.find_last (entry_name, '/'); bool entry_is_overridden = last_slash == nullptr ? false : !should_register (last_slash + 1); +#else + constexpr bool entry_is_overridden = false; +#endif - if ((utils.ends_with (entry_name, ".pdb") || utils.ends_with (entry_name, ".mdb")) && - register_debug_symbols && - !entry_is_overridden && - bundled_assembly_index >= 1) { - md_mmap_info map_info = md_mmap_apk_file(fd, data_offset, file_size, entry_name.get (), apk_name); - if (register_debug_symbols_for_assembly (entry_name, bundled_assemblies [bundled_assembly_index - 1], (const mono_byte*)map_info.area, static_cast(file_size))) - continue; + if (register_debug_symbols && !entry_is_overridden && is_debug_file (entry_name)) { + if (bundled_debug_data == nullptr) { + bundled_debug_data = new std::vector (); + bundled_debug_data->reserve (application_config.number_of_assemblies_in_apk); + } + + bundled_debug_data->emplace_back (); + set_debug_entry_data (bundled_debug_data->back (), fd, data_offset, file_size, prefix_len, max_assembly_name_size, entry_name); + continue; } #if !defined(NET6) - if (utils.ends_with (entry_name, ".config") && !bundled_assemblies.empty ()) { + if (utils.ends_with (entry_name, ".config")) { char *assembly_name = strdup (basename (entry_name.get ())); // Remove '.config' suffix *strrchr (assembly_name, '.') = '\0'; - md_mmap_info map_info = md_mmap_apk_file (fd, data_offset, file_size, entry_name.get (), apk_name); + md_mmap_info map_info = md_mmap_apk_file (fd, data_offset, file_size, entry_name.get ()); mono_register_config_for_assembly (assembly_name, (const char*)map_info.area); continue; @@ -157,42 +164,61 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, monodroid_sh if (!utils.ends_with (entry_name, ".dll")) continue; +#if defined (DEBUG) if (entry_is_overridden) continue; +#endif - assembly_count--; - MonoBundledAssembly *cur; - if (XA_UNLIKELY (assembly_count < 0 || (bundled_assemblies_slow_path && bundled_assemblies.size () <= bundled_assembly_index))) { - if (assembly_count == -1) { + if (XA_UNLIKELY (bundled_assembly_index >= application_config.number_of_assemblies_in_apk || bundled_assemblies_slow_path)) { + if (!bundled_assemblies_slow_path && bundled_assembly_index == application_config.number_of_assemblies_in_apk) { log_warn (LOG_ASSEMBLY, "Number of assemblies stored at build time (%u) was incorrect, switching to slow bundling path."); } - bundled_assemblies.emplace_back (); - cur = &bundled_assemblies.back (); - } else { - cur = &bundled_assemblies [bundled_assembly_index]; - } - bundled_assembly_index++; - md_mmap_info map_info = md_mmap_apk_file (fd, data_offset, file_size, entry_name.get (), apk_name); - cur->name = utils.strdup_new (entry_name.get () + prefix_len, entry_name.length () - prefix_len); - cur->data = (const unsigned char*)map_info.area; + if (extra_bundled_assemblies == nullptr) { + extra_bundled_assemblies = new std::vector (); + } - // MonoBundledAssembly::size is const?! - unsigned int *psize = (unsigned int*) &cur->size; - *psize = static_cast(file_size); + extra_bundled_assemblies->emplace_back (); + // means we need to allocate memory to store the entry name, only the entries pre-allocated during + // build have valid pointer to the name storage area + set_entry_data (extra_bundled_assemblies->back (), fd, data_offset, file_size, prefix_len, max_assembly_name_size, entry_name); + continue; + } - if (XA_UNLIKELY (utils.should_log (LOG_ASSEMBLY))) { - const char *p = (const char*) cur->data; + set_assembly_entry_data (bundled_assemblies [bundled_assembly_index], fd, data_offset, file_size, prefix_len, max_assembly_name_size, entry_name); + bundled_assembly_index++; + } - std::array header; - for (size_t j = 0; j < header.size () - 1; ++j) - header[j] = isprint (p [j]) ? p [j] : '.'; - header [header.size () - 1] = '\0'; + have_and_want_debug_symbols = register_debug_symbols && bundled_debug_data != nullptr; +} - log_info_nocheck (LOG_ASSEMBLY, "file-offset: % 8x start: %08p end: %08p len: % 12i zip-entry: %s name: %s [%s]", - (int) data_offset, cur->data, cur->data + *psize, (int) file_size, entry_name.get (), cur->name, header.data ()); - } +template +force_inline void +EmbeddedAssemblies::set_entry_data (XamarinAndroidBundledAssembly &entry, int apk_fd, uint32_t data_offset, uint32_t data_size, uint32_t prefix_len, uint32_t max_name_size, dynamic_local_string const& entry_name) noexcept +{ + entry.apk_fd = apk_fd; + if constexpr (NeedsNameAlloc) { + entry.name = utils.strdup_new (entry_name.get () + prefix_len); + } else { + // entry.name is preallocated on build time here and is max_name_size + 1 bytes long, filled with 0s, thus we + // don't need to append the terminating NUL even for strings of `max_name_size` characters + strncpy (entry.name, entry_name.get () + prefix_len, max_name_size); } + entry.name_length = std::min (static_cast(entry_name.length ()) - prefix_len, max_name_size); + entry.data_offset = data_offset; + entry.data_size = data_size; +} + +force_inline void +EmbeddedAssemblies::set_assembly_entry_data (XamarinAndroidBundledAssembly &entry, int apk_fd, uint32_t data_offset, uint32_t data_size, uint32_t prefix_len, uint32_t max_name_size, dynamic_local_string const& entry_name) noexcept +{ + set_entry_data (entry, apk_fd, data_offset, data_size, prefix_len, max_name_size, entry_name); +} + +force_inline void +EmbeddedAssemblies::set_debug_entry_data (XamarinAndroidBundledAssembly &entry, int apk_fd, uint32_t data_offset, uint32_t data_size, uint32_t prefix_len, uint32_t max_name_size, dynamic_local_string const& entry_name) noexcept +{ + set_entry_data (entry, apk_fd, data_offset, data_size, prefix_len, max_name_size, entry_name); } bool @@ -207,7 +233,7 @@ EmbeddedAssemblies::zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_ std::array eocd; ssize_t nread = ::read (fd, eocd.data (), static_cast(eocd.size ())); - if (nread < 0 || nread != ZIP_EOCD_LEN) { + if (nread < 0 || nread != eocd.size ()) { log_error (LOG_ASSEMBLY, "Failed to read EOCD from the APK: %s (nread: %d; errno: %d)", std::strerror (errno), nread, errno); return false; } @@ -276,7 +302,7 @@ EmbeddedAssemblies::zip_adjust_data_offset (int fd, size_t local_header_offset, std::array local_header; std::array signature; - ssize_t nread = ::read (fd, local_header.data (), static_cast(ZIP_LOCAL_LEN)); + ssize_t nread = ::read (fd, local_header.data (), local_header.size ()); if (nread < 0 || nread != ZIP_LOCAL_LEN) { log_error (LOG_ASSEMBLY, "Failed to read local header at offset %u: %s (nread: %d; errno: %d)", local_header_offset, std::strerror (errno), nread, errno); return false; @@ -288,7 +314,7 @@ EmbeddedAssemblies::zip_adjust_data_offset (int fd, size_t local_header_offset, return false; } - if (memcmp (signature.data (), ZIP_LOCAL_MAGIC, sizeof(signature)) != 0) { + if (memcmp (signature.data (), ZIP_LOCAL_MAGIC, signature.size ()) != 0) { log_error (LOG_ASSEMBLY, "Invalid Local Header entry signature at offset %u", local_header_offset); return false; } @@ -307,7 +333,7 @@ EmbeddedAssemblies::zip_adjust_data_offset (int fd, size_t local_header_offset, return false; } - data_start_offset = static_cast(local_header_offset) + file_name_length + extra_field_length + static_cast(ZIP_LOCAL_LEN); + data_start_offset = static_cast(local_header_offset) + file_name_length + extra_field_length + local_header.size (); return true; } @@ -316,9 +342,9 @@ template bool EmbeddedAssemblies::zip_extract_cd_info (std::array const& buf, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries) { - static constexpr size_t EOCD_TOTAL_ENTRIES_OFFSET = 10; - static constexpr size_t EOCD_CD_SIZE_OFFSET = 12; - static constexpr size_t EOCD_CD_START_OFFSET = 16; + constexpr size_t EOCD_TOTAL_ENTRIES_OFFSET = 10; + constexpr size_t EOCD_CD_SIZE_OFFSET = 12; + constexpr size_t EOCD_CD_START_OFFSET = 16; static_assert (BufSize >= ZIP_EOCD_LEN, "Buffer too short for EOCD"); @@ -409,12 +435,12 @@ EmbeddedAssemblies::zip_read_field (T const& buf, size_t index, size_t count, dy bool EmbeddedAssemblies::zip_read_entry_info (std::vector const& buf, size_t& buf_offset, uint16_t& compression_method, uint32_t& local_header_offset, uint32_t& file_size, dynamic_local_string& file_name) { - static constexpr size_t CD_COMPRESSION_METHOD_OFFSET = 10; - static constexpr size_t CD_UNCOMPRESSED_SIZE_OFFSET = 24; - static constexpr size_t CD_FILENAME_LENGTH_OFFSET = 28; - static constexpr size_t CD_EXTRA_LENGTH_OFFSET = 30; - static constexpr size_t CD_LOCAL_HEADER_POS_OFFSET = 42; - static constexpr size_t CD_COMMENT_LENGTH_OFFSET = 32; + constexpr size_t CD_COMPRESSION_METHOD_OFFSET = 10; + constexpr size_t CD_UNCOMPRESSED_SIZE_OFFSET = 24; + constexpr size_t CD_FILENAME_LENGTH_OFFSET = 28; + constexpr size_t CD_EXTRA_LENGTH_OFFSET = 30; + constexpr size_t CD_LOCAL_HEADER_POS_OFFSET = 42; + constexpr size_t CD_COMMENT_LENGTH_OFFSET = 32; size_t index = buf_offset; zip_ensure_valid_params (buf, index, ZIP_CENTRAL_LEN); @@ -425,7 +451,7 @@ EmbeddedAssemblies::zip_read_entry_info (std::vector const& buf, size_t return false; } - if (memcmp (signature.data (), ZIP_CENTRAL_MAGIC, sizeof(signature)) != 0) { + if (memcmp (signature.data (), ZIP_CENTRAL_MAGIC, signature.size ()) != 0) { log_error (LOG_ASSEMBLY, "Invalid Central Directory entry signature"); return false; } @@ -480,25 +506,3 @@ EmbeddedAssemblies::zip_read_entry_info (std::vector const& buf, size_t buf_offset += ZIP_CENTRAL_LEN + file_name_length + extra_field_length + comment_length; return true; } - -template -bool -EmbeddedAssemblies::register_debug_symbols_for_assembly (dynamic_local_string const& entry_name, MonoBundledAssembly const& assembly, const mono_byte *debug_contents, int debug_size) -{ - const char *entry_basename = utils.find_last (entry_name, '/') + 1; // strrchr (entry_name, '/') + 1; - // System.dll, System.dll.mdb case - if (strncmp (assembly.name, entry_basename, strlen (assembly.name)) != 0) { - // That failed; try for System.dll, System.pdb case - const char *eb_ext = utils.find_last (entry_name, '.'); - if (eb_ext == nullptr) - return false; - off_t basename_len = static_cast(eb_ext - entry_basename); - abort_unless (basename_len > 0, "basename must have a length!"); - if (strncmp (assembly.name, entry_basename, static_cast(basename_len)) != 0) - return false; - } - - mono_register_symfile_for_assembly (assembly.name, debug_contents, debug_size); - - return true; -} diff --git a/src/monodroid/jni/embedded-assemblies.cc b/src/monodroid/jni/embedded-assemblies.cc index 7ea97831cdb..bdd290eff21 100644 --- a/src/monodroid/jni/embedded-assemblies.cc +++ b/src/monodroid/jni/embedded-assemblies.cc @@ -18,6 +18,7 @@ #include #include #include +#include #include "java-interop-util.h" @@ -34,7 +35,7 @@ using namespace xamarin::android::internal; // A utility class which allows us to manage memory allocated by `mono_guid_to_string` in an elegant way. We can create // temporary instances of this class in calls to e.g. `log_debug` which are executed ONLY when debug logging is enabled -class MonoGuidString +class MonoGuidString final { public: explicit MonoGuidString (const uint8_t *id) noexcept @@ -64,7 +65,7 @@ void EmbeddedAssemblies::set_assemblies_prefix (const char *prefix) } force_inline void -EmbeddedAssemblies::get_assembly_data (MonoBundledAssembly const& e, char*& assembly_data, uint32_t& assembly_data_size) +EmbeddedAssemblies::get_assembly_data (XamarinAndroidBundledAssembly const& e, uint8_t*& assembly_data, uint32_t& assembly_data_size) { #if defined (ANDROID) && defined (HAVE_LZ4) && defined (RELEASE) auto header = reinterpret_cast(e.data); @@ -79,7 +80,7 @@ EmbeddedAssemblies::get_assembly_data (MonoBundledAssembly const& e, char*& asse } CompressedAssemblyDescriptor &cad = compressed_assemblies.descriptors[header->descriptor_index]; - assembly_data_size = e.size - sizeof(CompressedAssemblyHeader); + assembly_data_size = e.data_size - sizeof(CompressedAssemblyHeader); if (!cad.loaded) { if (XA_UNLIKELY (cad.data == nullptr)) { log_fatal (LOG_ASSEMBLY, "Invalid compressed assembly descriptor at %u: no data", header->descriptor_index); @@ -121,13 +122,13 @@ EmbeddedAssemblies::get_assembly_data (MonoBundledAssembly const& e, char*& asse } cad.loaded = true; } - assembly_data = reinterpret_cast(cad.data); + assembly_data = reinterpret_cast(cad.data); assembly_data_size = cad.uncompressed_file_size; } else #endif { - assembly_data = reinterpret_cast(const_cast(e.data)); - assembly_data_size = e.size; + assembly_data = e.data; + assembly_data_size = e.data_size; } } @@ -135,10 +136,10 @@ EmbeddedAssemblies::get_assembly_data (MonoBundledAssembly const& e, char*& asse MonoAssembly* EmbeddedAssemblies::open_from_bundles (MonoAssemblyName* aname, MonoAssemblyLoadContextGCHandle alc_gchandle, [[maybe_unused]] MonoError *error) { - auto loader = [&] (char *assembly_data, uint32_t assembly_data_size, const char *name) -> MonoImage* { + auto loader = [&] (uint8_t *assembly_data, uint32_t assembly_data_size, const char *name) -> MonoImage* { return mono_image_open_from_data_alc ( alc_gchandle, - assembly_data, + reinterpret_cast(assembly_data), assembly_data_size, 0 /* need_copy */, nullptr /* status */, @@ -153,9 +154,9 @@ EmbeddedAssemblies::open_from_bundles (MonoAssemblyName* aname, MonoAssemblyLoad MonoAssembly* EmbeddedAssemblies::open_from_bundles (MonoAssemblyName* aname, bool ref_only) { - auto loader = [&] (char *assembly_data, uint32_t assembly_data_size, const char *name) -> MonoImage* { + auto loader = [&] (uint8_t *assembly_data, uint32_t assembly_data_size, const char *name) -> MonoImage* { return mono_image_open_from_data_with_name ( - assembly_data, + reinterpret_cast(assembly_data), assembly_data_size, 0, nullptr, @@ -167,8 +168,147 @@ EmbeddedAssemblies::open_from_bundles (MonoAssemblyName* aname, bool ref_only) return open_from_bundles (aname, loader, ref_only); } +template +force_inline void +EmbeddedAssemblies::map_runtime_file (XamarinAndroidBundledAssembly& file) noexcept +{ + md_mmap_info map_info = md_mmap_apk_file (file.apk_fd, file.data_offset, file.data_size, file.name); + if (monodroidRuntime.is_startup_in_progress ()) { + file.data = static_cast(map_info.area); + } else { + // + // We could use either standard std::atomic<> here, but it would cost us some performance during startup + // where we don't need synchronization but we would still need to use the atomic operations. + // + // Another option is the GCC/clang built-in atomic operations, but these can be compiler and compiler + // version specific, so it's better to use something standard. + // + // C++20 comes with a binary_semaphore, we could use that but it requires the std::chrono library and we + // should keep XA runtime slim unless absolutely necessary + // + // POSIX semaphores should be perfectly fine for us here. + // + PosixSemaphoreGuard sem (assembly_mmap_semaphore); + + if constexpr (AbortOnFailure) { + abort_unless (sem.result () == 0, "Failed to acquire assembly mapping semaphore. %s", strerror (errno)); + } else { + if (sem.result () != 0) { + log_warn (LOG_ASSEMBLY, "File '%s' will not be mapped, failed to acquire assembly mapping semaphore. %s", file.name, strerror (errno)); + return; + } + } + + if (file.data == nullptr) { + file.data = static_cast(map_info.area); + } else { + log_debug (LOG_ASSEMBLY, "Assembly %s already mmapped by another thread, unmapping our copy", file.name); + munmap (map_info.area, file.data_size); + map_info.area = nullptr; + } + } + + if constexpr (LogMapping) { + if (XA_UNLIKELY (utils.should_log (LOG_ASSEMBLY) && map_info.area != nullptr)) { + const char *p = (const char*) file.data; + + std::array header; + for (size_t j = 0; j < header.size () - 1; ++j) + header[j] = isprint (p [j]) ? p [j] : '.'; + header [header.size () - 1] = '\0'; + + log_info_nocheck (LOG_ASSEMBLY, "file-offset: % 8x start: %08p end: %08p len: % 12i zip-entry: %s name: %s [%s]", + (int) file.data_offset, file.data, file.data + file.data_size, (int) file.data_size, file.name, file.name, header.data ()); + } + } +} + +force_inline void +EmbeddedAssemblies::map_assembly (XamarinAndroidBundledAssembly& file) noexcept +{ + map_runtime_file (file); +} + +force_inline void +EmbeddedAssemblies::map_debug_data (XamarinAndroidBundledAssembly& file) noexcept +{ + map_runtime_file (file); +} + +force_inline MonoAssembly* +EmbeddedAssemblies::load_bundled_assembly ( + XamarinAndroidBundledAssembly& assembly, + dynamic_local_string const& name, + dynamic_local_string const& abi_name, + std::function loader, + bool ref_only) noexcept +{ + if (assembly.name == nullptr || assembly.name[0] == '\0') { + return nullptr; + } + + if (strcmp (assembly.name, name.get ()) != 0) { + if (strcmp (assembly.name, abi_name.get ()) != 0) { + return nullptr; + } else { + log_debug (LOG_ASSEMBLY, "open_from_bundles: found architecture-specific: '%s'", abi_name.get ()); + } + } + + if (assembly.data == nullptr) { + map_assembly (assembly); + } + + uint8_t *assembly_data; + uint32_t assembly_data_size; + + get_assembly_data (assembly, assembly_data, assembly_data_size); + MonoImage *image = loader (assembly_data, assembly_data_size, name.get ()); + if (image == nullptr) { + return nullptr; + } + + if (have_and_want_debug_symbols) { + uint32_t base_name_length = assembly.name_length - 3; // we need the trailing dot + for (XamarinAndroidBundledAssembly& debug_file : *bundled_debug_data) { + if (debug_file.name_length < base_name_length) { + continue; + } + + if (strncmp (debug_file.name, assembly.name, base_name_length) != 0) { + continue; + } + + if (debug_file.data == nullptr) { + map_debug_data (debug_file); + } + + if (debug_file.data != nullptr) { + if (debug_file.data_size > std::numeric_limits::max ()) { + log_warn (LOG_ASSEMBLY, "Debug info file '%s' is too big for Mono to consume", debug_file.name); + } else { + mono_debug_open_image_from_memory (image, reinterpret_cast(debug_file.data), static_cast(debug_file.data_size)); + } + } + break; + } + } + + MonoImageOpenStatus status; + MonoAssembly *a = mono_assembly_load_from_full (image, name.get (), &status, ref_only); + if (a == nullptr) { + return nullptr; + } + +#if !defined (NET6) + // In dotnet the call is a no-op + mono_config_for_assembly (image); +#endif + return a; +} + MonoAssembly* -EmbeddedAssemblies::open_from_bundles (MonoAssemblyName* aname, std::function loader, bool ref_only) +EmbeddedAssemblies::open_from_bundles (MonoAssemblyName* aname, std::function loader, bool ref_only) { const char *culture = mono_assembly_name_get_culture (aname); const char *asmname = mono_assembly_name_get_name (aname); @@ -194,49 +334,26 @@ EmbeddedAssemblies::open_from_bundles (MonoAssemblyName* aname, std::functionassembly_name, java_type_name); return nullptr; @@ -547,7 +672,6 @@ EmbeddedAssemblies::typemap_managed_to_java ([[maybe_unused]] MonoType *type, Mo return nullptr; } - uint32_t token = mono_class_get_type_token (klass); const TypeMapModule *map; size_t map_entry_count; map = map_modules; @@ -564,6 +688,7 @@ EmbeddedAssemblies::typemap_managed_to_java ([[maybe_unused]] MonoType *type, Mo return nullptr; } + uint32_t token = mono_class_get_type_token (klass); log_debug (LOG_ASSEMBLY, "typemap: MVID [%s] maps to assembly %s, looking for token %d (0x%x), table index %d", MonoGuidString (mvid).get (), match->assembly_name, token, token, token & 0x00FFFFFF); // Each map entry is a pair of 32-bit integers: [TypeTokenID][JavaMapArrayIndex] const TypeMapModuleEntry *entry = binary_search (&token, match->map, match->entry_count); @@ -635,20 +760,20 @@ EmbeddedAssemblies::typemap_managed_to_java (MonoReflectionType *reflection_type } EmbeddedAssemblies::md_mmap_info -EmbeddedAssemblies::md_mmap_apk_file (int fd, uint32_t offset, uint32_t size, const char* filename, const char* apk) +EmbeddedAssemblies::md_mmap_apk_file (int fd, uint32_t offset, size_t size, const char* filename) { md_mmap_info file_info; md_mmap_info mmap_info; - size_t pageSize = static_cast(utils.monodroid_getpagesize ()); - uint32_t offsetFromPage = static_cast(offset % pageSize); - uint32_t offsetPage = offset - offsetFromPage; - uint32_t offsetSize = size + offsetFromPage; + size_t pageSize = static_cast(utils.monodroid_getpagesize ()); + size_t offsetFromPage = offset % pageSize; + size_t offsetPage = offset - offsetFromPage; + size_t offsetSize = size + offsetFromPage; mmap_info.area = mmap (nullptr, offsetSize, PROT_READ, MAP_PRIVATE, fd, static_cast(offsetPage)); if (mmap_info.area == MAP_FAILED) { - log_fatal (LOG_DEFAULT, "Could not `mmap` apk `%s` entry `%s`: %s", apk, filename, strerror (errno)); + log_fatal (LOG_DEFAULT, "Could not `mmap` apk fd %d entry `%s`: %s", fd, filename, strerror (errno)); exit (FATAL_EXIT_CANNOT_FIND_APK); } @@ -656,9 +781,9 @@ EmbeddedAssemblies::md_mmap_apk_file (int fd, uint32_t offset, uint32_t size, co file_info.area = (void*)((const char*)mmap_info.area + offsetFromPage); file_info.size = size; - log_info (LOG_ASSEMBLY, " mmap_start: %08p mmap_end: %08p mmap_len: % 12u file_start: %08p file_end: %08p file_len: % 12u apk: %s file: %s", - mmap_info.area, reinterpret_cast (mmap_info.area) + mmap_info.size, (unsigned int) mmap_info.size, - file_info.area, reinterpret_cast (file_info.area) + file_info.size, (unsigned int) file_info.size, apk, filename); + log_info (LOG_ASSEMBLY, " mmap_start: %08p mmap_end: %08p mmap_len: % 12u file_start: %08p file_end: %08p file_len: % 12u apk descriptor: %d file: %s", + mmap_info.area, reinterpret_cast (mmap_info.area) + mmap_info.size, mmap_info.size, + file_info.area, reinterpret_cast (file_info.area) + file_info.size, file_info.size, fd, filename); return file_info; } @@ -672,9 +797,9 @@ EmbeddedAssemblies::gather_bundled_assemblies_from_apk (const char* apk, monodro log_error (LOG_DEFAULT, "ERROR: Unable to load application package %s.", apk); exit (FATAL_EXIT_NO_ASSEMBLIES); } + log_info (LOG_ASSEMBLY, "APK %s FD: %d", apk, fd); - zip_load_entries (fd, utils.strdup_new (apk), should_register); - close(fd); + zip_load_entries (fd, apk, should_register); } #if defined (DEBUG) || !defined (ANDROID) diff --git a/src/monodroid/jni/embedded-assemblies.hh b/src/monodroid/jni/embedded-assemblies.hh index 3cede35756a..2da163c300a 100644 --- a/src/monodroid/jni/embedded-assemblies.hh +++ b/src/monodroid/jni/embedded-assemblies.hh @@ -12,10 +12,12 @@ #include #endif // __has_include +#include #include #include #include #include +#include #include #include @@ -46,7 +48,7 @@ namespace xamarin::android::internal { #define ByteArrayContainer class #endif - class EmbeddedAssemblies + class EmbeddedAssemblies final { struct md_mmap_info { void *area; @@ -81,6 +83,12 @@ namespace xamarin::android::internal { #endif // def NET6 MonoReflectionType* typemap_java_to_managed (MonoString *java_type); + void prepare_for_multiple_threads () noexcept + { + int ret = sem_init (&assembly_mmap_semaphore, 0 /* pshared */, 1 /* value */); + abort_unless (ret == 0, "Failed to initialize assembly mapping semaphore. %s", strerror (errno)); + } + /* returns current number of *all* assemblies found from all invocations */ template size_t register_from (const char *apk_file) @@ -125,7 +133,18 @@ namespace xamarin::android::internal { MonoAssembly* open_from_bundles (MonoAssemblyName* aname, MonoAssemblyLoadContextGCHandle alc_gchandle, MonoError *error); #endif // def NET6 MonoAssembly* open_from_bundles (MonoAssemblyName* aname, bool ref_only); - MonoAssembly* open_from_bundles (MonoAssemblyName* aname, std::function loader, bool ref_only); + MonoAssembly* open_from_bundles (MonoAssemblyName* aname, std::function loader, bool ref_only); + + template + void map_runtime_file (XamarinAndroidBundledAssembly& file) noexcept; + void map_assembly (XamarinAndroidBundledAssembly& file) noexcept; + void map_debug_data (XamarinAndroidBundledAssembly& file) noexcept; + MonoAssembly* load_bundled_assembly ( + XamarinAndroidBundledAssembly& assembly, + dynamic_local_string const& name, + dynamic_local_string const& abi_name, + std::function loader, + bool ref_only) noexcept; #if defined (DEBUG) || !defined (ANDROID) template @@ -137,17 +156,15 @@ namespace xamarin::android::internal { static ssize_t do_read (int fd, void *buf, size_t count); const TypeMapEntry *typemap_managed_to_java (const char *managed_type_name); #endif // DEBUG || !ANDROID - template - bool register_debug_symbols_for_assembly (dynamic_local_string const& entry_name, MonoBundledAssembly const& assembly, const mono_byte *debug_contents, int debug_size); - static md_mmap_info md_mmap_apk_file (int fd, uint32_t offset, uint32_t size, const char* filename, const char* apk); + static md_mmap_info md_mmap_apk_file (int fd, uint32_t offset, size_t size, const char* filename); static MonoAssembly* open_from_bundles_full (MonoAssemblyName *aname, char **assemblies_path, void *user_data); #if defined (NET6) static MonoAssembly* open_from_bundles (MonoAssemblyLoadContextGCHandle alc_gchandle, MonoAssemblyName *aname, char **assemblies_path, void *user_data, MonoError *error); #else // def NET6 static MonoAssembly* open_from_bundles_refonly (MonoAssemblyName *aname, char **assemblies_path, void *user_data); #endif // ndef NET6 - static void get_assembly_data (MonoBundledAssembly const& e, char*& assembly_data, uint32_t& assembly_data_size); + static void get_assembly_data (XamarinAndroidBundledAssembly const& e, uint8_t*& assembly_data, uint32_t& assembly_data_size); void zip_load_entries (int fd, const char *apk_name, monodroid_should_register should_register); bool zip_read_cd_info (int fd, uint32_t& cd_offset, uint32_t& cd_size, uint16_t& cd_entries); @@ -189,11 +206,13 @@ namespace xamarin::android::internal { return assemblies_prefix_override != nullptr ? assemblies_prefix_override : assemblies_prefix; } - size_t get_assemblies_prefix_length () const noexcept + uint32_t get_assemblies_prefix_length () const noexcept { - return assemblies_prefix_override != nullptr ? strlen (assemblies_prefix_override) : sizeof(assemblies_prefix) - 1; + return assemblies_prefix_override != nullptr ? static_cast(strlen (assemblies_prefix_override)) : sizeof(assemblies_prefix) - 1; } + bool is_debug_file (dynamic_local_string const& name) noexcept; + template const Entry* binary_search (const Key *key, const Entry *base, size_t nmemb, size_t extra_size = 0); @@ -204,10 +223,18 @@ namespace xamarin::android::internal { static int compare_type_token (const uint32_t *token, const TypeMapModuleEntry *entry); static int compare_java_name (const char *java_name, const TypeMapJava *entry); #endif + template + void set_entry_data (XamarinAndroidBundledAssembly &entry, int apk_fd, uint32_t data_offset, uint32_t data_size, uint32_t prefix_len, uint32_t max_name_size, dynamic_local_string const& entry_name) noexcept; + void set_assembly_entry_data (XamarinAndroidBundledAssembly &entry, int apk_fd, uint32_t data_offset, uint32_t data_size, uint32_t prefix_len, uint32_t max_name_size, dynamic_local_string const& entry_name) noexcept; + void set_debug_entry_data (XamarinAndroidBundledAssembly &entry, int apk_fd, uint32_t data_offset, uint32_t data_size, uint32_t prefix_len, uint32_t max_name_size, dynamic_local_string const& entry_name) noexcept; private: + std::vector *bundled_debug_data = nullptr; + std::vector *extra_bundled_assemblies = nullptr; + bool register_debug_symbols; - std::vector bundled_assemblies; + bool have_and_want_debug_symbols; + sem_t assembly_mmap_semaphore; size_t bundled_assembly_index = 0; #if defined (DEBUG) || !defined (ANDROID) TypeMappingInfo *java_to_managed_maps; diff --git a/src/monodroid/jni/monodroid-glue-internal.hh b/src/monodroid/jni/monodroid-glue-internal.hh index f8624d36d7d..69ba8258f2c 100644 --- a/src/monodroid/jni/monodroid-glue-internal.hh +++ b/src/monodroid/jni/monodroid-glue-internal.hh @@ -145,6 +145,11 @@ namespace xamarin::android::internal #endif jint Java_JNI_OnLoad (JavaVM *vm, void *reserved); + bool is_startup_in_progress () const noexcept + { + return startup_in_progress; + } + int get_android_api_level () const { return android_api_level; @@ -329,6 +334,7 @@ namespace xamarin::android::internal * able to switch our different contexts from different threads. */ int current_context_id = -1; + bool startup_in_progress = true; #if defined (NET6) MonoAssemblyLoadContextGCHandle default_alc = nullptr; diff --git a/src/monodroid/jni/monodroid-glue.cc b/src/monodroid/jni/monodroid-glue.cc index 9b1c56ee489..47b9c507de6 100644 --- a/src/monodroid/jni/monodroid-glue.cc +++ b/src/monodroid/jni/monodroid-glue.cc @@ -1612,7 +1612,7 @@ MonodroidRuntime::set_profile_options () while (value.next_token (start_index, ',', param)) { dynamic_local_string temp; temp.assign (param.start (), param.length ()); - if (!param.starts_with (OUTPUT_ARG, OUTPUT_ARG_LEN) || param.length () == OUTPUT_ARG_LEN) { + if (!param.starts_with (OUTPUT_ARG) || param.length () == OUTPUT_ARG_LEN) { continue; } @@ -2211,6 +2211,9 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl #endif // def ANDROID } + embeddedAssemblies.prepare_for_multiple_threads (); + startup_in_progress = false; + if (XA_UNLIKELY (utils.should_log (LOG_TIMING))) { total_time.mark_end (); diff --git a/src/monodroid/jni/pinvoke-override-api.cc b/src/monodroid/jni/pinvoke-override-api.cc index 39da7ac64ad..528e528472a 100644 --- a/src/monodroid/jni/pinvoke-override-api.cc +++ b/src/monodroid/jni/pinvoke-override-api.cc @@ -609,7 +609,7 @@ MonodroidRuntime::load_library_entry (std::string const& library_name, std::stri return nullptr; } - log_warn (LOG_ASSEMBLY, "Caching p/invoke entry %s @ %s", library_name.c_str (), entrypoint_name.c_str ()); + log_debug (LOG_ASSEMBLY, "Caching p/invoke entry %s @ %s", library_name.c_str (), entrypoint_name.c_str ()); (*api_map)[entrypoint_name] = entry_handle; return entry_handle; } diff --git a/src/monodroid/jni/strings.hh b/src/monodroid/jni/strings.hh index b3e019f096d..472fd6bf9a8 100644 --- a/src/monodroid/jni/strings.hh +++ b/src/monodroid/jni/strings.hh @@ -76,7 +76,7 @@ namespace xamarin::android::internal return memcmp (_start, s, length ()) == 0; } - force_inline bool starts_with (const char *s) const noexcept + force_inline bool starts_with_c (const char *s) const noexcept { if (s == nullptr) return false; diff --git a/src/monodroid/jni/util.cc b/src/monodroid/jni/util.cc index b8b83e5d060..bcee4cd6f6d 100644 --- a/src/monodroid/jni/util.cc +++ b/src/monodroid/jni/util.cc @@ -83,6 +83,17 @@ timing_diff::timing_diff (const timing_period &period) ns = static_cast(nsec % ms_in_nsec); } +Util::Util () +{ +#ifndef WINDOWS + page_size = getpagesize (); +#else // defined(WINDOWS) + SYSTEM_INFO info; + GetSystemInfo (&info); + page_size = info.dwPageSize; +#endif // defined(WINDOWS) +} + int Util::send_uninterrupted (int fd, void *buf, size_t len) { @@ -336,15 +347,3 @@ Util::get_class_from_runtime_field (JNIEnv *env, jclass runtime, const char *nam return reinterpret_cast (make_gref ? osBridge.lref_to_gref (env, field) : field); } - -int -Util::monodroid_getpagesize (void) -{ -#ifndef WINDOWS - return getpagesize (); -#else // defined(WINDOWS) - SYSTEM_INFO info; - GetSystemInfo (&info); - return info.dwPageSize; -#endif // defined(WINDOWS) -} diff --git a/src/monodroid/jni/util.hh b/src/monodroid/jni/util.hh index 551df9e7d59..7f2e8e67bbe 100644 --- a/src/monodroid/jni/util.hh +++ b/src/monodroid/jni/util.hh @@ -82,7 +82,13 @@ namespace xamarin::android static constexpr uint32_t ms_in_nsec = 1000000ULL; public: - int monodroid_getpagesize (); + Util (); + + int monodroid_getpagesize () const noexcept + { + return page_size; + } + void monodroid_store_package_name (const char *name); MonoAssembly *monodroid_load_assembly (MonoDomain *domain, const char *basename); #if defined (NET6) @@ -118,6 +124,7 @@ namespace xamarin::android private: char package_property_suffix[9]; + int page_size; }; } #endif // __cplusplus diff --git a/src/monodroid/jni/xamarin-app.hh b/src/monodroid/jni/xamarin-app.hh index fe034ccb4bc..06f7668da62 100644 --- a/src/monodroid/jni/xamarin-app.hh +++ b/src/monodroid/jni/xamarin-app.hh @@ -96,6 +96,16 @@ struct CompressedAssemblies CompressedAssemblyDescriptor *descriptors; }; +struct XamarinAndroidBundledAssembly final +{ + int32_t apk_fd; + uint32_t data_offset; + uint32_t data_size; + uint8_t *data; + uint32_t name_length; + char *name; +}; + struct ApplicationConfig { bool uses_mono_llvm; @@ -111,6 +121,7 @@ struct ApplicationConfig uint32_t environment_variable_count; uint32_t system_property_count; uint32_t number_of_assemblies_in_apk; + uint32_t bundled_assembly_name_width; const char *android_package_name; }; @@ -132,4 +143,7 @@ MONO_API const char* app_environment_variables[]; MONO_API const char* app_system_properties[]; MONO_API const char* mono_aot_mode_name; + +MONO_API XamarinAndroidBundledAssembly bundled_assemblies[]; + #endif // __XAMARIN_ANDROID_TYPEMAP_H