From ffcb7d6f75d2e846ae7b6a50209836893f3b76fc Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 3 Jul 2025 16:01:30 +0200 Subject: [PATCH 01/32] Scaffolding for the new app --- tools/apput/projects/.placeholder | 1 + .../ApplicationAssembly.cs | 25 +++++++ .../apput/src/AssemblyStore/AssemblyStore.cs | 24 +++++++ tools/apput/src/Common/IAspect.cs | 32 +++++++++ tools/apput/src/Common/NativeArchitecture.cs | 11 +++ tools/apput/src/Native/SharedLibrary.cs | 68 +++++++++++++++++++ tools/apput/src/Package/ApplicationPackage.cs | 21 ++++++ tools/apput/src/Package/PackageAAB.cs | 6 ++ tools/apput/src/Package/PackageAPK.cs | 6 ++ tools/apput/src/Package/PackageBase.cs | 6 ++ tools/apput/src/Program.cs | 8 +++ tools/apput/src/apput.csproj | 28 ++++++++ 12 files changed, 236 insertions(+) create mode 100644 tools/apput/projects/.placeholder create mode 100644 tools/apput/src/ApplicationAssembly/ApplicationAssembly.cs create mode 100644 tools/apput/src/AssemblyStore/AssemblyStore.cs create mode 100644 tools/apput/src/Common/IAspect.cs create mode 100644 tools/apput/src/Common/NativeArchitecture.cs create mode 100644 tools/apput/src/Native/SharedLibrary.cs create mode 100644 tools/apput/src/Package/ApplicationPackage.cs create mode 100644 tools/apput/src/Package/PackageAAB.cs create mode 100644 tools/apput/src/Package/PackageAPK.cs create mode 100644 tools/apput/src/Package/PackageBase.cs create mode 100644 tools/apput/src/Program.cs create mode 100644 tools/apput/src/apput.csproj diff --git a/tools/apput/projects/.placeholder b/tools/apput/projects/.placeholder new file mode 100644 index 00000000000..a18be027f41 --- /dev/null +++ b/tools/apput/projects/.placeholder @@ -0,0 +1 @@ +This directory will contain .csproj files to be used by 3rd parties (e.g. XABT tests) diff --git a/tools/apput/src/ApplicationAssembly/ApplicationAssembly.cs b/tools/apput/src/ApplicationAssembly/ApplicationAssembly.cs new file mode 100644 index 00000000000..37427304ca2 --- /dev/null +++ b/tools/apput/src/ApplicationAssembly/ApplicationAssembly.cs @@ -0,0 +1,25 @@ +using System; +using System.IO; + +namespace ApplicationUtility; + +public class ApplicationAssembly : IAspect +{ + public static string AspectName { get; } = "Application assembly"; + + public bool IsCompressed { get; private set; } + public string Name { get; private set; } = ""; + public ulong CompressedSize { get; private set; } + public ulong Size { get; private set; } + public bool IgnoreOnLoad { get; private set; } + + public static IAspect LoadAspect (Stream stream, string description) + { + throw new NotImplementedException (); + } + + public static bool ProbeAspect (Stream stream) + { + throw new NotImplementedException (); + } +} diff --git a/tools/apput/src/AssemblyStore/AssemblyStore.cs b/tools/apput/src/AssemblyStore/AssemblyStore.cs new file mode 100644 index 00000000000..32c7f96efa4 --- /dev/null +++ b/tools/apput/src/AssemblyStore/AssemblyStore.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace ApplicationUtility; + +public class AssemblyStore : IAspect +{ + public static string AspectName { get; } = "Assembly Store"; + + public IDictionary Assemblies { get; private set; } = null!; + public NativeArchitecture Architecture { get; private set; } = NativeArchitecture.Unknown; + public ulong NumberOfAssemblies => (ulong)(Assemblies?.Count ?? 0); + + public static IAspect LoadAspect (Stream stream, string description) + { + throw new NotImplementedException (); + } + + public static bool ProbeAspect (Stream stream) + { + throw new NotImplementedException (); + } +} diff --git a/tools/apput/src/Common/IAspect.cs b/tools/apput/src/Common/IAspect.cs new file mode 100644 index 00000000000..c078a5e9fb2 --- /dev/null +++ b/tools/apput/src/Common/IAspect.cs @@ -0,0 +1,32 @@ +using System.IO; + +namespace ApplicationUtility; + +/// +/// Represets an aspect of a .NET for Android application. An aspect can be an +/// individual assembly, the whole APK/AAB package, a shared library etc. +/// If it exists as a definable, separate entity in the application, that can +/// be identified/detected by looking at its format/location it is most +/// likely an aspect. +/// +public interface IAspect +{ + /// + /// Aspect name, for presentation purposes. + /// + abstract static string AspectName { get; } + + /// + /// Probes whether contains something this aspect + /// recognizes and supports. Returns `true` if it can handle the data, + /// `false` otherwise. + /// + abstract static bool ProbeAspect (Stream stream); + + /// + /// Load the aspect and return instance of a class implementing support for it. + /// The parameter can be anything that makes + /// sense for the given aspect (e.g. a file name). + /// + abstract static IAspect LoadAspect (Stream stream, string description); +} diff --git a/tools/apput/src/Common/NativeArchitecture.cs b/tools/apput/src/Common/NativeArchitecture.cs new file mode 100644 index 00000000000..919dc142abc --- /dev/null +++ b/tools/apput/src/Common/NativeArchitecture.cs @@ -0,0 +1,11 @@ +namespace ApplicationUtility; + +public enum NativeArchitecture +{ + Unknown, + + Arm, + Arm64, + X86, + X64, +} \ No newline at end of file diff --git a/tools/apput/src/Native/SharedLibrary.cs b/tools/apput/src/Native/SharedLibrary.cs new file mode 100644 index 00000000000..b807c6f6782 --- /dev/null +++ b/tools/apput/src/Native/SharedLibrary.cs @@ -0,0 +1,68 @@ +using System; +using System.IO; + +using ApplicationUtility; + +public class SharedLibrary : IAspect +{ + public static string AspectName { get; } = "Native shared library"; + + public bool HasAndroidPayload => payloadSize > 0; + public string Name => libraryName; + + readonly ulong payloadOffset; + readonly ulong payloadSize; + readonly string libraryName; + + SharedLibrary (Stream stream, string libraryName) + { + (payloadOffset, payloadSize) = FindAndroidPayload (stream); + this.libraryName = libraryName; + } + + public static IAspect LoadAspect (Stream stream, string description) + { + if (!IsELFSharedLibrary (stream)) { + throw new InvalidOperationException ("Stream is not an ELF shared library"); + } + + return new SharedLibrary (stream, description); + } + + public static bool ProbeAspect (Stream stream) => IsELFSharedLibrary (stream); + + /// + /// If the library has .NET for Android payload section, this + /// method will read the data and write it to the + /// stream. All the data in the output stream will be overwritten. + /// + public void CopyAndroidPayload (Stream dest) + { + Stream payload = OpenAndroidPayload (); + throw new NotImplementedException (); + } + + /// + /// Creates a stream referring to the Android payload data inside + /// the shared library. No data is read, the open stream is returned + /// to the user. Ownership of the stream is transferred to the caller. + /// + public Stream OpenAndroidPayload () + { + if (!HasAndroidPayload) { + throw new InvalidOperationException ("Payload section not found"); + } + + throw new NotImplementedException (); + } + + static bool IsELFSharedLibrary (Stream stream) + { + throw new NotImplementedException (); + } + + (ulong offset, ulong size) FindAndroidPayload (Stream stream) + { + throw new NotImplementedException (); + } +} diff --git a/tools/apput/src/Package/ApplicationPackage.cs b/tools/apput/src/Package/ApplicationPackage.cs new file mode 100644 index 00000000000..4ce40927a01 --- /dev/null +++ b/tools/apput/src/Package/ApplicationPackage.cs @@ -0,0 +1,21 @@ +using System; +using System.IO; + +namespace ApplicationUtility; + +public abstract class ApplicationPackage : IAspect +{ + public static string AspectName { get; } = "Application package"; + + public abstract string PackageFormat { get; } + + public static IAspect LoadAspect (Stream stream, string description) + { + throw new NotImplementedException (); + } + + public static bool ProbeAspect (Stream stream) + { + throw new NotImplementedException (); + } +} diff --git a/tools/apput/src/Package/PackageAAB.cs b/tools/apput/src/Package/PackageAAB.cs new file mode 100644 index 00000000000..49a6748b40c --- /dev/null +++ b/tools/apput/src/Package/PackageAAB.cs @@ -0,0 +1,6 @@ +namespace ApplicationUtility; + +class PackageAAB : ApplicationPackage +{ + public override string PackageFormat { get; } = "AAB package"; +} diff --git a/tools/apput/src/Package/PackageAPK.cs b/tools/apput/src/Package/PackageAPK.cs new file mode 100644 index 00000000000..bad2317a666 --- /dev/null +++ b/tools/apput/src/Package/PackageAPK.cs @@ -0,0 +1,6 @@ +namespace ApplicationUtility; + +class PackageAPK : ApplicationPackage +{ + public override string PackageFormat { get; } = "APK package"; +} diff --git a/tools/apput/src/Package/PackageBase.cs b/tools/apput/src/Package/PackageBase.cs new file mode 100644 index 00000000000..d218daf5845 --- /dev/null +++ b/tools/apput/src/Package/PackageBase.cs @@ -0,0 +1,6 @@ +namespace ApplicationUtility; + +class PackageBase : ApplicationPackage +{ + public override string PackageFormat { get; } = "Base application package"; +} diff --git a/tools/apput/src/Program.cs b/tools/apput/src/Program.cs new file mode 100644 index 00000000000..c3e891cbb0a --- /dev/null +++ b/tools/apput/src/Program.cs @@ -0,0 +1,8 @@ +namespace ApplicationUtility; + +class Program +{ + static void Main(string[] args) + { + } +} diff --git a/tools/apput/src/apput.csproj b/tools/apput/src/apput.csproj new file mode 100644 index 00000000000..03f2193cf54 --- /dev/null +++ b/tools/apput/src/apput.csproj @@ -0,0 +1,28 @@ + + + + + Microsoft Corporation + 2025 Microsoft Corporation + 0.0.1 + $(DotNetStableTargetFramework) + false + ../../bin/$(Configuration)/bin/apput + Exe + true + enable + Major + disable + + + + + + + + + + + + + From 17b462a3985ddb77bdf8673ea8ac69ab085cb4ac Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 4 Jul 2025 17:41:43 +0200 Subject: [PATCH 02/32] Slight IAspect changes + some flesh for the skeleton --- .../ApplicationAssembly.cs | 4 +- .../apput/src/AssemblyStore/AssemblyStore.cs | 4 +- tools/apput/src/Common/IAspect.cs | 12 +- tools/apput/src/Common/Log.cs | 149 ++++++++++++++++++ tools/apput/src/Common/NativeArchitecture.cs | 15 +- tools/apput/src/Detector.cs | 67 ++++++++ tools/apput/src/Native/SharedLibrary.cs | 12 +- tools/apput/src/Package/ApplicationPackage.cs | 99 +++++++++++- tools/apput/src/Package/ApplicationRuntime.cs | 8 + tools/apput/src/Package/PackageAAB.cs | 6 + tools/apput/src/Package/PackageAPK.cs | 6 + tools/apput/src/Package/PackageBase.cs | 6 + tools/apput/src/Program.cs | 4 +- tools/apput/src/apput.csproj | 5 +- 14 files changed, 370 insertions(+), 27 deletions(-) create mode 100644 tools/apput/src/Common/Log.cs create mode 100644 tools/apput/src/Detector.cs create mode 100644 tools/apput/src/Package/ApplicationRuntime.cs diff --git a/tools/apput/src/ApplicationAssembly/ApplicationAssembly.cs b/tools/apput/src/ApplicationAssembly/ApplicationAssembly.cs index 37427304ca2..211ccb47dde 100644 --- a/tools/apput/src/ApplicationAssembly/ApplicationAssembly.cs +++ b/tools/apput/src/ApplicationAssembly/ApplicationAssembly.cs @@ -13,12 +13,12 @@ public class ApplicationAssembly : IAspect public ulong Size { get; private set; } public bool IgnoreOnLoad { get; private set; } - public static IAspect LoadAspect (Stream stream, string description) + public static IAspect LoadAspect (Stream stream, string? description) { throw new NotImplementedException (); } - public static bool ProbeAspect (Stream stream) + public static bool ProbeAspect (Stream stream, string? description) { throw new NotImplementedException (); } diff --git a/tools/apput/src/AssemblyStore/AssemblyStore.cs b/tools/apput/src/AssemblyStore/AssemblyStore.cs index 32c7f96efa4..ba36988088f 100644 --- a/tools/apput/src/AssemblyStore/AssemblyStore.cs +++ b/tools/apput/src/AssemblyStore/AssemblyStore.cs @@ -12,12 +12,12 @@ public class AssemblyStore : IAspect public NativeArchitecture Architecture { get; private set; } = NativeArchitecture.Unknown; public ulong NumberOfAssemblies => (ulong)(Assemblies?.Count ?? 0); - public static IAspect LoadAspect (Stream stream, string description) + public static IAspect LoadAspect (Stream stream, string? description) { throw new NotImplementedException (); } - public static bool ProbeAspect (Stream stream) + public static bool ProbeAspect (Stream stream, string? description) { throw new NotImplementedException (); } diff --git a/tools/apput/src/Common/IAspect.cs b/tools/apput/src/Common/IAspect.cs index c078a5e9fb2..62654673f3f 100644 --- a/tools/apput/src/Common/IAspect.cs +++ b/tools/apput/src/Common/IAspect.cs @@ -1,9 +1,10 @@ +using System; using System.IO; namespace ApplicationUtility; /// -/// Represets an aspect of a .NET for Android application. An aspect can be an +/// Represents an aspect of a .NET for Android application. An aspect can be an /// individual assembly, the whole APK/AAB package, a shared library etc. /// If it exists as a definable, separate entity in the application, that can /// be identified/detected by looking at its format/location it is most @@ -14,19 +15,20 @@ public interface IAspect /// /// Aspect name, for presentation purposes. /// - abstract static string AspectName { get; } + static string AspectName => throw new NotImplementedException (); /// /// Probes whether contains something this aspect /// recognizes and supports. Returns `true` if it can handle the data, - /// `false` otherwise. + /// `false` otherwise. The parameter can be anything that makes + /// sense for the given aspect (e.g. a file name). /// - abstract static bool ProbeAspect (Stream stream); + static bool ProbeAspect (Stream stream, string? description = null) => throw new NotImplementedException (); /// /// Load the aspect and return instance of a class implementing support for it. /// The parameter can be anything that makes /// sense for the given aspect (e.g. a file name). /// - abstract static IAspect LoadAspect (Stream stream, string description); + static IAspect LoadAspect (Stream stream, string? description = null) => throw new NotImplementedException (); } diff --git a/tools/apput/src/Common/Log.cs b/tools/apput/src/Common/Log.cs new file mode 100644 index 00000000000..b9815b1907f --- /dev/null +++ b/tools/apput/src/Common/Log.cs @@ -0,0 +1,149 @@ +using System; + +namespace ApplicationUtility; + +static class Log +{ + public const ConsoleColor ErrorColor = ConsoleColor.Red; + public const ConsoleColor WarningColor = ConsoleColor.Yellow; + public const ConsoleColor InfoColor = ConsoleColor.Green; + public const ConsoleColor DebugColor = ConsoleColor.DarkGray; + + static bool showDebug = false; + + static void WriteStderr (string message) + { + Console.Error.Write (message); + } + + static void WriteStderr (ConsoleColor color, string message) + { + ConsoleColor oldFG = Console.ForegroundColor; + Console.ForegroundColor = color; + WriteStderr (message); + Console.ForegroundColor = oldFG; + } + + static void WriteLineStderr (string message) + { + Console.Error.WriteLine (message); + } + + static void WriteLineStderr (ConsoleColor color, string message) + { + ConsoleColor oldFG = Console.ForegroundColor; + Console.ForegroundColor = color; + WriteLineStderr (message); + Console.ForegroundColor = oldFG; + } + + static void Write (string message) + { + Console.Write (message); + } + + static void Write (ConsoleColor color, string message) + { + ConsoleColor oldFG = Console.ForegroundColor; + Console.ForegroundColor = color; + Write (message); + Console.ForegroundColor = oldFG; + } + + static void WriteLine (string message) + { + Console.WriteLine (message); + } + + static void WriteLine (ConsoleColor color, string message) + { + ConsoleColor oldFG = Console.ForegroundColor; + Console.ForegroundColor = color; + WriteLine (message); + Console.ForegroundColor = oldFG; + } + + public static void SetVerbose (bool verbose) + { + showDebug = verbose; + } + + public static void Error (string message = "") + { + Error (tag: String.Empty, message); + } + + public static void Error (string tag, string message) + { + if (message.Length > 0) { + WriteStderr (ErrorColor, "[E] "); + } + + if (tag.Length > 0) { + WriteStderr (ErrorColor, $"{tag}: "); + } + + WriteLineStderr (message); + } + + public static void Warning (string message = "") + { + Warning (tag: String.Empty, message); + } + + public static void Warning (string tag, string message) + { + if (message.Length > 0) { + WriteStderr (WarningColor, "[W] "); + } + + if (tag.Length > 0) { + WriteStderr (WarningColor, $"{tag}: "); + } + + WriteLineStderr (message); + } + + public static void Info (string message = "") + { + Info (tag: String.Empty, message); + } + + public static void Info (string tag, string message) + { + if (tag.Length > 0) { + Write (InfoColor, $"{tag}: "); + } + + WriteLine (InfoColor,message); + } + + public static void Debug (string message = "") + { + Debug (tag: String.Empty, message); + } + + public static void Debug (string tag, string message) + { + if (!showDebug) { + return; + } + + if (message.Length > 0) { + Write (DebugColor, "[D] "); + } + + if (tag.Length > 0) { + Write (DebugColor, $"{tag}: "); + } + + WriteLine (message); + } + + public static void ExceptionError (string message, Exception ex) + { + Log.Error (message); + Log.Error ("Exception was thrown:"); + Log.Error (ex.ToString ()); + } +} diff --git a/tools/apput/src/Common/NativeArchitecture.cs b/tools/apput/src/Common/NativeArchitecture.cs index 919dc142abc..90a9cac70b0 100644 --- a/tools/apput/src/Common/NativeArchitecture.cs +++ b/tools/apput/src/Common/NativeArchitecture.cs @@ -1,11 +1,14 @@ +using System; + namespace ApplicationUtility; +[Flags] public enum NativeArchitecture { - Unknown, + Unknown = 0x00, - Arm, - Arm64, - X86, - X64, -} \ No newline at end of file + Arm = 0x01, + Arm64 = 0x02, + X86 = 0x04, + X64 = 0x08, +} diff --git a/tools/apput/src/Detector.cs b/tools/apput/src/Detector.cs new file mode 100644 index 00000000000..61495c4bf42 --- /dev/null +++ b/tools/apput/src/Detector.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; + +namespace ApplicationUtility; + +/// +/// Given path to a file, or a stream, this class tries to +/// detect whether or not the thing is an application aspect +/// we know or we can handle. +/// +class Detector +{ + readonly static List KnownTopLevelAspects = new () { + typeof (ApplicationPackage), + typeof (AssemblyStore), + typeof (ApplicationAssembly), + typeof (SharedLibrary), + }; + + public static IAspect? FindAspect (string path) + { + Log.Debug ($"Looking for aspect matching '{path}'"); + if (!File.Exists (path)) { + return null; + } + + using Stream fs = File.OpenRead (path); + return TryFindAspect (fs, path); + } + + public static IAspect? FindAspect (Stream stream, string? description = null) + { + Log.Debug ($"Looking for aspect supporting a stream ('{description}')"); + return TryFindAspect (stream, description); + } + + static IAspect? TryFindAspect (Stream stream, string? description) + { + var args = new object?[] { stream, description }; + var flags = BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static; + + foreach (Type aspect in KnownTopLevelAspects) { + Log.Debug ($"Probing aspect: {aspect}"); + + object? result = aspect.InvokeMember ( + "ProbeAspect", flags, null, null, args + ); + + if (result == null || (result is bool success && !success)) { + continue; + } + + Log.Debug ($"Loading aspect: {aspect}"); + result = aspect.InvokeMember ( + "LoadAspect", flags, null, null, args + ); + if (result != null) { + return (IAspect)result; + } + } + + return null; + } + +} diff --git a/tools/apput/src/Native/SharedLibrary.cs b/tools/apput/src/Native/SharedLibrary.cs index b807c6f6782..ce5acd17515 100644 --- a/tools/apput/src/Native/SharedLibrary.cs +++ b/tools/apput/src/Native/SharedLibrary.cs @@ -20,16 +20,20 @@ public class SharedLibrary : IAspect this.libraryName = libraryName; } - public static IAspect LoadAspect (Stream stream, string description) + public static IAspect LoadAspect (Stream stream, string? description) { - if (!IsELFSharedLibrary (stream)) { + if (String.IsNullOrEmpty (description)) { + throw new ArgumentException ("Must be a shared library name", nameof (description)); + } + + if (!IsELFSharedLibrary (stream, description)) { throw new InvalidOperationException ("Stream is not an ELF shared library"); } return new SharedLibrary (stream, description); } - public static bool ProbeAspect (Stream stream) => IsELFSharedLibrary (stream); + public static bool ProbeAspect (Stream stream, string? description) => IsELFSharedLibrary (stream, description); /// /// If the library has .NET for Android payload section, this @@ -56,7 +60,7 @@ public Stream OpenAndroidPayload () throw new NotImplementedException (); } - static bool IsELFSharedLibrary (Stream stream) + static bool IsELFSharedLibrary (Stream stream, string? description) { throw new NotImplementedException (); } diff --git a/tools/apput/src/Package/ApplicationPackage.cs b/tools/apput/src/Package/ApplicationPackage.cs index 4ce40927a01..eaebcae440d 100644 --- a/tools/apput/src/Package/ApplicationPackage.cs +++ b/tools/apput/src/Package/ApplicationPackage.cs @@ -1,21 +1,112 @@ using System; +using System.Collections.Generic; using System.IO; +using System.IO.Compression; +using System.Linq; namespace ApplicationUtility; public abstract class ApplicationPackage : IAspect { + readonly static HashSet KnownApkEntries = new (StringComparer.Ordinal) { + "AndroidManifest.xml", + "classes.dex", + }; + + readonly static HashSet KnownAabEntries = new (StringComparer.Ordinal) { + "BundleConfig.pb", + "base/manifest/AndroidManifest.xml", + "base/dex/classes.dex", + }; + + readonly static HashSet KnownBaseEntries = new (StringComparer.Ordinal) { + "manifest/AndroidManifest.xml", + "dex/classes.dex", + }; + public static string AspectName { get; } = "Application package"; public abstract string PackageFormat { get; } - public static IAspect LoadAspect (Stream stream, string description) + protected ZipArchive Zip { get; } + public string? Description { get; } + + public bool Signed { get; protected set; } + public ApplicationRuntime Runtime { get; protected set; } = ApplicationRuntime.Unknown; + public string PackageName { get; protected set; } = ""; + public List? AssemblyStores { get; protected set; } + public NativeArchitecture Architectures { get; protected set; } + + protected ApplicationPackage (ZipArchive zip, string? description) + { + Zip = zip; + Description = description; + } + + public static IAspect LoadAspect (Stream stream, string? description) + { + Log.Debug ($"ApplicationPackage: opening stream ('{description}') as a ZIP archive"); + ZipArchive? zip = TryOpenAsZip (stream); + if (zip == null) { + throw new InvalidOperationException ("Stream is not a ZIP archive. Call ProbeAspect first."); + } + + ApplicationPackage ret; + if (IsAPK (zip)) { + ret = new PackageAPK (zip, description); + } else if (IsAAB (zip)) { + ret = new PackageAAB (zip, description); + } else if (IsBase (zip)) { + ret = new PackageBase (zip, description); + } else { + throw new InvalidOperationException ("Stream is not a supported Android ZIP package. Call ProbeAspect first."); + } + + Log.Debug ($"ApplicationPackage: stream ('{description}') is: {ret.PackageFormat}"); + return ret; + } + + public static bool ProbeAspect (Stream stream, string? description) + { + Log.Debug ($"ApplicationPackage: checking if stream ('{description}') is a ZIP archive"); + using ZipArchive? zip = TryOpenAsZip (stream); + if (zip == null) { + return false; + } + + Log.Debug ($"ApplicationPackage: checking if stream ('{description}') is a supported Android ZIP package"); + // OK, it's a ZIP. Find out if it's what we support + string? kind = null; + if (IsAPK (zip)) { + kind = "APK"; + } else if (IsAAB (zip)) { + kind = "AAB"; + } else if (IsBase (zip)) { + kind = "Base"; + } else { + return false; + } + + Log.Debug ($"ApplicationPackage: archive is {kind}"); + return true; + } + + static bool IsAPK (ZipArchive zip) => HasEntries (zip, KnownApkEntries); + static bool IsAAB (ZipArchive zip) => HasEntries (zip, KnownAabEntries); + static bool IsBase (ZipArchive zip) => HasEntries (zip, KnownBaseEntries); + + static bool HasEntries (ZipArchive zip, HashSet knownEntries) { - throw new NotImplementedException (); + return zip.Entries.Where ((ZipArchiveEntry entry) => knownEntries.Contains (entry.FullName)).Any (); } - public static bool ProbeAspect (Stream stream) + static ZipArchive? TryOpenAsZip (Stream stream) { - throw new NotImplementedException (); + stream.Seek (0, SeekOrigin.Begin); + try { + return new ZipArchive (stream, ZipArchiveMode.Read, leaveOpen: true); + } catch (InvalidDataException) { + return null; + } } } diff --git a/tools/apput/src/Package/ApplicationRuntime.cs b/tools/apput/src/Package/ApplicationRuntime.cs new file mode 100644 index 00000000000..0b0922a737c --- /dev/null +++ b/tools/apput/src/Package/ApplicationRuntime.cs @@ -0,0 +1,8 @@ +namespace ApplicationUtility; + +public enum ApplicationRuntime +{ + Unknown, + MonoVM, + CoreCLR, +} diff --git a/tools/apput/src/Package/PackageAAB.cs b/tools/apput/src/Package/PackageAAB.cs index 49a6748b40c..cbccd69fdcf 100644 --- a/tools/apput/src/Package/PackageAAB.cs +++ b/tools/apput/src/Package/PackageAAB.cs @@ -1,6 +1,12 @@ +using System.IO.Compression; + namespace ApplicationUtility; class PackageAAB : ApplicationPackage { public override string PackageFormat { get; } = "AAB package"; + + public PackageAAB (ZipArchive zip, string? description) + : base (zip, description) + {} } diff --git a/tools/apput/src/Package/PackageAPK.cs b/tools/apput/src/Package/PackageAPK.cs index bad2317a666..e2c3b939d58 100644 --- a/tools/apput/src/Package/PackageAPK.cs +++ b/tools/apput/src/Package/PackageAPK.cs @@ -1,6 +1,12 @@ +using System.IO.Compression; + namespace ApplicationUtility; class PackageAPK : ApplicationPackage { public override string PackageFormat { get; } = "APK package"; + + public PackageAPK (ZipArchive zip, string? description) + : base (zip, description) + {} } diff --git a/tools/apput/src/Package/PackageBase.cs b/tools/apput/src/Package/PackageBase.cs index d218daf5845..b5977b520c4 100644 --- a/tools/apput/src/Package/PackageBase.cs +++ b/tools/apput/src/Package/PackageBase.cs @@ -1,6 +1,12 @@ +using System.IO.Compression; + namespace ApplicationUtility; class PackageBase : ApplicationPackage { public override string PackageFormat { get; } = "Base application package"; + + public PackageBase (ZipArchive zip, string? description) + : base (zip, description) + {} } diff --git a/tools/apput/src/Program.cs b/tools/apput/src/Program.cs index c3e891cbb0a..f8d37657343 100644 --- a/tools/apput/src/Program.cs +++ b/tools/apput/src/Program.cs @@ -2,7 +2,9 @@ namespace ApplicationUtility; class Program { - static void Main(string[] args) + static void Main (string[] args) { + Log.SetVerbose (true); + IAspect? aspect = Detector.FindAspect (args[0]); } } diff --git a/tools/apput/src/apput.csproj b/tools/apput/src/apput.csproj index 03f2193cf54..a052461f525 100644 --- a/tools/apput/src/apput.csproj +++ b/tools/apput/src/apput.csproj @@ -1,11 +1,11 @@ - + Microsoft Corporation 2025 Microsoft Corporation 0.0.1 - $(DotNetStableTargetFramework) + $(DotNetStableTargetFramework) false ../../bin/$(Configuration)/bin/apput Exe @@ -19,7 +19,6 @@ - From 5fe97aee5c1849917057ac83407fbd5b88683b1a Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 7 Jul 2025 15:02:20 +0200 Subject: [PATCH 03/32] A few steps more --- .../apput/src/AssemblyStore/AssemblyStore.cs | 4 +- tools/apput/src/Common/Log.cs | 11 ++ tools/apput/src/Package/ApplicationPackage.cs | 176 +++++++++++++++++- tools/apput/src/Package/ApplicationRuntime.cs | 1 + tools/apput/src/Package/PackageAAB.cs | 2 + tools/apput/src/Package/PackageAPK.cs | 2 + tools/apput/src/Package/PackageBase.cs | 2 + tools/apput/src/apput.csproj | 8 + 8 files changed, 199 insertions(+), 7 deletions(-) diff --git a/tools/apput/src/AssemblyStore/AssemblyStore.cs b/tools/apput/src/AssemblyStore/AssemblyStore.cs index ba36988088f..525440cfd7d 100644 --- a/tools/apput/src/AssemblyStore/AssemblyStore.cs +++ b/tools/apput/src/AssemblyStore/AssemblyStore.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.IO; +using Xamarin.Android.Tools; + namespace ApplicationUtility; public class AssemblyStore : IAspect @@ -9,7 +11,7 @@ public class AssemblyStore : IAspect public static string AspectName { get; } = "Assembly Store"; public IDictionary Assemblies { get; private set; } = null!; - public NativeArchitecture Architecture { get; private set; } = NativeArchitecture.Unknown; + public AndroidTargetArch Architecture { get; private set; } = AndroidTargetArch.None; public ulong NumberOfAssemblies => (ulong)(Assemblies?.Count ?? 0); public static IAspect LoadAspect (Stream stream, string? description) diff --git a/tools/apput/src/Common/Log.cs b/tools/apput/src/Common/Log.cs index b9815b1907f..6ffef4d784e 100644 --- a/tools/apput/src/Common/Log.cs +++ b/tools/apput/src/Common/Log.cs @@ -123,6 +123,7 @@ public static void Debug (string message = "") Debug (tag: String.Empty, message); } + // TODO: debug should go to file if verbose output isn't enabled public static void Debug (string tag, string message) { if (!showDebug) { @@ -140,6 +141,16 @@ public static void Debug (string tag, string message) WriteLine (message); } + public static void Debug (string message, Exception ex) + { + if (!showDebug) { + return; + } + + Debug (tag: String.Empty, message); + Debug (tag: String.Empty, ex.ToString ()); + } + public static void ExceptionError (string message, Exception ex) { Log.Error (message); diff --git a/tools/apput/src/Package/ApplicationPackage.cs b/tools/apput/src/Package/ApplicationPackage.cs index eaebcae440d..ef95f1edc60 100644 --- a/tools/apput/src/Package/ApplicationPackage.cs +++ b/tools/apput/src/Package/ApplicationPackage.cs @@ -4,6 +4,9 @@ using System.IO.Compression; using System.Linq; +using Xamarin.Android.Tasks; +using Xamarin.Android.Tools; + namespace ApplicationUtility; public abstract class ApplicationPackage : IAspect @@ -24,18 +27,28 @@ public abstract class ApplicationPackage : IAspect "dex/classes.dex", }; + readonly static HashSet KnownSignatureEntries = new (StringComparer.Ordinal) { + "META-INF/BNDLTOOL.RSA", + "META-INF/ANDROIDD.RSA", + }; + public static string AspectName { get; } = "Application package"; public abstract string PackageFormat { get; } + protected abstract string NativeLibDirBase { get; } + protected abstract string AndroidManifestPath { get; } protected ZipArchive Zip { get; } public string? Description { get; } public bool Signed { get; protected set; } + public bool ValidAndroidPackage { get; protected set; } + public bool Debuggable { get; protected set; } public ApplicationRuntime Runtime { get; protected set; } = ApplicationRuntime.Unknown; public string PackageName { get; protected set; } = ""; + public string MainActivity { get; protected set; } = ""; public List? AssemblyStores { get; protected set; } - public NativeArchitecture Architectures { get; protected set; } + public List Architectures { get; protected set; } = new (); protected ApplicationPackage (ZipArchive zip, string? description) { @@ -61,11 +74,147 @@ public static IAspect LoadAspect (Stream stream, string? description) } else { throw new InvalidOperationException ("Stream is not a supported Android ZIP package. Call ProbeAspect first."); } - Log.Debug ($"ApplicationPackage: stream ('{description}') is: {ret.PackageFormat}"); + + // TODO: for all of the below, add support for detection of older XA apps (just to warn that this version doesn't support + // and that people should use older tools) + ret.TryDetectArchitectures (); // This must be called first, some further steps depend on it + ret.TryDetectRuntime (); + ret.TryDetectWhetherIsSigned (); + ret.TryLoadAssemblyStores (); + ret.TryLoadAndroidManifest (); + return ret; } + void TryDetectArchitectures () + { + foreach (AndroidTargetArch arch in Enum.GetValues ()) { + if (!MonoAndroidHelper.SupportedTargetArchitectures.Contains (arch)) { + continue; + } + + // We can't simply test for presence of the libDir below, because it's possible + // that a separate entry for the "directory" (they are only a naming convention + // in the ZIP archive, not a separate entity) won't exist. Instead, we look for + // any entry starting with the path. + if (!HasEntryStartingWith (Zip, GetNativeLibDir (arch))) { + continue; + } + Architectures.Add (arch); + Log.Debug ($"Detected architecture: {arch}"); + } + } + + void TryDetectRuntime () + { + ApplicationRuntime runtime = ApplicationRuntime.Unknown; + string runtimePath; + foreach (AndroidTargetArch arch in Architectures) { + runtimePath = GetNativeLibFile (arch, "libcoreclr.so"); + if (HasEntry (Zip, runtimePath)) { + runtime = ApplicationRuntime.CoreCLR; + break; + } + + runtimePath = GetNativeLibFile (arch, "libmonosgen-2.0.so"); + if (HasEntry (Zip, runtimePath)) { + runtime = ApplicationRuntime.MonoVM; + break; + } + } + + if (runtime != ApplicationRuntime.Unknown || Architectures.Count == 0) { + Log.Debug ($"Detected runtime: {runtime}"); + return; + } + + runtimePath = GetNativeLibFile (Architectures[0], "libmonodroid.so"); + if (!HasEntry (Zip, runtimePath)) { + return; + } + + // TODO: it might be statically linked CoreCLR runtime. Need to check for presence of + // some public symbols to verify that. + } + + void TryDetectWhetherIsSigned () + { + Signed = HasAnyEntries (Zip, KnownSignatureEntries); + Log.Debug ($"Signature detected: {Signed}"); + } + + void TryLoadAssemblyStores () + { + foreach (AndroidTargetArch arch in Architectures) { + string storePath = GetNativeLibFile (arch, $"libassemblies.{MonoAndroidHelper.ArchToAbi (arch)}.blob.so"); + Log.Debug ($"Trying assembly store: {storePath}"); + if (!HasEntry (Zip, storePath)) { + Log.Debug ($"Assembly store '{storePath}' not found"); + continue; + } + + Log.Debug ($"Found assembly store entry for architecture {arch}"); + AssemblyStore? store = TryLoadAssemblyStore (storePath); + if (store == null) { + continue; + } + } + } + + AssemblyStore? TryLoadAssemblyStore (string storePath) + { + // AssemblyStore class owns the stream, don't dispose it here + Stream? storeStream = TryGetEntryStream (storePath); + if (storeStream == null) { + return null; + } + + try { + if (!AssemblyStore.ProbeAspect (storeStream, storePath)) { + Log.Debug ($"Assembly store '{storePath}' is not in a supported format"); + return null; + } + + return (AssemblyStore)AssemblyStore.LoadAspect (storeStream, storePath); + } catch (Exception ex) { + Log.Debug ($"Failed to load assembly store '{storePath}'", ex); + return null; + } + } + + void TryLoadAndroidManifest () + { + ValidAndroidPackage = HasEntry (Zip, AndroidManifestPath); + if (!ValidAndroidPackage) { + Log.Debug ($"Package is missing manifest entry '{AndroidManifestPath}'"); + return; + } + + Log.Debug ($"Found Android manifest '{AndroidManifestPath}'"); + using Stream? manifestStream = TryGetEntryStream (AndroidManifestPath); + // TODO: parse + } + + string GetNativeLibDir (AndroidTargetArch arch) => $"{NativeLibDirBase}/{MonoAndroidHelper.ArchToAbi (arch)}/"; + string GetNativeLibFile (AndroidTargetArch arch, string fileName) => $"{GetNativeLibDir (arch)}{fileName}"; + + Stream? TryGetEntryStream (string path) + { + try { + ZipArchiveEntry? entry = Zip.GetEntry (path); + if (entry == null) { + Log.Debug ($"ZIP entry '{path}' could not be loaded."); + return null; + } + + return entry.Open (); + } catch (Exception ex) { + Log.Debug ($"Failed to load entry '{path}' from the archive.", ex); + return null; + } + } + public static bool ProbeAspect (Stream stream, string? description) { Log.Debug ($"ApplicationPackage: checking if stream ('{description}') is a ZIP archive"); @@ -91,15 +240,30 @@ public static bool ProbeAspect (Stream stream, string? description) return true; } - static bool IsAPK (ZipArchive zip) => HasEntries (zip, KnownApkEntries); - static bool IsAAB (ZipArchive zip) => HasEntries (zip, KnownAabEntries); - static bool IsBase (ZipArchive zip) => HasEntries (zip, KnownBaseEntries); + static bool IsAPK (ZipArchive zip) => HasAllEntries (zip, KnownApkEntries); + static bool IsAAB (ZipArchive zip) => HasAllEntries (zip, KnownAabEntries); + static bool IsBase (ZipArchive zip) => HasAllEntries (zip, KnownBaseEntries); - static bool HasEntries (ZipArchive zip, HashSet knownEntries) + static bool HasAnyEntries (ZipArchive zip, HashSet knownEntries) { return zip.Entries.Where ((ZipArchiveEntry entry) => knownEntries.Contains (entry.FullName)).Any (); } + static bool HasAllEntries (ZipArchive zip, HashSet knownEntries) + { + return zip.Entries.Where ((ZipArchiveEntry entry) => knownEntries.Contains (entry.FullName)).Count () == knownEntries.Count; + } + + static bool HasEntry (ZipArchive zip, string path) + { + return zip.Entries.Where ((ZipArchiveEntry entry) => entry.FullName == path).Any (); + } + + static bool HasEntryStartingWith (ZipArchive zip, string path) + { + return zip.Entries.Where ((ZipArchiveEntry entry) => entry.FullName.StartsWith (path, StringComparison.Ordinal)).Any (); + } + static ZipArchive? TryOpenAsZip (Stream stream) { stream.Seek (0, SeekOrigin.Begin); diff --git a/tools/apput/src/Package/ApplicationRuntime.cs b/tools/apput/src/Package/ApplicationRuntime.cs index 0b0922a737c..9efa9ff598c 100644 --- a/tools/apput/src/Package/ApplicationRuntime.cs +++ b/tools/apput/src/Package/ApplicationRuntime.cs @@ -5,4 +5,5 @@ public enum ApplicationRuntime Unknown, MonoVM, CoreCLR, + StaticCoreCLR, } diff --git a/tools/apput/src/Package/PackageAAB.cs b/tools/apput/src/Package/PackageAAB.cs index cbccd69fdcf..6cc96068e60 100644 --- a/tools/apput/src/Package/PackageAAB.cs +++ b/tools/apput/src/Package/PackageAAB.cs @@ -5,6 +5,8 @@ namespace ApplicationUtility; class PackageAAB : ApplicationPackage { public override string PackageFormat { get; } = "AAB package"; + protected override string NativeLibDirBase => "base/lib"; + protected override string AndroidManifestPath => "base/manifest/AndroidManifest.xml"; public PackageAAB (ZipArchive zip, string? description) : base (zip, description) diff --git a/tools/apput/src/Package/PackageAPK.cs b/tools/apput/src/Package/PackageAPK.cs index e2c3b939d58..fa8120fc0fd 100644 --- a/tools/apput/src/Package/PackageAPK.cs +++ b/tools/apput/src/Package/PackageAPK.cs @@ -5,6 +5,8 @@ namespace ApplicationUtility; class PackageAPK : ApplicationPackage { public override string PackageFormat { get; } = "APK package"; + protected override string NativeLibDirBase => "lib"; + protected override string AndroidManifestPath => "AndroidManifest.xml"; public PackageAPK (ZipArchive zip, string? description) : base (zip, description) diff --git a/tools/apput/src/Package/PackageBase.cs b/tools/apput/src/Package/PackageBase.cs index b5977b520c4..738ec6fd858 100644 --- a/tools/apput/src/Package/PackageBase.cs +++ b/tools/apput/src/Package/PackageBase.cs @@ -5,6 +5,8 @@ namespace ApplicationUtility; class PackageBase : ApplicationPackage { public override string PackageFormat { get; } = "Base application package"; + protected override string NativeLibDirBase => "lib"; + protected override string AndroidManifestPath => "manifest/AndroidManifest.xml"; public PackageBase (ZipArchive zip, string? description) : base (zip, description) diff --git a/tools/apput/src/apput.csproj b/tools/apput/src/apput.csproj index a052461f525..e70dffcd648 100644 --- a/tools/apput/src/apput.csproj +++ b/tools/apput/src/apput.csproj @@ -24,4 +24,12 @@ + + + + + + + + From 262a56f0424c08a88a8547f5a0f339b16ef3fc25 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 7 Jul 2025 19:04:57 +0200 Subject: [PATCH 04/32] Assembly stores progress --- .../apput/src/AssemblyStore/AssemblyStore.cs | 41 ++++++++++++++++++- .../src/AssemblyStore/AssemblyStoreAbi.cs | 10 +++++ .../src/AssemblyStore/AssemblyStoreHeader.cs | 20 +++++++++ .../src/AssemblyStore/AssemblyStoreVersion.cs | 15 +++++++ tools/apput/src/AssemblyStore/Format_V3.cs | 5 +++ tools/apput/src/Common/Utilities.cs | 34 +++++++++++++++ tools/apput/src/Package/ApplicationPackage.cs | 14 +++++-- tools/apput/src/Program.cs | 25 ++++++++--- 8 files changed, 154 insertions(+), 10 deletions(-) create mode 100644 tools/apput/src/AssemblyStore/AssemblyStoreAbi.cs create mode 100644 tools/apput/src/AssemblyStore/AssemblyStoreHeader.cs create mode 100644 tools/apput/src/AssemblyStore/AssemblyStoreVersion.cs create mode 100644 tools/apput/src/AssemblyStore/Format_V3.cs create mode 100644 tools/apput/src/Common/Utilities.cs diff --git a/tools/apput/src/AssemblyStore/AssemblyStore.cs b/tools/apput/src/AssemblyStore/AssemblyStore.cs index 525440cfd7d..563214dd9b5 100644 --- a/tools/apput/src/AssemblyStore/AssemblyStore.cs +++ b/tools/apput/src/AssemblyStore/AssemblyStore.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Text; using Xamarin.Android.Tools; @@ -8,9 +9,12 @@ namespace ApplicationUtility; public class AssemblyStore : IAspect { + const int MinimumStoreSize = 8; + const uint MagicNumber = 0x41424158; // 'XABA', little-endian + public static string AspectName { get; } = "Assembly Store"; - public IDictionary Assemblies { get; private set; } = null!; + public IDictionary Assemblies { get; private set; } = new Dictionary (StringComparer.Ordinal); public AndroidTargetArch Architecture { get; private set; } = AndroidTargetArch.None; public ulong NumberOfAssemblies => (ulong)(Assemblies?.Count ?? 0); @@ -21,6 +25,39 @@ public static IAspect LoadAspect (Stream stream, string? description) public static bool ProbeAspect (Stream stream, string? description) { - throw new NotImplementedException (); + // TODO: check if it's an ELF .so and extract the payload, if necessary + + // All assembly store files are at least 8 bytes long - space taken up by + // the magic number + store version. + if (stream.Length < MinimumStoreSize) { + Log.Debug ($"AssemblyStore: stream ('{description}') isn't long enough. Need at least {MinimumStoreSize} bytes"); + return false; + } + + stream.Seek (0, SeekOrigin.Begin); + using var reader = new BinaryReader (stream, Encoding.UTF8, leaveOpen: true); + uint magic = reader.ReadUInt32 (); + if (magic != MagicNumber) { + Log.Debug ($"AssemblyStore: stream ('{description}') doesn't have the correct signature."); + return false; + } + + uint version = reader.ReadUInt32 (); + + // We currently support version 3. Main store version is kept in the lower 16 bits of the version word + uint mainVersion = version & 0xFFFF; + switch (mainVersion) { + case 3: + return ValidateFormatVersion3 (stream, description); + + default: + Log.Debug ($"AssemblyStore: unsupported store version: {mainVersion}"); + return false; + } + } + + static bool ValidateFormatVersion3 (Stream stream, string? description) + { + return true; } } diff --git a/tools/apput/src/AssemblyStore/AssemblyStoreAbi.cs b/tools/apput/src/AssemblyStore/AssemblyStoreAbi.cs new file mode 100644 index 00000000000..e5a0546034d --- /dev/null +++ b/tools/apput/src/AssemblyStore/AssemblyStoreAbi.cs @@ -0,0 +1,10 @@ +namespace ApplicationUtility; + +// Values correspond to those in `xamarin-app.hh` +enum AssemblyStoreABI +{ + Arm64 = 0x00010000, + Arm = 0x00020000, + X86 = 0x00030000, + X64 = 0x00040000, +} diff --git a/tools/apput/src/AssemblyStore/AssemblyStoreHeader.cs b/tools/apput/src/AssemblyStore/AssemblyStoreHeader.cs new file mode 100644 index 00000000000..566c95ce46f --- /dev/null +++ b/tools/apput/src/AssemblyStore/AssemblyStoreHeader.cs @@ -0,0 +1,20 @@ +namespace ApplicationUtility; + +/// +/// Represents a high-level description of the store hader. It means that this class +/// does **not** correspond to a physical format of the header in the store file. Instead, +/// it contains all the information gathered from the physical file, in a forward compatible +/// way. Forward compatibility means that all public the properties are virtual and nullable, +/// since it's possible that some of them will not be present in the future revisions of the +/// on-disk structure. No public property shall be removed, but any and all of them may be +/// `null` for any given version of the assembly store format. The only exception to this rule +/// is the `Version` property, since it is expected to be present in one way or another in all +/// the future format revisions. +/// +class AssemblyStoreHeader +{ + public AssemblyStoreVersion Version { get; protected set; } + public uint? EntryCount { get; protected set; } + public uint? IndexEntryCount { get; protected set; } + public uint? IndexSize { get; protected set; } +} diff --git a/tools/apput/src/AssemblyStore/AssemblyStoreVersion.cs b/tools/apput/src/AssemblyStore/AssemblyStoreVersion.cs new file mode 100644 index 00000000000..38083a9107c --- /dev/null +++ b/tools/apput/src/AssemblyStore/AssemblyStoreVersion.cs @@ -0,0 +1,15 @@ +namespace ApplicationUtility; + +class AssemblyStoreVersion +{ + public uint MainVersion { get; } + public AssemblyStoreABI ABI { get; } + public bool Is64Bit { get; } + + internal AssemblyStoreVersion (uint mainVersion, AssemblyStoreABI abi, bool is64Bit) + { + MainVersion = mainVersion; + ABI = abi; + Is64Bit = is64Bit; + } +} diff --git a/tools/apput/src/AssemblyStore/Format_V3.cs b/tools/apput/src/AssemblyStore/Format_V3.cs new file mode 100644 index 00000000000..871a9482109 --- /dev/null +++ b/tools/apput/src/AssemblyStore/Format_V3.cs @@ -0,0 +1,5 @@ +namespace ApplicationUtility; + +class Format_V3 +{ +} diff --git a/tools/apput/src/Common/Utilities.cs b/tools/apput/src/Common/Utilities.cs new file mode 100644 index 00000000000..fb2a9f35bc4 --- /dev/null +++ b/tools/apput/src/Common/Utilities.cs @@ -0,0 +1,34 @@ +using System; +using System.IO; + +namespace ApplicationUtility; + +class Utilities +{ + public static void DeleteFile (string path, bool quiet = true) + { + try { + File.Delete (path); + } catch (Exception ex) { + Log.Debug ($"Failed to delete file '{path}'.", ex); + if (!quiet) { + throw; + } + } + } + + public static void CloseAndDeleteFile (FileStream stream, bool quiet = true) + { + string path = stream.Name; + try { + stream.Close (); + } catch (Exception ex) { + Log.Debug ($"Failed to close file stream.", ex); + if (!quiet) { + throw; + } + } + + DeleteFile (path); + } +} diff --git a/tools/apput/src/Package/ApplicationPackage.cs b/tools/apput/src/Package/ApplicationPackage.cs index ef95f1edc60..9aa4c9ccf1a 100644 --- a/tools/apput/src/Package/ApplicationPackage.cs +++ b/tools/apput/src/Package/ApplicationPackage.cs @@ -165,7 +165,7 @@ void TryLoadAssemblyStores () AssemblyStore? TryLoadAssemblyStore (string storePath) { // AssemblyStore class owns the stream, don't dispose it here - Stream? storeStream = TryGetEntryStream (storePath); + FileStream? storeStream = TryGetEntryStream (storePath); if (storeStream == null) { return null; } @@ -173,6 +173,7 @@ void TryLoadAssemblyStores () try { if (!AssemblyStore.ProbeAspect (storeStream, storePath)) { Log.Debug ($"Assembly store '{storePath}' is not in a supported format"); + storeStream.Close (); return null; } @@ -199,7 +200,7 @@ void TryLoadAndroidManifest () string GetNativeLibDir (AndroidTargetArch arch) => $"{NativeLibDirBase}/{MonoAndroidHelper.ArchToAbi (arch)}/"; string GetNativeLibFile (AndroidTargetArch arch, string fileName) => $"{GetNativeLibDir (arch)}{fileName}"; - Stream? TryGetEntryStream (string path) + FileStream? TryGetEntryStream (string path) { try { ZipArchiveEntry? entry = Zip.GetEntry (path); @@ -208,9 +209,16 @@ void TryLoadAndroidManifest () return null; } - return entry.Open (); + string tempFile = Path.GetTempFileName (); + TempFileManager.RegisterFile (tempFile); + + Log.Debug ($"Extracting entry '{path}' to '{tempFile}'"); + entry.ExtractToFile (tempFile, overwrite: true); + return File.OpenRead (tempFile); } catch (Exception ex) { Log.Debug ($"Failed to load entry '{path}' from the archive.", ex); + + // TODO: remove temp file (using a helper method, which doesn't exist yet) return null; } } diff --git a/tools/apput/src/Program.cs b/tools/apput/src/Program.cs index f8d37657343..de0b10192d1 100644 --- a/tools/apput/src/Program.cs +++ b/tools/apput/src/Program.cs @@ -1,10 +1,25 @@ +using System; + namespace ApplicationUtility; class Program { - static void Main (string[] args) - { - Log.SetVerbose (true); - IAspect? aspect = Detector.FindAspect (args[0]); - } + static int Main (string[] args) + { + Log.SetVerbose (true); + try { + return Run (args); + } catch (Exception ex) { + Log.ExceptionError ("Unhandled exception", ex); + return 1; + } finally { + TempFileManager.Cleanup (); + } + } + + static int Run (string[] args) + { + IAspect? aspect = Detector.FindAspect (args[0]); + return 0; + } } From 7847e5a07de609c6701ff48e55cc6cd684189e65 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 8 Jul 2025 09:18:34 +0200 Subject: [PATCH 05/32] Oops, forgot to add this one, doh --- tools/apput/src/Common/TempFileManager.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tools/apput/src/Common/TempFileManager.cs diff --git a/tools/apput/src/Common/TempFileManager.cs b/tools/apput/src/Common/TempFileManager.cs new file mode 100644 index 00000000000..ef75d92f734 --- /dev/null +++ b/tools/apput/src/Common/TempFileManager.cs @@ -0,0 +1,14 @@ +namespace ApplicationUtility; + +class TempFileManager +{ + public static void RegisterFile (string path) + { + // TODO: implement + } + + public static void Cleanup () + { + // TODO: implement + } +} From 0435410e77e6a38c2fae45a23be6b0b1ed298235 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 8 Jul 2025 16:55:15 +0200 Subject: [PATCH 06/32] Progressing with assembly stores + shared libraries --- .../ApplicationAssembly.cs | 4 +- .../apput/src/AssemblyStore/AssemblyStore.cs | 60 +++++-- .../AssemblyStore/AssemblyStoreAspectState.cs | 13 ++ .../src/AssemblyStore/AssemblyStoreIndex.cs | 5 + tools/apput/src/AssemblyStore/FormatBase.cs | 17 ++ tools/apput/src/AssemblyStore/Format_V2.cs | 16 ++ tools/apput/src/AssemblyStore/Format_V3.cs | 14 +- tools/apput/src/Common/BasicAspectState.cs | 11 ++ tools/apput/src/Common/IAspect.cs | 4 +- tools/apput/src/Common/IAspectState.cs | 15 ++ tools/apput/src/Detector.cs | 8 +- tools/apput/src/Native/SharedLibrary.cs | 161 ++++++++++++++++-- .../src/Native/SharedLibraryPayloadStream.cs | 69 ++++++++ tools/apput/src/Package/ApplicationPackage.cs | 16 +- 14 files changed, 370 insertions(+), 43 deletions(-) create mode 100644 tools/apput/src/AssemblyStore/AssemblyStoreAspectState.cs create mode 100644 tools/apput/src/AssemblyStore/AssemblyStoreIndex.cs create mode 100644 tools/apput/src/AssemblyStore/FormatBase.cs create mode 100644 tools/apput/src/AssemblyStore/Format_V2.cs create mode 100644 tools/apput/src/Common/BasicAspectState.cs create mode 100644 tools/apput/src/Common/IAspectState.cs create mode 100644 tools/apput/src/Native/SharedLibraryPayloadStream.cs diff --git a/tools/apput/src/ApplicationAssembly/ApplicationAssembly.cs b/tools/apput/src/ApplicationAssembly/ApplicationAssembly.cs index 211ccb47dde..48f4416a0b6 100644 --- a/tools/apput/src/ApplicationAssembly/ApplicationAssembly.cs +++ b/tools/apput/src/ApplicationAssembly/ApplicationAssembly.cs @@ -13,12 +13,12 @@ public class ApplicationAssembly : IAspect public ulong Size { get; private set; } public bool IgnoreOnLoad { get; private set; } - public static IAspect LoadAspect (Stream stream, string? description) + public static IAspect LoadAspect (Stream stream, IAspectState state, string? description) { throw new NotImplementedException (); } - public static bool ProbeAspect (Stream stream, string? description) + public static IAspectState ProbeAspect (Stream stream, string? description) { throw new NotImplementedException (); } diff --git a/tools/apput/src/AssemblyStore/AssemblyStore.cs b/tools/apput/src/AssemblyStore/AssemblyStore.cs index 563214dd9b5..916136e6688 100644 --- a/tools/apput/src/AssemblyStore/AssemblyStore.cs +++ b/tools/apput/src/AssemblyStore/AssemblyStore.cs @@ -18,46 +18,78 @@ public class AssemblyStore : IAspect public AndroidTargetArch Architecture { get; private set; } = AndroidTargetArch.None; public ulong NumberOfAssemblies => (ulong)(Assemblies?.Count ?? 0); - public static IAspect LoadAspect (Stream stream, string? description) + public static IAspect LoadAspect (Stream stream, IAspectState state, string? description) { + var storeState = state as AssemblyStoreAspectState; throw new NotImplementedException (); } - public static bool ProbeAspect (Stream stream, string? description) + public static IAspectState ProbeAspect (Stream stream, string? description) { - // TODO: check if it's an ELF .so and extract the payload, if necessary + Stream? storeStream = null; + try { + IAspectState state = SharedLibrary.ProbeAspect (stream, description); + if (!state.Success) { + return DoProbeAspect (stream, description); + } + + var library = (SharedLibrary)SharedLibrary.LoadAspect (stream, state, description); + if (!library.HasAndroidPayload) { + Log.Debug ($"AssemblyStore: stream ('{description}') is an ELF shared library, without payload"); + return new BasicAspectState (false); + } + Log.Debug ($"AssemblyStore: stream ('{description}') is an ELF shared library with .NET for Android payload section"); + storeStream = library.OpenAndroidPayload (); + return DoProbeAspect (storeStream, description); + } finally { + storeStream?.Dispose (); + } + } + + // We return `BasicAspectState` instance for all failures, since there's no extra information we can + // pass on. + static IAspectState DoProbeAspect (Stream storeStream, string? description) + { // All assembly store files are at least 8 bytes long - space taken up by // the magic number + store version. - if (stream.Length < MinimumStoreSize) { + if (storeStream.Length < MinimumStoreSize) { Log.Debug ($"AssemblyStore: stream ('{description}') isn't long enough. Need at least {MinimumStoreSize} bytes"); - return false; + return new BasicAspectState (false); } - stream.Seek (0, SeekOrigin.Begin); - using var reader = new BinaryReader (stream, Encoding.UTF8, leaveOpen: true); + storeStream.Seek (0, SeekOrigin.Begin); + using var reader = new BinaryReader (storeStream, Encoding.UTF8, leaveOpen: true); uint magic = reader.ReadUInt32 (); if (magic != MagicNumber) { Log.Debug ($"AssemblyStore: stream ('{description}') doesn't have the correct signature."); - return false; + return new BasicAspectState (false); } uint version = reader.ReadUInt32 (); // We currently support version 3. Main store version is kept in the lower 16 bits of the version word uint mainVersion = version & 0xFFFF; + FormatBase? validator = null; + switch (mainVersion) { + case 2: + validator = new Format_V2 (storeStream, description); + break; + case 3: - return ValidateFormatVersion3 (stream, description); + validator = new Format_V3 (storeStream, description); + break; default: Log.Debug ($"AssemblyStore: unsupported store version: {mainVersion}"); - return false; + return new BasicAspectState (false); } - } - static bool ValidateFormatVersion3 (Stream stream, string? description) - { - return true; + if (validator == null) { + throw new InvalidOperationException ("Internal error: validator should never be null here"); + } + + return validator.Validate (); } } diff --git a/tools/apput/src/AssemblyStore/AssemblyStoreAspectState.cs b/tools/apput/src/AssemblyStore/AssemblyStoreAspectState.cs new file mode 100644 index 00000000000..5f4202ab872 --- /dev/null +++ b/tools/apput/src/AssemblyStore/AssemblyStoreAspectState.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace ApplicationUtility; + +class AssemblyStoreAspectState : BasicAspectState +{ + public AssemblyStoreHeader Header { get; } + public AssemblyStoreIndex Index { get; } + + public AssemblyStoreAspectState (bool success) + : base (success) + {} +} diff --git a/tools/apput/src/AssemblyStore/AssemblyStoreIndex.cs b/tools/apput/src/AssemblyStore/AssemblyStoreIndex.cs new file mode 100644 index 00000000000..83ae5195d5e --- /dev/null +++ b/tools/apput/src/AssemblyStore/AssemblyStoreIndex.cs @@ -0,0 +1,5 @@ +using ApplicationUtility; + +class AssemblyStoreIndex +{ +} diff --git a/tools/apput/src/AssemblyStore/FormatBase.cs b/tools/apput/src/AssemblyStore/FormatBase.cs new file mode 100644 index 00000000000..d337f03e2fe --- /dev/null +++ b/tools/apput/src/AssemblyStore/FormatBase.cs @@ -0,0 +1,17 @@ +using System.IO; + +namespace ApplicationUtility; + +abstract class FormatBase +{ + protected Stream StoreStream { get; } + protected string? Description { get; } + + protected FormatBase (Stream storeStream, string? description) + { + this.StoreStream = storeStream; + this.Description = description; + } + + public abstract IAspectState Validate (); +} diff --git a/tools/apput/src/AssemblyStore/Format_V2.cs b/tools/apput/src/AssemblyStore/Format_V2.cs new file mode 100644 index 00000000000..cceeeb72347 --- /dev/null +++ b/tools/apput/src/AssemblyStore/Format_V2.cs @@ -0,0 +1,16 @@ +using System; +using System.IO; + +namespace ApplicationUtility; + +class Format_V2 : FormatBase +{ + public Format_V2 (Stream storeStream, string? description) + : base (storeStream, description) + {} + + public override IAspectState Validate () + { + throw new NotImplementedException (); + } +} diff --git a/tools/apput/src/AssemblyStore/Format_V3.cs b/tools/apput/src/AssemblyStore/Format_V3.cs index 871a9482109..4092119a1d7 100644 --- a/tools/apput/src/AssemblyStore/Format_V3.cs +++ b/tools/apput/src/AssemblyStore/Format_V3.cs @@ -1,5 +1,17 @@ +using System.IO; + namespace ApplicationUtility; -class Format_V3 +class Format_V3 : FormatBase { + public Format_V3 (Stream storeStream, string? description) + : base (storeStream, description) + {} + + public override IAspectState Validate () + { + // TODO: validate that the store has correct format and populate the state below accordingly + // to save time later. + return new AssemblyStoreAspectState (true); + } } diff --git a/tools/apput/src/Common/BasicAspectState.cs b/tools/apput/src/Common/BasicAspectState.cs new file mode 100644 index 00000000000..d88fe1ec88f --- /dev/null +++ b/tools/apput/src/Common/BasicAspectState.cs @@ -0,0 +1,11 @@ +namespace ApplicationUtility; + +class BasicAspectState : IAspectState +{ + public bool Success { get; } + + public BasicAspectState (bool success) + { + Success = success; + } +} diff --git a/tools/apput/src/Common/IAspect.cs b/tools/apput/src/Common/IAspect.cs index 62654673f3f..73182a2d6bf 100644 --- a/tools/apput/src/Common/IAspect.cs +++ b/tools/apput/src/Common/IAspect.cs @@ -23,12 +23,12 @@ public interface IAspect /// `false` otherwise. The parameter can be anything that makes /// sense for the given aspect (e.g. a file name). /// - static bool ProbeAspect (Stream stream, string? description = null) => throw new NotImplementedException (); + static IAspectState ProbeAspect (Stream stream, string? description = null) => throw new NotImplementedException (); /// /// Load the aspect and return instance of a class implementing support for it. /// The parameter can be anything that makes /// sense for the given aspect (e.g. a file name). /// - static IAspect LoadAspect (Stream stream, string? description = null) => throw new NotImplementedException (); + static IAspect LoadAspect (Stream stream, IAspectState state, string? description = null) => throw new NotImplementedException (); } diff --git a/tools/apput/src/Common/IAspectState.cs b/tools/apput/src/Common/IAspectState.cs new file mode 100644 index 00000000000..554be193fb1 --- /dev/null +++ b/tools/apput/src/Common/IAspectState.cs @@ -0,0 +1,15 @@ +namespace ApplicationUtility; + +/// +/// An empty interface which can be used by the aspect detection mechanism to +/// preserve some state between and +/// calls, to optimize resource usage. +/// +public interface IAspectState +{ + /// + /// Indicates that whatever method returned instance of this interface, the operation was + /// successful if `true`. + /// + bool Success { get; } +} diff --git a/tools/apput/src/Detector.cs b/tools/apput/src/Detector.cs index 61495c4bf42..c9248e46e76 100644 --- a/tools/apput/src/Detector.cs +++ b/tools/apput/src/Detector.cs @@ -38,23 +38,23 @@ class Detector static IAspect? TryFindAspect (Stream stream, string? description) { - var args = new object?[] { stream, description }; var flags = BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static; foreach (Type aspect in KnownTopLevelAspects) { Log.Debug ($"Probing aspect: {aspect}"); object? result = aspect.InvokeMember ( - "ProbeAspect", flags, null, null, args + "ProbeAspect", flags, null, null, new object?[] { stream, description } ); - if (result == null || (result is bool success && !success)) { + var state = result as IAspectState; + if (state == null || !state.Success) { continue; } Log.Debug ($"Loading aspect: {aspect}"); result = aspect.InvokeMember ( - "LoadAspect", flags, null, null, args + "LoadAspect", flags, null, null, new object?[] { stream, state, description } ); if (result != null) { return (IAspect)result; diff --git a/tools/apput/src/Native/SharedLibrary.cs b/tools/apput/src/Native/SharedLibrary.cs index ce5acd17515..ca5df68b31d 100644 --- a/tools/apput/src/Native/SharedLibrary.cs +++ b/tools/apput/src/Native/SharedLibrary.cs @@ -1,10 +1,16 @@ using System; using System.IO; +using System.Text; + +using ELFSharp.ELF; +using ELFSharp.ELF.Sections; using ApplicationUtility; -public class SharedLibrary : IAspect +public class SharedLibrary : IAspect, IDisposable { + const uint ELF_MAGIC = 0x464c457f; + public static string AspectName { get; } = "Native shared library"; public bool HasAndroidPayload => payloadSize > 0; @@ -13,27 +19,33 @@ public class SharedLibrary : IAspect readonly ulong payloadOffset; readonly ulong payloadSize; readonly string libraryName; + readonly bool is64Bit; + readonly Stream libraryStream; + IELF elf; + bool disposed; SharedLibrary (Stream stream, string libraryName) { - (payloadOffset, payloadSize) = FindAndroidPayload (stream); + this.libraryStream = stream; this.libraryName = libraryName; + (elf, is64Bit) = LoadELF (stream, libraryName); + (payloadOffset, payloadSize) = FindAndroidPayload (elf); } - public static IAspect LoadAspect (Stream stream, string? description) + public static IAspect LoadAspect (Stream stream, IAspectState? state, string? description) { if (String.IsNullOrEmpty (description)) { throw new ArgumentException ("Must be a shared library name", nameof (description)); } - if (!IsELFSharedLibrary (stream, description)) { - throw new InvalidOperationException ("Stream is not an ELF shared library"); + if (!IsSupportedELFSharedLibrary (stream, description)) { + throw new InvalidOperationException ("Stream is not a supported ELF shared library"); } return new SharedLibrary (stream, description); } - public static bool ProbeAspect (Stream stream, string? description) => IsELFSharedLibrary (stream, description); + public static IAspectState ProbeAspect (Stream stream, string? description) => new BasicAspectState (IsSupportedELFSharedLibrary (stream, description)); /// /// If the library has .NET for Android payload section, this @@ -42,8 +54,8 @@ public static IAspect LoadAspect (Stream stream, string? description) /// public void CopyAndroidPayload (Stream dest) { - Stream payload = OpenAndroidPayload (); - throw new NotImplementedException (); + using Stream payload = OpenAndroidPayload (); + payload.CopyTo (dest); } /// @@ -57,16 +69,139 @@ public Stream OpenAndroidPayload () throw new InvalidOperationException ("Payload section not found"); } - throw new NotImplementedException (); + if (payloadOffset > Int64.MaxValue) { + throw new InvalidOperationException ($"Payload offset of {payloadOffset} is too large to support."); + } + + if (payloadSize > Int64.MaxValue) { + throw new InvalidOperationException ($"Payload offset of {payloadSize} is too large to support."); + } + + return new SharedLibraryPayloadStream (libraryStream, (long)payloadOffset, (long)payloadSize); + } + + static bool IsSupportedELFSharedLibrary (Stream stream, string? description) + { + if (stream.Length < 4) { // Less than that and we know there isn't room for ELF magic + Log.Debug ($"SharedLibrary: stream ('{description}') is too short to be an ELF image."); + return false; + } + stream.Seek (0, SeekOrigin.Begin); + + using var reader = new BinaryReader (stream, Encoding.UTF8, leaveOpen: true); + uint magic = reader.ReadUInt32 (); + if (magic != ELF_MAGIC) { + Log.Debug ($"SharedLibrary: stream ('{description}') is not an ELF image."); + return false; + } + stream.Seek (0, SeekOrigin.Begin); + + Class elfClass = ELFReader.CheckELFType (stream); + if (elfClass == Class.NotELF) { + Log.Debug ($"SharedLibrary: stream ('{description}') is not a supported ELF class."); + return false; + } + + if (!ELFReader.TryLoad (stream, shouldOwnStream: false, out IELF? elf) || elf == null) { + Log.Debug ($"SharedLibrary: stream ('{description}') failed to load as an ELF image while checking support."); + return false; + } + + if (elf.Type != FileType.SharedObject) { + Log.Debug ($"SharedLibrary: stream ('{description}') is not an ELF shared library image."); + return false; + } + + if (elf.Endianess != ELFSharp.Endianess.LittleEndian) { + Log.Debug ($"SharedLibrary: stream ('{description}') is not a little-endian ELF image."); + return false; + } + + bool supported = elf.Machine switch { + Machine.ARM => true, + Machine.Intel386 => true, + Machine.AArch64 => true, + Machine.AMD64 => true, + _ => false + }; + + string not = supported ? String.Empty : " not"; + Log.Debug ($"SharedLibrary: stream ('{description}') is{not} a supported ELF architecture ('{elf.Machine}')"); + + elf.Dispose (); + return supported; } - static bool IsELFSharedLibrary (Stream stream, string? description) + // We assume below that stream corresponds to a valid and supported by us ELF image. This should have been asserted by + // the `LoadAspect` method. + (IELF elf, bool is64bit) LoadELF (Stream stream, string? libraryName) { - throw new NotImplementedException (); + stream.Seek (0, SeekOrigin.Begin); + if (!ELFReader.TryLoad (stream, shouldOwnStream: false, out IELF? elf) || elf == null) { + Log.Debug ($"SharedLibrary: stream ('{libraryName}') failed to load as an ELF image."); + throw new InvalidOperationException ($"Failed to load ELF library '{libraryName}'."); + } + + bool is64 = elf.Machine switch { + Machine.ARM => false, + Machine.Intel386 => false, + + Machine.AArch64 => true, + Machine.AMD64 => true, + + _ => throw new NotSupportedException ($"Unsupported ELF architecture '{elf.Machine}'") + }; + + return (elf, is64); + } + + (ulong offset, ulong size) FindAndroidPayload (IELF elf) + { + if (!elf.TryGetSection ("payload", out ISection? payloadSection)) { + Log.Debug ($"SharedLibrary: shared library '{libraryName}' doesn't have the 'payload' section."); + return (0, 0); + } + + ulong offset; + ulong size; + + if (is64Bit) { + (offset, size) = GetOffsetAndSize64 ((Section)payloadSection); + } else { + (offset, size) = GetOffsetAndSize32 ((Section)payloadSection); + } + + Log.Debug ($"SharedLibrary: found payload section at offset {offset}, size of {size} bytes."); + return (offset, size); + + (ulong offset, ulong size) GetOffsetAndSize64 (Section payload) + { + return (payload.Offset, payload.Size); + } + + (ulong offset, ulong size) GetOffsetAndSize32 (Section payload) + { + return ((ulong)payload.Offset, (ulong)payload.Size); + } + } + + protected virtual void Dispose (bool disposing) + { + if (disposed) { + return; + } + + if (disposing) { + elf?.Dispose (); + } + + disposed = true; } - (ulong offset, ulong size) FindAndroidPayload (Stream stream) + public void Dispose () { - throw new NotImplementedException (); + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose (disposing: true); + GC.SuppressFinalize (this); } } diff --git a/tools/apput/src/Native/SharedLibraryPayloadStream.cs b/tools/apput/src/Native/SharedLibraryPayloadStream.cs new file mode 100644 index 00000000000..27ec09b879d --- /dev/null +++ b/tools/apput/src/Native/SharedLibraryPayloadStream.cs @@ -0,0 +1,69 @@ +using System; +using System.IO; + +namespace ApplicationUtility; + +class SharedLibraryPayloadStream : Stream +{ + readonly Stream baseStream; + readonly long length; + readonly long offsetInBaseStream; + + public override bool CanRead => true; + public override bool CanSeek => true; + public override bool CanWrite => false; + public override long Length => length; + + public override long Position { + get => throw new NotSupportedException (); + set => throw new NotSupportedException (); + } + + public SharedLibraryPayloadStream (Stream baseStream, long offset, long length) + { + if (!baseStream.CanSeek) { + throw new InvalidOperationException ($"Base stream must support seeking"); + } + + if (!baseStream.CanRead) { + throw new InvalidOperationException ($"Base stream must support reading"); + } + + if (offset >= baseStream.Length) { + throw new ArgumentOutOfRangeException (nameof (offset), $"{offset} exceeds length of the base stream ({baseStream.Length})"); + } + + if (offset + length > baseStream.Length) { + throw new InvalidOperationException ($"Not enough data in base stream after offset {offset}, length of {length} bytes is too big."); + } + + this.baseStream = baseStream; + this.length = length; + offsetInBaseStream = offset; + } + + public override int Read (byte [] buffer, int offset, int count) + { + return baseStream.Read (buffer, offset, count); + } + + public override long Seek (long offset, SeekOrigin origin) + { + return baseStream.Seek (offset + offsetInBaseStream, origin); + } + + public override void Flush () + { + throw new NotSupportedException (); + } + + public override void SetLength (long value) + { + throw new NotSupportedException (); + } + + public override void Write (byte [] buffer, int offset, int count) + { + throw new NotSupportedException (); + } +} diff --git a/tools/apput/src/Package/ApplicationPackage.cs b/tools/apput/src/Package/ApplicationPackage.cs index 9aa4c9ccf1a..03c4caa5368 100644 --- a/tools/apput/src/Package/ApplicationPackage.cs +++ b/tools/apput/src/Package/ApplicationPackage.cs @@ -56,7 +56,7 @@ protected ApplicationPackage (ZipArchive zip, string? description) Description = description; } - public static IAspect LoadAspect (Stream stream, string? description) + public static IAspect LoadAspect (Stream stream, IAspectState state, string? description) { Log.Debug ($"ApplicationPackage: opening stream ('{description}') as a ZIP archive"); ZipArchive? zip = TryOpenAsZip (stream); @@ -170,14 +170,16 @@ void TryLoadAssemblyStores () return null; } + string fullStorePath = $"{Description}@!{storePath}"; try { - if (!AssemblyStore.ProbeAspect (storeStream, storePath)) { + IAspectState state = AssemblyStore.ProbeAspect (storeStream, fullStorePath); + if (!state.Success) { Log.Debug ($"Assembly store '{storePath}' is not in a supported format"); storeStream.Close (); return null; } - return (AssemblyStore)AssemblyStore.LoadAspect (storeStream, storePath); + return (AssemblyStore)AssemblyStore.LoadAspect (storeStream, state, fullStorePath); } catch (Exception ex) { Log.Debug ($"Failed to load assembly store '{storePath}'", ex); return null; @@ -223,12 +225,12 @@ void TryLoadAndroidManifest () } } - public static bool ProbeAspect (Stream stream, string? description) + public static IAspectState ProbeAspect (Stream stream, string? description) { Log.Debug ($"ApplicationPackage: checking if stream ('{description}') is a ZIP archive"); using ZipArchive? zip = TryOpenAsZip (stream); if (zip == null) { - return false; + return new BasicAspectState (false); } Log.Debug ($"ApplicationPackage: checking if stream ('{description}') is a supported Android ZIP package"); @@ -241,11 +243,11 @@ public static bool ProbeAspect (Stream stream, string? description) } else if (IsBase (zip)) { kind = "Base"; } else { - return false; + return new BasicAspectState (false); } Log.Debug ($"ApplicationPackage: archive is {kind}"); - return true; + return new BasicAspectState (true); } static bool IsAPK (ZipArchive zip) => HasAllEntries (zip, KnownApkEntries); From c7f105760d3e58922273bf6116725b3f67814429 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 9 Jul 2025 18:21:53 +0200 Subject: [PATCH 07/32] More assembly store code --- .../apput/src/AssemblyStore/AssemblyStore.cs | 9 +- .../src/AssemblyStore/AssemblyStoreAbi.cs | 12 +- .../AssemblyStore/AssemblyStoreAspectState.cs | 2 +- .../AssemblyStoreAssemblyDescriptor.cs | 4 + .../AssemblyStoreAssemblyDescriptorV2.cs | 12 ++ .../AssemblyStoreAssemblyDescriptorV3.cs | 5 + .../src/AssemblyStore/AssemblyStoreHeader.cs | 13 +- .../src/AssemblyStore/AssemblyStoreIndex.cs | 5 - .../AssemblyStoreIndexEntryV3.cs | 6 + .../src/AssemblyStore/AssemblyStoreVersion.cs | 29 +++- tools/apput/src/AssemblyStore/FormatBase.cs | 155 +++++++++++++++++- tools/apput/src/AssemblyStore/Format_V2.cs | 2 +- tools/apput/src/AssemblyStore/Format_V3.cs | 26 ++- tools/apput/src/Package/ApplicationPackage.cs | 2 +- 14 files changed, 252 insertions(+), 30 deletions(-) create mode 100644 tools/apput/src/AssemblyStore/AssemblyStoreAssemblyDescriptor.cs create mode 100644 tools/apput/src/AssemblyStore/AssemblyStoreAssemblyDescriptorV2.cs create mode 100644 tools/apput/src/AssemblyStore/AssemblyStoreAssemblyDescriptorV3.cs delete mode 100644 tools/apput/src/AssemblyStore/AssemblyStoreIndex.cs create mode 100644 tools/apput/src/AssemblyStore/AssemblyStoreIndexEntryV3.cs diff --git a/tools/apput/src/AssemblyStore/AssemblyStore.cs b/tools/apput/src/AssemblyStore/AssemblyStore.cs index 916136e6688..d358aafb59e 100644 --- a/tools/apput/src/AssemblyStore/AssemblyStore.cs +++ b/tools/apput/src/AssemblyStore/AssemblyStore.cs @@ -67,12 +67,11 @@ static IAspectState DoProbeAspect (Stream storeStream, string? description) } uint version = reader.ReadUInt32 (); - - // We currently support version 3. Main store version is kept in the lower 16 bits of the version word - uint mainVersion = version & 0xFFFF; + var storeVersion = new AssemblyStoreVersion (version); FormatBase? validator = null; + Log.Debug ($"AssemblyStore: store format version {storeVersion.MainVersion}"); - switch (mainVersion) { + switch (storeVersion.MainVersion) { case 2: validator = new Format_V2 (storeStream, description); break; @@ -82,7 +81,7 @@ static IAspectState DoProbeAspect (Stream storeStream, string? description) break; default: - Log.Debug ($"AssemblyStore: unsupported store version: {mainVersion}"); + Log.Debug ($"AssemblyStore: unsupported store version: {storeVersion.MainVersion}"); return new BasicAspectState (false); } diff --git a/tools/apput/src/AssemblyStore/AssemblyStoreAbi.cs b/tools/apput/src/AssemblyStore/AssemblyStoreAbi.cs index e5a0546034d..e5e05e26aea 100644 --- a/tools/apput/src/AssemblyStore/AssemblyStoreAbi.cs +++ b/tools/apput/src/AssemblyStore/AssemblyStoreAbi.cs @@ -1,10 +1,12 @@ namespace ApplicationUtility; // Values correspond to those in `xamarin-app.hh` -enum AssemblyStoreABI +enum AssemblyStoreABI : uint { - Arm64 = 0x00010000, - Arm = 0x00020000, - X86 = 0x00030000, - X64 = 0x00040000, + Unknown = 0x00000000, + + Arm64 = 0x00010000, + Arm = 0x00020000, + X86 = 0x00030000, + X64 = 0x00040000, } diff --git a/tools/apput/src/AssemblyStore/AssemblyStoreAspectState.cs b/tools/apput/src/AssemblyStore/AssemblyStoreAspectState.cs index 5f4202ab872..2ae0b6b77f1 100644 --- a/tools/apput/src/AssemblyStore/AssemblyStoreAspectState.cs +++ b/tools/apput/src/AssemblyStore/AssemblyStoreAspectState.cs @@ -5,7 +5,7 @@ namespace ApplicationUtility; class AssemblyStoreAspectState : BasicAspectState { public AssemblyStoreHeader Header { get; } - public AssemblyStoreIndex Index { get; } + public FormatBase Format { get; } public AssemblyStoreAspectState (bool success) : base (success) diff --git a/tools/apput/src/AssemblyStore/AssemblyStoreAssemblyDescriptor.cs b/tools/apput/src/AssemblyStore/AssemblyStoreAssemblyDescriptor.cs new file mode 100644 index 00000000000..bae35595473 --- /dev/null +++ b/tools/apput/src/AssemblyStore/AssemblyStoreAssemblyDescriptor.cs @@ -0,0 +1,4 @@ +namespace ApplicationUtility; + +abstract class AssemblyStoreAssemblyDescriptor +{} diff --git a/tools/apput/src/AssemblyStore/AssemblyStoreAssemblyDescriptorV2.cs b/tools/apput/src/AssemblyStore/AssemblyStoreAssemblyDescriptorV2.cs new file mode 100644 index 00000000000..523e8ca9df8 --- /dev/null +++ b/tools/apput/src/AssemblyStore/AssemblyStoreAssemblyDescriptorV2.cs @@ -0,0 +1,12 @@ +namespace ApplicationUtility; + +class AssemblyStoreAssemblyDescriptorV2 : AssemblyStoreAssemblyDescriptor +{ + public uint MappingIndex { get; internal set; } + public uint DataOffset { get; internal set; } + public uint DataSize { get; internal set; } + public uint DebugDataOffset { get; internal set; } + public uint DebugDataSize { get; internal set; } + public uint ConfigDataOffset { get; internal set; } + public uint ConfigDataSize { get; internal set; } +} diff --git a/tools/apput/src/AssemblyStore/AssemblyStoreAssemblyDescriptorV3.cs b/tools/apput/src/AssemblyStore/AssemblyStoreAssemblyDescriptorV3.cs new file mode 100644 index 00000000000..18c1ac4974e --- /dev/null +++ b/tools/apput/src/AssemblyStore/AssemblyStoreAssemblyDescriptorV3.cs @@ -0,0 +1,5 @@ +namespace ApplicationUtility; + +// Format is identical to V2, class exists merely for versioning consistency +class AssemblyStoreAssemblyDescriptorV3 : AssemblyStoreAssemblyDescriptorV2 +{} diff --git a/tools/apput/src/AssemblyStore/AssemblyStoreHeader.cs b/tools/apput/src/AssemblyStore/AssemblyStoreHeader.cs index 566c95ce46f..7bd71890da8 100644 --- a/tools/apput/src/AssemblyStore/AssemblyStoreHeader.cs +++ b/tools/apput/src/AssemblyStore/AssemblyStoreHeader.cs @@ -13,8 +13,13 @@ namespace ApplicationUtility; /// class AssemblyStoreHeader { - public AssemblyStoreVersion Version { get; protected set; } - public uint? EntryCount { get; protected set; } - public uint? IndexEntryCount { get; protected set; } - public uint? IndexSize { get; protected set; } + public AssemblyStoreVersion Version { get; } + public uint? EntryCount { get; internal set; } + public uint? IndexEntryCount { get; internal set; } + public uint? IndexSize { get; internal set; } + + public AssemblyStoreHeader (AssemblyStoreVersion version) + { + Version = version; + } } diff --git a/tools/apput/src/AssemblyStore/AssemblyStoreIndex.cs b/tools/apput/src/AssemblyStore/AssemblyStoreIndex.cs deleted file mode 100644 index 83ae5195d5e..00000000000 --- a/tools/apput/src/AssemblyStore/AssemblyStoreIndex.cs +++ /dev/null @@ -1,5 +0,0 @@ -using ApplicationUtility; - -class AssemblyStoreIndex -{ -} diff --git a/tools/apput/src/AssemblyStore/AssemblyStoreIndexEntryV3.cs b/tools/apput/src/AssemblyStore/AssemblyStoreIndexEntryV3.cs new file mode 100644 index 00000000000..7f42e5d5965 --- /dev/null +++ b/tools/apput/src/AssemblyStore/AssemblyStoreIndexEntryV3.cs @@ -0,0 +1,6 @@ +namespace ApplicationUtility; + +class AssemblyStoreIndexEntryV3 +{ + +} diff --git a/tools/apput/src/AssemblyStore/AssemblyStoreVersion.cs b/tools/apput/src/AssemblyStore/AssemblyStoreVersion.cs index 38083a9107c..a1183e20603 100644 --- a/tools/apput/src/AssemblyStore/AssemblyStoreVersion.cs +++ b/tools/apput/src/AssemblyStore/AssemblyStoreVersion.cs @@ -1,15 +1,36 @@ +using System; + namespace ApplicationUtility; class AssemblyStoreVersion { + public uint RawVersion { get; } public uint MainVersion { get; } public AssemblyStoreABI ABI { get; } public bool Is64Bit { get; } - internal AssemblyStoreVersion (uint mainVersion, AssemblyStoreABI abi, bool is64Bit) + internal AssemblyStoreVersion (uint rawVersion) { - MainVersion = mainVersion; - ABI = abi; - Is64Bit = is64Bit; + RawVersion = rawVersion; + Log.Debug ($"AssemblyStoreVersion: raw version is 0x{rawVersion:x}"); + + // Main store version is kept in the lower 16 bits of the version word + MainVersion = rawVersion & 0xFFFF; + Log.Debug ($"AssemblyStoreVersion: main version is {MainVersion}"); + + // ABI is kept in the higher 15 bits of the version word + uint abi = rawVersion & 0x7FFF0000; + Log.Debug ($"AssemblyStoreVersion: raw ABI value is 0x{abi:x}"); + + if (Enum.IsDefined (typeof(AssemblyStoreABI), abi)) { + ABI = (AssemblyStoreABI)abi; + } else { + ABI = AssemblyStoreABI.Unknown; + } + Log.Debug ($"AssemblyStoreVersion: ABI is {ABI}"); + + // 64-bit flag is the leftmost bit in the word + Is64Bit = (rawVersion & 0x80000000) == 0x80000000; + Log.Debug ($"AssemblyStoreVersion: is store 64-bit? {Is64Bit}"); } } diff --git a/tools/apput/src/AssemblyStore/FormatBase.cs b/tools/apput/src/AssemblyStore/FormatBase.cs index d337f03e2fe..6652000edf7 100644 --- a/tools/apput/src/AssemblyStore/FormatBase.cs +++ b/tools/apput/src/AssemblyStore/FormatBase.cs @@ -1,17 +1,170 @@ +using System; +using System.Collections.Generic; using System.IO; +using System.Text; namespace ApplicationUtility; +/// +/// `FormatBase` class is the base class for all format-specific validators/readers. It will +/// always implement reading the current (i.e. the `main` branch) assembly store format, with +/// subclasses required to handle differences. Subclasses are expected to override the virtual +/// `Read*` methods and completely handle reading of the respective structure, without calling +/// up to the base class. +/// abstract class FormatBase { protected Stream StoreStream { get; } protected string? Description { get; } + public AssemblyStoreHeader? Header { get; protected set; } + public List? Descriptors { get; protected set; } + protected FormatBase (Stream storeStream, string? description) { this.StoreStream = storeStream; this.Description = description; } - public abstract IAspectState Validate (); + public void Read () + { + using var reader = new BinaryReader (StoreStream, Encoding.UTF8, leaveOpen: true); + + // They can be `null` if `Validate` wasn't called for some reason. + if (Header == null && ReadHeader (reader, out AssemblyStoreHeader? header)) { + Header = header; + } + + if (Descriptors == null && ReadAssemblyDescriptors (reader, out List? descriptors)) { + Descriptors = descriptors; + } + } + + public IAspectState Validate () + { + using var reader = new BinaryReader (StoreStream, Encoding.UTF8, leaveOpen: true); + + if (ReadHeader (reader, out AssemblyStoreHeader? header)) { + Header = header; + } + + if (ReadAssemblyDescriptors (reader, out List? descriptors)) { + Descriptors = descriptors; + } + + return ValidateInner (); + } + + protected abstract IAspectState ValidateInner (); + + protected virtual bool ReadHeader (BinaryReader reader, out AssemblyStoreHeader? header) + { + header = null; + try { + header = DoReadHeader (reader); + Log.Debug ("AssemblyStore/FormatBase: read store header."); + Log.Debug ($" Raw version: 0x{header.Version.RawVersion:x}"); + Log.Debug ($" Main version: {header.Version.MainVersion}"); + Log.Debug ($" ABI: {header.Version.ABI}"); + Log.Debug ($" 64-bit: {header.Version.Is64Bit}"); + Log.Debug ($" Entry count: {header.EntryCount}"); + Log.Debug ($" Index entry count: {header.IndexEntryCount}"); + Log.Debug ($" Index size (bytes): {header.IndexSize}"); + } catch (Exception ex) { + Log.Debug ($"AssemblyStore/FormatBase: Failed to read assembly store header. Exception thrown:", ex); + return false; + } + + return header != null; + } + + AssemblyStoreHeader? DoReadHeader (BinaryReader reader) + { + StoreStream.Seek (0, SeekOrigin.Begin); + + // From src/native/clr/include/xamarin-app.hh + // + // HEADER (fixed size) + // [MAGIC] uint; value: 0x41424158 + // [FORMAT_VERSION] uint; store format version number + // [ENTRY_COUNT] uint; number of entries in the store + // [INDEX_ENTRY_COUNT] uint; number of entries in the index + // [INDEX_SIZE] uint; index size in bytes + // + + // By the time we are called, the magic number has been verified. We simply ignore it. + uint uintValue = reader.ReadUInt32 (); // magic + uintValue = reader.ReadUInt32 (); // format version + var storeVersion = new AssemblyStoreVersion (uintValue); + + uint entryCount = reader.ReadUInt32 (); + uint indexEntryCount = reader.ReadUInt32 (); + uint indexSize = reader.ReadUInt32 (); + + return new AssemblyStoreHeader (storeVersion) { + EntryCount = entryCount, + IndexEntryCount = indexEntryCount, + IndexSize = indexSize, + }; + } + + protected virtual bool ReadAssemblyDescriptors (BinaryReader reader, out List? descriptors) + { + descriptors = null; + try { + descriptors = DoReadAssemblyDescriptors (reader); + } catch (Exception ex) { + Log.Debug ($"AssemblyStore/FormatBase: failed to read assembly descriptors. Exception thrown:", ex); + return false; + } + + return descriptors != null && descriptors.Count > 0; + } + + List? DoReadAssemblyDescriptors (BinaryReader reader) + { + if (Header == null) { + Log.Debug ($"AssemblyStore/FormatBase: unable to read descriptors, header hasn't been read."); + return null; + } + + if (Header.EntryCount == null) { + Log.Debug ($"AssemblyStore/FormatBase: unable to read descriptors, header entry count hasn't been read."); + return null; + } + + ulong indexEntrySize = Header.Version.Is64Bit ? Format_V3.IndexEntrySize64 : Format_V3.IndexEntrySize32; + ulong descriptorsOffset = (ulong)(Format_V3.HeaderSize + ((Header.EntryCount * 2) * indexEntrySize)); + + if (descriptorsOffset > Int64.MaxValue) { + Log.Debug ($"AssemblyStore/FormatBase: descriptors offset exceeds the maximum value handled by System.IO.Stream"); + return null; + } + + reader.BaseStream.Seek ((long)descriptorsOffset, SeekOrigin.Begin); + var descriptors = new List (); + + for (uint i = 0; i < Header.EntryCount; i++) { + uint mappingIndex = reader.ReadUInt32 (); + uint dataOffset = reader.ReadUInt32 (); + uint dataSize = reader.ReadUInt32 (); + uint debugDataOffset = reader.ReadUInt32 (); + uint debugDataSize = reader.ReadUInt32 (); + uint configDataOffset = reader.ReadUInt32 (); + uint configDataSize = reader.ReadUInt32 (); + + var desc = new AssemblyStoreAssemblyDescriptorV3 { + MappingIndex = mappingIndex, + DataOffset = dataOffset, + DataSize = dataSize, + DebugDataOffset = debugDataOffset, + DebugDataSize = debugDataSize, + ConfigDataOffset = configDataOffset, + ConfigDataSize = configDataSize, + }; + descriptors.Add (desc); + } + + return descriptors; + } } diff --git a/tools/apput/src/AssemblyStore/Format_V2.cs b/tools/apput/src/AssemblyStore/Format_V2.cs index cceeeb72347..0550923aee9 100644 --- a/tools/apput/src/AssemblyStore/Format_V2.cs +++ b/tools/apput/src/AssemblyStore/Format_V2.cs @@ -9,7 +9,7 @@ public Format_V2 (Stream storeStream, string? description) : base (storeStream, description) {} - public override IAspectState Validate () + protected override IAspectState ValidateInner () { throw new NotImplementedException (); } diff --git a/tools/apput/src/AssemblyStore/Format_V3.cs b/tools/apput/src/AssemblyStore/Format_V3.cs index 4092119a1d7..049f4f94e74 100644 --- a/tools/apput/src/AssemblyStore/Format_V3.cs +++ b/tools/apput/src/AssemblyStore/Format_V3.cs @@ -4,14 +4,34 @@ namespace ApplicationUtility; class Format_V3 : FormatBase { + public const uint HeaderSize = 5 * sizeof(uint); + public const uint IndexEntrySize32 = sizeof(uint) + sizeof(uint) + sizeof(byte); + public const uint IndexEntrySize64 = sizeof(ulong) + sizeof(uint) + sizeof(byte); + public const uint AssemblyDescriptorSize = 7 * sizeof(uint); + public Format_V3 (Stream storeStream, string? description) : base (storeStream, description) {} - public override IAspectState Validate () + protected override IAspectState ValidateInner () { - // TODO: validate that the store has correct format and populate the state below accordingly - // to save time later. + Log.Debug ("AssemblyStore/Format_V3: validating store format."); + if (Header == null || Header.EntryCount == null || Header.IndexEntryCount == null || Header.IndexSize == null) { + return ValidationFailed ($"AssemblyStore/Format_V3: invalid header data."); + } + + if (Descriptors == null || Descriptors.Count == 0) { + return ValidationFailed ($"AssemblyStore/Format_V3: no descriptors read."); + } + + // TODO: validate stream size + // TODO: populate return new AssemblyStoreAspectState (true); + + BasicAspectState ValidationFailed (string message) + { + Log.Debug (message); + return new BasicAspectState (false); + } } } diff --git a/tools/apput/src/Package/ApplicationPackage.cs b/tools/apput/src/Package/ApplicationPackage.cs index 03c4caa5368..0eb1461aa88 100644 --- a/tools/apput/src/Package/ApplicationPackage.cs +++ b/tools/apput/src/Package/ApplicationPackage.cs @@ -181,7 +181,7 @@ void TryLoadAssemblyStores () return (AssemblyStore)AssemblyStore.LoadAspect (storeStream, state, fullStorePath); } catch (Exception ex) { - Log.Debug ($"Failed to load assembly store '{storePath}'", ex); + Log.Debug ($"Failed to load assembly store '{storePath}'. Exception thrown:", ex); return null; } } From ba02502f09debdee553512a1b5473a8094129f07 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 10 Jul 2025 16:28:57 +0200 Subject: [PATCH 08/32] AssemblyStore + Assembly reading --- .../apput/src/AssemblyStore/AssemblyStore.cs | 33 ++++- .../AssemblyStore/AssemblyStoreAspectState.cs | 9 +- .../src/AssemblyStore/AssemblyStoreHeader.cs | 4 + .../src/AssemblyStore/AssemblyStoreVersion.cs | 5 + tools/apput/src/AssemblyStore/FormatBase.cs | 60 +++++++-- tools/apput/src/AssemblyStore/Format_V2.cs | 8 ++ tools/apput/src/AssemblyStore/Format_V3.cs | 126 ++++++++++++++++-- tools/apput/src/Native/SharedLibrary.cs | 2 +- .../src/Native/SharedLibraryPayloadStream.cs | 69 ---------- 9 files changed, 218 insertions(+), 98 deletions(-) delete mode 100644 tools/apput/src/Native/SharedLibraryPayloadStream.cs diff --git a/tools/apput/src/AssemblyStore/AssemblyStore.cs b/tools/apput/src/AssemblyStore/AssemblyStore.cs index d358aafb59e..c0f42b7d5b3 100644 --- a/tools/apput/src/AssemblyStore/AssemblyStore.cs +++ b/tools/apput/src/AssemblyStore/AssemblyStore.cs @@ -18,10 +18,41 @@ public class AssemblyStore : IAspect public AndroidTargetArch Architecture { get; private set; } = AndroidTargetArch.None; public ulong NumberOfAssemblies => (ulong)(Assemblies?.Count ?? 0); + AssemblyStoreAspectState storeState; + string? description; + + AssemblyStore (AssemblyStoreAspectState state, string? description) + { + storeState = state; + this.description = description; + } + + bool Read () + { + if (!storeState.Format.Read ()) { + return false; + } + + foreach (ApplicationAssembly asm in storeState.Format.Assemblies) { + Assemblies.Add (asm.Name, asm); + } + + return true; + } + public static IAspect LoadAspect (Stream stream, IAspectState state, string? description) { var storeState = state as AssemblyStoreAspectState; - throw new NotImplementedException (); + if (storeState == null) { + throw new InvalidOperationException ("Internal error: unexpected aspect state. Was ProbeAspect unsuccessful?"); + } + + var store = new AssemblyStore (storeState, description); + if (store.Read ()) { + return store; + } + + throw new InvalidOperationException ($"Failed to load assembly store '{description}'"); } public static IAspectState ProbeAspect (Stream stream, string? description) diff --git a/tools/apput/src/AssemblyStore/AssemblyStoreAspectState.cs b/tools/apput/src/AssemblyStore/AssemblyStoreAspectState.cs index 2ae0b6b77f1..f81e4ada7ac 100644 --- a/tools/apput/src/AssemblyStore/AssemblyStoreAspectState.cs +++ b/tools/apput/src/AssemblyStore/AssemblyStoreAspectState.cs @@ -4,10 +4,11 @@ namespace ApplicationUtility; class AssemblyStoreAspectState : BasicAspectState { - public AssemblyStoreHeader Header { get; } public FormatBase Format { get; } - public AssemblyStoreAspectState (bool success) - : base (success) - {} + public AssemblyStoreAspectState (FormatBase format) + : base (success: true) + { + Format = format; + } } diff --git a/tools/apput/src/AssemblyStore/AssemblyStoreHeader.cs b/tools/apput/src/AssemblyStore/AssemblyStoreHeader.cs index 7bd71890da8..b55065f198a 100644 --- a/tools/apput/src/AssemblyStore/AssemblyStoreHeader.cs +++ b/tools/apput/src/AssemblyStore/AssemblyStoreHeader.cs @@ -22,4 +22,8 @@ public AssemblyStoreHeader (AssemblyStoreVersion version) { Version = version; } + + internal AssemblyStoreHeader () + : this (new AssemblyStoreVersion ()) + {} } diff --git a/tools/apput/src/AssemblyStore/AssemblyStoreVersion.cs b/tools/apput/src/AssemblyStore/AssemblyStoreVersion.cs index a1183e20603..f59cc0d4096 100644 --- a/tools/apput/src/AssemblyStore/AssemblyStoreVersion.cs +++ b/tools/apput/src/AssemblyStore/AssemblyStoreVersion.cs @@ -9,6 +9,11 @@ class AssemblyStoreVersion public AssemblyStoreABI ABI { get; } public bool Is64Bit { get; } + internal AssemblyStoreVersion () + { + ABI = AssemblyStoreABI.Unknown; + } + internal AssemblyStoreVersion (uint rawVersion) { RawVersion = rawVersion; diff --git a/tools/apput/src/AssemblyStore/FormatBase.cs b/tools/apput/src/AssemblyStore/FormatBase.cs index 6652000edf7..8e353734c82 100644 --- a/tools/apput/src/AssemblyStore/FormatBase.cs +++ b/tools/apput/src/AssemblyStore/FormatBase.cs @@ -7,18 +7,21 @@ namespace ApplicationUtility; /// /// `FormatBase` class is the base class for all format-specific validators/readers. It will -/// always implement reading the current (i.e. the `main` branch) assembly store format, with -/// subclasses required to handle differences. Subclasses are expected to override the virtual +/// always implement reading the current (i.e. the `main` branch) assembly store format by default, +/// with subclasses required to handle differences. Subclasses are expected to override the virtual /// `Read*` methods and completely handle reading of the respective structure, without calling /// up to the base class. /// abstract class FormatBase { + protected abstract string LogTag { get; } + protected Stream StoreStream { get; } protected string? Description { get; } public AssemblyStoreHeader? Header { get; protected set; } - public List? Descriptors { get; protected set; } + public IList? Descriptors { get; protected set; } + public IList Assemblies { get; protected set; } = null!; protected FormatBase (Stream storeStream, string? description) { @@ -26,20 +29,42 @@ protected FormatBase (Stream storeStream, string? description) this.Description = description; } - public void Read () + public bool Read () { + bool success = true; using var reader = new BinaryReader (StoreStream, Encoding.UTF8, leaveOpen: true); // They can be `null` if `Validate` wasn't called for some reason. - if (Header == null && ReadHeader (reader, out AssemblyStoreHeader? header)) { - Header = header; + if (Header == null) { + if (ReadHeader (reader, out AssemblyStoreHeader? header) && header != null) { + Header = header; + } else { + success = false; + Header = new (); + } } - if (Descriptors == null && ReadAssemblyDescriptors (reader, out List? descriptors)) { - Descriptors = descriptors; + if (Descriptors == null) { + if (ReadAssemblyDescriptors (reader, out IList? descriptors) && descriptors != null) { + Descriptors = descriptors; + } else { + success = false; + Descriptors = new List ().AsReadOnly (); + } } + + if (ReadAssemblies (reader, out IList? assemblies) && assemblies != null) { + Assemblies = assemblies; + } else { + success = false; + Assemblies = new List ().AsReadOnly (); + } + + return success; } + protected abstract bool ReadAssemblies (BinaryReader reader, out IList? assemblies); + public IAspectState Validate () { using var reader = new BinaryReader (StoreStream, Encoding.UTF8, leaveOpen: true); @@ -48,7 +73,7 @@ public IAspectState Validate () Header = header; } - if (ReadAssemblyDescriptors (reader, out List? descriptors)) { + if (ReadAssemblyDescriptors (reader, out IList? descriptors)) { Descriptors = descriptors; } @@ -57,6 +82,12 @@ public IAspectState Validate () protected abstract IAspectState ValidateInner (); + protected BasicAspectState ValidationFailed (string message) + { + Log.Debug (message); + return new BasicAspectState (false); + } + protected virtual bool ReadHeader (BinaryReader reader, out AssemblyStoreHeader? header) { header = null; @@ -108,7 +139,7 @@ protected virtual bool ReadHeader (BinaryReader reader, out AssemblyStoreHeader? }; } - protected virtual bool ReadAssemblyDescriptors (BinaryReader reader, out List? descriptors) + protected virtual bool ReadAssemblyDescriptors (BinaryReader reader, out IList? descriptors) { descriptors = null; try { @@ -121,7 +152,7 @@ protected virtual bool ReadAssemblyDescriptors (BinaryReader reader, out List 0; } - List? DoReadAssemblyDescriptors (BinaryReader reader) + IList? DoReadAssemblyDescriptors (BinaryReader reader) { if (Header == null) { Log.Debug ($"AssemblyStore/FormatBase: unable to read descriptors, header hasn't been read."); @@ -165,6 +196,11 @@ protected virtual bool ReadAssemblyDescriptors (BinaryReader reader, out List ReadAssemblyNames (BinaryReader reader) + { + throw new NotImplementedException (); } } diff --git a/tools/apput/src/AssemblyStore/Format_V2.cs b/tools/apput/src/AssemblyStore/Format_V2.cs index 0550923aee9..dec1593e8b8 100644 --- a/tools/apput/src/AssemblyStore/Format_V2.cs +++ b/tools/apput/src/AssemblyStore/Format_V2.cs @@ -1,14 +1,22 @@ using System; +using System.Collections.Generic; using System.IO; namespace ApplicationUtility; class Format_V2 : FormatBase { + protected override string LogTag => "AssemblyStore/Format_V2"; + public Format_V2 (Stream storeStream, string? description) : base (storeStream, description) {} + protected override bool ReadAssemblies (BinaryReader reader, out IList? assemblies) + { + throw new NotImplementedException (); + } + protected override IAspectState ValidateInner () { throw new NotImplementedException (); diff --git a/tools/apput/src/AssemblyStore/Format_V3.cs b/tools/apput/src/AssemblyStore/Format_V3.cs index 049f4f94e74..fa9351a9297 100644 --- a/tools/apput/src/AssemblyStore/Format_V3.cs +++ b/tools/apput/src/AssemblyStore/Format_V3.cs @@ -1,37 +1,141 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; using System.IO; +using System.Text; namespace ApplicationUtility; class Format_V3 : FormatBase { + protected override string LogTag => "AssemblyStore/Format_V3"; + public const uint HeaderSize = 5 * sizeof(uint); public const uint IndexEntrySize32 = sizeof(uint) + sizeof(uint) + sizeof(byte); public const uint IndexEntrySize64 = sizeof(ulong) + sizeof(uint) + sizeof(byte); public const uint AssemblyDescriptorSize = 7 * sizeof(uint); + ulong assemblyNamesOffset; + public Format_V3 (Stream storeStream, string? description) : base (storeStream, description) {} - protected override IAspectState ValidateInner () + protected bool EnsureValidState (string where, out IAspectState? retval) { - Log.Debug ("AssemblyStore/Format_V3: validating store format."); + retval = null; if (Header == null || Header.EntryCount == null || Header.IndexEntryCount == null || Header.IndexSize == null) { - return ValidationFailed ($"AssemblyStore/Format_V3: invalid header data."); + retval = ValidationFailed ($"{LogTag}: invalid header data in {where}."); + return false; } if (Descriptors == null || Descriptors.Count == 0) { - return ValidationFailed ($"AssemblyStore/Format_V3: no descriptors read."); + retval = ValidationFailed ($"{LogTag}: no descriptors read in {where}."); + return false; } - // TODO: validate stream size - // TODO: populate - return new AssemblyStoreAspectState (true); + return true; + } - BasicAspectState ValidationFailed (string message) - { - Log.Debug (message); - return new BasicAspectState (false); + protected override IAspectState ValidateInner () + { + Log.Debug ($"{LogTag}: validating store format."); + if (!EnsureValidState (nameof (ValidateInner), out IAspectState? retval)) { + return retval!; } + + // Repetitive to `EnsureValidState`, but it's better than using `!` all over the place below... + Debug.Assert (Header != null); + Debug.Assert (Header.EntryCount != null); + Debug.Assert (Header.IndexEntryCount != null); + Debug.Assert (Descriptors != null); + + ulong indexEntrySize = Header.Version.Is64Bit ? IndexEntrySize64 : IndexEntrySize32; + ulong indexSize = (indexEntrySize * (ulong)Header.IndexEntryCount!); + ulong descriptorsSize = AssemblyDescriptorSize * (ulong)Header.EntryCount!; + ulong requiredStreamSize = HeaderSize + indexSize + descriptorsSize; + + // It points to the start of the assembly names block + assemblyNamesOffset = requiredStreamSize; + + // This is a trick to avoid having to read all the assembly names, but if the stream is valid, it won't be a + // problem and otherwise, well, we're validating after all. First descriptor's data offset points to the next + // byte after assembly names block. + ulong assemblyNamesSize = ((AssemblyStoreAssemblyDescriptorV3)Descriptors[0]).DataOffset - requiredStreamSize; + requiredStreamSize += assemblyNamesSize; + + foreach (var d in Descriptors) { + var desc = (AssemblyStoreAssemblyDescriptorV3)d; + + requiredStreamSize += desc.DataSize + desc.DebugDataSize + desc.ConfigDataSize; + } + Log.Debug ($"{LogTag}: calculated the required stream size to be {requiredStreamSize}"); + + if (requiredStreamSize > Int64.MaxValue) { + return ValidationFailed ($"{LogTag}: required stream size is too long for the stream API to handle."); + } + + if ((long)requiredStreamSize != StoreStream.Length) { + return ValidationFailed ($"{LogTag}: stream has invalid size, expected {requiredStreamSize} bytes, found {StoreStream.Length} instead."); + } else { + Log.Debug ($"{LogTag}: stream size is valid."); + } + + return new AssemblyStoreAspectState (this); + } + + protected override IList ReadAssemblyNames (BinaryReader reader) + { + Debug.Assert (Header != null); + Debug.Assert (Header.EntryCount != null); + + reader.BaseStream.Seek ((long)assemblyNamesOffset, SeekOrigin.Begin); + var ret = new List (); + + for (ulong i = 0; i < Header.EntryCount; i++) { + uint length = reader.ReadUInt32 (); + if (length == 0) { + continue; + } + + byte[] nameBytes = reader.ReadBytes ((int)length); + ret.Add (Encoding.UTF8.GetString (nameBytes)); + } + + return ret.AsReadOnly (); + } + + protected override bool ReadAssemblies (BinaryReader reader, out IList? assemblies) + { + Debug.Assert (Descriptors != null); + + assemblies = null; + if (!EnsureValidState (nameof (ReadAssemblies), out _)) { + return false; + } + + IList assemblyNames = ReadAssemblyNames (reader); + if (assemblyNames.Count != Descriptors.Count) { + Log.Debug ($"{LogTag}: assembly name count ({assemblyNames.Count}) is different to descriptor count ({Descriptors.Count})"); + return false; + } + + var ret = new List (); + for (int i = 0; i < Descriptors.Count; i++) { + var desc = (AssemblyStoreAssemblyDescriptorV3)Descriptors[i]; + string name = assemblyNames[i]; + var assemblyStream = new SubStream (reader.BaseStream, (long)desc.DataOffset, (long)desc.DataSize); + IAspectState assemblyState = ApplicationAssembly.ProbeAspect (assemblyStream, name); + if (!assemblyState.Success) { + assemblyStream.Dispose (); + continue; + } + + var assembly = (ApplicationAssembly)ApplicationAssembly.LoadAspect (assemblyStream, assemblyState, name); + ret.Add (assembly); + } + + assemblies = ret.AsReadOnly (); + return true; } } diff --git a/tools/apput/src/Native/SharedLibrary.cs b/tools/apput/src/Native/SharedLibrary.cs index ca5df68b31d..64ba7490ad2 100644 --- a/tools/apput/src/Native/SharedLibrary.cs +++ b/tools/apput/src/Native/SharedLibrary.cs @@ -77,7 +77,7 @@ public Stream OpenAndroidPayload () throw new InvalidOperationException ($"Payload offset of {payloadSize} is too large to support."); } - return new SharedLibraryPayloadStream (libraryStream, (long)payloadOffset, (long)payloadSize); + return new SubStream (libraryStream, (long)payloadOffset, (long)payloadSize); } static bool IsSupportedELFSharedLibrary (Stream stream, string? description) diff --git a/tools/apput/src/Native/SharedLibraryPayloadStream.cs b/tools/apput/src/Native/SharedLibraryPayloadStream.cs deleted file mode 100644 index 27ec09b879d..00000000000 --- a/tools/apput/src/Native/SharedLibraryPayloadStream.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System; -using System.IO; - -namespace ApplicationUtility; - -class SharedLibraryPayloadStream : Stream -{ - readonly Stream baseStream; - readonly long length; - readonly long offsetInBaseStream; - - public override bool CanRead => true; - public override bool CanSeek => true; - public override bool CanWrite => false; - public override long Length => length; - - public override long Position { - get => throw new NotSupportedException (); - set => throw new NotSupportedException (); - } - - public SharedLibraryPayloadStream (Stream baseStream, long offset, long length) - { - if (!baseStream.CanSeek) { - throw new InvalidOperationException ($"Base stream must support seeking"); - } - - if (!baseStream.CanRead) { - throw new InvalidOperationException ($"Base stream must support reading"); - } - - if (offset >= baseStream.Length) { - throw new ArgumentOutOfRangeException (nameof (offset), $"{offset} exceeds length of the base stream ({baseStream.Length})"); - } - - if (offset + length > baseStream.Length) { - throw new InvalidOperationException ($"Not enough data in base stream after offset {offset}, length of {length} bytes is too big."); - } - - this.baseStream = baseStream; - this.length = length; - offsetInBaseStream = offset; - } - - public override int Read (byte [] buffer, int offset, int count) - { - return baseStream.Read (buffer, offset, count); - } - - public override long Seek (long offset, SeekOrigin origin) - { - return baseStream.Seek (offset + offsetInBaseStream, origin); - } - - public override void Flush () - { - throw new NotSupportedException (); - } - - public override void SetLength (long value) - { - throw new NotSupportedException (); - } - - public override void Write (byte [] buffer, int offset, int count) - { - throw new NotSupportedException (); - } -} From 161fdf62b2f165c812a84cdb98a3d0919a7b4bd7 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 11 Jul 2025 12:19:19 +0200 Subject: [PATCH 09/32] Oops, forgot to commit this one --- tools/apput/src/Common/SubStream.cs | 69 +++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 tools/apput/src/Common/SubStream.cs diff --git a/tools/apput/src/Common/SubStream.cs b/tools/apput/src/Common/SubStream.cs new file mode 100644 index 00000000000..4539489ad2f --- /dev/null +++ b/tools/apput/src/Common/SubStream.cs @@ -0,0 +1,69 @@ +using System; +using System.IO; + +namespace ApplicationUtility; + +class SubStream : Stream +{ + readonly Stream baseStream; + readonly long length; + readonly long offsetInParentStream; + + public override bool CanRead => true; + public override bool CanSeek => true; + public override bool CanWrite => false; + public override long Length => length; + + public override long Position { + get => throw new NotSupportedException (); + set => throw new NotSupportedException (); + } + + public SubStream (Stream baseStream, long offsetInParentStream, long length) + { + if (!baseStream.CanSeek) { + throw new InvalidOperationException ($"Base stream must support seeking"); + } + + if (!baseStream.CanRead) { + throw new InvalidOperationException ($"Base stream must support reading"); + } + + if (offsetInParentStream >= baseStream.Length) { + throw new ArgumentOutOfRangeException (nameof (offsetInParentStream), $"{offsetInParentStream} exceeds length of the base stream ({baseStream.Length})"); + } + + if (offsetInParentStream + length > baseStream.Length) { + throw new InvalidOperationException ($"Not enough data in base stream after offset {offsetInParentStream}, length of {length} bytes is too big."); + } + + this.baseStream = baseStream; + this.length = length; + this.offsetInParentStream = offsetInParentStream; + } + + public override int Read (byte [] buffer, int offset, int count) + { + return baseStream.Read (buffer, offset, count); + } + + public override long Seek (long offset, SeekOrigin origin) + { + return baseStream.Seek (offset + offsetInParentStream, origin); + } + + public override void Flush () + { + throw new NotSupportedException (); + } + + public override void SetLength (long value) + { + throw new NotSupportedException (); + } + + public override void Write (byte [] buffer, int offset, int count) + { + throw new NotSupportedException (); + } +} From c92a75b43d06428162cf15fa21b6cb6e468b0542 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 11 Jul 2025 16:56:40 +0200 Subject: [PATCH 10/32] More assembly store + assemblies --- .../ApplicationAssembly.cs | 125 +++++++++++++++++- .../AssemblyStore/AssemblyStoreIndexEntry.cs | 4 + .../AssemblyStoreIndexEntryV3.cs | 11 +- tools/apput/src/AssemblyStore/FormatBase.cs | 10 +- tools/apput/src/AssemblyStore/Format_V3.cs | 76 +++++++++-- tools/apput/src/Common/Utilities.cs | 13 ++ 6 files changed, 215 insertions(+), 24 deletions(-) create mode 100644 tools/apput/src/AssemblyStore/AssemblyStoreIndexEntry.cs diff --git a/tools/apput/src/ApplicationAssembly/ApplicationAssembly.cs b/tools/apput/src/ApplicationAssembly/ApplicationAssembly.cs index 48f4416a0b6..b44de13deb0 100644 --- a/tools/apput/src/ApplicationAssembly/ApplicationAssembly.cs +++ b/tools/apput/src/ApplicationAssembly/ApplicationAssembly.cs @@ -5,21 +5,134 @@ namespace ApplicationUtility; public class ApplicationAssembly : IAspect { + const string LogTag = "ApplicationAssembly"; + const uint COMPRESSED_MAGIC = 0x5A4C4158; // 'XALZ', little-endian + const ushort MSDOS_EXE_MAGIC = 0x5A4D; // 'MZ' + const uint PE_EXE_MAGIC = 0x00004550; // 'PE\0\0' + public static string AspectName { get; } = "Application assembly"; - public bool IsCompressed { get; private set; } - public string Name { get; private set; } = ""; - public ulong CompressedSize { get; private set; } - public ulong Size { get; private set; } - public bool IgnoreOnLoad { get; private set; } + public bool IsCompressed { get; } + public string Name { get; } + public ulong CompressedSize { get; } + public ulong Size { get; } + public bool IgnoreOnLoad { get; } + public ulong NameHash { get; internal set; } + + readonly Stream? assemblyStream; + + ApplicationAssembly (Stream stream, uint uncompressedSize, string? description, bool isCompressed) + { + assemblyStream = stream; + Size = uncompressedSize; + CompressedSize = isCompressed ? (ulong)stream.Length : 0; + IsCompressed = isCompressed; + Name = NameMe (description); + } + + ApplicationAssembly (string? description, bool isIgnored) + { + IgnoreOnLoad = isIgnored; + Name = NameMe (description); + } + + static string NameMe (string? description) => String.IsNullOrEmpty (description) ? "Unnamed" : description; + + // This is a special case, as much as I hate to have one. Ignored assemblies exist only in the assembly store's + // index. They have an associated descriptor, but no data whatsoever. For that reason, we can't go the `ProbeAspect` + // + `LoadAspect` route, so `AssemblyStore` will call this method for them. + public static IAspect CreateIgnoredAssembly (string? description, ulong nameHash) + { + Log.Debug ($"{LogTag}: stream ('{description}') is an ignored assembly."); + return new ApplicationAssembly (description, isIgnored: true) { + NameHash = nameHash, + }; + } public static IAspect LoadAspect (Stream stream, IAspectState state, string? description) { - throw new NotImplementedException (); + using var reader = Utilities.GetReaderAndRewindStream (stream); + if (ReadCompressedHeader (reader, out uint uncompressedLength)) { + return new ApplicationAssembly (stream, uncompressedLength, description, isCompressed: true); + } + + return new ApplicationAssembly (stream, (uint)stream.Length, description, isCompressed: false); } public static IAspectState ProbeAspect (Stream stream, string? description) + { + Log.Debug ($"{LogTag}: probing stream ('{description}')"); + if (stream.Length == 0) { + // It can happen if the assembly store index or name table are corrupted and we cannot + // determine if an assembly is ignored or not. If it is ignored, it will have no data + // available and so the stream will have length of 0 + return new BasicAspectState (false); + } + + // If we detect compressed assembly signature, we won't proceed with checking whether + // the rest of data is actually a valid managed assembly. This is to avoid doing a + // costly operation of decompressing when e.g. loading data from an assemblystore, when + // we potentially create a lot of `ApplicationAssembly` instances. Presence of the compression + // header is enough for the probing stage. + + using var reader = Utilities.GetReaderAndRewindStream (stream); + if (ReadCompressedHeader (reader, out _)) { + Log.Debug ($"{LogTag}: stream ('{description}') is a compressed assembly."); + return new BasicAspectState (true); + } + + // We could use PEReader (https://learn.microsoft.com/en-us/dotnet/api/system.reflection.portableexecutable.pereader) + // but it would be too heavy for our purpose here. + reader.BaseStream.Seek (0, SeekOrigin.Begin); + ushort mzExeMagic = reader.ReadUInt16 (); + if (mzExeMagic != MSDOS_EXE_MAGIC) { + return Utilities.GetFailureAspectState ($"{LogTag}: stream doesn't have MS-DOS executable signature."); + } + + const long PE_HEADER_OFFSET = 0x3c; + if (reader.BaseStream.Length <= PE_HEADER_OFFSET) { + return Utilities.GetFailureAspectState ($"{LogTag}: stream contains a corrupted MS-DOS executable image (too short, offset {PE_HEADER_OFFSET} is bigger than stream size)."); + } + + // Offset at 0x3C is where we can read the 32-bit offset to the PE header + reader.BaseStream.Seek (PE_HEADER_OFFSET, SeekOrigin.Begin); + uint uintVal = reader.ReadUInt32 (); + if (reader.BaseStream.Length <= (long)uintVal) { + return Utilities.GetFailureAspectState ($"{LogTag}: stream contains a corrupted PE executable image (too short, offset {uintVal} is bigger than stream size)."); + } + + reader.BaseStream.Seek ((long)uintVal, SeekOrigin.Begin); + uintVal = reader.ReadUInt32 (); + if (uintVal != PE_EXE_MAGIC) { + return Utilities.GetFailureAspectState ($"{LogTag}: stream doesn't have PE executable signature."); + } + // This is good enough for us + + Log.Debug ($"{LogTag}: stream ('{description}') appears to be a PE image."); + return new BasicAspectState (true); + } + + /// + /// Writes assembly data to the indicated file, uncompressing it if necessary. If the destination + /// file exists, it will be overwritten. + /// + public void SaveToFile (string filePath) { throw new NotImplementedException (); } + + // We don't care about the descriptor index here, it's only needed during the run time + static bool ReadCompressedHeader (BinaryReader reader, out uint uncompressedLength) + { + uncompressedLength = 0; + + uint uintVal = reader.ReadUInt32 (); + if (uintVal != COMPRESSED_MAGIC) { + return false; + } + + uintVal = reader.ReadUInt32 (); // descriptor index + uncompressedLength = reader.ReadUInt32 (); + return true; + } } diff --git a/tools/apput/src/AssemblyStore/AssemblyStoreIndexEntry.cs b/tools/apput/src/AssemblyStore/AssemblyStoreIndexEntry.cs new file mode 100644 index 00000000000..743fa3c9556 --- /dev/null +++ b/tools/apput/src/AssemblyStore/AssemblyStoreIndexEntry.cs @@ -0,0 +1,4 @@ +namespace ApplicationUtility; + +abstract class AssemblyStoreIndexEntry +{} diff --git a/tools/apput/src/AssemblyStore/AssemblyStoreIndexEntryV3.cs b/tools/apput/src/AssemblyStore/AssemblyStoreIndexEntryV3.cs index 7f42e5d5965..590b6e3b9ac 100644 --- a/tools/apput/src/AssemblyStore/AssemblyStoreIndexEntryV3.cs +++ b/tools/apput/src/AssemblyStore/AssemblyStoreIndexEntryV3.cs @@ -1,6 +1,15 @@ namespace ApplicationUtility; -class AssemblyStoreIndexEntryV3 +class AssemblyStoreIndexEntryV3 : AssemblyStoreIndexEntry { + public ulong NameHash { get; } + public uint DescriptorIndex { get; } + public bool Ignore { get; } + public AssemblyStoreIndexEntryV3 (ulong nameHash, uint descriptorIndex, byte ignore) + { + NameHash = nameHash; + DescriptorIndex = descriptorIndex; + Ignore = ignore != 0; + } } diff --git a/tools/apput/src/AssemblyStore/FormatBase.cs b/tools/apput/src/AssemblyStore/FormatBase.cs index 8e353734c82..3db5b50043c 100644 --- a/tools/apput/src/AssemblyStore/FormatBase.cs +++ b/tools/apput/src/AssemblyStore/FormatBase.cs @@ -32,7 +32,7 @@ protected FormatBase (Stream storeStream, string? description) public bool Read () { bool success = true; - using var reader = new BinaryReader (StoreStream, Encoding.UTF8, leaveOpen: true); + using var reader = Utilities.GetReaderAndRewindStream (StoreStream); // They can be `null` if `Validate` wasn't called for some reason. if (Header == null) { @@ -67,7 +67,7 @@ public bool Read () public IAspectState Validate () { - using var reader = new BinaryReader (StoreStream, Encoding.UTF8, leaveOpen: true); + using var reader = Utilities.GetReaderAndRewindStream (StoreStream); if (ReadHeader (reader, out AssemblyStoreHeader? header)) { Header = header; @@ -82,12 +82,6 @@ public IAspectState Validate () protected abstract IAspectState ValidateInner (); - protected BasicAspectState ValidationFailed (string message) - { - Log.Debug (message); - return new BasicAspectState (false); - } - protected virtual bool ReadHeader (BinaryReader reader, out AssemblyStoreHeader? header) { header = null; diff --git a/tools/apput/src/AssemblyStore/Format_V3.cs b/tools/apput/src/AssemblyStore/Format_V3.cs index fa9351a9297..352081a02bf 100644 --- a/tools/apput/src/AssemblyStore/Format_V3.cs +++ b/tools/apput/src/AssemblyStore/Format_V3.cs @@ -4,6 +4,8 @@ using System.IO; using System.Text; +using Xamarin.Android.Tasks; + namespace ApplicationUtility; class Format_V3 : FormatBase @@ -25,12 +27,12 @@ protected bool EnsureValidState (string where, out IAspectState? retval) { retval = null; if (Header == null || Header.EntryCount == null || Header.IndexEntryCount == null || Header.IndexSize == null) { - retval = ValidationFailed ($"{LogTag}: invalid header data in {where}."); + retval = Utilities.GetFailureAspectState ($"{LogTag}: invalid header data in {where}."); return false; } if (Descriptors == null || Descriptors.Count == 0) { - retval = ValidationFailed ($"{LogTag}: no descriptors read in {where}."); + retval = Utilities.GetFailureAspectState ($"{LogTag}: no descriptors read in {where}."); return false; } @@ -47,11 +49,12 @@ protected override IAspectState ValidateInner () // Repetitive to `EnsureValidState`, but it's better than using `!` all over the place below... Debug.Assert (Header != null); Debug.Assert (Header.EntryCount != null); + Debug.Assert (Header.IndexSize != null); Debug.Assert (Header.IndexEntryCount != null); Debug.Assert (Descriptors != null); ulong indexEntrySize = Header.Version.Is64Bit ? IndexEntrySize64 : IndexEntrySize32; - ulong indexSize = (indexEntrySize * (ulong)Header.IndexEntryCount!); + ulong indexSize = (ulong)Header.IndexSize; // (indexEntrySize * (ulong)Header.IndexEntryCount!); ulong descriptorsSize = AssemblyDescriptorSize * (ulong)Header.EntryCount!; ulong requiredStreamSize = HeaderSize + indexSize + descriptorsSize; @@ -72,11 +75,11 @@ protected override IAspectState ValidateInner () Log.Debug ($"{LogTag}: calculated the required stream size to be {requiredStreamSize}"); if (requiredStreamSize > Int64.MaxValue) { - return ValidationFailed ($"{LogTag}: required stream size is too long for the stream API to handle."); + return Utilities.GetFailureAspectState ($"{LogTag}: required stream size is too long for the stream API to handle."); } if ((long)requiredStreamSize != StoreStream.Length) { - return ValidationFailed ($"{LogTag}: stream has invalid size, expected {requiredStreamSize} bytes, found {StoreStream.Length} instead."); + return Utilities.GetFailureAspectState ($"{LogTag}: stream has invalid size, expected {requiredStreamSize} bytes, found {StoreStream.Length} instead."); } else { Log.Debug ($"{LogTag}: stream size is valid."); } @@ -107,6 +110,8 @@ protected override IList ReadAssemblyNames (BinaryReader reader) protected override bool ReadAssemblies (BinaryReader reader, out IList? assemblies) { + Debug.Assert (Header != null); + Debug.Assert (Header.IndexEntryCount != null); Debug.Assert (Descriptors != null); assemblies = null; @@ -115,16 +120,42 @@ protected override bool ReadAssemblies (BinaryReader reader, out IList assemblyNames = ReadAssemblyNames (reader); - if (assemblyNames.Count != Descriptors.Count) { - Log.Debug ($"{LogTag}: assembly name count ({assemblyNames.Count}) is different to descriptor count ({Descriptors.Count})"); - return false; + bool assemblyNamesUnreliable = assemblyNames.Count != Descriptors.Count; + if (assemblyNamesUnreliable) { + Log.Error ($"{LogTag}: assembly name count ({assemblyNames.Count}) is different to descriptor count ({Descriptors.Count})"); + } + + bool is64Bit = Header.Version.Is64Bit; + var index = new Dictionary (); + reader.BaseStream.Seek ((long)HeaderSize, SeekOrigin.Begin); + for (uint i = 0; i < Header.IndexEntryCount; i++) { + ulong hash = is64Bit ? reader.ReadUInt64 () : reader.ReadUInt32 (); + uint descIdx = reader.ReadUInt32 (); + byte ignore = reader.ReadByte (); + + if (index.ContainsKey (hash)) { + Log.Error ($"{LogTag}: duplicate assembly name hash (0x{hash:x}) found in the '{Description}' assembly store."); + continue; + } + Log.Debug ($"{LogTag}: index entry {i} hash == 0x{hash:x}"); + index.Add (hash, new AssemblyStoreIndexEntryV3 (hash, descIdx, ignore)); } var ret = new List (); for (int i = 0; i < Descriptors.Count; i++) { var desc = (AssemblyStoreAssemblyDescriptorV3)Descriptors[i]; - string name = assemblyNames[i]; + string name = assemblyNamesUnreliable ? "" : assemblyNames[i]; var assemblyStream = new SubStream (reader.BaseStream, (long)desc.DataOffset, (long)desc.DataSize); + + ulong hash = NameHash (name); + Log.Debug ($"{LogTag}: hash for assembly '{name}' is 0x{hash:x}"); + + bool isIgnored = CheckIgnored (hash); + if (isIgnored) { + ret.Add ((ApplicationAssembly)ApplicationAssembly.CreateIgnoredAssembly (name, hash)); + continue; + } + IAspectState assemblyState = ApplicationAssembly.ProbeAspect (assemblyStream, name); if (!assemblyState.Success) { assemblyStream.Dispose (); @@ -132,10 +163,37 @@ protected override bool ReadAssemblies (BinaryReader reader, out IList Date: Mon, 14 Jul 2025 18:45:00 +0200 Subject: [PATCH 11/32] Android binary XML parser (for in-package AndroidManifest.xml) A big buggy still, TBC --- tools/apput/src/Android/ARSCHeader.cs | 60 +++ tools/apput/src/Android/AXMLParser.cs | 378 ++++++++++++++++++ tools/apput/src/Android/AndroidManifest.cs | 58 +++ .../src/Android/AndroidManifestAspectState.cs | 12 + .../Android/AndroidManifestAttributeType.cs | 52 +++ .../src/Android/AndroidManifestChunkType.cs | 23 ++ .../src/Android/AndroidManifestStringBlock.cs | 176 ++++++++ tools/apput/src/Detector.cs | 12 +- tools/apput/src/Package/ApplicationPackage.cs | 36 +- 9 files changed, 799 insertions(+), 8 deletions(-) create mode 100644 tools/apput/src/Android/ARSCHeader.cs create mode 100644 tools/apput/src/Android/AXMLParser.cs create mode 100644 tools/apput/src/Android/AndroidManifest.cs create mode 100644 tools/apput/src/Android/AndroidManifestAspectState.cs create mode 100644 tools/apput/src/Android/AndroidManifestAttributeType.cs create mode 100644 tools/apput/src/Android/AndroidManifestChunkType.cs create mode 100644 tools/apput/src/Android/AndroidManifestStringBlock.cs diff --git a/tools/apput/src/Android/ARSCHeader.cs b/tools/apput/src/Android/ARSCHeader.cs new file mode 100644 index 00000000000..446d831ad8a --- /dev/null +++ b/tools/apput/src/Android/ARSCHeader.cs @@ -0,0 +1,60 @@ +using System; +using System.IO; + +namespace ApplicationUtility; + +class ARSCHeader +{ + // This is the minimal size such a header must have. There might be other header data too! + const long MinimumSize = 2 + 2 + 4; + + readonly long start; + readonly uint size; + readonly ushort type; + readonly ushort headerSize; + readonly bool unknownType; + + public AndroidManifestChunkType Type => unknownType ? AndroidManifestChunkType.Null : (AndroidManifestChunkType)type; + public ushort TypeRaw => type; + public ushort HeaderSize => headerSize; + public uint Size => size; + public long End => start + (long)size; + + public ARSCHeader (Stream data, AndroidManifestChunkType? expectedType = null) + { + start = data.Position; + if (data.Length < start + MinimumSize) { + throw new InvalidDataException ($"Input data not large enough. Offset: {start}"); + } + + // Data in AXML is little-endian, which is fortuitous as that's the only format BinaryReader understands. + using BinaryReader reader = Utilities.GetReaderAndRewindStream (data); + + // ushort: type + // ushort: header_size + // uint: size + type = reader.ReadUInt16 (); + headerSize = reader.ReadUInt16 (); + + // Total size of the chunk, including the header + size = reader.ReadUInt32 (); + + if (expectedType != null && type != (ushort)expectedType) { + throw new InvalidOperationException ($"Header type is not equal to the expected type ({expectedType}): got 0x{type:x}, expected 0x{(ushort)expectedType:x}"); + } + + unknownType = !Enum.IsDefined (typeof(AndroidManifestChunkType), type); + + if (headerSize < MinimumSize) { + throw new InvalidDataException ($"Declared header size is smaller than required size of {MinimumSize}. Offset: {start}"); + } + + if (size < MinimumSize) { + throw new InvalidDataException ($"Declared chunk size is smaller than required size of {MinimumSize}. Offset: {start}"); + } + + if (size < headerSize) { + throw new InvalidDataException ($"Declared chunk size ({size}) is smaller than header size ({headerSize})! Offset: {start}"); + } + } +} diff --git a/tools/apput/src/Android/AXMLParser.cs b/tools/apput/src/Android/AXMLParser.cs new file mode 100644 index 00000000000..80c9151c6aa --- /dev/null +++ b/tools/apput/src/Android/AXMLParser.cs @@ -0,0 +1,378 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Xml; + +namespace ApplicationUtility; + +// +// Based on https://github.com/androguard/androguard/tree/832104db3eb5dc3cc66b30883fa8ce8712dfa200/androguard/core/axml +// +class AXMLParser +{ + // Position of fields inside an attribute + const int ATTRIBUTE_IX_NAMESPACE_URI = 0; + const int ATTRIBUTE_IX_NAME = 1; + const int ATTRIBUTE_IX_VALUE_STRING = 2; + const int ATTRIBUTE_IX_VALUE_TYPE = 3; + const int ATTRIBUTE_IX_VALUE_DATA = 4; + const int ATTRIBUTE_LENGHT = 5; + + const long MinimumDataSize = 8; + const long MaximumDataSize = (long)UInt32.MaxValue; + + const uint ComplexUnitMask = 0x0f; + + static readonly float[] RadixMultipliers = { + 0.00390625f, + 3.051758E-005f, + 1.192093E-007f, + 4.656613E-010f, + }; + + static readonly string[] DimensionUnits = { + "px", + "dip", + "sp", + "pt", + "in", + "mm", + }; + + static readonly string[] FractionUnits = { + "%", + "%p", + }; + + Stream data; + long dataSize; + ARSCHeader axmlHeader; + uint fileSize; + AndroidManifestStringBlock stringPool; + bool valid = true; + long initialPosition; + + public bool IsValid => valid; + + public AXMLParser (Stream data) + { + this.data = data; + dataSize = data.Length; + + // Minimum is a single ARSCHeader, which would be a strange edge case... + if (dataSize < MinimumDataSize) { + throw new InvalidDataException ($"Input data size too small for it to be valid AXML content ({dataSize} < {MinimumDataSize})"); + } + + // This would be even stranger, if an AXML file is larger than 4GB... + // But this is not possible as the maximum chunk size is a unsigned 4 byte int. + if (dataSize > MaximumDataSize) { + throw new InvalidDataException ($"Input data size too large for it to be a valid AXML content ({dataSize} > {MaximumDataSize})"); + } + + try { + axmlHeader = new ARSCHeader (data); + } catch (Exception) { + Log.Error ("Error parsing the first data header"); + throw; + } + + if (axmlHeader.HeaderSize != 8) { + throw new InvalidDataException ($"This does not look like AXML data. header size does not equal 8. header size = {axmlHeader.Size}"); + } + + fileSize = axmlHeader.Size; + if (fileSize > dataSize) { + throw new InvalidDataException ($"This does not look like AXML data. Declared data size does not match real size: {fileSize} vs {dataSize}"); + } + + if (fileSize < dataSize) { + Log.Warning ($"Declared data size ({fileSize}) is smaller than total data size ({dataSize}). Was something appended to the file? Trying to parse it anyways."); + } + + if (axmlHeader.Type != AndroidManifestChunkType.Xml) { + Log.Warning ($"AXML file has an unusual resource type, trying to parse it anyways. Resource Type: 0x{(ushort)axmlHeader.Type:04x}"); + } + + ARSCHeader stringPoolHeader = new ARSCHeader (data, AndroidManifestChunkType.StringPool); + if (stringPoolHeader.HeaderSize != 28) { + throw new InvalidDataException ($"This does not look like an AXML file. String chunk header size does not equal 28. Header size = {stringPoolHeader.Size}"); + } + + stringPool = new AndroidManifestStringBlock (data, stringPoolHeader); + initialPosition = data.Position; + } + + public XmlDocument? Parse () + { + valid = true; + + XmlDocument ret = new XmlDocument (); + XmlDeclaration declaration = ret.CreateXmlDeclaration ("1.0", stringPool.IsUTF8 ? "UTF-8" : "UTF-16", null); + ret.InsertBefore (declaration, ret.DocumentElement); + + using var reader = Utilities.GetReaderAndRewindStream (data); + ARSCHeader? header; + string? nsPrefix = null; + string? nsUri = null; + uint prefixIndex = 0; + uint uriIndex = 0; + var nsUriToPrefix = new Dictionary (StringComparer.Ordinal); + XmlNode? currentNode = ret.DocumentElement; + + while (data.Position < dataSize) { + header = new ARSCHeader (data); + + // Special chunk: Resource Map. This chunk might follow the string pool. + if (header.Type == AndroidManifestChunkType.XmlResourceMap) { + if (!SkipOverResourceMap (header, reader)) { + valid = false; + break; + } + continue; + } + + // XML chunks + + // Skip over unknown types + if (!Enum.IsDefined (typeof(AndroidManifestChunkType), header.TypeRaw)) { + Log.Warning ($"Unknown chunk type 0x{header.TypeRaw:x} at offset {data.Position}. Skipping over {header.Size} bytes"); + data.Seek (header.Size, SeekOrigin.Current); + continue; + } + + // Check that we read a correct header + if (header.HeaderSize != 16) { + Log.Warning ($"XML chunk header size is not 16. Chunk type {header.Type} (0x{header.TypeRaw:x}), chunk size {header.Size}"); + data.Seek (header.Size, SeekOrigin.Current); + continue; + } + + // Line Number of the source file, only used as meta information + uint lineNumber = reader.ReadUInt32 (); + + // Comment_Index (usually 0xffffffff) + uint commentIndex = reader.ReadUInt32 (); + + if (commentIndex != 0xffffffff && (header.Type == AndroidManifestChunkType.XmlStartNamespace || header.Type == AndroidManifestChunkType.XmlEndNamespace)) { + Log.Warning ($"Unhandled Comment at namespace chunk: {commentIndex}"); + } + + if (header.Type == AndroidManifestChunkType.XmlStartNamespace) { + prefixIndex = reader.ReadUInt32 (); + uriIndex = reader.ReadUInt32 (); + + nsPrefix = stringPool.GetString (prefixIndex); + nsUri = stringPool.GetString (uriIndex); + + if (!String.IsNullOrEmpty (nsUri)) { + nsUriToPrefix[nsUri] = nsPrefix ?? String.Empty; + } + + Log.Debug ($"Start of Namespace mapping: prefix {prefixIndex}: '{nsPrefix}' --> uri {uriIndex}: '{nsUri}'"); + + if (String.IsNullOrEmpty (nsUri)) { + Log.Warning ($"Namespace prefix '{nsPrefix}' resolves to empty URI."); + } + + continue; + } + + if (header.Type == AndroidManifestChunkType.XmlEndNamespace) { + // Namespace handling is **really** simplified, since we expect to deal only with AndroidManifest.xml which should have just one namespace. + // There should be no problems with that. Famous last words. + uint endPrefixIndex = reader.ReadUInt32 (); + uint endUriIndex = reader.ReadUInt32 (); + + Log.Debug ($"End of Namespace mapping: prefix {endPrefixIndex}, uri {endUriIndex}"); + if (endPrefixIndex != prefixIndex) { + Log.Warning ($"Prefix index of Namespace end doesn't match the last Namespace prefix index: {prefixIndex} != {endPrefixIndex}"); + } + + if (endUriIndex != uriIndex) { + Log.Warning ($"URI index of Namespace end doesn't match the last Namespace URI index: {uriIndex} != {endUriIndex}"); + } + + string? endUri = stringPool.GetString (endUriIndex); + if (!String.IsNullOrEmpty (endUri) && nsUriToPrefix.ContainsKey (endUri)) { + nsUriToPrefix.Remove (endUri); + } + + nsPrefix = null; + nsUri = null; + prefixIndex = 0; + uriIndex = 0; + + continue; + } + + uint tagNsUriIndex; + uint tagNameIndex; + string? tagName; +// string? tagNs; // TODO: implement + + if (header.Type == AndroidManifestChunkType.XmlStartElement) { + // The TAG consists of some fields: + // * (chunk_size, line_number, comment_index - we read before) + // * namespace_uri + // * name + // * flags + // * attribute_count + // * class_attribute + // After that, there are two lists of attributes, 20 bytes each + tagNsUriIndex = reader.ReadUInt32 (); + tagNameIndex = reader.ReadUInt32 (); + uint tagFlags = reader.ReadUInt32 (); + uint attributeCount = reader.ReadUInt32 () & 0xffff; + uint classAttribute = reader.ReadUInt32 (); + + // Tag name is, of course, required but instead of throwing an exception should we find none, we use a fake name in hope that we can still salvage + // the document. + tagName = stringPool.GetString (tagNameIndex) ?? "unnamedTag"; + Log.Debug ($"Start of tag '{tagName}', NS URI index {tagNsUriIndex}"); + Log.Debug ($"Reading tag attributes ({attributeCount}):"); + + string? tagNsUri = tagNsUriIndex != 0xffffffff ? stringPool.GetString (tagNsUriIndex) : null; + string? tagNsPrefix; + + if (String.IsNullOrEmpty (tagNsUri) || !nsUriToPrefix.TryGetValue (tagNsUri, out tagNsPrefix)) { + tagNsPrefix = null; + } + + XmlElement element = ret.CreateElement (tagNsPrefix, tagName, tagNsUri); + if (currentNode == null) { + ret.AppendChild (element); + if (!String.IsNullOrEmpty (nsPrefix) && !String.IsNullOrEmpty (nsUri)) { + ret.DocumentElement!.SetAttribute ($"xmlns:{nsPrefix}", nsUri); + } + } else { + currentNode.AppendChild (element); + } + currentNode = element; + + for (uint i = 0; i < attributeCount; i++) { + uint attrNsIdx = reader.ReadUInt32 (); // string index + uint attrNameIdx = reader.ReadUInt32 (); // string index + uint attrValue = reader.ReadUInt32 (); + uint attrType = reader.ReadUInt32 () >> 24; + uint attrData = reader.ReadUInt32 (); + + string? attrNs = attrNsIdx != 0xffffffff ? stringPool.GetString (attrNsIdx) : String.Empty; + string? attrName = stringPool.GetString (attrNameIdx); + + if (String.IsNullOrEmpty (attrName)) { + Log.Warning ($"Attribute without name, ignoring. Offset: {data.Position}"); + continue; + } + + Log.Debug ($" '{attrName}': ns == '{attrNs}'; value == 0x{attrValue:x}; type == 0x{attrType:x}; data == 0x{attrData:x}"); + XmlAttribute attr; + + if (!String.IsNullOrEmpty (attrNs)) { + attr = ret.CreateAttribute (nsUriToPrefix[attrNs], attrName, attrNs); + } else { + attr = ret.CreateAttribute (attrName!); + } + attr.Value = GetAttributeValue (attrValue, attrType, attrData); + element.SetAttributeNode (attr); + } + continue; + } + + if (header.Type == AndroidManifestChunkType.XmlEndElement) { + tagNsUriIndex = reader.ReadUInt32 (); + tagNameIndex = reader.ReadUInt32 (); + + tagName = stringPool.GetString (tagNameIndex); + Log.Debug ($"End of tag '{tagName}', NS URI index {tagNsUriIndex}"); + currentNode = currentNode?.ParentNode!; + continue; + } + + // TODO: add support for CDATA + } + + return ret; + } + + string GetAttributeValue (uint attrValue, uint attrType, uint attrData) + { + if (!Enum.IsDefined (typeof(AndroidManifestAttributeType), attrType)) { + Log.Warning ($"Unknown attribute type value 0x{attrType:x}, returning empty attribute value (data == 0x{attrData:x}). Offset: {data.Position}"); + return String.Empty; + } + + switch ((AndroidManifestAttributeType)attrType) { + case AndroidManifestAttributeType.Null: + return attrData == 0 ? "?NULL?" : String.Empty; + + case AndroidManifestAttributeType.Reference: + return $"@{MaybePrefix()}{attrData:x08}"; + + case AndroidManifestAttributeType.Attribute: + return $"?{MaybePrefix()}{attrData:x08}"; + + case AndroidManifestAttributeType.String: + return stringPool.GetString (attrData) ?? String.Empty; + + case AndroidManifestAttributeType.Float: + return $"{(float)attrData}"; + + case AndroidManifestAttributeType.Dimension: + return $"{ComplexToFloat(attrData)}{DimensionUnits[attrData & ComplexUnitMask]}"; + + case AndroidManifestAttributeType.Fraction: + return $"{ComplexToFloat(attrData) * 100.0f}{FractionUnits[attrData & ComplexUnitMask]}"; + + case AndroidManifestAttributeType.IntDec: + return attrData.ToString (); + + case AndroidManifestAttributeType.IntHex: + return $"0x{attrData:X08}"; + + case AndroidManifestAttributeType.IntBoolean: + return attrData == 0 ? "false" : "true"; + + case AndroidManifestAttributeType.IntColorARGB8: + case AndroidManifestAttributeType.IntColorRGB8: + case AndroidManifestAttributeType.IntColorARGB4: + case AndroidManifestAttributeType.IntColorRGB4: + return $"#{attrData:X08}"; + } + + return String.Empty; + + string MaybePrefix () + { + if (attrData >> 24 == 1) { + return "android:"; + } + return String.Empty; + } + + float ComplexToFloat (uint value) + { + return (float)(value & 0xffffff00) * RadixMultipliers[(value >> 4) & 3]; + } + } + + bool SkipOverResourceMap (ARSCHeader header, BinaryReader reader) + { + Log.Debug ("AXML contains a resource map"); + + // Check size: < 8 bytes mean that the chunk is not complete + // Should be aligned to 4 bytes. + if (header.Size < 8 || (header.Size % 4) != 0) { + Log.Error ("Invalid chunk size in chunk XML_RESOURCE_MAP"); + return false; + } + + // Since our main interest is in reading AndroidManifest.xml, we're going to skip over the table + for (int i = 0; i < (header.Size - header.HeaderSize) / 4; i++) { + reader.ReadUInt32 (); + } + + return true; + } +} diff --git a/tools/apput/src/Android/AndroidManifest.cs b/tools/apput/src/Android/AndroidManifest.cs new file mode 100644 index 00000000000..c1778e528b3 --- /dev/null +++ b/tools/apput/src/Android/AndroidManifest.cs @@ -0,0 +1,58 @@ +using System; +using System.IO; + +namespace ApplicationUtility; + +public class AndroidManifest : IAspect +{ + public string Description { get; } + + AXMLParser? binaryParser; + + AndroidManifest (AXMLParser binaryParser, string? description) + { + Description = String.IsNullOrEmpty (description) ? "Android manifest" : description; + this.binaryParser = binaryParser; + } + + public static IAspect LoadAspect (Stream stream, IAspectState state, string? description) + { + var manifestState = state as AndroidManifestAspectState; + if (manifestState == null) { + throw new InvalidOperationException ("Internal error: unexpected aspect state. Was ProbeAspect unsuccessful?"); + } + + AndroidManifest ret; + if (manifestState.BinaryParser != null) { + ret = new AndroidManifest (manifestState.BinaryParser, description); + } else { + throw new NotImplementedException (); + } + ret.Read (); + + return ret; + } + + public static IAspectState ProbeAspect (Stream stream, string? description) + { + try { + stream.Seek (0, SeekOrigin.Begin); + + // The constructor will throw if it cannot recognize the format + var binaryParser = new AXMLParser (stream); + + // We leave parsing of the data to `LoadAspect`, here we only detect the format + return new AndroidManifestAspectState (binaryParser); + } catch (Exception ex) { + Log.Debug ($"Failed to instantiate AXML binary parser for '{description}'", ex); + } + + // TODO: detect plain XML + throw new NotImplementedException (); + } + + void Read () + { + throw new NotImplementedException (); + } +} diff --git a/tools/apput/src/Android/AndroidManifestAspectState.cs b/tools/apput/src/Android/AndroidManifestAspectState.cs new file mode 100644 index 00000000000..732e335c4a3 --- /dev/null +++ b/tools/apput/src/Android/AndroidManifestAspectState.cs @@ -0,0 +1,12 @@ +namespace ApplicationUtility; + +class AndroidManifestAspectState : IAspectState +{ + public bool Success => true; + public AXMLParser? BinaryParser { get; } + + public AndroidManifestAspectState (AXMLParser? binaryParser) + { + BinaryParser = binaryParser; + } +} diff --git a/tools/apput/src/Android/AndroidManifestAttributeType.cs b/tools/apput/src/Android/AndroidManifestAttributeType.cs new file mode 100644 index 00000000000..c8962929e36 --- /dev/null +++ b/tools/apput/src/Android/AndroidManifestAttributeType.cs @@ -0,0 +1,52 @@ +namespace ApplicationUtility; + +enum AndroidManifestAttributeType : uint +{ + // The 'data' field is either 0 or 1, specifying this resource is either undefined or empty, respectively. + Null = 0x00, + + // The 'data' field holds a ResTable_ref, a reference to another resource + Reference = 0x01, + + // The 'data' field holds an attribute resource identifier. + Attribute = 0x02, + + // The 'data' field holds an index into the containing resource table's global value string pool. + String = 0x03, + + // The 'data' field holds a single-precision floating point number. + Float = 0x04, + + // The 'data' holds a complex number encoding a dimension value such as "100in". + Dimension = 0x05, + + // The 'data' holds a complex number encoding a fraction of a container. + Fraction = 0x06, + + // The 'data' holds a dynamic ResTable_ref, which needs to be resolved before it can be used like a Reference + DynamicReference = 0x07, + + // The 'data' holds an attribute resource identifier, which needs to be resolved before it can be used like a Attribute. + DynamicAttribute = 0x08, + + // The 'data' is a raw integer value of the form n..n. + IntDec = 0x10, + + // The 'data' is a raw integer value of the form 0xn..n. + IntHex = 0x11, + + // The 'data' is either 0 or 1, for input "false" or "true" respectively. + IntBoolean = 0x12, + + // The 'data' is a raw integer value of the form #aarrggbb. + IntColorARGB8 = 0x1c, + + // The 'data' is a raw integer value of the form #rrggbb. + IntColorRGB8 = 0x1d, + + // The 'data' is a raw integer value of the form #argb. + IntColorARGB4 = 0x1e, + + // The 'data' is a raw integer value of the form #rgb. + IntColorRGB4 = 0x1f, +} diff --git a/tools/apput/src/Android/AndroidManifestChunkType.cs b/tools/apput/src/Android/AndroidManifestChunkType.cs new file mode 100644 index 00000000000..5b689bf3b1b --- /dev/null +++ b/tools/apput/src/Android/AndroidManifestChunkType.cs @@ -0,0 +1,23 @@ +namespace ApplicationUtility; + +enum AndroidManifestChunkType : ushort +{ + Null = 0x0000, + StringPool = 0x0001, + Table = 0x0002, + Xml = 0x0003, + + XmlFirstChunk = 0x0100, + XmlStartNamespace = 0x0100, + XmlEndNamespace = 0x0101, + XmlStartElement = 0x0102, + XmlEndElement = 0x0103, + XmlCData = 0x0104, + XmlLastChunk = 0x017f, + XmlResourceMap = 0x0180, + + TablePackage = 0x0200, + TableType = 0x0201, + TableTypeSpec = 0x0202, + TableLibrary = 0x0203, +} diff --git a/tools/apput/src/Android/AndroidManifestStringBlock.cs b/tools/apput/src/Android/AndroidManifestStringBlock.cs new file mode 100644 index 00000000000..884102de80e --- /dev/null +++ b/tools/apput/src/Android/AndroidManifestStringBlock.cs @@ -0,0 +1,176 @@ +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace ApplicationUtility; + +class AndroidManifestStringBlock +{ + const uint FlagSorted = 1 << 0; + const uint FlagUTF8 = 1 << 0; + + ARSCHeader header; + uint stringCount; + uint stringsOffset; + uint flags; + bool isUTF8; + List stringOffsets; + byte[] chars; + Dictionary stringCache; + + public uint StringCount => stringCount; + public bool IsUTF8 => isUTF8; + + public AndroidManifestStringBlock (Stream data, ARSCHeader stringPoolHeader) + { + header = stringPoolHeader; + + using var reader = Utilities.GetReaderAndRewindStream (data); + + stringCount = reader.ReadUInt32 (); + uint styleCount = reader.ReadUInt32 (); + + flags = reader.ReadUInt32 (); + isUTF8 = (flags & FlagUTF8) == FlagUTF8; + + stringsOffset = reader.ReadUInt32 (); + uint stylesOffset = reader.ReadUInt32 (); + + if (styleCount == 0 && stylesOffset > 0) { + Log.Info ("Styles Offset given, but styleCount is zero. This is not a problem but could indicate packers."); + } + + stringOffsets = new List (); + + for (uint i = 0; i < stringCount; i++) { + stringOffsets.Add (reader.ReadUInt32 ()); + } + + // We're not interested in styles, skip over their offsets + for (uint i = 0; i < styleCount; i++) { + reader.ReadUInt32 (); + } + + bool haveStyles = stylesOffset != 0 && styleCount != 0; + uint size = header.Size - stringsOffset; + if (haveStyles) { + size = stylesOffset - stringsOffset; + } + + if (size % 4 != 0) { + Log.Warning ("Size of strings is not aligned on four bytes."); + } + + chars = new byte[size]; + reader.Read (chars, 0, (int)size); + + if (haveStyles) { + size = header.Size - stylesOffset; + + if (size % 4 != 0) { + Log.Warning ("Size of styles is not aligned on four bytes."); + } + + // Not interested in them, skip + for (uint i = 0; i < size / 4; i++) { + reader.ReadUInt32 (); + } + } + + stringCache = new Dictionary (); + } + + public string? GetString (uint idx) + { + if (stringCache.TryGetValue (idx, out string? ret)) { + return ret; + } + + if (idx < 0 || idx > stringOffsets.Count || stringOffsets.Count == 0) { + return null; + } + + uint offset = stringOffsets[(int)idx]; + if (isUTF8) { + ret = DecodeUTF8 (offset); + } else { + ret = DecodeUTF16 (offset); + } + stringCache[idx] = ret; + + return ret; + } + + string DecodeUTF8 (uint offset) + { + // UTF-8 Strings contain two lengths, as they might differ: + // 1) the string length in characters + (uint length, uint nbytes) = DecodeLength (offset, sizeOfChar: 1); + offset += nbytes; + + // 2) the number of bytes the encoded string occupies + (uint encodedBytes, nbytes) = DecodeLength (offset, sizeOfChar: 1); + offset += nbytes; + + if (chars[offset + encodedBytes] != 0) { + throw new InvalidDataException ($"UTF-8 string is not NUL-terminated. Offset: offset"); + } + + return Encoding.UTF8.GetString (chars, (int)offset, (int)encodedBytes); + } + + string DecodeUTF16 (uint offset) + { + (uint length, uint nbytes) = DecodeLength (offset, sizeOfChar: 2); + offset += nbytes; + + uint encodedBytes = length * 2; + if (chars[offset + encodedBytes] != 0 && chars[offset + encodedBytes + 1] != 0) { + throw new InvalidDataException ($"UTF-16 string is not NUL-terminated. Offset: offset"); + } + + return Encoding.Unicode.GetString (chars, (int)offset, (int)encodedBytes); + } + + (uint length, uint nbytes) DecodeLength (uint offset, uint sizeOfChar) + { + uint sizeOfTwoChars = sizeOfChar << 1; + uint highBit = 0x80u << (8 * ((int)sizeOfChar - 1)); + uint length1, length2; + + // Length is tored as 1 or 2 characters of `sizeofChar` size + if (sizeOfChar == 1) { + // UTF-8 encoding, each character is a byte + length1 = chars[offset]; + length2 = chars[offset + 1]; + } else { + // UTF-16 encoding, each character is a short + length1 = (uint)((chars[offset]) | (chars[offset + 1] << 8)); + length2 = (uint)((chars[offset + 2]) | (chars[offset + 3] << 8)); + } + + uint length; + uint nbytes; + if ((length1 & highBit) != 0) { + length = ((length1 & ~highBit) << (8 * (int)sizeOfChar)) | length2; + nbytes = sizeOfTwoChars; + } else { + length = length1; + nbytes = sizeOfChar; + } + + // 8 bit strings: maximum of 0x7FFF bytes, http://androidxref.com/9.0.0_r3/xref/frameworks/base/libs/androidfw/ResourceTypes.cpp#692 + // 16 bit strings: maximum of 0x7FFFFFF bytes, http://androidxref.com/9.0.0_r3/xref/frameworks/base/libs/androidfw/ResourceTypes.cpp#670 + if (sizeOfChar == 1) { + if (length > 0x7fff) { + throw new InvalidDataException ("UTF-8 string is too long. Offset: {offset}"); + } + } else { + if (length > 0x7fffffff) { + throw new InvalidDataException ("UTF-16 string is too long. Offset: {offset}"); + } + } + + return (length, nbytes); + } +} diff --git a/tools/apput/src/Detector.cs b/tools/apput/src/Detector.cs index c9248e46e76..ea9ea5674e9 100644 --- a/tools/apput/src/Detector.cs +++ b/tools/apput/src/Detector.cs @@ -41,7 +41,7 @@ class Detector var flags = BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static; foreach (Type aspect in KnownTopLevelAspects) { - Log.Debug ($"Probing aspect: {aspect}"); + LogBanner ($"Probing aspect: {aspect}"); object? result = aspect.InvokeMember ( "ProbeAspect", flags, null, null, new object?[] { stream, description } @@ -52,7 +52,7 @@ class Detector continue; } - Log.Debug ($"Loading aspect: {aspect}"); + LogBanner ($"Loading aspect: {aspect}"); result = aspect.InvokeMember ( "LoadAspect", flags, null, null, new object?[] { stream, state, description } ); @@ -62,6 +62,14 @@ class Detector } return null; + + void LogBanner (string what) + { + Log.Debug (); + Log.Debug ("##########"); + Log.Debug (what); + Log.Debug (); + } } } diff --git a/tools/apput/src/Package/ApplicationPackage.cs b/tools/apput/src/Package/ApplicationPackage.cs index 0eb1461aa88..f3de6bdc38f 100644 --- a/tools/apput/src/Package/ApplicationPackage.cs +++ b/tools/apput/src/Package/ApplicationPackage.cs @@ -50,6 +50,8 @@ public abstract class ApplicationPackage : IAspect public List? AssemblyStores { get; protected set; } public List Architectures { get; protected set; } = new (); + AndroidManifest? manifest; + protected ApplicationPackage (ZipArchive zip, string? description) { Zip = zip; @@ -165,7 +167,7 @@ void TryLoadAssemblyStores () AssemblyStore? TryLoadAssemblyStore (string storePath) { // AssemblyStore class owns the stream, don't dispose it here - FileStream? storeStream = TryGetEntryStream (storePath); + Stream? storeStream = TryGetEntryStream (storePath); if (storeStream == null) { return null; } @@ -195,14 +197,29 @@ void TryLoadAndroidManifest () } Log.Debug ($"Found Android manifest '{AndroidManifestPath}'"); - using Stream? manifestStream = TryGetEntryStream (AndroidManifestPath); - // TODO: parse + + try { + Stream? manifestStream = TryGetEntryStream (AndroidManifestPath, extractToMemory: true); + if (manifestStream == null) { + Log.Error ("Failed to read android manifest from the application package."); + return; + } + IAspectState manifestState = AndroidManifest.ProbeAspect (manifestStream, AndroidManifestPath); + if (!manifestState.Success) { + Log.Debug ($"Failed to detect '{AndroidManifestPath}' package entry as supported Android manifest data."); + manifestStream.Dispose (); + return; + } + manifest = (AndroidManifest)AndroidManifest.LoadAspect (manifestStream, manifestState, AndroidManifestPath); + } catch (Exception ex) { + Log.Debug ($"Failed to load android manifest '{AndroidManifestPath}' from the archive.", ex); + } } string GetNativeLibDir (AndroidTargetArch arch) => $"{NativeLibDirBase}/{MonoAndroidHelper.ArchToAbi (arch)}/"; string GetNativeLibFile (AndroidTargetArch arch, string fileName) => $"{GetNativeLibDir (arch)}{fileName}"; - FileStream? TryGetEntryStream (string path) + Stream? TryGetEntryStream (string path, bool extractToMemory = false) { try { ZipArchiveEntry? entry = Zip.GetEntry (path); @@ -211,6 +228,15 @@ void TryLoadAndroidManifest () return null; } + if (extractToMemory) { + Log.Debug ($"Extracting entry '{path}' to a memory stream"); + using var inputStream = entry.Open (); + var outputStream = new MemoryStream (); + inputStream.CopyTo (outputStream); + inputStream.Flush (); + return outputStream; + } + string tempFile = Path.GetTempFileName (); TempFileManager.RegisterFile (tempFile); @@ -219,8 +245,6 @@ void TryLoadAndroidManifest () return File.OpenRead (tempFile); } catch (Exception ex) { Log.Debug ($"Failed to load entry '{path}' from the archive.", ex); - - // TODO: remove temp file (using a helper method, which doesn't exist yet) return null; } } From 97e2446c81b167138622fb1ef64a487b9508198f Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 15 Jul 2025 16:41:04 +0200 Subject: [PATCH 12/32] Android manifest almost finished (protobuf missing) + native bits Beginnings of support for reading ELF binaries, needed for typemaps and friends --- tools/apput/src/Android/ARSCHeader.cs | 2 +- tools/apput/src/Android/AXMLParser.cs | 2 +- tools/apput/src/Android/AndroidManifest.cs | 44 ++- .../src/Android/AndroidManifestAspectState.cs | 8 + tools/apput/src/Common/Utilities.cs | 9 +- tools/apput/src/Native/AnELF.cs | 331 ++++++++++++++++++ tools/apput/src/Native/ELF32.cs | 91 +++++ tools/apput/src/Native/ELF64.cs | 206 +++++++++++ .../src/Native/ELF_RelocationWithAddend.cs | 52 +++ tools/apput/src/Native/LibXamarinApp.cs | 38 ++ tools/apput/src/Native/NativeAppInfo.cs | 8 + tools/apput/src/Native/NativeUtils.cs | 72 ++++ tools/apput/src/Native/RelocationSection.cs | 30 ++ tools/apput/src/Native/RelocationTypes.cs | 118 +++++++ tools/apput/src/Native/SharedLibrary.cs | 6 +- tools/apput/src/Package/ApplicationPackage.cs | 37 ++ 16 files changed, 1043 insertions(+), 11 deletions(-) create mode 100644 tools/apput/src/Native/AnELF.cs create mode 100644 tools/apput/src/Native/ELF32.cs create mode 100644 tools/apput/src/Native/ELF64.cs create mode 100644 tools/apput/src/Native/ELF_RelocationWithAddend.cs create mode 100644 tools/apput/src/Native/LibXamarinApp.cs create mode 100644 tools/apput/src/Native/NativeAppInfo.cs create mode 100644 tools/apput/src/Native/NativeUtils.cs create mode 100644 tools/apput/src/Native/RelocationSection.cs create mode 100644 tools/apput/src/Native/RelocationTypes.cs diff --git a/tools/apput/src/Android/ARSCHeader.cs b/tools/apput/src/Android/ARSCHeader.cs index 446d831ad8a..3872a0a6446 100644 --- a/tools/apput/src/Android/ARSCHeader.cs +++ b/tools/apput/src/Android/ARSCHeader.cs @@ -28,7 +28,7 @@ public ARSCHeader (Stream data, AndroidManifestChunkType? expectedType = null) } // Data in AXML is little-endian, which is fortuitous as that's the only format BinaryReader understands. - using BinaryReader reader = Utilities.GetReaderAndRewindStream (data); + using BinaryReader reader = Utilities.GetReaderAndRewindStream (data, rewindStream: false); // ushort: type // ushort: header_size diff --git a/tools/apput/src/Android/AXMLParser.cs b/tools/apput/src/Android/AXMLParser.cs index 80c9151c6aa..6df7ecd7a6d 100644 --- a/tools/apput/src/Android/AXMLParser.cs +++ b/tools/apput/src/Android/AXMLParser.cs @@ -108,7 +108,7 @@ public AXMLParser (Stream data) { valid = true; - XmlDocument ret = new XmlDocument (); + var ret = new XmlDocument (); XmlDeclaration declaration = ret.CreateXmlDeclaration ("1.0", stringPool.IsUTF8 ? "UTF-8" : "UTF-16", null); ret.InsertBefore (declaration, ret.DocumentElement); diff --git a/tools/apput/src/Android/AndroidManifest.cs b/tools/apput/src/Android/AndroidManifest.cs index c1778e528b3..e709c053641 100644 --- a/tools/apput/src/Android/AndroidManifest.cs +++ b/tools/apput/src/Android/AndroidManifest.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Xml; namespace ApplicationUtility; @@ -8,6 +9,7 @@ public class AndroidManifest : IAspect public string Description { get; } AXMLParser? binaryParser; + XmlDocument? xmlDoc; AndroidManifest (AXMLParser binaryParser, string? description) { @@ -35,6 +37,7 @@ public static IAspect LoadAspect (Stream stream, IAspectState state, string? des public static IAspectState ProbeAspect (Stream stream, string? description) { + Log.Debug ($"Checking if '{description}' is an Android binary XML document."); try { stream.Seek (0, SeekOrigin.Begin); @@ -44,15 +47,48 @@ public static IAspectState ProbeAspect (Stream stream, string? description) // We leave parsing of the data to `LoadAspect`, here we only detect the format return new AndroidManifestAspectState (binaryParser); } catch (Exception ex) { - Log.Debug ($"Failed to instantiate AXML binary parser for '{description}'", ex); + Log.Debug ($"Failed to instantiate AXML binary parser for '{description}'. Exception thrown:", ex); } - // TODO: detect plain XML - throw new NotImplementedException (); + Log.Debug ($"Checking if '{description}' is an plain XML document."); + try { + return new AndroidManifestAspectState (ParsePlainXML (stream)); + } catch (Exception ex) { + Log.Debug ($"Failed to parse '{description}' as XML document. Exception thrown:", ex); + } + + // TODO: AndroidManifest.xml in AAB files is actually a protobuf data dump. Attempt to + // deserialize it here. + return new BasicAspectState (success: false); } void Read () { - throw new NotImplementedException (); + if (binaryParser == null) { + throw new NotImplementedException (); + } + + xmlDoc = binaryParser.Parse (); + if (xmlDoc == null || !binaryParser.IsValid) { + Log.Debug ($"AXML parser didn't render a valid document for '{Description}'"); + return; + } + Log.Debug ($"'{Description}' loaded and parsed correctly."); + } + + static XmlDocument ParsePlainXML (Stream stream) + { + stream.Seek (0, SeekOrigin.Begin); + var settings = new XmlReaderSettings { + IgnoreComments = true, + IgnoreProcessingInstructions = true, + IgnoreWhitespace = true, + }; + + using var reader = XmlReader.Create (stream, settings); + var doc = new XmlDocument (); + doc.Load (reader); + + return doc; } } diff --git a/tools/apput/src/Android/AndroidManifestAspectState.cs b/tools/apput/src/Android/AndroidManifestAspectState.cs index 732e335c4a3..863b63ef3af 100644 --- a/tools/apput/src/Android/AndroidManifestAspectState.cs +++ b/tools/apput/src/Android/AndroidManifestAspectState.cs @@ -1,12 +1,20 @@ +using System.Xml; + namespace ApplicationUtility; class AndroidManifestAspectState : IAspectState { public bool Success => true; public AXMLParser? BinaryParser { get; } + public XmlDocument? Xml { get; } public AndroidManifestAspectState (AXMLParser? binaryParser) { BinaryParser = binaryParser; } + + public AndroidManifestAspectState (XmlDocument? xmlDoc) + { + Xml = xmlDoc; + } } diff --git a/tools/apput/src/Common/Utilities.cs b/tools/apput/src/Common/Utilities.cs index b2f51ca132e..a5ec008cc04 100644 --- a/tools/apput/src/Common/Utilities.cs +++ b/tools/apput/src/Common/Utilities.cs @@ -33,9 +33,12 @@ public static void CloseAndDeleteFile (FileStream stream, bool quiet = true) DeleteFile (path); } - public static BinaryReader GetReaderAndRewindStream (Stream stream) + public static BinaryReader GetReaderAndRewindStream (Stream stream, bool rewindStream = false) { - stream.Seek (0, SeekOrigin.Begin); + if (rewindStream) { + stream.Seek (0, SeekOrigin.Begin); + } + return new BinaryReader (stream, Encoding.UTF8, leaveOpen: true); } @@ -44,4 +47,6 @@ public static BasicAspectState GetFailureAspectState (string message) Log.Debug (message); return new BasicAspectState (false); } + + public static string ToStringOrNull (T? reference) => reference == null ? "" : reference.ToString () ?? "[unknown]"; } diff --git a/tools/apput/src/Native/AnELF.cs b/tools/apput/src/Native/AnELF.cs new file mode 100644 index 00000000000..5dfec85c2fb --- /dev/null +++ b/tools/apput/src/Native/AnELF.cs @@ -0,0 +1,331 @@ +using System; +using System.IO; +using System.Linq; +using System.Text; + +using ELFSharp; +using ELFSharp.ELF; +using ELFSharp.ELF.Sections; + +namespace ApplicationUtility; + +abstract class AnELF +{ + protected static readonly byte[] EmptyArray = Array.Empty (); + + const string DynsymSectionName = ".dynsym"; + const string SymtabSectionName = ".symtab"; + const string RodataSectionName = ".rodata"; + + ISymbolTable dynamicSymbolsSection; + ISection rodataSection; + ISymbolTable? symbolsSection; + string filePath; + IELF elf; + Stream elfStream; + + protected ISymbolTable DynSymSection => dynamicSymbolsSection; + protected ISymbolTable? SymSection => symbolsSection; + protected ISection RodataSection => rodataSection; + public IELF AnyELF => elf; + protected Stream ELFStream => elfStream; + + public string FilePath => filePath; + public int PointerSize => Is64Bit ? 8 : 4; + + public abstract bool Is64Bit { get; } + public abstract string Bitness { get; } + + protected AnELF (Stream stream, string filePath, IELF elf, ISymbolTable dynsymSection, ISection rodataSection, ISymbolTable? symSection) + { + this.filePath = filePath; + this.elf = elf; + elfStream = stream; + dynamicSymbolsSection = dynsymSection; + this.rodataSection = rodataSection; + symbolsSection = symSection; + } + + public ISymbolEntry? GetSymbol (string symbolName) + { + ISymbolEntry? symbol = null; + + if (symbolsSection != null) { + symbol = GetSymbol (symbolsSection, symbolName); + } + + if (symbol == null) { + symbol = GetSymbol (dynamicSymbolsSection, symbolName); + } + + return symbol; + } + + protected static ISymbolEntry? GetSymbol (ISymbolTable symtab, string symbolName) + { + return symtab.Entries.Where (entry => String.Compare (entry.Name, symbolName, StringComparison.Ordinal) == 0).FirstOrDefault (); + } + + protected static SymbolEntry? GetSymbol (SymbolTable symtab, T symbolValue) where T: struct + { + return symtab.Entries.Where (entry => entry.Value.Equals (symbolValue)).FirstOrDefault (); + } + + public bool HasSymbol (string symbolName) + { + return GetSymbol (symbolName) != null; + } + + public byte[] GetData (string symbolName) + { + return GetData (symbolName, out ISymbolEntry? _); + } + + public byte[] GetData (string symbolName, out ISymbolEntry? symbolEntry) + { + Log.Debug ($"Looking for symbol: {symbolName}"); + symbolEntry = GetSymbol (symbolName); + if (symbolEntry == null) + return EmptyArray; + + if (Is64Bit) { + var symbol64 = symbolEntry as SymbolEntry; + if (symbol64 == null) + throw new InvalidOperationException ($"Symbol '{symbolName}' is not a valid 64-bit symbol"); + return GetData (symbol64); + } + + var symbol32 = symbolEntry as SymbolEntry; + if (symbol32 == null) + throw new InvalidOperationException ($"Symbol '{symbolName}' is not a valid 32-bit symbol"); + + return GetData (symbol32); + } + + public string? GetStringFromPointer (ISymbolEntry symbolEntry) + { + return GetStringFromPointerField (symbolEntry, 0); + } + + public abstract string? GetStringFromPointerField (ISymbolEntry symbolEntry, ulong pointerFieldOffset); + public abstract byte[] GetData (ulong symbolValue, ulong size); + + public string? GetASCIIZ (ulong symbolValue) + { + return GetASCIIZ (GetData (symbolValue, 0), 0); + } + + public string? GetASCIIZ (byte[] data, ulong offset) + { + if (offset >= (ulong)data.LongLength) { + Log.Debug ("Not enough data to retrieve an ASCIIZ string"); + return null; + } + + int count = data.Length; + + for (ulong i = offset; i < (ulong)data.LongLength; i++) { + if (data[i] == 0) { + count = (int)(i - offset); + break; + } + } + + return Encoding.ASCII.GetString (data, (int)offset, count); + } + + public ulong GetPaddedSize (ulong sizeSoFar) => NativeUtils.GetPaddedSize (sizeSoFar, Is64Bit); + + public ulong GetPaddedSize (ulong sizeSoFar, S _) + { + return GetPaddedSize (sizeSoFar); + } + + protected virtual byte[] GetData (SymbolEntry symbol) + { + throw new NotSupportedException (); + } + + protected virtual byte[] GetData (SymbolEntry symbol) + { + throw new NotSupportedException (); + } + + protected byte[] GetData (ISymbolEntry symbol, ulong size, ulong offset) + { + return GetData (symbol.PointedSection, size, offset); + } + + protected byte[] GetData (ISection section, ulong size, ulong offset) + { + ulong sectionOffset = (elf.Class == Class.Bit64 ? ((Section)section).Offset : ((Section)section).Offset); + Log.Debug ($"AnELF.GetData: section == {section.Name}; type == {section.Type}; flags == {section.Flags}; offset into binary == {sectionOffset}; size == {size}"); + byte[] data = section.GetContents (); + + Log.Debug ($" section data length: {data.Length} (long: {data.LongLength})"); + Log.Debug ($" offset into section: {offset}; symbol data length: {size}"); + if ((ulong)data.LongLength < (offset + size)) { + return EmptyArray; + } + + if (size == 0) + size = (ulong)data.Length - offset; + + var ret = new byte[size]; + checked { + Array.Copy (data, (int)offset, ret, 0, (int)size); + } + + return ret; + } + + public uint GetUInt32 (string symbolName) + { + return GetUInt32 (GetData (symbolName), 0, symbolName); + } + + public uint GetUInt32 (ulong symbolValue) + { + return GetUInt32 (GetData (symbolValue, 4), 0, symbolValue.ToString ()); + } + + protected uint GetUInt32 (byte[] data, ulong offset, string symbolName) + { + if (data.Length < 4) { + throw new InvalidOperationException ($"Data not big enough to retrieve a 32-bit integer from it (need 4, got {data.Length})"); + } + + return BitConverter.ToUInt32 (GetIntegerData (4, data, offset, symbolName), 0); + } + + public ulong GetUInt64 (string symbolName) + { + return GetUInt64 (GetData (symbolName), 0, symbolName); + } + + public ulong GetUInt64 (ulong symbolValue) + { + return GetUInt64 (GetData (symbolValue, 8), 0, symbolValue.ToString ()); + } + + protected ulong GetUInt64 (byte[] data, ulong offset, string symbolName) + { + if (data.Length < 8) { + throw new InvalidOperationException ("Data not big enough to retrieve a 64-bit integer from it"); + } + return BitConverter.ToUInt64 (GetIntegerData (8, data, offset, symbolName), 0); + } + + byte[] GetIntegerData (uint size, byte[] data, ulong offset, string symbolName) + { + if ((ulong)data.LongLength < (offset + size)) { + string bits = size == 4 ? "32" : "64"; + throw new InvalidOperationException ($"Unable to read UInt{bits} value for symbol '{symbolName}': data not long enough"); + } + + byte[] ret = new byte[size]; + Array.Copy (data, (int)offset, ret, 0, ret.Length); + Endianess myEndianness = BitConverter.IsLittleEndian ? Endianess.LittleEndian : Endianess.BigEndian; + if (AnyELF.Endianess != myEndianness) { + Array.Reverse (ret); + } + + return ret; + } + + public static bool TryLoad (string filePath, out AnELF? anElf) + { + using var fs = File.OpenRead (filePath); + return TryLoad (fs, filePath, out anElf); + } + + public static bool TryLoad (Stream stream, string filePath, out AnELF? anElf) + { + anElf = null; + Class elfClass = ELFReader.CheckELFType (stream); + if (elfClass == Class.NotELF) { + Log.Warning ($"AnELF.TryLoad: {filePath} is not an ELF binary"); + return false; + } + + IELF elf = ELFReader.Load (stream, shouldOwnStream: false); + + if (elf.Type != FileType.SharedObject) { + Log.Warning ($"AnELF.TryLoad: {filePath} is not a shared library"); + return false; + } + + if (elf.Endianess != Endianess.LittleEndian) { + Log.Warning ($"AnELF.TryLoad: {filePath} is not a little-endian binary"); + return false; + } + + bool is64; + switch (elf.Machine) { + case Machine.ARM: + case Machine.Intel386: + is64 = false; + + break; + + case Machine.AArch64: + case Machine.AMD64: + is64 = true; + + break; + + default: + Log.Warning ($"{filePath} is for an unsupported machine type {elf.Machine}"); + return false; + } + + ISymbolTable? symtab = GetSymbolTable (elf, DynsymSectionName); + if (symtab == null) { + Log.Warning ($"{filePath} does not contain dynamic symbol section '{DynsymSectionName}'"); + return false; + } + ISymbolTable dynsym = symtab; + + ISection? sec = GetSection (elf, RodataSectionName); + if (sec == null) { + Log.Warning ("${filePath} does not contain read-only data section ('{RodataSectionName}')"); + return false; + } + ISection rodata = sec; + + ISymbolTable? sym = GetSymbolTable (elf, SymtabSectionName); + + if (is64) { + anElf = new ELF64 (stream, filePath, elf, dynsym, rodata, sym); + } else { + anElf = new ELF32 (stream, filePath, elf, dynsym, rodata, sym); + } + + Log.Debug ($"AnELF.TryLoad: {filePath} is a {anElf.Bitness}-bit ELF binary ({elf.Machine})"); + return true; + } + + protected static ISymbolTable? GetSymbolTable (IELF elf, string sectionName) + { + ISection? section = GetSection (elf, sectionName); + if (section == null) { + return null; + } + + var symtab = section as ISymbolTable; + if (symtab == null) { + return null; + } + + return symtab; + } + + protected static ISection? GetSection (IELF elf, string sectionName) + { + if (!elf.TryGetSection (sectionName, out ISection section)) { + return null; + } + + return section; + } +} diff --git a/tools/apput/src/Native/ELF32.cs b/tools/apput/src/Native/ELF32.cs new file mode 100644 index 00000000000..03a0d921f52 --- /dev/null +++ b/tools/apput/src/Native/ELF32.cs @@ -0,0 +1,91 @@ +using System; +using System.IO; + +using ELFSharp.ELF; +using ELFSharp.ELF.Sections; + +namespace ApplicationUtility; + +class ELF32 : AnELF +{ + public override bool Is64Bit => false; + public override string Bitness => "32"; + + SymbolTable DynamicSymbols => (SymbolTable)DynSymSection; + SymbolTable? Symbols => (SymbolTable?)SymSection; + Section Rodata => (Section)RodataSection; + ELF ELF => (ELF)AnyELF; + + public ELF32 (Stream stream, string filePath, IELF elf, ISymbolTable dynsymSection, ISection rodataSection, ISymbolTable? symSection) + : base (stream, filePath, elf, dynsymSection, rodataSection, symSection) + {} + + public override string GetStringFromPointerField(ISymbolEntry symbolEntry, ulong pointerFieldOffset) + { + throw new NotImplementedException(); + } + + public override byte[] GetData (ulong symbolValue, ulong size = 0) + { + checked { + return GetData ((uint)symbolValue, size); + } + } + + byte[] GetData (uint symbolValue, ulong size) + { + Log.Debug ($"ELF64.GetData: Looking for symbol value {symbolValue:X08}"); + + SymbolEntry? symbol = GetSymbol (DynamicSymbols, symbolValue); + if (symbol == null && Symbols != null) { + symbol = GetSymbol (Symbols, symbolValue); + } + + if (symbol != null) { + Log.Debug ($"ELF64.GetData: found in section {symbol.PointedSection.Name}"); + return GetData (symbol); + } + + Section section = FindSectionForValue (symbolValue); + + Log.Debug ($"ELF64.GetData: found in section {section} {section.Name}"); + return GetData (section, size, OffsetInSection (section, symbolValue)); + } + + protected override byte[] GetData (SymbolEntry symbol) + { + ulong offset = symbol.Value - symbol.PointedSection.LoadAddress; + return GetData (symbol, symbol.Size, offset); + } + + Section FindSectionForValue (uint symbolValue) + { + Log.Debug ($"FindSectionForValue ({symbolValue:X08})"); + int nsections = ELF.Sections.Count; + + for (int i = nsections - 1; i >= 0; i--) { + Section section = ELF.GetSection (i); + if (section.Type != SectionType.ProgBits) + continue; + + if (SectionInRange (section, symbolValue)) + return section; + } + + throw new InvalidOperationException ($"Section matching symbol value {symbolValue:X08} cannot be found"); + } + + bool SectionInRange (Section section, uint symbolValue) + { + Log.Debug ($"SectionInRange ({section.Name}, {symbolValue:X08})"); + Log.Debug ($" address == {section.LoadAddress:X08}; size == {section.Size}; last address = {section.LoadAddress + section.Size:X08}"); + Log.Debug ($" symbolValue >= section.LoadAddress? {symbolValue >= section.LoadAddress}"); + Log.Debug ($" (section.LoadAddress + section.Size) >= symbolValue? {(section.LoadAddress + section.Size) >= symbolValue}"); + return symbolValue >= section.LoadAddress && (section.LoadAddress + section.Size) >= symbolValue; + } + + ulong OffsetInSection (Section section, uint symbolValue) + { + return symbolValue - section.LoadAddress; + } +} diff --git a/tools/apput/src/Native/ELF64.cs b/tools/apput/src/Native/ELF64.cs new file mode 100644 index 00000000000..67ba5193c71 --- /dev/null +++ b/tools/apput/src/Native/ELF64.cs @@ -0,0 +1,206 @@ +using System; +using System.IO; + +using ELFSharp.ELF; +using ELFSharp.ELF.Sections; + +namespace ApplicationUtility; + +class ELF64 : AnELF +{ + public override bool Is64Bit => true; + public override string Bitness => "64"; + + SymbolTable DynamicSymbols => (SymbolTable)DynSymSection; + SymbolTable? Symbols => (SymbolTable?)SymSection; + Section Rodata => (Section)RodataSection; + ELF ELF => (ELF)AnyELF; + + public ELF64 (Stream stream, string filePath, IELF elf, ISymbolTable dynsymSection, ISection rodataSection, ISymbolTable? symSection) + : base (stream, filePath, elf, dynsymSection, rodataSection, symSection) + {} + + public override string? GetStringFromPointerField (ISymbolEntry symbolEntry, ulong pointerFieldOffset) + { + var symbol = symbolEntry as SymbolEntry; + if (symbol == null) { + throw new InvalidOperationException ($"Expected a 64-bit symbol entry, got {symbolEntry}"); + } + + switch (ELF.Machine) { + case Machine.AArch64: + return GetStringFromPointerField_ARM64 (symbol, pointerFieldOffset); + + case Machine.AMD64: + return GetStringFromPointerField_X64 (symbol, pointerFieldOffset); + + default: + throw new InvalidOperationException ($"Unsupported ELF machine type '{ELF.Machine}'"); + } + } + + string? GetStringFromPointerField_ARM64 (SymbolEntry symbolEntry, ulong pointerFieldOffset) + { + return GetStringFromPointerField_Common ( + symbolEntry, + pointerFieldOffset, + (ELF64_Rela rela) => { + // We only support R_AARCH64_RELATIVE right now + return (RelocationTypeARM64)rela.r_info == RelocationTypeARM64.R_AARCH64_RELATIVE; + } + ); + } + + string? GetStringFromPointerField_X64 (SymbolEntry symbolEntry, ulong pointerFieldOffset) + { + return GetStringFromPointerField_Common ( + symbolEntry, + pointerFieldOffset, + (ELF64_Rela rela) => { + // We only support R_X86_64_RELATIVE right now + return (RelocationTypeX64)rela.r_info == RelocationTypeX64.R_X86_64_RELATIVE; + } + ); + } + + string? GetStringFromPointerField_Common (SymbolEntry symbolEntry, ulong pointerFieldOffset, Func validRelocation) + { + Log.Debug ($"[ARM64] Getting string from a pointer field in symbol '{symbolEntry.Name}', at offset {pointerFieldOffset} into the structure"); + + if (symbolEntry.PointedSection.Type != SectionType.ProgBits || !symbolEntry.PointedSection.Flags.HasFlag (SectionFlags.Writable)) { + Log.Debug (" Symbol section isn't a writable data one, pointers require a writable section to apply relocations"); + Log.Debug ($" Section info: {symbolEntry.PointedSection}"); + return null; + } + + // Steps: + // + // 1. Calculate address of the field in the symbol data: [symbol section virtual address] + [symbol offset into section] + pointerFieldOffset + // ELFSharp does part of the job for us - symbol's value is its virtual address + ulong pointerVA = symbolEntry.Value + pointerFieldOffset; + Log.Debug ($" Section address == 0x{symbolEntry.PointedSection.LoadAddress:x}; offset == 0x{symbolEntry.PointedSection.Offset:x}"); + Log.Debug ($" Symbol entry value == 0x{symbolEntry.Value:x}"); + Log.Debug ($" Virtual address of the pointer: 0x{pointerVA:x} ({pointerVA})"); + + // 2. Find the .rela.dyn section + const string RelaDynSectionName = ".rela.dyn"; + Section? relaDynSection = ELF.GetSection (RelaDynSectionName); + Log.Debug ($" Relocation section: {Utilities.ToStringOrNull (relaDynSection)}"); + if (relaDynSection == null) { + Log.Debug ($" Section '{RelaDynSectionName}' not found"); + return null; + } + + // Make sure section type is what we need and expect + if (relaDynSection.Type != SectionType.RelocationAddends) { + Log.Debug ($" Section '{RelaDynSectionName}' has invalid type. Expected {SectionType.RelocationAddends}, got {relaDynSection.Type}"); + return null; + } + var relocationReader = new RelocationSectionAddend64 (relaDynSection); + + // 3. Find relocation entry with offset matching the address calculated in 1. Relocation entry should have code 0x403 (1027) - R_AARCH64_RELATIVE + if (!relocationReader.Entries.TryGetValue (pointerVA, out ELF64_Rela? relocation) || relocation == null) { + Log.Debug ($" Relocation for pointer address 0x{pointerVA:x} not found"); + return null; + } + Log.Debug ($" Found relocation: {relocation}"); + + if (!validRelocation (relocation)) { + // Yell, so that we can fix it + throw new NotSupportedException ($"AArch64 relocation type {relocation.r_info} not supported. Please report at https://github.com/xamarin/xamarin.android/issues/"); + } + + // 4. Read relocation entry (see elf(5) for Elf32_Rela and Elf64_Rela structures) and get the addend value + ulong addend = (ulong)relocation.r_addend; + + // 5. Find section the addend from 4. falls within + Section? pointeeSection = FindSectionForValue (addend); + if (pointeeSection == null) { + Log.Debug ($" Unable to find section in which pointee 0x{addend:x} resides"); + return null; + } + Log.Debug ($" Pointee 0x{addend:x} falls within section {pointeeSection}"); + + // 6. Read that section data + byte[] data = pointeeSection.GetContents (); + + // 7. Subtract section address from the addend, this will give offset into the section + ulong addendSectionOffset = addend - pointeeSection.LoadAddress; + Log.Debug ($" Pointee offset into section data == 0x{addendSectionOffset:x} ({addendSectionOffset})"); + + // 8. Read ASCIIZ data from the offset obtained in 7. + return GetASCIIZ (data, addendSectionOffset); + } + + public override byte[] GetData (ulong symbolValue, ulong size = 0) + { + Log.Debug ($"ELF64.GetData: Looking for symbol value {symbolValue:X08}"); + + SymbolEntry? symbol = GetSymbol (DynamicSymbols, symbolValue); + if (symbol == null && Symbols != null) { + symbol = GetSymbol (Symbols, symbolValue); + } + + if (symbol != null) { + Log.Debug ($"ELF64.GetData: found in section {symbol.PointedSection.Name}"); + if (symbol.Size == 0) { + return EmptyArray; + } + + return GetData (symbol); + } + + Section section = FindProgBitsSectionForValue (symbolValue); + + Log.Debug ($"ELF64.GetData: found in section {section} {section.Name}"); + return GetData (section, size, OffsetInSection (section, symbolValue)); + } + + protected override byte[] GetData (SymbolEntry symbol) + { + if (symbol.Size == 0) { + return EmptyArray; + } + + return GetData (symbol, symbol.Size, OffsetInSection (symbol.PointedSection, symbol.Value)); + } + + Section FindProgBitsSectionForValue (ulong symbolValue) + { + return FindSectionForValue (symbolValue, SectionType.ProgBits) ?? throw new InvalidOperationException ($"Section matching symbol value {symbolValue:X08} cannot be found"); + } + + Section? FindSectionForValue (ulong symbolValue, SectionType requiredType = SectionType.Null) + { + Log.Debug ($"FindSectionForValue ({symbolValue:X08}, {requiredType})"); + int nsections = ELF.Sections.Count; + + for (int i = nsections - 1; i >= 0; i--) { + Section section = ELF.GetSection (i); + if (requiredType != SectionType.Null && section.Type != requiredType) { + continue; + } + + if (SectionInRange (section, symbolValue)) { + return section; + } + } + + Log.Debug ($"Section matching symbol value {symbolValue:X08} cannot be found"); + return null; + } + + bool SectionInRange (Section section, ulong symbolValue) + { + Log.Debug ($"SectionInRange ({section.Name}, {symbolValue:X08})"); + Log.Debug ($" address == {section.LoadAddress:X08}; size == {section.Size}; last address = {section.LoadAddress + section.Size:X08}"); + Log.Debug ($" symbolValue >= section.LoadAddress? {symbolValue >= section.LoadAddress}"); + Log.Debug ($" (section.LoadAddress + section.Size) >= symbolValue? {(section.LoadAddress + section.Size) >= symbolValue}"); + return symbolValue >= section.LoadAddress && (section.LoadAddress + section.Size) >= symbolValue; + } + + ulong OffsetInSection (Section section, ulong symbolValue) + { + return symbolValue - section.LoadAddress; + } +} diff --git a/tools/apput/src/Native/ELF_RelocationWithAddend.cs b/tools/apput/src/Native/ELF_RelocationWithAddend.cs new file mode 100644 index 00000000000..d50c28a2d69 --- /dev/null +++ b/tools/apput/src/Native/ELF_RelocationWithAddend.cs @@ -0,0 +1,52 @@ +using System; +using System.IO; + +namespace ApplicationUtility; + +abstract class ELF_Rela +{ + protected abstract long StructureSize { get; } + + public readonly TUnsigned r_offset; + public readonly TUnsigned r_info; + public readonly TSigned r_addend; + + protected ELF_Rela (BinaryReader reader, ulong offsetIntoData) + { + if (reader.BaseStream.Length < (long)offsetIntoData + StructureSize) { + throw new ArgumentOutOfRangeException ("Data array too short"); + } + ReadData (reader, out r_offset, out r_info, out r_addend); + } + + protected abstract void ReadData (BinaryReader reader, out TUnsigned offset, out TUnsigned info, out TSigned addend); + + public override string ToString() + { + return $"{GetType ()}: r_offset == 0x{r_offset:x} ({r_offset}); r_info == 0x{r_info:x} ({r_info}); r_addend == 0x{r_addend:x} ({r_addend})"; + } +} + +// Corresponds to Elf64_Rela structure from ELF documentation: +// +// typedef struct { +// Elf64_Addr r_offset; +// uint64_t r_info; +// int64_t r_addend; +// } Elf64_Rela; +// +sealed class ELF64_Rela : ELF_Rela +{ + protected override long StructureSize => 3 * sizeof (ulong); + + public ELF64_Rela (BinaryReader data, ulong offsetIntoData) + : base (data, offsetIntoData) + {} + + protected override void ReadData (BinaryReader reader, out ulong offset, out ulong info, out long addend) + { + offset = reader.ReadUInt64 (); + info = reader.ReadUInt64 (); + addend = reader.ReadInt64 (); + } +} diff --git a/tools/apput/src/Native/LibXamarinApp.cs b/tools/apput/src/Native/LibXamarinApp.cs new file mode 100644 index 00000000000..572d07d4ce2 --- /dev/null +++ b/tools/apput/src/Native/LibXamarinApp.cs @@ -0,0 +1,38 @@ +using System; +using System.IO; + +namespace ApplicationUtility; + +// TODO: make it an abstract class, we need to support different formats +class LibXamarinApp : SharedLibrary, IAspect +{ + LibXamarinApp (Stream stream, string description) + : base (stream, description) + {} + + public static new IAspect LoadAspect (Stream stream, IAspectState state, string? description) + { + if (String.IsNullOrEmpty (description)) { + throw new ArgumentException ("Must be a shared library name", nameof (description)); + } + + if (!IsSupportedELFSharedLibrary (stream, description)) { + throw new InvalidOperationException ("Stream is not a supported ELF shared library"); + } + + // TODO: this needs to be versioned + return new LibXamarinApp (stream, description); + } + + public static new IAspectState ProbeAspect (Stream stream, string? description) + { + IAspectState sharedLibState = SharedLibrary.ProbeAspect (stream, description); + if (!sharedLibState.Success) { + return sharedLibState; + } + + // TODO: check for presence of a handful of fields and read at least `format_tag` to determine + // format version. + throw new NotImplementedException (); + } +} diff --git a/tools/apput/src/Native/NativeAppInfo.cs b/tools/apput/src/Native/NativeAppInfo.cs new file mode 100644 index 00000000000..7f026d8ecc5 --- /dev/null +++ b/tools/apput/src/Native/NativeAppInfo.cs @@ -0,0 +1,8 @@ +namespace ApplicationUtility; + +public class NativeAppInfo +{ + internal NativeAppInfo (LibXamarinApp xamarinAppLibrary) + { + } +} diff --git a/tools/apput/src/Native/NativeUtils.cs b/tools/apput/src/Native/NativeUtils.cs new file mode 100644 index 00000000000..4c0648b0345 --- /dev/null +++ b/tools/apput/src/Native/NativeUtils.cs @@ -0,0 +1,72 @@ +using System; + +namespace ApplicationUtility; + +class NativeUtils +{ + static ulong GetPadding (ulong sizeSoFar, bool is64Bit, out ulong typeSize) + { + typeSize = GetNativeTypeSize (is64Bit); + if (typeSize == 1) { + return 0; + } + + ulong modulo; + if (is64Bit) { + modulo = typeSize < 8 ? 4u : 8u; + } else { + modulo = 4u; + } + + ulong alignment = sizeSoFar % modulo; + if (alignment == 0) { + return 0; + } + + return modulo - alignment; + } + + public static ulong GetPadding (ulong sizeSoFar, bool is64Bit) + { + return GetPadding (sizeSoFar, is64Bit, out ulong _); + } + + public static ulong GetPaddedSize (ulong sizeSoFar, bool is64Bit) + { + ulong padding = GetPadding (sizeSoFar, is64Bit, out ulong typeSize); + + if (padding == 0) { + return typeSize; + } + + return typeSize + padding; + } + + public static ulong GetNativeTypeSize (bool is64Bit) + { + Type type = typeof(S); + + if (type == typeof(string) || type == typeof(IntPtr)) { + // We treat `string` as a generic pointer + return is64Bit ? 8u : 4u; + } + + if (type == typeof(byte)) { + return 1u; + } + + if (type == typeof(bool)) { + return 1u; + } + + if (type == typeof(Int32) || type == typeof(UInt32)) { + return 4u; + } + + if (type == typeof(Int64) || type == typeof(UInt64)) { + return 8u; + } + + throw new InvalidOperationException ($"Unable to map managed type {type} to native assembler type"); + } +} diff --git a/tools/apput/src/Native/RelocationSection.cs b/tools/apput/src/Native/RelocationSection.cs new file mode 100644 index 00000000000..f496639057d --- /dev/null +++ b/tools/apput/src/Native/RelocationSection.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; +using System.IO; + +using ELFSharp.ELF.Sections; + +namespace ApplicationUtility; + +abstract class RelocationSectionAddend + where TUnsigned: notnull + where TRela: notnull, ELF_Rela +{ + public abstract Dictionary Entries { get; } +} + +class RelocationSectionAddend64 : RelocationSectionAddend +{ + public override Dictionary Entries { get; } = new Dictionary (); + + public RelocationSectionAddend64 (Section relaDynSection) + { + byte[] data = relaDynSection.GetContents (); + using var stream = new MemoryStream (data); + using var reader = new BinaryReader (stream); + + while (stream.Position < stream.Length) { + var entry = new ELF64_Rela (reader, (ulong)stream.Position); + Entries.Add (entry.r_offset, entry); + } + } +} diff --git a/tools/apput/src/Native/RelocationTypes.cs b/tools/apput/src/Native/RelocationTypes.cs new file mode 100644 index 00000000000..9323c076f46 --- /dev/null +++ b/tools/apput/src/Native/RelocationTypes.cs @@ -0,0 +1,118 @@ +namespace ApplicationUtility; + +enum RelocationTypeARM64 +{ + R_AARCH64_TLSGD_MOVW_G1 = 515, // GOT-rel. MOV{N,Z} 31:16. + R_AARCH64_TLSGD_MOVW_G0_NC = 516, // GOT-rel. MOVK imm. 15:0. + R_AARCH64_TLSLD_ADR_PREL21 = 517, // Like 512; local dynamic model. + R_AARCH64_TLSLD_ADR_PAGE21 = 518, // Like 513; local dynamic model. + R_AARCH64_TLSLD_ADD_LO12_NC = 519, // Like 514; local dynamic model. + R_AARCH64_TLSLD_MOVW_G1 = 520, // Like 515; local dynamic model. + R_AARCH64_TLSLD_MOVW_G0_NC = 521, // Like 516; local dynamic model. + R_AARCH64_TLSLD_LD_PREL19 = 522, // TLS PC-rel. load imm. 20:2. + R_AARCH64_TLSLD_MOVW_DTPREL_G2 = 523, // TLS DTP-rel. MOV{N,Z} 47:32. + R_AARCH64_TLSLD_MOVW_DTPREL_G1 = 524, // TLS DTP-rel. MOV{N,Z} 31:16. + R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC = 525, // Likewise; MOVK; no check. + R_AARCH64_TLSLD_MOVW_DTPREL_G0 = 526, // TLS DTP-rel. MOV{N,Z} 15:0. + R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC = 527, // Likewise; MOVK; no check. + R_AARCH64_TLSLD_ADD_DTPREL_HI12 = 528, // DTP-rel. ADD imm. from 23:12. + R_AARCH64_TLSLD_ADD_DTPREL_LO12 = 529, // DTP-rel. ADD imm. from 11:0. + R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC = 530, // Likewise; no ovfl. check. + R_AARCH64_TLSLD_LDST8_DTPREL_LO12 = 531, // DTP-rel. LD/ST imm. 11:0. + R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC = 532, // Likewise; no check. + R_AARCH64_TLSLD_LDST16_DTPREL_LO12 = 533, // DTP-rel. LD/ST imm. 11:1. + R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC = 534, // Likewise; no check. + R_AARCH64_TLSLD_LDST32_DTPREL_LO12 = 535, // DTP-rel. LD/ST imm. 11:2. + R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC = 536, // Likewise; no check. + R_AARCH64_TLSLD_LDST64_DTPREL_LO12 = 537, // DTP-rel. LD/ST imm. 11:3. + R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC = 538, // Likewise; no check. + R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 = 539, // GOT-rel. MOV{N,Z} 31:16. + R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC = 540, // GOT-rel. MOVK 15:0. + R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 = 541, // Page-rel. ADRP 32:12. + R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC = 542, // Direct LD off. 11:3. + R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 = 543, // PC-rel. load imm. 20:2. + R_AARCH64_TLSLE_MOVW_TPREL_G2 = 544, // TLS TP-rel. MOV{N,Z} 47:32. + R_AARCH64_TLSLE_MOVW_TPREL_G1 = 545, // TLS TP-rel. MOV{N,Z} 31:16. + R_AARCH64_TLSLE_MOVW_TPREL_G1_NC = 546, // Likewise; MOVK; no check. + R_AARCH64_TLSLE_MOVW_TPREL_G0 = 547, // TLS TP-rel. MOV{N,Z} 15:0. + R_AARCH64_TLSLE_MOVW_TPREL_G0_NC = 548, // Likewise; MOVK; no check. + R_AARCH64_TLSLE_ADD_TPREL_HI12 = 549, // TP-rel. ADD imm. 23:12. + R_AARCH64_TLSLE_ADD_TPREL_LO12 = 550, // TP-rel. ADD imm. 11:0. + R_AARCH64_TLSLE_ADD_TPREL_LO12_NC = 551, // Likewise; no ovfl. check. + R_AARCH64_TLSLE_LDST8_TPREL_LO12 = 552, // TP-rel. LD/ST off. 11:0. + R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC = 553, // Likewise; no ovfl. check. + R_AARCH64_TLSLE_LDST16_TPREL_LO12 = 554, // TP-rel. LD/ST off. 11:1. + R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC = 555, // Likewise; no check. + R_AARCH64_TLSLE_LDST32_TPREL_LO12 = 556, // TP-rel. LD/ST off. 11:2. + R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC = 557, // Likewise; no check. + R_AARCH64_TLSLE_LDST64_TPREL_LO12 = 558, // TP-rel. LD/ST off. 11:3. + R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC = 559, // Likewise; no check. + R_AARCH64_TLSDESC_LD_PREL19 = 560, // PC-rel. load immediate 20:2. + R_AARCH64_TLSDESC_ADR_PREL21 = 561, // PC-rel. ADR immediate 20:0. + R_AARCH64_TLSDESC_ADR_PAGE21 = 562, // Page-rel. ADRP imm. 32:12. + R_AARCH64_TLSDESC_LD64_LO12 = 563, // Direct LD off. from 11:3. + R_AARCH64_TLSDESC_ADD_LO12 = 564, // Direct ADD imm. from 11:0. + R_AARCH64_TLSDESC_OFF_G1 = 565, // GOT-rel. MOV{N,Z} imm. 31:16. + R_AARCH64_TLSDESC_OFF_G0_NC = 566, // GOT-rel. MOVK imm. 15:0; no ck. + R_AARCH64_TLSDESC_LDR = 567, // Relax LDR. + R_AARCH64_TLSDESC_ADD = 568, // Relax ADD. + R_AARCH64_TLSDESC_CALL = 569, // Relax BLR. + R_AARCH64_TLSLE_LDST128_TPREL_LO12 = 570, // TP-rel. LD/ST off. 11:4. + R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC = 571, // Likewise; no check. + R_AARCH64_TLSLD_LDST128_DTPREL_LO12 = 572, // DTP-rel. LD/ST imm. 11:4. + R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC = 573, // Likewise; no check. + R_AARCH64_COPY = 1024, // Copy symbol at runtime. + R_AARCH64_GLOB_DAT = 1025, // Create GOT entry. + R_AARCH64_JUMP_SLOT = 1026, // Create PLT entry. + R_AARCH64_RELATIVE = 1027, // Adjust by program base. + R_AARCH64_TLS_DTPMOD = 1028, // Module number, 64 bit. + R_AARCH64_TLS_DTPREL = 1029, // Module-relative offset, 64 bit. + R_AARCH64_TLS_TPREL = 1030, // TP-relative offset, 64 bit. + R_AARCH64_TLSDESC = 1031, // TLS Descriptor. + R_AARCH64_IRELATIVE = 1032, // STT_GNU_IFUNC relocation. +} + +enum RelocationTypeX64 +{ + R_X86_64_NONE = 0, // No reloc + R_X86_64_64 = 1, // Direct 64 bit + R_X86_64_PC32 = 2, // PC relative 32 bit signed + R_X86_64_GOT32 = 3, // 32 bit GOT entry + R_X86_64_PLT32 = 4, // 32 bit PLT address + R_X86_64_COPY = 5, // Copy symbol at runtime + R_X86_64_GLOB_DAT = 6, // Create GOT entry + R_X86_64_JUMP_SLOT = 7, // Create PLT entry + R_X86_64_RELATIVE = 8, // Adjust by program base + R_X86_64_GOTPCREL = 9, // 32 bit signed PC relative offset to GOT + R_X86_64_32 = 10, // Direct 32 bit zero extended + R_X86_64_32S = 11, // Direct 32 bit sign extended + R_X86_64_16 = 12, // Direct 16 bit zero extended + R_X86_64_PC16 = 13, // 16 bit sign extended pc relative + R_X86_64_8 = 14, // Direct 8 bit sign extended + R_X86_64_PC8 = 15, // 8 bit sign extended pc relative + R_X86_64_DTPMOD64 = 16, // ID of module containing symbol + R_X86_64_DTPOFF64 = 17, // Offset in module's TLS block + R_X86_64_TPOFF64 = 18, // Offset in initial TLS block + R_X86_64_TLSGD = 19, // 32 bit signed PC relative offset to two GOT entries for GD symbol + R_X86_64_TLSLD = 20, // 32 bit signed PC relative offset to two GOT entries for LD symbol + R_X86_64_DTPOFF32 = 21, // Offset in TLS block + R_X86_64_GOTTPOFF = 22, // 32 bit signed PC relative offset to GOT entry for IE symbol + R_X86_64_TPOFF32 = 23, // Offset in initial TLS block + R_X86_64_PC64 = 24, // PC relative 64 bit + R_X86_64_GOTOFF64 = 25, // 64 bit offset to GOT + R_X86_64_GOTPC32 = 26, // 32 bit signed pc relative offset to GOT + R_X86_64_GOT64 = 27, // 64-bit GOT entry offset + R_X86_64_GOTPCREL64 = 28, // 64-bit PC relative offset to GOT entry + R_X86_64_GOTPC64 = 29, // 64-bit PC relative offset to GOT + R_X86_64_GOTPLT64 = 30, // like GOT64, says PLT entry needed + R_X86_64_PLTOFF64 = 31, // 64-bit GOT relative offset to PLT entry + R_X86_64_SIZE32 = 32, // Size of symbol plus 32-bit addend + R_X86_64_SIZE64 = 33, // Size of symbol plus 64-bit addend + R_X86_64_GOTPC32_TLSDESC = 34, // GOT offset for TLS descriptor. + R_X86_64_TLSDESC_CALL = 35, // Marker for call through TLS descriptor. + R_X86_64_TLSDESC = 36, // TLS descriptor. + R_X86_64_IRELATIVE = 37, // Adjust indirectly by program base + R_X86_64_RELATIVE64 = 38, // 64-bit adjust by program base + R_X86_64_GOTPCRELX = 41, // Load from 32 bit signed pc relative offset to GOT entry without REX prefix, relaxable. + R_X86_64_REX_GOTPCRELX = 42, // Load from 32 bit signed pc relative offset to GOT entry with REX prefix, relaxable. +} diff --git a/tools/apput/src/Native/SharedLibrary.cs b/tools/apput/src/Native/SharedLibrary.cs index 64ba7490ad2..b85be5b4955 100644 --- a/tools/apput/src/Native/SharedLibrary.cs +++ b/tools/apput/src/Native/SharedLibrary.cs @@ -7,7 +7,7 @@ using ApplicationUtility; -public class SharedLibrary : IAspect, IDisposable +class SharedLibrary : IAspect, IDisposable { const uint ELF_MAGIC = 0x464c457f; @@ -24,7 +24,7 @@ public class SharedLibrary : IAspect, IDisposable IELF elf; bool disposed; - SharedLibrary (Stream stream, string libraryName) + protected SharedLibrary (Stream stream, string libraryName) { this.libraryStream = stream; this.libraryName = libraryName; @@ -80,7 +80,7 @@ public Stream OpenAndroidPayload () return new SubStream (libraryStream, (long)payloadOffset, (long)payloadSize); } - static bool IsSupportedELFSharedLibrary (Stream stream, string? description) + protected static bool IsSupportedELFSharedLibrary (Stream stream, string? description) { if (stream.Length < 4) { // Less than that and we know there isn't room for ELF magic Log.Debug ($"SharedLibrary: stream ('{description}') is too short to be an ELF image."); diff --git a/tools/apput/src/Package/ApplicationPackage.cs b/tools/apput/src/Package/ApplicationPackage.cs index f3de6bdc38f..20d8edfb2b3 100644 --- a/tools/apput/src/Package/ApplicationPackage.cs +++ b/tools/apput/src/Package/ApplicationPackage.cs @@ -49,6 +49,7 @@ public abstract class ApplicationPackage : IAspect public string MainActivity { get; protected set; } = ""; public List? AssemblyStores { get; protected set; } public List Architectures { get; protected set; } = new (); + public List NativeAppInfos { get; protected set; } = new (); AndroidManifest? manifest; @@ -85,6 +86,7 @@ public static IAspect LoadAspect (Stream stream, IAspectState state, string? des ret.TryDetectWhetherIsSigned (); ret.TryLoadAssemblyStores (); ret.TryLoadAndroidManifest (); + ret.TryLoadXamarinAppLibraries (); return ret; } @@ -140,6 +142,41 @@ void TryDetectRuntime () // some public symbols to verify that. } + void TryLoadXamarinAppLibraries () + { + foreach (AndroidTargetArch arch in Architectures) { + string libPath = GetNativeLibFile (arch, "libxamarin-app.so"); + LibXamarinApp? lib = TryLoadLibXamarinApp (libPath); + if (lib == null) { + continue; + } + NativeAppInfos.Add (new NativeAppInfo (lib)); + } + } + + LibXamarinApp? TryLoadLibXamarinApp (string libPath) + { + Stream? libStream = TryGetEntryStream (libPath); + if (libStream == null) { + return null; + } + + string fullLibPath = $"{Description}@!{libPath}"; + try { + IAspectState state = LibXamarinApp.ProbeAspect (libStream, fullLibPath); + if (!state.Success) { + Log.Debug ($"Assembly store '{libPath}' is not in a supported format"); + libStream.Close (); + return null; + } + + return (LibXamarinApp)LibXamarinApp.LoadAspect (libStream, state, fullLibPath); + } catch (Exception ex) { + Log.Debug ($"Failed to load Xamarin app library '{libPath}'. Exception thrown:", ex); + return null; + } + } + void TryDetectWhetherIsSigned () { Signed = HasAnyEntries (Zip, KnownSignatureEntries); From 01bb148e87325e13ac9791fb9f54d6abb02dcfdb Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 22 Sep 2025 15:56:01 +0200 Subject: [PATCH 13/32] NativeAOT detection support --- tools/apput/src/Native/SharedLibrary.cs | 17 +++ tools/apput/src/Package/ApplicationPackage.cs | 102 ++++++++++++++++-- tools/apput/src/Package/ApplicationRuntime.cs | 1 + 3 files changed, 114 insertions(+), 6 deletions(-) diff --git a/tools/apput/src/Native/SharedLibrary.cs b/tools/apput/src/Native/SharedLibrary.cs index b85be5b4955..b956f3373f8 100644 --- a/tools/apput/src/Native/SharedLibrary.cs +++ b/tools/apput/src/Native/SharedLibrary.cs @@ -185,6 +185,23 @@ protected static bool IsSupportedELFSharedLibrary (Stream stream, string? descri } } + public bool HasSection (string name, SectionType type = SectionType.Null) + { + Log.Debug ($"Checking for section '{name}' with type {type} in library '{libraryName}'"); + if (!elf.TryGetSection (name, out ISection? section)) { + Log.Debug ("Section not found"); + return false; + } + + if (type == SectionType.Null) { + Log.Debug ("Section present, type check not requested"); + return true; + } + + Log.Debug ($"Section present, type {section.Type}"); + return section.Type == type; + } + protected virtual void Dispose (bool disposing) { if (disposed) { diff --git a/tools/apput/src/Package/ApplicationPackage.cs b/tools/apput/src/Package/ApplicationPackage.cs index 20d8edfb2b3..e0a86acc51a 100644 --- a/tools/apput/src/Package/ApplicationPackage.cs +++ b/tools/apput/src/Package/ApplicationPackage.cs @@ -4,6 +4,7 @@ using System.IO.Compression; using System.Linq; +using ELFSharp.ELF.Sections; using Xamarin.Android.Tasks; using Xamarin.Android.Tools; @@ -32,6 +33,14 @@ public abstract class ApplicationPackage : IAspect "META-INF/ANDROIDD.RSA", }; + readonly static List<(string sectionName, SectionType type)> NativeAotSections = new () { + ("__managedcode", SectionType.ProgBits), + (".dotnet_eh_table", SectionType.ProgBits), + ("__unbox", SectionType.ProgBits), + ("__modules", SectionType.ProgBits), + (".hydrated", SectionType.NoBits), + }; + public static string AspectName { get; } = "Application package"; public abstract string PackageFormat { get; } @@ -112,6 +121,19 @@ void TryDetectArchitectures () void TryDetectRuntime () { + try { + Runtime = GetRuntimeMaybe (); + } catch (Exception ex) { + Log.Debug ("Exception caught while detecting runtime.", ex); + Runtime = ApplicationRuntime.Unknown; + } + + Log.Debug ($"Detected runtime: {Runtime}"); + } + + ApplicationRuntime GetRuntimeMaybe () + { + Log.Debug ("Trying to detect runtime"); ApplicationRuntime runtime = ApplicationRuntime.Unknown; string runtimePath; foreach (AndroidTargetArch arch in Architectures) { @@ -129,17 +151,85 @@ void TryDetectRuntime () } if (runtime != ApplicationRuntime.Unknown || Architectures.Count == 0) { - Log.Debug ($"Detected runtime: {runtime}"); - return; + return runtime; } runtimePath = GetNativeLibFile (Architectures[0], "libmonodroid.so"); - if (!HasEntry (Zip, runtimePath)) { - return; + if (HasEntry (Zip, runtimePath)) { + Log.Debug ("Unknown runtime. libmonodroid.so present but no CoreCLR or MonoVM libraries found."); + return ApplicationRuntime.Unknown; + } + + // TODO: it might be statically linked CoreCLR runtime or a NativeAOT application. + // Need to check for presence of some public symbols to verify that. + if (TryDetectNativeAotRuntime ()) { + return ApplicationRuntime.NativeAOT; + } + + return ApplicationRuntime.Unknown; + } + + bool TryDetectNativeAotRuntime () + { + Log.Debug ("Probing for NativeAOT runtime"); + foreach (AndroidTargetArch arch in Architectures) { + string libDir = GetNativeLibDir (arch); + + foreach (ZipArchiveEntry? entry in Zip.Entries) { + if (entry == null) { + continue; + } + + // See if it's in the right directory... + if (!entry.FullName.StartsWith (libDir, StringComparison.Ordinal)) { + continue; + } + + // ...and that it's a shared library... + if (!entry.FullName.EndsWith (".so", StringComparison.Ordinal)) { + continue; + } + + Log.Debug ($"Considering {entry.FullName}"); + // ...and that it has NativeAOT markers + if (!SharedLibraryIsNativeAOT (entry)) { + continue; + } + + Log.Debug ("Found NativeAOT shared library"); + // Yep, got it. Just one hit is enough, no need to check all the architectures + return true; + } + } + + return false; + } + + bool SharedLibraryIsNativeAOT (ZipArchiveEntry entry) + { + Stream? stream = TryGetEntryStream (entry.FullName); + if (stream == null) { + return false; + } + + IAspectState aspectState = SharedLibrary.ProbeAspect (stream, entry.FullName); + if (!aspectState.Success) { + return false; + } + + var dso = SharedLibrary.LoadAspect (stream, aspectState, entry.FullName) as SharedLibrary; + if (dso == null) { + throw new InvalidOperationException ("Internal error: unexpected SharedLibrary load result."); + } + + // Just one match should be enough + foreach (var naotSection in NativeAotSections) { + if (dso.HasSection (naotSection.sectionName, naotSection.type)) { + return true; + } } - // TODO: it might be statically linked CoreCLR runtime. Need to check for presence of - // some public symbols to verify that. + return false; } void TryLoadXamarinAppLibraries () diff --git a/tools/apput/src/Package/ApplicationRuntime.cs b/tools/apput/src/Package/ApplicationRuntime.cs index 9efa9ff598c..fbd5b51778d 100644 --- a/tools/apput/src/Package/ApplicationRuntime.cs +++ b/tools/apput/src/Package/ApplicationRuntime.cs @@ -6,4 +6,5 @@ public enum ApplicationRuntime MonoVM, CoreCLR, StaticCoreCLR, + NativeAOT, } From d0e87346efd8f13a4a377ef50764642bfc9826a4 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 23 Sep 2025 16:41:04 +0200 Subject: [PATCH 14/32] Let's do some reporting --- .../src/Common/AspectReporterAttribute.cs | 14 +++ tools/apput/src/Detector.cs | 7 +- .../src/Native/NativeAotSharedLibrary.cs | 55 +++++++++ tools/apput/src/Native/SharedLibrary.cs | 62 +++++++---- tools/apput/src/Program.cs | 4 + tools/apput/src/Reporter.cs | 105 ++++++++++++++++++ tools/apput/src/Reporters/BaseReporter.cs | 48 ++++++++ tools/apput/src/Reporters/IReporter.cs | 6 + .../NativeAotSharedLibraryReporter.cs | 18 +++ 9 files changed, 296 insertions(+), 23 deletions(-) create mode 100644 tools/apput/src/Common/AspectReporterAttribute.cs create mode 100644 tools/apput/src/Native/NativeAotSharedLibrary.cs create mode 100644 tools/apput/src/Reporter.cs create mode 100644 tools/apput/src/Reporters/BaseReporter.cs create mode 100644 tools/apput/src/Reporters/IReporter.cs create mode 100644 tools/apput/src/Reporters/NativeAotSharedLibraryReporter.cs diff --git a/tools/apput/src/Common/AspectReporterAttribute.cs b/tools/apput/src/Common/AspectReporterAttribute.cs new file mode 100644 index 00000000000..7720308c860 --- /dev/null +++ b/tools/apput/src/Common/AspectReporterAttribute.cs @@ -0,0 +1,14 @@ +using System; + +namespace ApplicationUtility; + +[AttributeUsage (AttributeTargets.Class, Inherited = false, AllowMultiple = false)] +class AspectReporterAttribute : Attribute +{ + public Type AspectType { get; } + + public AspectReporterAttribute (Type aspectType) + { + AspectType = aspectType; + } +} diff --git a/tools/apput/src/Detector.cs b/tools/apput/src/Detector.cs index ea9ea5674e9..891534c06e5 100644 --- a/tools/apput/src/Detector.cs +++ b/tools/apput/src/Detector.cs @@ -10,12 +10,15 @@ namespace ApplicationUtility; /// detect whether or not the thing is an application aspect /// we know or we can handle. /// -class Detector +public class Detector { - readonly static List KnownTopLevelAspects = new () { + // Aspects must be listed in the order of detection, from the biggest (the most generic) to the + // smallest (the least generic) aspects. + public readonly static List KnownTopLevelAspects = new () { typeof (ApplicationPackage), typeof (AssemblyStore), typeof (ApplicationAssembly), + typeof (NativeAotSharedLibrary), typeof (SharedLibrary), }; diff --git a/tools/apput/src/Native/NativeAotSharedLibrary.cs b/tools/apput/src/Native/NativeAotSharedLibrary.cs new file mode 100644 index 00000000000..d6f0f5fa85d --- /dev/null +++ b/tools/apput/src/Native/NativeAotSharedLibrary.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.IO; +using ELFSharp.ELF; +using ELFSharp.ELF.Sections; + +namespace ApplicationUtility; + +class NativeAotSharedLibrary : SharedLibrary +{ + readonly static List<(string sectionName, SectionType type)> NativeAotSections = new () { + ("__managedcode", SectionType.ProgBits), + (".dotnet_eh_table", SectionType.ProgBits), + ("__unbox", SectionType.ProgBits), + ("__modules", SectionType.ProgBits), + (".hydrated", SectionType.NoBits), + }; + + protected NativeAotSharedLibrary (Stream stream, string libraryName) + : base (stream, libraryName) + { + // TODO: perhaps gather some more stats? Code size, data size, alignment, stuff like that + } + + public new static IAspect LoadAspect (Stream stream, IAspectState? state, string? description) + { + if (String.IsNullOrEmpty (description)) { + throw new ArgumentException ("Must be a shared library name", nameof (description)); + } + + if (!IsNativeAotSharedLibrary (stream, description)) { + throw new InvalidOperationException ("Stream is not a supported NativeAOT shared library"); + } + + return new NativeAotSharedLibrary (stream, description); + } + + public new static IAspectState ProbeAspect (Stream stream, string? description) => new BasicAspectState (IsNativeAotSharedLibrary (stream, description)); + + static bool IsNativeAotSharedLibrary (Stream stream, string description) + { + if (!IsSupportedELFSharedLibrary (stream, description, out IELF? elf) || elf == null) { + return false; + } + + // Just one match should be enough + foreach (var naotSection in NativeAotSections) { + if (HasSection (elf, description, naotSection.sectionName, naotSection.type)) { + return true; + } + } + + return false; + } +} diff --git a/tools/apput/src/Native/SharedLibrary.cs b/tools/apput/src/Native/SharedLibrary.cs index b956f3373f8..9fe6900f684 100644 --- a/tools/apput/src/Native/SharedLibrary.cs +++ b/tools/apput/src/Native/SharedLibrary.cs @@ -5,30 +5,36 @@ using ELFSharp.ELF; using ELFSharp.ELF.Sections; -using ApplicationUtility; +namespace ApplicationUtility; class SharedLibrary : IAspect, IDisposable { const uint ELF_MAGIC = 0x464c457f; - public static string AspectName { get; } = "Native shared library"; - - public bool HasAndroidPayload => payloadSize > 0; - public string Name => libraryName; - readonly ulong payloadOffset; readonly ulong payloadSize; readonly string libraryName; readonly bool is64Bit; readonly Stream libraryStream; + IELF elf; bool disposed; + NativeArchitecture nativeArch = NativeArchitecture.Unknown; + + public static string AspectName { get; } = "Native shared library"; + + public bool HasAndroidPayload => payloadSize > 0; + public string Name => libraryName; + public NativeArchitecture TargetArchitecture => nativeArch; + public bool Is64Bit => is64Bit; + + protected IELF ELF => elf; protected SharedLibrary (Stream stream, string libraryName) { this.libraryStream = stream; this.libraryName = libraryName; - (elf, is64Bit) = LoadELF (stream, libraryName); + (elf, is64Bit, nativeArch) = LoadELF (stream, libraryName); (payloadOffset, payloadSize) = FindAndroidPayload (elf); } @@ -80,8 +86,10 @@ public Stream OpenAndroidPayload () return new SubStream (libraryStream, (long)payloadOffset, (long)payloadSize); } - protected static bool IsSupportedELFSharedLibrary (Stream stream, string? description) + protected static bool IsSupportedELFSharedLibrary (Stream stream, string? description, out IELF? elf) { + elf = null; + if (stream.Length < 4) { // Less than that and we know there isn't room for ELF magic Log.Debug ($"SharedLibrary: stream ('{description}') is too short to be an ELF image."); return false; @@ -102,7 +110,7 @@ protected static bool IsSupportedELFSharedLibrary (Stream stream, string? descri return false; } - if (!ELFReader.TryLoad (stream, shouldOwnStream: false, out IELF? elf) || elf == null) { + if (!ELFReader.TryLoad (stream, shouldOwnStream: false, out elf) || elf == null) { Log.Debug ($"SharedLibrary: stream ('{description}') failed to load as an ELF image while checking support."); return false; } @@ -128,13 +136,22 @@ protected static bool IsSupportedELFSharedLibrary (Stream stream, string? descri string not = supported ? String.Empty : " not"; Log.Debug ($"SharedLibrary: stream ('{description}') is{not} a supported ELF architecture ('{elf.Machine}')"); - elf.Dispose (); return supported; } + protected static bool IsSupportedELFSharedLibrary (Stream stream, string? description) + { + if (!IsSupportedELFSharedLibrary (stream, description, out IELF? elf) || elf == null) { + return false; + } + + elf.Dispose (); + return true; + } + // We assume below that stream corresponds to a valid and supported by us ELF image. This should have been asserted by // the `LoadAspect` method. - (IELF elf, bool is64bit) LoadELF (Stream stream, string? libraryName) + (IELF elf, bool is64bit, NativeArchitecture nativeArch) LoadELF (Stream stream, string? libraryName) { stream.Seek (0, SeekOrigin.Begin); if (!ELFReader.TryLoad (stream, shouldOwnStream: false, out IELF? elf) || elf == null) { @@ -142,17 +159,15 @@ protected static bool IsSupportedELFSharedLibrary (Stream stream, string? descri throw new InvalidOperationException ($"Failed to load ELF library '{libraryName}'."); } - bool is64 = elf.Machine switch { - Machine.ARM => false, - Machine.Intel386 => false, - - Machine.AArch64 => true, - Machine.AMD64 => true, - + (bool is64, NativeArchitecture arch) = elf.Machine switch { + Machine.ARM => (false, NativeArchitecture.Arm), + Machine.Intel386 => (false, NativeArchitecture.X86), + Machine.AArch64 => (true, NativeArchitecture.Arm64), + Machine.AMD64 => (true, NativeArchitecture.X64), _ => throw new NotSupportedException ($"Unsupported ELF architecture '{elf.Machine}'") }; - return (elf, is64); + return (elf, is64, arch); } (ulong offset, ulong size) FindAndroidPayload (IELF elf) @@ -187,8 +202,13 @@ protected static bool IsSupportedELFSharedLibrary (Stream stream, string? descri public bool HasSection (string name, SectionType type = SectionType.Null) { - Log.Debug ($"Checking for section '{name}' with type {type} in library '{libraryName}'"); - if (!elf.TryGetSection (name, out ISection? section)) { + return HasSection (elf, libraryName, name, type); + } + + protected static bool HasSection (IELF elf, string libraryName, string sectionName, SectionType type = SectionType.Null) + { + Log.Debug ($"Checking for section '{sectionName}' with type {type} in library '{libraryName}'"); + if (!elf.TryGetSection (sectionName, out ISection? section)) { Log.Debug ("Section not found"); return false; } diff --git a/tools/apput/src/Program.cs b/tools/apput/src/Program.cs index de0b10192d1..8a3f9cf1e88 100644 --- a/tools/apput/src/Program.cs +++ b/tools/apput/src/Program.cs @@ -20,6 +20,10 @@ static int Main (string[] args) static int Run (string[] args) { IAspect? aspect = Detector.FindAspect (args[0]); + if (aspect == null) { + return 1; + } + Reporter.Report (aspect); return 0; } } diff --git a/tools/apput/src/Reporter.cs b/tools/apput/src/Reporter.cs new file mode 100644 index 00000000000..027b0106553 --- /dev/null +++ b/tools/apput/src/Reporter.cs @@ -0,0 +1,105 @@ +using System; +using System.Reflection; + +namespace ApplicationUtility; + +class Reporter +{ + public static void Report (IAspect aspect) + { + Type aspectType = aspect.GetType (); + + // We match the type **exactly** on purpose, we only want to dispatch on + // the known top-level aspects here. + Type? knownType = null; + foreach (Type topLevelAspectType in Detector.KnownTopLevelAspects) { + if (topLevelAspectType != aspectType) { + continue; + } + knownType = topLevelAspectType; + break; + } + + if (knownType == null) { + throw new InvalidOperationException ($"Internal error: cannot generate report for type '{aspectType}'"); + } + + IReporter? reporter = CreateSpecificReporter (aspectType, aspect); + if (reporter == null) { + throw new InvalidOperationException ($"Internal error: failed to instantiate reporter for type '{aspectType}'"); + } + + reporter.Report (); + } + + static IReporter? CreateSpecificReporter (Type aspectType, IAspect aspect) + { + Log.Debug ($"Looking for type {aspectType} reporter class"); + Assembly asm = typeof(Reporter).Assembly; + Type? reporterType = null; + ConstructorInfo? ctor = null; + var ctorArgs = new Type[] { aspectType }; + + foreach (Type type in asm.GetTypes ()) { + (reporterType, ctor) = GetAspectReporterRecursively (type, aspectType, ctorArgs); + if (reporterType != null) { + break; + } + } + + if (reporterType == null || ctor == null) { + Log.Debug ($"Reporter for type '{aspectType}' not found."); + return null; + } + + try { + return (IReporter)ctor.Invoke (new object[] { aspect }); + } catch (Exception ex) { + throw new InvalidOperationException ($"Internal error: failed to instantiate reporter type '{reporterType}'", ex); + } + } + + static (Type?, ConstructorInfo?) GetAspectReporterRecursively (Type type, Type aspectType, Type[] ctorArgs) + { + if (IsReporterForAspect (type, aspectType, ctorArgs, out ConstructorInfo? ctor)) { + return (type, ctor); + } + + foreach (Type nestedType in type.GetNestedTypes ()) { + (Type? matching, ctor) = GetAspectReporterRecursively (nestedType, aspectType, ctorArgs); + if (matching != null) { + return (matching, ctor); + } + } + + return (null, null); + } + + static bool IsReporterForAspect (Type type, Type aspectType, Type[] ctorArgs, out ConstructorInfo? ctor) + { + ctor = null; + + // We don't support generic types, for simplicity + if (type.IsAbstract || !type.IsClass || type.IsGenericType) { + return false; + } + + var attr = type.GetCustomAttribute (); + if (attr == null || attr.AspectType != aspectType) { + return false; + } + + ctor = type.GetConstructor (ctorArgs); + if (ctor == null) { + throw new InvalidOperationException ($"Internal error: type '{type}' claims to be a reporter for '{aspectType}' but lacks the correct public constructor."); + } + + foreach (Type it in type.GetInterfaces ()) { + if (it == typeof(IReporter)) { + return true; + } + } + + throw new InvalidOperationException ($"Internal error: type '{type}' claims to be a reporter but it does not implement the IReporter interface"); + } +} diff --git a/tools/apput/src/Reporters/BaseReporter.cs b/tools/apput/src/Reporters/BaseReporter.cs new file mode 100644 index 00000000000..5e4e95b26ba --- /dev/null +++ b/tools/apput/src/Reporters/BaseReporter.cs @@ -0,0 +1,48 @@ +using System; + +namespace ApplicationUtility; + +abstract class BaseReporter : IReporter +{ + const ConsoleColor LabelColor = ConsoleColor.White; + const ConsoleColor ValueColor = ConsoleColor.Green; + + public abstract void Report (); + + protected void WriteAspectDesc (string text) + { + WriteItem ("Aspect type", text); + } + + protected void WriteNativeArch (NativeArchitecture arch) + { + WriteItem ("Native target architecture", arch.ToString ()); + } + + protected void WriteItem (string label, string value) + { + Write (LabelColor, $"{label}: "); + WriteLine (ValueColor, value); + } + + protected void WriteLine () + { + Console.WriteLine (); + } + + protected void WriteLine (ConsoleColor color, string text) + { + Write (color, text); + WriteLine (); + } + protected void Write (ConsoleColor color, string text) + { + ConsoleColor oldFG = Console.ForegroundColor; + try { + Console.ForegroundColor = color; + Console.Write (text); + } finally { + Console.ForegroundColor = oldFG; + } + } +} diff --git a/tools/apput/src/Reporters/IReporter.cs b/tools/apput/src/Reporters/IReporter.cs new file mode 100644 index 00000000000..4a86c7a11d9 --- /dev/null +++ b/tools/apput/src/Reporters/IReporter.cs @@ -0,0 +1,6 @@ +namespace ApplicationUtility; + +interface IReporter +{ + void Report (); +} diff --git a/tools/apput/src/Reporters/NativeAotSharedLibraryReporter.cs b/tools/apput/src/Reporters/NativeAotSharedLibraryReporter.cs new file mode 100644 index 00000000000..fd7fec07111 --- /dev/null +++ b/tools/apput/src/Reporters/NativeAotSharedLibraryReporter.cs @@ -0,0 +1,18 @@ +namespace ApplicationUtility; + +[AspectReporter (typeof (NativeAotSharedLibrary))] +class NativeAotSharedLibraryReporter : BaseReporter +{ + readonly NativeAotSharedLibrary library; + + public NativeAotSharedLibraryReporter (NativeAotSharedLibrary library) + { + this.library = library; + } + + public override void Report () + { + WriteAspectDesc ("NativeAOT shared library"); + WriteNativeArch (library.TargetArchitecture); + } +} From ae905d79d7ce30e670d946e238413f1da7b1453a Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 24 Sep 2025 12:34:30 +0200 Subject: [PATCH 15/32] More info about shared libraries --- .../src/Native/NativeAotSharedLibrary.cs | 4 +- tools/apput/src/Native/SharedLibrary.cs | 144 ++++++++++++++++-- tools/apput/src/Reporters/BaseReporter.cs | 17 ++- .../NativeAotSharedLibraryReporter.cs | 8 +- .../src/Reporters/SharedLibraryReporter.cs | 50 ++++++ 5 files changed, 204 insertions(+), 19 deletions(-) create mode 100644 tools/apput/src/Reporters/SharedLibraryReporter.cs diff --git a/tools/apput/src/Native/NativeAotSharedLibrary.cs b/tools/apput/src/Native/NativeAotSharedLibrary.cs index d6f0f5fa85d..ed06e690926 100644 --- a/tools/apput/src/Native/NativeAotSharedLibrary.cs +++ b/tools/apput/src/Native/NativeAotSharedLibrary.cs @@ -18,9 +18,7 @@ class NativeAotSharedLibrary : SharedLibrary protected NativeAotSharedLibrary (Stream stream, string libraryName) : base (stream, libraryName) - { - // TODO: perhaps gather some more stats? Code size, data size, alignment, stuff like that - } + {} public new static IAspect LoadAspect (Stream stream, IAspectState? state, string? description) { diff --git a/tools/apput/src/Native/SharedLibrary.cs b/tools/apput/src/Native/SharedLibrary.cs index 9fe6900f684..cfae8bf84e9 100644 --- a/tools/apput/src/Native/SharedLibrary.cs +++ b/tools/apput/src/Native/SharedLibrary.cs @@ -4,29 +4,45 @@ using ELFSharp.ELF; using ELFSharp.ELF.Sections; +using ELFSharp.ELF.Segments; namespace ApplicationUtility; class SharedLibrary : IAspect, IDisposable { const uint ELF_MAGIC = 0x464c457f; + const string DebugLinkSectionName = ".gnu_debuglink"; + const string PayloadSectionName = "payload"; + readonly IELF elf; + readonly NativeArchitecture nativeArch = NativeArchitecture.Unknown; + readonly Stream libraryStream; + readonly bool hasDebugInfo; + readonly bool is64Bit; + readonly string libraryName; + readonly string? androidIdent; + readonly string? buildId; + readonly string? debugLink; + readonly ulong libraryAlignment; readonly ulong payloadOffset; readonly ulong payloadSize; - readonly string libraryName; - readonly bool is64Bit; - readonly Stream libraryStream; - IELF elf; bool disposed; - NativeArchitecture nativeArch = NativeArchitecture.Unknown; public static string AspectName { get; } = "Native shared library"; - public bool HasAndroidPayload => payloadSize > 0; - public string Name => libraryName; public NativeArchitecture TargetArchitecture => nativeArch; + public bool HasAndroidIdent => !String.IsNullOrEmpty (androidIdent); + public bool HasAndroidPayload => payloadSize > 0; + public bool HasBuildID => !String.IsNullOrEmpty (buildId); + public bool HasDebugInfo => hasDebugInfo; + public bool HasDebugLink => !String.IsNullOrEmpty (debugLink); public bool Is64Bit => is64Bit; + public string Name => libraryName; + public string? AndroidIdent => androidIdent; + public string? BuildID => buildId; + public string? DebugLink => debugLink; + public ulong Alignment => libraryAlignment; protected IELF ELF => elf; @@ -36,6 +52,10 @@ protected SharedLibrary (Stream stream, string libraryName) this.libraryName = libraryName; (elf, is64Bit, nativeArch) = LoadELF (stream, libraryName); (payloadOffset, payloadSize) = FindAndroidPayload (elf); + libraryAlignment = DetectAlignment (elf, is64Bit); + (hasDebugInfo, debugLink) = DetectDebugInfo (elf, libraryName); + buildId = GetBuildID (elf, is64Bit); + androidIdent = GetAndroidIdent (elf, is64Bit); } public static IAspect LoadAspect (Stream stream, IAspectState? state, string? description) @@ -172,8 +192,8 @@ protected static bool IsSupportedELFSharedLibrary (Stream stream, string? descri (ulong offset, ulong size) FindAndroidPayload (IELF elf) { - if (!elf.TryGetSection ("payload", out ISection? payloadSection)) { - Log.Debug ($"SharedLibrary: shared library '{libraryName}' doesn't have the 'payload' section."); + if (!elf.TryGetSection (PayloadSectionName, out ISection? payloadSection)) { + Log.Debug ($"SharedLibrary: shared library '{libraryName}' doesn't have the '{PayloadSectionName}' section."); return (0, 0); } @@ -200,6 +220,112 @@ protected static bool IsSupportedELFSharedLibrary (Stream stream, string? descri } } + static (bool hasDebugInfo, string? debugLink) DetectDebugInfo (IELF elf, string libraryName) + { + bool hasDebugInfo = HasSection (elf, libraryName, ".debug_info", SectionType.ProgBits); + + if (!HasSection (elf, libraryName, DebugLinkSectionName, SectionType.ProgBits)) { + return (hasDebugInfo, null); + } + + return (hasDebugInfo, ReadDebugLinkSection (elf, libraryName)); + } + + static string? ReadDebugLinkSection (IELF elf, string libraryName) + { + Log.Debug ($"Trying to load debug link section from {libraryName}"); + if (!elf.TryGetSection (DebugLinkSectionName, out ISection? section)) { + Log.Debug ($"Debug link section '{DebugLinkSectionName}' could not be read"); + return null; + } + + // From https://sourceware.org/gdb/current/onlinedocs/gdb.html/Separate-Debug-Files.html + // + // * A filename, with any leading directory components removed, followed by a zero byte, + // * zero to three bytes of padding, as needed to reach the next four-byte boundary within the section, and + // * a four-byte CRC checksum, stored in the same endianness used for the executable file itself. The checksum is computed on the debugging information file’s full + // contents by the function given below, passing zero as the crc argument. + + // TODO: At this point we ignore the CRC, perhaps it would be worth reading it? + byte[] contents = section.GetContents (); + if (contents.Length < 4) { + // there must at least be the 4-byte CRC, otherwise section content is invalid + return null; + } + + int zeroIndex = 0; + for (int i = 0; i < contents.Length; i++) { + if (contents[i] != 0) { + continue; + } + + zeroIndex = i; + break; + } + + if (zeroIndex == 0) { + return null; + } + + return Encoding.UTF8.GetString (contents, 0, zeroIndex); + } + + static ulong DetectAlignment (IELF elf, bool is64Bit) + { + if (!elf.HasSegmentHeader) { + return 0; + } + + foreach (ISegment segment in elf.Segments) { + if (segment.Type != SegmentType.Load) { + continue; + } + + if (is64Bit) { + return ((Segment)segment).Alignment; + } + + return ((Segment)segment).Alignment; + } + + return 0; + } + + static string? GetBuildID (IELF elf, bool is64Bit) + { + byte[]? contents = GetNoteSectionContents (elf, is64Bit, ".note.gnu.build-id"); + if (contents == null) { + return null; + } + + // TODO: decode + return "decoding not implemented yet"; + } + + static string? GetAndroidIdent (IELF elf, bool is64Bit) + { + return GetNoteSectionContentsAsString (elf, is64Bit, ".note.android.ident");; + } + + static string? GetNoteSectionContentsAsString (IELF elf, bool is64Bit, string sectionName) + { + byte[]? contents = GetNoteSectionContents (elf, is64Bit, sectionName); + if (contents == null) { + return null; + } + + return Encoding.UTF8.GetString (contents); + } + + static byte[]? GetNoteSectionContents (IELF elf, bool is64Bit, string sectionName) + { + if (!elf.TryGetSection (sectionName, out ISection? section) || section == null || section.Type != SectionType.Note) { + return null; + } + + return ((INoteSection)section).Description; + } + public bool HasSection (string name, SectionType type = SectionType.Null) { return HasSection (elf, libraryName, name, type); diff --git a/tools/apput/src/Reporters/BaseReporter.cs b/tools/apput/src/Reporters/BaseReporter.cs index 5e4e95b26ba..81c92896ca8 100644 --- a/tools/apput/src/Reporters/BaseReporter.cs +++ b/tools/apput/src/Reporters/BaseReporter.cs @@ -4,8 +4,9 @@ namespace ApplicationUtility; abstract class BaseReporter : IReporter { - const ConsoleColor LabelColor = ConsoleColor.White; - const ConsoleColor ValueColor = ConsoleColor.Green; + protected const ConsoleColor LabelColor = ConsoleColor.White; + protected const ConsoleColor ValidValueColor = ConsoleColor.Green; + protected const ConsoleColor InvalidValueColor = ConsoleColor.Red; public abstract void Report (); @@ -19,10 +20,15 @@ protected void WriteNativeArch (NativeArchitecture arch) WriteItem ("Native target architecture", arch.ToString ()); } - protected void WriteItem (string label, string value) + protected void WriteLabel (string label) { Write (LabelColor, $"{label}: "); - WriteLine (ValueColor, value); + } + + protected void WriteItem (string label, string value) + { + WriteLabel (label); + WriteLine (ValidValueColor, value); } protected void WriteLine () @@ -35,6 +41,7 @@ protected void WriteLine (ConsoleColor color, string text) Write (color, text); WriteLine (); } + protected void Write (ConsoleColor color, string text) { ConsoleColor oldFG = Console.ForegroundColor; @@ -45,4 +52,6 @@ protected void Write (ConsoleColor color, string text) Console.ForegroundColor = oldFG; } } + + protected string YesNo (bool yes) => yes ? "yes" : "no"; } diff --git a/tools/apput/src/Reporters/NativeAotSharedLibraryReporter.cs b/tools/apput/src/Reporters/NativeAotSharedLibraryReporter.cs index fd7fec07111..2654e91c43a 100644 --- a/tools/apput/src/Reporters/NativeAotSharedLibraryReporter.cs +++ b/tools/apput/src/Reporters/NativeAotSharedLibraryReporter.cs @@ -1,18 +1,20 @@ namespace ApplicationUtility; [AspectReporter (typeof (NativeAotSharedLibrary))] -class NativeAotSharedLibraryReporter : BaseReporter +class NativeAotSharedLibraryReporter : SharedLibraryReporter { readonly NativeAotSharedLibrary library; + protected override string LibraryKind => "NativeAOT shared library"; + public NativeAotSharedLibraryReporter (NativeAotSharedLibrary library) + : base (library) { this.library = library; } public override void Report () { - WriteAspectDesc ("NativeAOT shared library"); - WriteNativeArch (library.TargetArchitecture); + base.Report (); } } diff --git a/tools/apput/src/Reporters/SharedLibraryReporter.cs b/tools/apput/src/Reporters/SharedLibraryReporter.cs new file mode 100644 index 00000000000..4530fb670cb --- /dev/null +++ b/tools/apput/src/Reporters/SharedLibraryReporter.cs @@ -0,0 +1,50 @@ +using System.Text; + +namespace ApplicationUtility; + +[AspectReporter (typeof (NativeAotSharedLibrary))] +class SharedLibraryReporter : BaseReporter +{ + readonly SharedLibrary library; + protected virtual string LibraryKind => "Shared library"; + + public SharedLibraryReporter (SharedLibrary library) + { + this.library = library; + } + + public override void Report () + { + WriteAspectDesc (LibraryKind); + WriteNativeArch (library.TargetArchitecture); + WriteItem ("Build ID", library.HasBuildID ? library.BuildID! : "none"); + WriteDebugInfoDesc (); + + if (library.HasAndroidIdent) { + WriteItem ("Android ident", library.AndroidIdent!); + } + } + + protected void WriteDebugInfoDesc () + { + WriteItem ("Has debug info", YesNo (library.HasDebugInfo)); + + var sb = new StringBuilder (YesNo (library.HasDebugLink)); + if (library.HasDebugLink) { + sb.Append (" ('"); + sb.Append (library.DebugLink); + sb.Append ("')"); + } + WriteItem ("Has debug link", sb.ToString ()); + + bool compatibleWith16k = library.Alignment >= 0x4000 && (library.Alignment % 0x4000 == 0); + sb.Clear (); + sb.Append ($"0x{library.Alignment:x} ("); + if (!compatibleWith16k) { + sb.Append ("NOT "); + } + sb.Append ("compatible with Android 16k library alignment)"); + WriteLabel ("Alignment"); + WriteLine (compatibleWith16k ? ValidValueColor : InvalidValueColor, sb.ToString ()); + } +} From 73eb4a1e4d8e44235ea063322bbeb501d5b75238 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 24 Sep 2025 17:10:06 +0200 Subject: [PATCH 16/32] More NAOT goodies --- tools/apput/src/Detector.cs | 20 +++- .../src/Native/NativeAotSharedLibrary.cs | 2 +- tools/apput/src/Native/SharedLibrary.cs | 105 +++++++++++++++--- tools/apput/src/Package/ApplicationPackage.cs | 31 ++---- tools/apput/src/Reporter.cs | 2 +- tools/apput/src/Reporters/BaseReporter.cs | 14 ++- .../NativeAotSharedLibraryReporter.cs | 12 +- .../src/Reporters/SharedLibraryReporter.cs | 20 ++-- 8 files changed, 143 insertions(+), 63 deletions(-) diff --git a/tools/apput/src/Detector.cs b/tools/apput/src/Detector.cs index 891534c06e5..cb839bc5807 100644 --- a/tools/apput/src/Detector.cs +++ b/tools/apput/src/Detector.cs @@ -19,6 +19,13 @@ public class Detector typeof (AssemblyStore), typeof (ApplicationAssembly), typeof (NativeAotSharedLibrary), + typeof (LibXamarinApp), + typeof (SharedLibrary), + }; + + readonly static List KnownSharedLibraryAspects = new () { + typeof (NativeAotSharedLibrary), + typeof (LibXamarinApp), typeof (SharedLibrary), }; @@ -30,16 +37,23 @@ public class Detector } using Stream fs = File.OpenRead (path); - return TryFindAspect (fs, path); + return TryFindTopLevelAspect (fs, path); } public static IAspect? FindAspect (Stream stream, string? description = null) { Log.Debug ($"Looking for aspect supporting a stream ('{description}')"); - return TryFindAspect (stream, description); + return TryFindTopLevelAspect (stream, description); + } + + public static SharedLibrary? FindSharedLibraryAspect (Stream stream, string? description = null) + { + Log.Debug ($"Looking for shared library aspect ('{description}')"); + // TODO: implement + return null; } - static IAspect? TryFindAspect (Stream stream, string? description) + static IAspect? TryFindTopLevelAspect (Stream stream, string? description) { var flags = BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static; diff --git a/tools/apput/src/Native/NativeAotSharedLibrary.cs b/tools/apput/src/Native/NativeAotSharedLibrary.cs index ed06e690926..128afe34c06 100644 --- a/tools/apput/src/Native/NativeAotSharedLibrary.cs +++ b/tools/apput/src/Native/NativeAotSharedLibrary.cs @@ -6,7 +6,7 @@ namespace ApplicationUtility; -class NativeAotSharedLibrary : SharedLibrary +public class NativeAotSharedLibrary : SharedLibrary { readonly static List<(string sectionName, SectionType type)> NativeAotSections = new () { ("__managedcode", SectionType.ProgBits), diff --git a/tools/apput/src/Native/SharedLibrary.cs b/tools/apput/src/Native/SharedLibrary.cs index cfae8bf84e9..707679705ba 100644 --- a/tools/apput/src/Native/SharedLibrary.cs +++ b/tools/apput/src/Native/SharedLibrary.cs @@ -8,41 +8,45 @@ namespace ApplicationUtility; -class SharedLibrary : IAspect, IDisposable +public class SharedLibrary : IAspect, IDisposable { const uint ELF_MAGIC = 0x464c457f; const string DebugLinkSectionName = ".gnu_debuglink"; const string PayloadSectionName = "payload"; - readonly IELF elf; - readonly NativeArchitecture nativeArch = NativeArchitecture.Unknown; - readonly Stream libraryStream; - readonly bool hasDebugInfo; - readonly bool is64Bit; - readonly string libraryName; readonly string? androidIdent; readonly string? buildId; readonly string? debugLink; + readonly IELF elf; + readonly bool hasDebugInfo; + readonly bool is64Bit; readonly ulong libraryAlignment; + readonly string libraryName; + readonly Stream libraryStream; + readonly NativeArchitecture nativeArch = NativeArchitecture.Unknown; readonly ulong payloadOffset; readonly ulong payloadSize; + readonly string? soname; bool disposed; public static string AspectName { get; } = "Native shared library"; - public NativeArchitecture TargetArchitecture => nativeArch; + public ulong Alignment => libraryAlignment; + public bool AlignmentCompatibleWith16k => libraryAlignment >= 0x4000 && (libraryAlignment % 0x4000 == 0); + public string? AndroidIdent => androidIdent; + public string? BuildID => buildId; + public string? DebugLink => debugLink; public bool HasAndroidIdent => !String.IsNullOrEmpty (androidIdent); public bool HasAndroidPayload => payloadSize > 0; public bool HasBuildID => !String.IsNullOrEmpty (buildId); public bool HasDebugInfo => hasDebugInfo; public bool HasDebugLink => !String.IsNullOrEmpty (debugLink); + public bool HasSoname => !String.IsNullOrEmpty (soname); public bool Is64Bit => is64Bit; public string Name => libraryName; - public string? AndroidIdent => androidIdent; - public string? BuildID => buildId; - public string? DebugLink => debugLink; - public ulong Alignment => libraryAlignment; + public string? Soname => soname; + public NativeArchitecture TargetArchitecture => nativeArch; protected IELF ELF => elf; @@ -56,6 +60,7 @@ protected SharedLibrary (Stream stream, string libraryName) (hasDebugInfo, debugLink) = DetectDebugInfo (elf, libraryName); buildId = GetBuildID (elf, is64Bit); androidIdent = GetAndroidIdent (elf, is64Bit); + soname = GetSoname (elf, is64Bit); } public static IAspect LoadAspect (Stream stream, IAspectState? state, string? description) @@ -291,15 +296,65 @@ static ulong DetectAlignment (IELF elf, bool is64Bit) return 0; } + static string? GetSoname (IELF elf, bool is64Bit) + { + IDynamicEntry? sonameEntry = null; + + foreach (IDynamicSection section in elf.GetSections ()) { + foreach (IDynamicEntry dyne in section.Entries) { + if (dyne.Tag != DynamicTag.SoName) { + continue; + } + sonameEntry = dyne; + break; + } + + if (sonameEntry != null) { + break; + } + } + + if (sonameEntry == null) { + return null; + } + + ulong stringIndex = is64Bit switch { + true => ((DynamicEntry)sonameEntry).Value, + false => ((DynamicEntry)sonameEntry).Value + }; + + // Offset is into the .dynstr section + if (!elf.TryGetSection (".dynstr", out ISection? strtabSection) || strtabSection == null || strtabSection.Type != SectionType.StringTable) { + return null; + } + + var strtab = (IStringTable)strtabSection; + try { + return strtab[(long)stringIndex]; + } catch (Exception ex) { + Log.Debug ($"Failed to obtain soname from the string table (asked for index {stringIndex})", ex); + return null; + } + } + static string? GetBuildID (IELF elf, bool is64Bit) { - byte[]? contents = GetNoteSectionContents (elf, is64Bit, ".note.gnu.build-id"); + // From elf_common.h + // + // #define NT_GNU_BUILD_ID 3 + // + const ulong NT_GNU_BUILD_ID = 0; + byte[]? contents = GetNoteSectionContents (elf, is64Bit, ".note.gnu.build-id", NT_GNU_BUILD_ID); if (contents == null) { return null; } - // TODO: decode - return "decoding not implemented yet"; + var sb = new StringBuilder (); + foreach (byte b in contents) { + sb.Append ($"{b:x02}"); + } + + return sb.ToString (); } static string? GetAndroidIdent (IELF elf, bool is64Bit) @@ -307,7 +362,7 @@ static ulong DetectAlignment (IELF elf, bool is64Bit) return GetNoteSectionContentsAsString (elf, is64Bit, ".note.android.ident");; } - static string? GetNoteSectionContentsAsString (IELF elf, bool is64Bit, string sectionName) + static string? GetNoteSectionContentsAsString (IELF elf, bool is64Bit, string sectionName, ulong noteType = 0) { byte[]? contents = GetNoteSectionContents (elf, is64Bit, sectionName); if (contents == null) { @@ -317,13 +372,27 @@ static ulong DetectAlignment (IELF elf, bool is64Bit) return Encoding.UTF8.GetString (contents); } - static byte[]? GetNoteSectionContents (IELF elf, bool is64Bit, string sectionName) + static byte[]? GetNoteSectionContents (IELF elf, bool is64Bit, string sectionName, ulong noteType = 0) { if (!elf.TryGetSection (sectionName, out ISection? section) || section == null || section.Type != SectionType.Note) { return null; } - return ((INoteSection)section).Description; + var note = (INoteSection)section; + if (noteType == 0) { + return note.Description; + } + + ulong type = is64Bit switch { + true => ((NoteSection)note).NoteType, + false => ((NoteSection)note).NoteType + }; + + if (type != noteType) { + return null; + } + + return note.Description; } public bool HasSection (string name, SectionType type = SectionType.Null) diff --git a/tools/apput/src/Package/ApplicationPackage.cs b/tools/apput/src/Package/ApplicationPackage.cs index e0a86acc51a..c364f3ec33a 100644 --- a/tools/apput/src/Package/ApplicationPackage.cs +++ b/tools/apput/src/Package/ApplicationPackage.cs @@ -4,7 +4,6 @@ using System.IO.Compression; using System.Linq; -using ELFSharp.ELF.Sections; using Xamarin.Android.Tasks; using Xamarin.Android.Tools; @@ -33,14 +32,6 @@ public abstract class ApplicationPackage : IAspect "META-INF/ANDROIDD.RSA", }; - readonly static List<(string sectionName, SectionType type)> NativeAotSections = new () { - ("__managedcode", SectionType.ProgBits), - (".dotnet_eh_table", SectionType.ProgBits), - ("__unbox", SectionType.ProgBits), - ("__modules", SectionType.ProgBits), - (".hydrated", SectionType.NoBits), - }; - public static string AspectName { get; } = "Application package"; public abstract string PackageFormat { get; } @@ -59,6 +50,7 @@ public abstract class ApplicationPackage : IAspect public List? AssemblyStores { get; protected set; } public List Architectures { get; protected set; } = new (); public List NativeAppInfos { get; protected set; } = new (); + public List SharedLibraries { get; protected set; } = new (); AndroidManifest? manifest; @@ -91,6 +83,7 @@ public static IAspect LoadAspect (Stream stream, IAspectState state, string? des // TODO: for all of the below, add support for detection of older XA apps (just to warn that this version doesn't support // and that people should use older tools) ret.TryDetectArchitectures (); // This must be called first, some further steps depend on it + ret.CollectSharedLibraries (); // This must be called second, some further steps need the collection of shared libraries ret.TryDetectRuntime (); ret.TryDetectWhetherIsSigned (); ret.TryLoadAssemblyStores (); @@ -100,6 +93,11 @@ public static IAspect LoadAspect (Stream stream, IAspectState state, string? des return ret; } + void CollectSharedLibraries () + { + // TODO: find and detect shared libraries + } + void TryDetectArchitectures () { foreach (AndroidTargetArch arch in Enum.GetValues ()) { @@ -175,6 +173,7 @@ bool TryDetectNativeAotRuntime () foreach (AndroidTargetArch arch in Architectures) { string libDir = GetNativeLibDir (arch); + // TODO: move .so search code to CollectSharedLibraries and just leave NAOT detection here foreach (ZipArchiveEntry? entry in Zip.Entries) { if (entry == null) { continue; @@ -212,23 +211,11 @@ bool SharedLibraryIsNativeAOT (ZipArchiveEntry entry) return false; } - IAspectState aspectState = SharedLibrary.ProbeAspect (stream, entry.FullName); + IAspectState aspectState = NativeAotSharedLibrary.ProbeAspect (stream, entry.FullName); if (!aspectState.Success) { return false; } - var dso = SharedLibrary.LoadAspect (stream, aspectState, entry.FullName) as SharedLibrary; - if (dso == null) { - throw new InvalidOperationException ("Internal error: unexpected SharedLibrary load result."); - } - - // Just one match should be enough - foreach (var naotSection in NativeAotSections) { - if (dso.HasSection (naotSection.sectionName, naotSection.type)) { - return true; - } - } - return false; } diff --git a/tools/apput/src/Reporter.cs b/tools/apput/src/Reporter.cs index 027b0106553..5d1cd5674fb 100644 --- a/tools/apput/src/Reporter.cs +++ b/tools/apput/src/Reporter.cs @@ -21,7 +21,7 @@ public static void Report (IAspect aspect) } if (knownType == null) { - throw new InvalidOperationException ($"Internal error: cannot generate report for type '{aspectType}'"); + throw new InvalidOperationException ($"Internal error: cannot generate report for unsupported type '{aspectType}'"); } IReporter? reporter = CreateSpecificReporter (aspectType, aspect); diff --git a/tools/apput/src/Reporters/BaseReporter.cs b/tools/apput/src/Reporters/BaseReporter.cs index 81c92896ca8..be9e2deae51 100644 --- a/tools/apput/src/Reporters/BaseReporter.cs +++ b/tools/apput/src/Reporters/BaseReporter.cs @@ -7,8 +7,19 @@ abstract class BaseReporter : IReporter protected const ConsoleColor LabelColor = ConsoleColor.White; protected const ConsoleColor ValidValueColor = ConsoleColor.Green; protected const ConsoleColor InvalidValueColor = ConsoleColor.Red; + protected const ConsoleColor BannerColor = ConsoleColor.Cyan; - public abstract void Report (); + protected abstract string AspectName { get; } + protected abstract string ShortDescription { get; } + + public void Report () + { + WriteLine (BannerColor, $"# {AspectName} ({ShortDescription})"); + DoReport (); + WriteLine (); + } + + protected abstract void DoReport (); protected void WriteAspectDesc (string text) { @@ -54,4 +65,5 @@ protected void Write (ConsoleColor color, string text) } protected string YesNo (bool yes) => yes ? "yes" : "no"; + protected string ValueOrNone (string? s) => String.IsNullOrEmpty (s) ? "none" : s; } diff --git a/tools/apput/src/Reporters/NativeAotSharedLibraryReporter.cs b/tools/apput/src/Reporters/NativeAotSharedLibraryReporter.cs index 2654e91c43a..7cd1a2eea5b 100644 --- a/tools/apput/src/Reporters/NativeAotSharedLibraryReporter.cs +++ b/tools/apput/src/Reporters/NativeAotSharedLibraryReporter.cs @@ -3,18 +3,10 @@ namespace ApplicationUtility; [AspectReporter (typeof (NativeAotSharedLibrary))] class NativeAotSharedLibraryReporter : SharedLibraryReporter { - readonly NativeAotSharedLibrary library; - + protected override string AspectName => NativeAotSharedLibrary.AspectName; protected override string LibraryKind => "NativeAOT shared library"; public NativeAotSharedLibraryReporter (NativeAotSharedLibrary library) : base (library) - { - this.library = library; - } - - public override void Report () - { - base.Report (); - } + {} } diff --git a/tools/apput/src/Reporters/SharedLibraryReporter.cs b/tools/apput/src/Reporters/SharedLibraryReporter.cs index 4530fb670cb..b351962b218 100644 --- a/tools/apput/src/Reporters/SharedLibraryReporter.cs +++ b/tools/apput/src/Reporters/SharedLibraryReporter.cs @@ -6,22 +6,29 @@ namespace ApplicationUtility; class SharedLibraryReporter : BaseReporter { readonly SharedLibrary library; + + protected override string AspectName => SharedLibrary.AspectName; protected virtual string LibraryKind => "Shared library"; + protected override string ShortDescription => library.Name; public SharedLibraryReporter (SharedLibrary library) { this.library = library; } - public override void Report () + protected override void DoReport () { WriteAspectDesc (LibraryKind); WriteNativeArch (library.TargetArchitecture); - WriteItem ("Build ID", library.HasBuildID ? library.BuildID! : "none"); + + if (library.HasSoname) { + WriteItem ("Soname", ValueOrNone (library.Soname)); + } + WriteItem ("Build ID", ValueOrNone (library.BuildID)); WriteDebugInfoDesc (); if (library.HasAndroidIdent) { - WriteItem ("Android ident", library.AndroidIdent!); + WriteItem ("Android ident", ValueOrNone (library.AndroidIdent)); } } @@ -37,14 +44,13 @@ protected void WriteDebugInfoDesc () } WriteItem ("Has debug link", sb.ToString ()); - bool compatibleWith16k = library.Alignment >= 0x4000 && (library.Alignment % 0x4000 == 0); sb.Clear (); sb.Append ($"0x{library.Alignment:x} ("); - if (!compatibleWith16k) { + if (!library.AlignmentCompatibleWith16k) { sb.Append ("NOT "); } - sb.Append ("compatible with Android 16k library alignment)"); + sb.Append ("compatible with Android 16k library alignment requirement)"); WriteLabel ("Alignment"); - WriteLine (compatibleWith16k ? ValidValueColor : InvalidValueColor, sb.ToString ()); + WriteLine (library.AlignmentCompatibleWith16k ? ValidValueColor : InvalidValueColor, sb.ToString ()); } } From 0c86a6fca970e0343ca58ac4f676c5269cc4517b Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 25 Sep 2025 12:01:03 +0200 Subject: [PATCH 17/32] Moving on with reporters --- .../src/Common/AspectReporterAttribute.cs | 2 +- tools/apput/src/Detector.cs | 61 +++++++----- tools/apput/src/Native/AnELF.cs | 1 + tools/apput/src/Native/LibXamarinApp.cs | 38 -------- .../src/Native/NativeAotSharedLibrary.cs | 2 +- tools/apput/src/Native/NativeAppInfo.cs | 2 +- .../Native/XamarinAppLibraryAspectState.cs | 12 +++ .../src/Native/XamarinAppSharedLibrary.cs | 65 +++++++++++++ tools/apput/src/Package/ApplicationPackage.cs | 95 +++++++++---------- tools/apput/src/Reporter.cs | 13 ++- .../Reporters/ApplicationPackageReporter.cs | 22 +++++ 11 files changed, 196 insertions(+), 117 deletions(-) delete mode 100644 tools/apput/src/Native/LibXamarinApp.cs create mode 100644 tools/apput/src/Native/XamarinAppLibraryAspectState.cs create mode 100644 tools/apput/src/Native/XamarinAppSharedLibrary.cs create mode 100644 tools/apput/src/Reporters/ApplicationPackageReporter.cs diff --git a/tools/apput/src/Common/AspectReporterAttribute.cs b/tools/apput/src/Common/AspectReporterAttribute.cs index 7720308c860..03880b310de 100644 --- a/tools/apput/src/Common/AspectReporterAttribute.cs +++ b/tools/apput/src/Common/AspectReporterAttribute.cs @@ -2,7 +2,7 @@ namespace ApplicationUtility; -[AttributeUsage (AttributeTargets.Class, Inherited = false, AllowMultiple = false)] +[AttributeUsage (AttributeTargets.Class, Inherited = false, AllowMultiple = true)] class AspectReporterAttribute : Attribute { public Type AspectType { get; } diff --git a/tools/apput/src/Detector.cs b/tools/apput/src/Detector.cs index cb839bc5807..8d6a12ffc12 100644 --- a/tools/apput/src/Detector.cs +++ b/tools/apput/src/Detector.cs @@ -15,17 +15,19 @@ public class Detector // Aspects must be listed in the order of detection, from the biggest (the most generic) to the // smallest (the least generic) aspects. public readonly static List KnownTopLevelAspects = new () { - typeof (ApplicationPackage), + typeof (PackageAPK), + typeof (PackageAAB), + typeof (PackageBase), typeof (AssemblyStore), typeof (ApplicationAssembly), typeof (NativeAotSharedLibrary), - typeof (LibXamarinApp), + typeof (XamarinAppSharedLibrary), typeof (SharedLibrary), }; readonly static List KnownSharedLibraryAspects = new () { typeof (NativeAotSharedLibrary), - typeof (LibXamarinApp), + typeof (XamarinAppSharedLibrary), typeof (SharedLibrary), }; @@ -49,33 +51,44 @@ public class Detector public static SharedLibrary? FindSharedLibraryAspect (Stream stream, string? description = null) { Log.Debug ($"Looking for shared library aspect ('{description}')"); - // TODO: implement + return (SharedLibrary?)TryFindAspect (KnownSharedLibraryAspects, stream, description); + } + + static IAspect? TryFindTopLevelAspect (Stream stream, string? description) => TryFindAspect (KnownTopLevelAspects, stream, description); + + static IAspect? TryFindAspect (List aspectTypes, Stream stream, string? description) + { + foreach (Type aspectType in aspectTypes) { + IAspect? aspect = TryProbeAndLoadAspect (aspectType, stream, description); + if (aspect != null) { + return aspect; + } + } + return null; } - static IAspect? TryFindTopLevelAspect (Stream stream, string? description) + static IAspect? TryProbeAndLoadAspect (Type aspect, Stream stream, string? description) { - var flags = BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static; + const BindingFlags flags = BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy; - foreach (Type aspect in KnownTopLevelAspects) { - LogBanner ($"Probing aspect: {aspect}"); + LogBanner ($"Probing aspect: {aspect}"); + object? result = aspect.InvokeMember ( + "ProbeAspect", flags, null, null, new object?[] { stream, description } + ); - object? result = aspect.InvokeMember ( - "ProbeAspect", flags, null, null, new object?[] { stream, description } - ); + var state = result as IAspectState; + if (state == null || !state.Success) { + return null; + } - var state = result as IAspectState; - if (state == null || !state.Success) { - continue; - } + LogBanner ($"Loading aspect: {aspect}"); + result = aspect.InvokeMember ( + "LoadAspect", flags, null, null, new object?[] { stream, state, description } + ); - LogBanner ($"Loading aspect: {aspect}"); - result = aspect.InvokeMember ( - "LoadAspect", flags, null, null, new object?[] { stream, state, description } - ); - if (result != null) { - return (IAspect)result; - } + if (result != null) { + return (IAspect)result; } return null; @@ -83,10 +96,8 @@ public class Detector void LogBanner (string what) { Log.Debug (); - Log.Debug ("##########"); - Log.Debug (what); + Log.Debug ($"# {what}"); Log.Debug (); } } - } diff --git a/tools/apput/src/Native/AnELF.cs b/tools/apput/src/Native/AnELF.cs index 5dfec85c2fb..b4b8f126a60 100644 --- a/tools/apput/src/Native/AnELF.cs +++ b/tools/apput/src/Native/AnELF.cs @@ -242,6 +242,7 @@ public static bool TryLoad (string filePath, out AnELF? anElf) public static bool TryLoad (Stream stream, string filePath, out AnELF? anElf) { anElf = null; + stream.Seek (0, SeekOrigin.Begin); Class elfClass = ELFReader.CheckELFType (stream); if (elfClass == Class.NotELF) { Log.Warning ($"AnELF.TryLoad: {filePath} is not an ELF binary"); diff --git a/tools/apput/src/Native/LibXamarinApp.cs b/tools/apput/src/Native/LibXamarinApp.cs deleted file mode 100644 index 572d07d4ce2..00000000000 --- a/tools/apput/src/Native/LibXamarinApp.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.IO; - -namespace ApplicationUtility; - -// TODO: make it an abstract class, we need to support different formats -class LibXamarinApp : SharedLibrary, IAspect -{ - LibXamarinApp (Stream stream, string description) - : base (stream, description) - {} - - public static new IAspect LoadAspect (Stream stream, IAspectState state, string? description) - { - if (String.IsNullOrEmpty (description)) { - throw new ArgumentException ("Must be a shared library name", nameof (description)); - } - - if (!IsSupportedELFSharedLibrary (stream, description)) { - throw new InvalidOperationException ("Stream is not a supported ELF shared library"); - } - - // TODO: this needs to be versioned - return new LibXamarinApp (stream, description); - } - - public static new IAspectState ProbeAspect (Stream stream, string? description) - { - IAspectState sharedLibState = SharedLibrary.ProbeAspect (stream, description); - if (!sharedLibState.Success) { - return sharedLibState; - } - - // TODO: check for presence of a handful of fields and read at least `format_tag` to determine - // format version. - throw new NotImplementedException (); - } -} diff --git a/tools/apput/src/Native/NativeAotSharedLibrary.cs b/tools/apput/src/Native/NativeAotSharedLibrary.cs index 128afe34c06..41e37fffa85 100644 --- a/tools/apput/src/Native/NativeAotSharedLibrary.cs +++ b/tools/apput/src/Native/NativeAotSharedLibrary.cs @@ -35,7 +35,7 @@ protected NativeAotSharedLibrary (Stream stream, string libraryName) public new static IAspectState ProbeAspect (Stream stream, string? description) => new BasicAspectState (IsNativeAotSharedLibrary (stream, description)); - static bool IsNativeAotSharedLibrary (Stream stream, string description) + static bool IsNativeAotSharedLibrary (Stream stream, string? description) { if (!IsSupportedELFSharedLibrary (stream, description, out IELF? elf) || elf == null) { return false; diff --git a/tools/apput/src/Native/NativeAppInfo.cs b/tools/apput/src/Native/NativeAppInfo.cs index 7f026d8ecc5..882048daa7a 100644 --- a/tools/apput/src/Native/NativeAppInfo.cs +++ b/tools/apput/src/Native/NativeAppInfo.cs @@ -2,7 +2,7 @@ namespace ApplicationUtility; public class NativeAppInfo { - internal NativeAppInfo (LibXamarinApp xamarinAppLibrary) + internal NativeAppInfo (XamarinAppSharedLibrary xamarinAppLibrary) { } } diff --git a/tools/apput/src/Native/XamarinAppLibraryAspectState.cs b/tools/apput/src/Native/XamarinAppLibraryAspectState.cs new file mode 100644 index 00000000000..02a9bd59f98 --- /dev/null +++ b/tools/apput/src/Native/XamarinAppLibraryAspectState.cs @@ -0,0 +1,12 @@ +namespace ApplicationUtility; + +class XamarinAppLibraryAspectState : BasicAspectState +{ + public ulong FormatTag { get; } + + public XamarinAppLibraryAspectState (bool success, ulong formatTag) + : base (success) + { + FormatTag = formatTag; + } +} diff --git a/tools/apput/src/Native/XamarinAppSharedLibrary.cs b/tools/apput/src/Native/XamarinAppSharedLibrary.cs new file mode 100644 index 00000000000..6a5e8f49899 --- /dev/null +++ b/tools/apput/src/Native/XamarinAppSharedLibrary.cs @@ -0,0 +1,65 @@ +using System; +using System.IO; + +using ELFSharp.ELF; + +namespace ApplicationUtility; + +// TODO: make it an abstract class, we need to support different formats +class XamarinAppSharedLibrary : SharedLibrary +{ + const string FormatTagSymbol = "format_tag"; + + public ulong FormatTag { get; } + + XamarinAppSharedLibrary (Stream stream, string description, XamarinAppLibraryAspectState state) + : base (stream, description) + { + FormatTag = state.FormatTag; + } + + public static new IAspect LoadAspect (Stream stream, IAspectState state, string? description) + { + if (String.IsNullOrEmpty (description)) { + throw new ArgumentException ("Must be a shared library name", nameof (description)); + } + + if (!IsSupportedELFSharedLibrary (stream, description)) { + throw new InvalidOperationException ("Stream is not a supported ELF shared library"); + } + + // TODO: this needs to be versioned + return new XamarinAppSharedLibrary (stream, description, (XamarinAppLibraryAspectState)state); + } + + public static new IAspectState ProbeAspect (Stream stream, string? description) => IsXamarinAppSharedLibrary (stream, description); + + static XamarinAppLibraryAspectState IsXamarinAppSharedLibrary (Stream stream, string? description) + { + if (!IsSupportedELFSharedLibrary (stream, description, out IELF? elf) || elf == null) { + return GetErrorState (); + } + + if (!AnELF.TryLoad (stream, description ?? String.Empty, out AnELF? anElf) || anElf == null) { + Log.Debug ($"Failed to load '{description}' as a Xamarin.Android application shared library"); + return GetErrorState (); + } + + if (!anElf.HasSymbol (FormatTagSymbol)) { + return LogMissingSymbolAndReturn (FormatTagSymbol); + } + ulong formatTag = anElf.GetUInt64 (FormatTagSymbol); + + // TODO: check for presence of a handful of fields more + return GetState (success: true, formatTag); + + XamarinAppLibraryAspectState LogMissingSymbolAndReturn (string name) + { + Log.Debug ($"{description} is not a Xamarin.Android application shared library, it doesn't have the '{name}' symbol."); + return GetErrorState (); + } + + XamarinAppLibraryAspectState GetState (bool success, ulong formatTag) => new XamarinAppLibraryAspectState (success, formatTag); + XamarinAppLibraryAspectState GetErrorState () => GetState (success: false, formatTag: 0); + } +} diff --git a/tools/apput/src/Package/ApplicationPackage.cs b/tools/apput/src/Package/ApplicationPackage.cs index c364f3ec33a..e690e365cff 100644 --- a/tools/apput/src/Package/ApplicationPackage.cs +++ b/tools/apput/src/Package/ApplicationPackage.cs @@ -95,7 +95,32 @@ public static IAspect LoadAspect (Stream stream, IAspectState state, string? des void CollectSharedLibraries () { - // TODO: find and detect shared libraries + Log.Debug ("Collecting shared libraries"); + foreach (AndroidTargetArch arch in Architectures) { + string libDir = GetNativeLibDir (arch); + + foreach (ZipArchiveEntry? entry in Zip.Entries) { + if (entry == null) { + continue; + } + + // See if it's in the right directory... + if (!entry.FullName.StartsWith (libDir, StringComparison.Ordinal)) { + continue; + } + + // ...and that it's a shared library... + if (!entry.FullName.EndsWith (".so", StringComparison.Ordinal)) { + continue; + } + + Stream? stream = TryGetEntryStream (entry); + SharedLibrary? lib = Detector.FindSharedLibraryAspect (stream, entry.FullName); + if (lib != null) { + SharedLibraries.Add (lib); + } + } + } } void TryDetectArchitectures () @@ -170,33 +195,10 @@ ApplicationRuntime GetRuntimeMaybe () bool TryDetectNativeAotRuntime () { Log.Debug ("Probing for NativeAOT runtime"); - foreach (AndroidTargetArch arch in Architectures) { - string libDir = GetNativeLibDir (arch); - - // TODO: move .so search code to CollectSharedLibraries and just leave NAOT detection here - foreach (ZipArchiveEntry? entry in Zip.Entries) { - if (entry == null) { - continue; - } - - // See if it's in the right directory... - if (!entry.FullName.StartsWith (libDir, StringComparison.Ordinal)) { - continue; - } - - // ...and that it's a shared library... - if (!entry.FullName.EndsWith (".so", StringComparison.Ordinal)) { - continue; - } - - Log.Debug ($"Considering {entry.FullName}"); - // ...and that it has NativeAOT markers - if (!SharedLibraryIsNativeAOT (entry)) { - continue; - } - + foreach (SharedLibrary lib in SharedLibraries) { + var naotLib = lib as NativeAotSharedLibrary; + if (naotLib != null) { Log.Debug ("Found NativeAOT shared library"); - // Yep, got it. Just one hit is enough, no need to check all the architectures return true; } } @@ -204,26 +206,11 @@ bool TryDetectNativeAotRuntime () return false; } - bool SharedLibraryIsNativeAOT (ZipArchiveEntry entry) - { - Stream? stream = TryGetEntryStream (entry.FullName); - if (stream == null) { - return false; - } - - IAspectState aspectState = NativeAotSharedLibrary.ProbeAspect (stream, entry.FullName); - if (!aspectState.Success) { - return false; - } - - return false; - } - void TryLoadXamarinAppLibraries () { foreach (AndroidTargetArch arch in Architectures) { string libPath = GetNativeLibFile (arch, "libxamarin-app.so"); - LibXamarinApp? lib = TryLoadLibXamarinApp (libPath); + XamarinAppSharedLibrary? lib = TryLoadLibXamarinApp (libPath); if (lib == null) { continue; } @@ -231,7 +218,7 @@ void TryLoadXamarinAppLibraries () } } - LibXamarinApp? TryLoadLibXamarinApp (string libPath) + XamarinAppSharedLibrary? TryLoadLibXamarinApp (string libPath) { Stream? libStream = TryGetEntryStream (libPath); if (libStream == null) { @@ -240,14 +227,14 @@ void TryLoadXamarinAppLibraries () string fullLibPath = $"{Description}@!{libPath}"; try { - IAspectState state = LibXamarinApp.ProbeAspect (libStream, fullLibPath); + IAspectState state = XamarinAppSharedLibrary.ProbeAspect (libStream, fullLibPath); if (!state.Success) { Log.Debug ($"Assembly store '{libPath}' is not in a supported format"); libStream.Close (); return null; } - return (LibXamarinApp)LibXamarinApp.LoadAspect (libStream, state, fullLibPath); + return (XamarinAppSharedLibrary)XamarinAppSharedLibrary.LoadAspect (libStream, state, fullLibPath); } catch (Exception ex) { Log.Debug ($"Failed to load Xamarin app library '{libPath}'. Exception thrown:", ex); return null; @@ -342,8 +329,18 @@ void TryLoadAndroidManifest () return null; } + return TryGetEntryStream (entry, extractToMemory); + } catch (Exception ex) { + Log.Debug ($"Failed to load entry '{path}' from the archive.", ex); + return null; + } + } + + Stream? TryGetEntryStream (ZipArchiveEntry entry, bool extractToMemory = false) + { + try { if (extractToMemory) { - Log.Debug ($"Extracting entry '{path}' to a memory stream"); + Log.Debug ($"Extracting entry '{entry.FullName}' to a memory stream"); using var inputStream = entry.Open (); var outputStream = new MemoryStream (); inputStream.CopyTo (outputStream); @@ -354,11 +351,11 @@ void TryLoadAndroidManifest () string tempFile = Path.GetTempFileName (); TempFileManager.RegisterFile (tempFile); - Log.Debug ($"Extracting entry '{path}' to '{tempFile}'"); + Log.Debug ($"Extracting entry '{entry.FullName}' to '{tempFile}'"); entry.ExtractToFile (tempFile, overwrite: true); return File.OpenRead (tempFile); } catch (Exception ex) { - Log.Debug ($"Failed to load entry '{path}' from the archive.", ex); + Log.Debug ($"Failed to load entry '{entry.FullName}' from the archive.", ex); return null; } } diff --git a/tools/apput/src/Reporter.cs b/tools/apput/src/Reporter.cs index 5d1cd5674fb..193452fef20 100644 --- a/tools/apput/src/Reporter.cs +++ b/tools/apput/src/Reporter.cs @@ -84,11 +84,20 @@ static bool IsReporterForAspect (Type type, Type aspectType, Type[] ctorArgs, ou return false; } - var attr = type.GetCustomAttribute (); - if (attr == null || attr.AspectType != aspectType) { + bool found = false; + foreach (AspectReporterAttribute attr in type.GetCustomAttributes ()) { + if (attr.AspectType != aspectType) { + continue; + } + found = true; + break; + } + + if (!found) { return false; } + Log.Debug ($"Found reporter '{type}' for '{aspectType}'"); ctor = type.GetConstructor (ctorArgs); if (ctor == null) { throw new InvalidOperationException ($"Internal error: type '{type}' claims to be a reporter for '{aspectType}' but lacks the correct public constructor."); diff --git a/tools/apput/src/Reporters/ApplicationPackageReporter.cs b/tools/apput/src/Reporters/ApplicationPackageReporter.cs new file mode 100644 index 00000000000..b90909f3a09 --- /dev/null +++ b/tools/apput/src/Reporters/ApplicationPackageReporter.cs @@ -0,0 +1,22 @@ +namespace ApplicationUtility; + +[AspectReporter (typeof (PackageAPK))] +[AspectReporter (typeof (PackageAAB))] +[AspectReporter (typeof (PackageBase))] +class ApplicationPackageReporter : BaseReporter +{ + readonly ApplicationPackage package; + + protected override string AspectName => ApplicationPackage.AspectName; + protected override string ShortDescription => package.PackageFormat; + + public ApplicationPackageReporter (ApplicationPackage package) + { + this.package = package; + } + + protected override void DoReport () + { + throw new System.NotImplementedException (); + } +} From 344941ac67eaa1553922c62516b9086c44478ffd Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 25 Sep 2025 18:26:56 +0200 Subject: [PATCH 18/32] Application package reporter continued --- tools/apput/src/Android/AndroidManifest.cs | 136 +++++++++++++++++- tools/apput/src/Package/ApplicationPackage.cs | 1 + .../Reporters/ApplicationPackageReporter.cs | 13 +- tools/apput/src/Reporters/BaseReporter.cs | 45 +++++- 4 files changed, 188 insertions(+), 7 deletions(-) diff --git a/tools/apput/src/Android/AndroidManifest.cs b/tools/apput/src/Android/AndroidManifest.cs index e709c053641..f3379e7f82b 100644 --- a/tools/apput/src/Android/AndroidManifest.cs +++ b/tools/apput/src/Android/AndroidManifest.cs @@ -7,14 +7,18 @@ namespace ApplicationUtility; public class AndroidManifest : IAspect { public string Description { get; } + public string? PackageName { get; } - AXMLParser? binaryParser; XmlDocument? xmlDoc; + XmlNamespaceManager? nsmgr; AndroidManifest (AXMLParser binaryParser, string? description) { Description = String.IsNullOrEmpty (description) ? "Android manifest" : description; - this.binaryParser = binaryParser; + Read (binaryParser); + + nsmgr = PrepareForReading (xmlDoc); + PackageName = TryGetPackageName (xmlDoc, nsmgr); } public static IAspect LoadAspect (Stream stream, IAspectState state, string? description) @@ -30,7 +34,6 @@ public static IAspect LoadAspect (Stream stream, IAspectState state, string? des } else { throw new NotImplementedException (); } - ret.Read (); return ret; } @@ -62,7 +65,7 @@ public static IAspectState ProbeAspect (Stream stream, string? description) return new BasicAspectState (success: false); } - void Read () + void Read (AXMLParser? binaryParser) { if (binaryParser == null) { throw new NotImplementedException (); @@ -76,6 +79,131 @@ void Read () Log.Debug ($"'{Description}' loaded and parsed correctly."); } + static XmlNamespaceManager? PrepareForReading (XmlDocument? doc) + { + if (doc == null) { + return null; + } + + var nsmgr = new XmlNamespaceManager (doc.NameTable); + nsmgr.AddNamespace ("android", "http://schemas.android.com/apk/res/android"); + return nsmgr; + } + + static bool ValidXmlContext (XmlDocument? doc, XmlNamespaceManager? nsmgr, out XmlElement? root) + { + root = null; + if (doc == null || nsmgr == null) { + return false; + } + + root = doc.DocumentElement; + return root != null; + } + + static string? TryGetMainActivity (XmlDocument? doc, XmlNamespaceManager? nsmgr) + { + if (!ValidXmlContext (doc, nsmgr, out XmlElement? root)) { + return null; + } + + XmlNodeList? activities = root!.SelectNodes ("//manifest/application/activity", nsmgr!); + if (activities == null || activities.Count == 0) { + return null; + } + + foreach (XmlNode activity in activities) { + string? name = GetLauncherActivityName (activity); + if (name == null) { + continue; + } + + return name; + } + + return null; + + string? GetLauncherActivityName (XmlNode activity) + { + XmlNodeList? intentFilters = activity.SelectNodes ("./intent-filter", nsmgr!); + if (intentFilters == null || intentFilters.Count == 0) { + return null; + } + + bool isMain = false; + foreach (XmlNode intentFilter in intentFilters) { + XmlNodeList? actions = activity.SelectNodes ("./action", nsmgr!); + if (actions == null || actions.Count == 0) { + continue; + } + + if (!HaveNodeWithNameAttribute (actions, "android.intent.action.MAIN")) { + continue; + } + + XmlNodeList? categories = activity.SelectNodes ("./category", nsmgr!); + if (categories == null || categories.Count == 0) { + continue; + } + + if (!HaveNodeWithNameAttribute (categories, "android.intent.category.LAUNCHER")) { + continue; + } + + isMain = true; + break; + } + + if (!isMain) { + return null; + } + + var attr = activity.Attributes?.GetNamedItem ("android:name"); + if (attr == null) { + return null; + } + + return attr.Value; + } + + bool HaveNodeWithNameAttribute (XmlNodeList list, string nameValue) + { + foreach (XmlNode? node in list) { + var attr = node?.Attributes?.GetNamedItem ("android:name"); + if (attr == null || String.IsNullOrEmpty (attr.Value)) { + continue; + } + + if (attr.Value == nameValue) { + return true; + } + } + + return false; + } + } + + static string? TryGetPackageName (XmlDocument? doc, XmlNamespaceManager? nsmgr) + { + Log.Debug ("Trying to read package name"); + if (!ValidXmlContext (doc, nsmgr, out XmlElement? root) || root == null) { + return null; + } + + XmlNode? manifest = root.SelectSingleNode ("//manifest", nsmgr); + if (manifest == null || manifest.Attributes == null) { + Log.Debug ("`manifest` element not found or it has no attributes"); + return null; + } + + XmlNode? package = manifest.Attributes.GetNamedItem ("package"); + if (package == null) { + Log.Debug ("`package` attribute in the `manifest` element not found"); + } + + return package == null ? null : package.Value; + } + static XmlDocument ParsePlainXML (Stream stream) { stream.Seek (0, SeekOrigin.Begin); diff --git a/tools/apput/src/Package/ApplicationPackage.cs b/tools/apput/src/Package/ApplicationPackage.cs index e690e365cff..be8a585bba4 100644 --- a/tools/apput/src/Package/ApplicationPackage.cs +++ b/tools/apput/src/Package/ApplicationPackage.cs @@ -312,6 +312,7 @@ void TryLoadAndroidManifest () return; } manifest = (AndroidManifest)AndroidManifest.LoadAspect (manifestStream, manifestState, AndroidManifestPath); + PackageName = manifest.PackageName ?? String.Empty; } catch (Exception ex) { Log.Debug ($"Failed to load android manifest '{AndroidManifestPath}' from the archive.", ex); } diff --git a/tools/apput/src/Reporters/ApplicationPackageReporter.cs b/tools/apput/src/Reporters/ApplicationPackageReporter.cs index b90909f3a09..0a83332e434 100644 --- a/tools/apput/src/Reporters/ApplicationPackageReporter.cs +++ b/tools/apput/src/Reporters/ApplicationPackageReporter.cs @@ -17,6 +17,17 @@ public ApplicationPackageReporter (ApplicationPackage package) protected override void DoReport () { - throw new System.NotImplementedException (); + WriteAspectDesc (package.PackageFormat); + + WriteSubsectionBanner ("Generic Android application information"); + WriteNativeArch (package.Architectures); + WriteItem ("Package name", ValueOrNone (package.PackageName)); + WriteItem ("Main activity", ValueOrNone (package.MainActivity)); + WriteYesNo ("Valid Android package", package.ValidAndroidPackage); + WriteYesNo ("Signed", package.Signed); + WriteYesNo ("Debuggable", package.Debuggable); + + WriteSubsectionBanner (".NET for Android application information"); + WriteItem ("Runtime", package.Runtime.ToString ()); } } diff --git a/tools/apput/src/Reporters/BaseReporter.cs b/tools/apput/src/Reporters/BaseReporter.cs index be9e2deae51..34410dcf9cc 100644 --- a/tools/apput/src/Reporters/BaseReporter.cs +++ b/tools/apput/src/Reporters/BaseReporter.cs @@ -1,10 +1,17 @@ using System; +using System.Collections.Generic; +using System.Linq; + +using Xamarin.Android.Tools; namespace ApplicationUtility; abstract class BaseReporter : IReporter { - protected const ConsoleColor LabelColor = ConsoleColor.White; + const string NativeArchitectureLabel = "Native target architecture"; + const string NativeArchitecturesLabel = NativeArchitectureLabel + "s"; + + protected const ConsoleColor LabelColor = ConsoleColor.Gray; protected const ConsoleColor ValidValueColor = ConsoleColor.Green; protected const ConsoleColor InvalidValueColor = ConsoleColor.Red; protected const ConsoleColor BannerColor = ConsoleColor.Cyan; @@ -21,6 +28,12 @@ public void Report () protected abstract void DoReport (); + protected void WriteSubsectionBanner (string text) + { + WriteLine (); + WriteLine (BannerColor, $"## {text}"); + } + protected void WriteAspectDesc (string text) { WriteItem ("Aspect type", text); @@ -28,9 +41,37 @@ protected void WriteAspectDesc (string text) protected void WriteNativeArch (NativeArchitecture arch) { - WriteItem ("Native target architecture", arch.ToString ()); + WriteItem (NativeArchitectureLabel, arch.ToString ()); } + protected void WriteNativeArch (AndroidTargetArch arch) + { + WriteItem (NativeArchitectureLabel, arch.ToString ()); + } + + protected void WriteNativeArch (ICollection arches) + { + if (arches.Count == 1) { + WriteNativeArch (arches.First ()); + return; + } + + WriteLabel (NativeArchitecturesLabel); + if (arches.Count == 0) { + WriteLine (InvalidValueColor, "none"); + return; + } + + var architectures = new List (); + foreach (AndroidTargetArch arch in arches) { + architectures.Add (arch.ToString ()); + } + + WriteLine (ValidValueColor, String.Join (", ", architectures)); + } + + protected void WriteYesNo (string label, bool value) => WriteItem (label, YesNo (value)); + protected void WriteLabel (string label) { Write (LabelColor, $"{label}: "); From 219e8c9d62da4591a4fde3fd7e6b97a64f0213f2 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 26 Sep 2025 11:10:53 +0200 Subject: [PATCH 19/32] libxamarin-app.so reporter (beginnings) --- .../src/Reporters/SharedLibraryReporter.cs | 3 +++ .../XamarinAppSharedLibraryReporter.cs | 23 +++++++++++++++++++ tools/apput/src/apput.csproj | 2 +- 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 tools/apput/src/Reporters/XamarinAppSharedLibraryReporter.cs diff --git a/tools/apput/src/Reporters/SharedLibraryReporter.cs b/tools/apput/src/Reporters/SharedLibraryReporter.cs index b351962b218..216df0f4358 100644 --- a/tools/apput/src/Reporters/SharedLibraryReporter.cs +++ b/tools/apput/src/Reporters/SharedLibraryReporter.cs @@ -19,6 +19,8 @@ public SharedLibraryReporter (SharedLibrary library) protected override void DoReport () { WriteAspectDesc (LibraryKind); + + WriteSubsectionBanner ("Generic ELF shared library info"); WriteNativeArch (library.TargetArchitecture); if (library.HasSoname) { @@ -28,6 +30,7 @@ protected override void DoReport () WriteDebugInfoDesc (); if (library.HasAndroidIdent) { + WriteSubsectionBanner ("Android-specific ELF shared library info"); WriteItem ("Android ident", ValueOrNone (library.AndroidIdent)); } } diff --git a/tools/apput/src/Reporters/XamarinAppSharedLibraryReporter.cs b/tools/apput/src/Reporters/XamarinAppSharedLibraryReporter.cs new file mode 100644 index 00000000000..6fa72bd8f65 --- /dev/null +++ b/tools/apput/src/Reporters/XamarinAppSharedLibraryReporter.cs @@ -0,0 +1,23 @@ +namespace ApplicationUtility; + +[AspectReporter (typeof (XamarinAppSharedLibrary))] +class XamarinAppSharedLibraryReporter : SharedLibraryReporter +{ + readonly XamarinAppSharedLibrary library; + + protected override string AspectName => XamarinAppSharedLibrary.AspectName; + protected override string LibraryKind => "Xamarin.Android App shared library"; + + public XamarinAppSharedLibraryReporter (XamarinAppSharedLibrary library) + : base (library) + { + this.library = library; + } + + protected override void DoReport () + { + base.DoReport (); + WriteSubsectionBanner ("Xamarin.Android app library info"); + WriteItem ("Format tag", $"0x{library.FormatTag:x}"); + } +} diff --git a/tools/apput/src/apput.csproj b/tools/apput/src/apput.csproj index e70dffcd648..c66ec1f73ad 100644 --- a/tools/apput/src/apput.csproj +++ b/tools/apput/src/apput.csproj @@ -7,7 +7,7 @@ 0.0.1 $(DotNetStableTargetFramework) false - ../../bin/$(Configuration)/bin/apput + ..\..\..\bin\$(Configuration)\bin\apput Exe true enable From 15c62f86f05fb0aa7dbc89afbc58817a392280dd Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 26 Sep 2025 11:46:01 +0200 Subject: [PATCH 20/32] Some more basic app info from the manifest --- tools/apput/src/Android/AndroidManifest.cs | 55 ++++++++++++++++++- tools/apput/src/Native/AnELF.cs | 2 +- tools/apput/src/Package/ApplicationPackage.cs | 32 ++++++----- .../Reporters/ApplicationPackageReporter.cs | 15 ++++- 4 files changed, 85 insertions(+), 19 deletions(-) diff --git a/tools/apput/src/Android/AndroidManifest.cs b/tools/apput/src/Android/AndroidManifest.cs index f3379e7f82b..1268b3c4f88 100644 --- a/tools/apput/src/Android/AndroidManifest.cs +++ b/tools/apput/src/Android/AndroidManifest.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Xml; @@ -7,7 +8,12 @@ namespace ApplicationUtility; public class AndroidManifest : IAspect { public string Description { get; } + public string? MainActivity { get; } + public string? MinSdkVersion { get; } public string? PackageName { get; } + public string? TargetSdkVersion { get; } + public List? Permissions { get; } + public XmlDocument? RawXML => xmlDoc; XmlDocument? xmlDoc; XmlNamespaceManager? nsmgr; @@ -19,6 +25,9 @@ public class AndroidManifest : IAspect nsmgr = PrepareForReading (xmlDoc); PackageName = TryGetPackageName (xmlDoc, nsmgr); + MainActivity = TryGetMainActivity (xmlDoc, nsmgr); + (MinSdkVersion, TargetSdkVersion) = TryGetSdkVersions (xmlDoc, nsmgr); + Permissions = TryGetPermissions (xmlDoc, nsmgr); } public static IAspect LoadAspect (Stream stream, IAspectState state, string? description) @@ -101,6 +110,48 @@ static bool ValidXmlContext (XmlDocument? doc, XmlNamespaceManager? nsmgr, out X return root != null; } + static List? TryGetPermissions (XmlDocument? doc, XmlNamespaceManager? nsmgr) + { + if (!ValidXmlContext (doc, nsmgr, out XmlElement? root)) { + return null; + } + + XmlNodeList? permissions = root!.SelectNodes ("//manifest/uses-permission"); + if (permissions == null || permissions.Count == 0) { + return null; + } + + var ret = new List (); + foreach (XmlNode permission in permissions) { + var name = permission.Attributes?.GetNamedItem ("android:name"); + if (name == null || String.IsNullOrEmpty (name.Value)) { + continue; + } + + ret.Add (name.Value); + } + + ret.Sort (); + return ret; + } + + static (string? minSdk, string? targetSdk) TryGetSdkVersions (XmlDocument? doc, XmlNamespaceManager? nsmgr) + { + if (!ValidXmlContext (doc, nsmgr, out XmlElement? root)) { + return (null, null); + } + + XmlNode? usesSdk = root!.SelectSingleNode ("//manifest/uses-sdk"); + if (usesSdk == null) { + return (null, null); + } + + var minSdkVersionAttr = usesSdk.Attributes?.GetNamedItem ("android:minSdkVersion"); + var targetSdkVersionAttr = usesSdk.Attributes?.GetNamedItem ("android:targetSdkVersion"); + + return (minSdkVersionAttr?.Value, targetSdkVersionAttr?.Value); + } + static string? TryGetMainActivity (XmlDocument? doc, XmlNamespaceManager? nsmgr) { if (!ValidXmlContext (doc, nsmgr, out XmlElement? root)) { @@ -132,7 +183,7 @@ static bool ValidXmlContext (XmlDocument? doc, XmlNamespaceManager? nsmgr, out X bool isMain = false; foreach (XmlNode intentFilter in intentFilters) { - XmlNodeList? actions = activity.SelectNodes ("./action", nsmgr!); + XmlNodeList? actions = intentFilter.SelectNodes ("./action", nsmgr!); if (actions == null || actions.Count == 0) { continue; } @@ -141,7 +192,7 @@ static bool ValidXmlContext (XmlDocument? doc, XmlNamespaceManager? nsmgr, out X continue; } - XmlNodeList? categories = activity.SelectNodes ("./category", nsmgr!); + XmlNodeList? categories = intentFilter.SelectNodes ("./category", nsmgr!); if (categories == null || categories.Count == 0) { continue; } diff --git a/tools/apput/src/Native/AnELF.cs b/tools/apput/src/Native/AnELF.cs index b4b8f126a60..0c2630ab0a3 100644 --- a/tools/apput/src/Native/AnELF.cs +++ b/tools/apput/src/Native/AnELF.cs @@ -289,7 +289,7 @@ public static bool TryLoad (Stream stream, string filePath, out AnELF? anElf) ISection? sec = GetSection (elf, RodataSectionName); if (sec == null) { - Log.Warning ("${filePath} does not contain read-only data section ('{RodataSectionName}')"); + Log.Warning ($"{filePath} does not contain read-only data section ('{RodataSectionName}')"); return false; } ISection rodata = sec; diff --git a/tools/apput/src/Package/ApplicationPackage.cs b/tools/apput/src/Package/ApplicationPackage.cs index be8a585bba4..e1308d0f70e 100644 --- a/tools/apput/src/Package/ApplicationPackage.cs +++ b/tools/apput/src/Package/ApplicationPackage.cs @@ -32,27 +32,30 @@ public abstract class ApplicationPackage : IAspect "META-INF/ANDROIDD.RSA", }; + AndroidManifest? manifest; + public static string AspectName { get; } = "Application package"; - public abstract string PackageFormat { get; } - protected abstract string NativeLibDirBase { get; } protected abstract string AndroidManifestPath { get; } + protected abstract string NativeLibDirBase { get; } + public abstract string PackageFormat { get; } - protected ZipArchive Zip { get; } - public string? Description { get; } - - public bool Signed { get; protected set; } - public bool ValidAndroidPackage { get; protected set; } - public bool Debuggable { get; protected set; } - public ApplicationRuntime Runtime { get; protected set; } = ApplicationRuntime.Unknown; - public string PackageName { get; protected set; } = ""; - public string MainActivity { get; protected set; } = ""; - public List? AssemblyStores { get; protected set; } + public AndroidManifest? AndroidManifest => manifest; public List Architectures { get; protected set; } = new (); + public List? AssemblyStores { get; protected set; } + public bool Debuggable { get; protected set; } + public string? Description { get; } + public string? MainActivity => manifest?.MainActivity; + public string? MinSdkVersion => manifest?.MinSdkVersion; public List NativeAppInfos { get; protected set; } = new (); + public string? PackageName => manifest?.PackageName; + public List? Permissions => manifest?.Permissions; + public ApplicationRuntime Runtime { get; protected set; } = ApplicationRuntime.Unknown; public List SharedLibraries { get; protected set; } = new (); - - AndroidManifest? manifest; + public bool Signed { get; protected set; } + public string? TargetSdkVersion => manifest?.TargetSdkVersion; + public bool ValidAndroidPackage { get; protected set; } + protected ZipArchive Zip { get; } protected ApplicationPackage (ZipArchive zip, string? description) { @@ -312,7 +315,6 @@ void TryLoadAndroidManifest () return; } manifest = (AndroidManifest)AndroidManifest.LoadAspect (manifestStream, manifestState, AndroidManifestPath); - PackageName = manifest.PackageName ?? String.Empty; } catch (Exception ex) { Log.Debug ($"Failed to load android manifest '{AndroidManifestPath}' from the archive.", ex); } diff --git a/tools/apput/src/Reporters/ApplicationPackageReporter.cs b/tools/apput/src/Reporters/ApplicationPackageReporter.cs index 0a83332e434..6e0eed03692 100644 --- a/tools/apput/src/Reporters/ApplicationPackageReporter.cs +++ b/tools/apput/src/Reporters/ApplicationPackageReporter.cs @@ -21,12 +21,25 @@ protected override void DoReport () WriteSubsectionBanner ("Generic Android application information"); WriteNativeArch (package.Architectures); + WriteYesNo ("Valid Android package", package.ValidAndroidPackage); WriteItem ("Package name", ValueOrNone (package.PackageName)); WriteItem ("Main activity", ValueOrNone (package.MainActivity)); - WriteYesNo ("Valid Android package", package.ValidAndroidPackage); + WriteItem ("Minimum SDK version", ValueOrNone (package.MinSdkVersion)); + WriteItem ("Target SDK version", ValueOrNone (package.TargetSdkVersion)); WriteYesNo ("Signed", package.Signed); WriteYesNo ("Debuggable", package.Debuggable); + if (package.Permissions == null || package.Permissions.Count == 0) { + WriteItem ("Permissions", "none"); + } else { + WriteLine (LabelColor, "Permissions:"); + + foreach (string permission in package.Permissions) { + Write (LabelColor, " * "); + WriteLine (ValidValueColor, permission); + } + } + WriteSubsectionBanner (".NET for Android application information"); WriteItem ("Runtime", package.Runtime.ToString ()); } From 100f5c28272dddf3848bcaea0b80f2c5f3cfd419 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 26 Sep 2025 12:30:01 +0200 Subject: [PATCH 21/32] Revamp shared libraries aspect states, lighter now --- tools/apput/src/Detector.cs | 2 + .../apput/src/Native/MonoAotSharedLibrary.cs | 47 ++++++++++++++++++ .../Native/MonoAotSharedLibraryAspectState.cs | 12 +++++ .../src/Native/NativeAotSharedLibrary.cs | 23 +++++---- .../NativeAotSharedLibraryAspectState.cs | 10 ++++ tools/apput/src/Native/SharedLibrary.cs | 49 ++++++++++--------- .../src/Native/SharedLibraryAspectState.cs | 14 ++++++ .../Native/XamarinAppLibraryAspectState.cs | 8 +-- .../src/Native/XamarinAppSharedLibrary.cs | 14 +++--- 9 files changed, 134 insertions(+), 45 deletions(-) create mode 100644 tools/apput/src/Native/MonoAotSharedLibrary.cs create mode 100644 tools/apput/src/Native/MonoAotSharedLibraryAspectState.cs create mode 100644 tools/apput/src/Native/NativeAotSharedLibraryAspectState.cs create mode 100644 tools/apput/src/Native/SharedLibraryAspectState.cs diff --git a/tools/apput/src/Detector.cs b/tools/apput/src/Detector.cs index 8d6a12ffc12..92bddde782c 100644 --- a/tools/apput/src/Detector.cs +++ b/tools/apput/src/Detector.cs @@ -22,12 +22,14 @@ public class Detector typeof (ApplicationAssembly), typeof (NativeAotSharedLibrary), typeof (XamarinAppSharedLibrary), + typeof (MonoAotSharedLibrary), typeof (SharedLibrary), }; readonly static List KnownSharedLibraryAspects = new () { typeof (NativeAotSharedLibrary), typeof (XamarinAppSharedLibrary), + typeof (MonoAotSharedLibrary), typeof (SharedLibrary), }; diff --git a/tools/apput/src/Native/MonoAotSharedLibrary.cs b/tools/apput/src/Native/MonoAotSharedLibrary.cs new file mode 100644 index 00000000000..c61de908552 --- /dev/null +++ b/tools/apput/src/Native/MonoAotSharedLibrary.cs @@ -0,0 +1,47 @@ +using System; +using System.IO; +using ELFSharp.ELF; + +namespace ApplicationUtility; + +class MonoAotSharedLibrary : SharedLibrary +{ + const string MonoAotDataSymbol = "mono_aot_file_info"; + + protected MonoAotSharedLibrary (Stream stream, string libraryName, MonoAotSharedLibraryAspectState state) + : base (stream, libraryName, state) + {} + + public new static IAspect LoadAspect (Stream stream, IAspectState? state, string? description) + { + if (String.IsNullOrEmpty (description)) { + throw new ArgumentException ("Must be a shared library name", nameof (description)); + } + + var libState = EnsureValidAspectState (state); + return new MonoAotSharedLibrary (stream, description, libState); + } + + public static new IAspectState ProbeAspect (Stream stream, string? description) => IsMonoAotSharedLibrary (stream, description); + + static MonoAotSharedLibraryAspectState IsMonoAotSharedLibrary (Stream stream, string? description) + { + Log.Debug ($"Checking if '{description}' is a Mono AOT shared library"); + if (!IsSupportedELFSharedLibrary (stream, description, out IELF? elf) || elf == null) { + return GetErrorState (); + } + + if (!AnELF.TryLoad (stream, description ?? String.Empty, out AnELF? anElf) || anElf == null) { + return GetErrorState (); + } + + if (!anElf.HasSymbol (MonoAotDataSymbol)) { + Log.Debug ($"Symbol '{MonoAotDataSymbol}' missing, not a Mono AOT shared library"); + return GetErrorState (); + } + + return new MonoAotSharedLibraryAspectState (true, anElf); + + MonoAotSharedLibraryAspectState GetErrorState () => new MonoAotSharedLibraryAspectState (false, null); + } +} diff --git a/tools/apput/src/Native/MonoAotSharedLibraryAspectState.cs b/tools/apput/src/Native/MonoAotSharedLibraryAspectState.cs new file mode 100644 index 00000000000..d975411d683 --- /dev/null +++ b/tools/apput/src/Native/MonoAotSharedLibraryAspectState.cs @@ -0,0 +1,12 @@ +namespace ApplicationUtility; + +class MonoAotSharedLibraryAspectState : SharedLibraryAspectState +{ + public AnELF? LoadedELF { get; } + + public MonoAotSharedLibraryAspectState (bool success, AnELF? elf) + : base (success, elf?.AnyELF) + { + LoadedELF = elf; + } +} diff --git a/tools/apput/src/Native/NativeAotSharedLibrary.cs b/tools/apput/src/Native/NativeAotSharedLibrary.cs index 41e37fffa85..53b3c46deb9 100644 --- a/tools/apput/src/Native/NativeAotSharedLibrary.cs +++ b/tools/apput/src/Native/NativeAotSharedLibrary.cs @@ -16,8 +16,8 @@ public class NativeAotSharedLibrary : SharedLibrary (".hydrated", SectionType.NoBits), }; - protected NativeAotSharedLibrary (Stream stream, string libraryName) - : base (stream, libraryName) + protected NativeAotSharedLibrary (Stream stream, string libraryName, IAspectState state) + : base (stream, libraryName, state) {} public new static IAspect LoadAspect (Stream stream, IAspectState? state, string? description) @@ -26,28 +26,27 @@ protected NativeAotSharedLibrary (Stream stream, string libraryName) throw new ArgumentException ("Must be a shared library name", nameof (description)); } - if (!IsNativeAotSharedLibrary (stream, description)) { - throw new InvalidOperationException ("Stream is not a supported NativeAOT shared library"); - } - - return new NativeAotSharedLibrary (stream, description); + var libState = EnsureValidAspectState (state); + return new NativeAotSharedLibrary (stream, description, libState); } - public new static IAspectState ProbeAspect (Stream stream, string? description) => new BasicAspectState (IsNativeAotSharedLibrary (stream, description)); + public new static IAspectState ProbeAspect (Stream stream, string? description) => IsNativeAotSharedLibrary (stream, description); - static bool IsNativeAotSharedLibrary (Stream stream, string? description) + static NativeAotSharedLibraryAspectState IsNativeAotSharedLibrary (Stream stream, string? description) { if (!IsSupportedELFSharedLibrary (stream, description, out IELF? elf) || elf == null) { - return false; + return GetErrorState (); } // Just one match should be enough foreach (var naotSection in NativeAotSections) { if (HasSection (elf, description, naotSection.sectionName, naotSection.type)) { - return true; + return new NativeAotSharedLibraryAspectState (true, elf); } } - return false; + return GetErrorState (); + + NativeAotSharedLibraryAspectState GetErrorState () => new NativeAotSharedLibraryAspectState (false, null); } } diff --git a/tools/apput/src/Native/NativeAotSharedLibraryAspectState.cs b/tools/apput/src/Native/NativeAotSharedLibraryAspectState.cs new file mode 100644 index 00000000000..7beb92f9e60 --- /dev/null +++ b/tools/apput/src/Native/NativeAotSharedLibraryAspectState.cs @@ -0,0 +1,10 @@ +using ELFSharp.ELF; + +namespace ApplicationUtility; + +class NativeAotSharedLibraryAspectState : SharedLibraryAspectState +{ + public NativeAotSharedLibraryAspectState (bool success, IELF? elf) + : base (success, elf) + {} +} diff --git a/tools/apput/src/Native/SharedLibrary.cs b/tools/apput/src/Native/SharedLibrary.cs index 707679705ba..2271980d943 100644 --- a/tools/apput/src/Native/SharedLibrary.cs +++ b/tools/apput/src/Native/SharedLibrary.cs @@ -50,11 +50,14 @@ public class SharedLibrary : IAspect, IDisposable protected IELF ELF => elf; - protected SharedLibrary (Stream stream, string libraryName) + protected SharedLibrary (Stream stream, string libraryName, IAspectState state) { + var libState = EnsureValidAspectState (state); + this.libraryStream = stream; this.libraryName = libraryName; - (elf, is64Bit, nativeArch) = LoadELF (stream, libraryName); + elf = libState.ElfImage!; + (is64Bit, nativeArch) = ValidateELF (libState.ElfImage!, libraryName); (payloadOffset, payloadSize) = FindAndroidPayload (elf); libraryAlignment = DetectAlignment (elf, is64Bit); (hasDebugInfo, debugLink) = DetectDebugInfo (elf, libraryName); @@ -63,20 +66,31 @@ protected SharedLibrary (Stream stream, string libraryName) soname = GetSoname (elf, is64Bit); } + protected static T EnsureValidAspectState (IAspectState? state) where T: IAspectState + { + if (!(state is SharedLibraryAspectState libState)) { + throw new InvalidOperationException ("Internal error: invalid aspect state, call ProbeAspect to get one."); + } + + if (!libState.Success || libState.ElfImage == null) { + throw new InvalidOperationException ("Internal error: ProbeAspect failed to detect a valid shared library."); + } + + return (T)((object)libState); + } + public static IAspect LoadAspect (Stream stream, IAspectState? state, string? description) { if (String.IsNullOrEmpty (description)) { throw new ArgumentException ("Must be a shared library name", nameof (description)); } - if (!IsSupportedELFSharedLibrary (stream, description)) { - throw new InvalidOperationException ("Stream is not a supported ELF shared library"); - } + var libState = EnsureValidAspectState (state); - return new SharedLibrary (stream, description); + return new SharedLibrary (stream, description, libState); } - public static IAspectState ProbeAspect (Stream stream, string? description) => new BasicAspectState (IsSupportedELFSharedLibrary (stream, description)); + public static IAspectState ProbeAspect (Stream stream, string? description) => IsSupportedELFSharedLibrary (stream, description); /// /// If the library has .NET for Android payload section, this @@ -164,35 +178,26 @@ protected static bool IsSupportedELFSharedLibrary (Stream stream, string? descri return supported; } - protected static bool IsSupportedELFSharedLibrary (Stream stream, string? description) + protected static IAspectState IsSupportedELFSharedLibrary (Stream stream, string? description) { if (!IsSupportedELFSharedLibrary (stream, description, out IELF? elf) || elf == null) { - return false; + return new SharedLibraryAspectState (false, null); } - elf.Dispose (); - return true; + return new SharedLibraryAspectState (true, elf); } - // We assume below that stream corresponds to a valid and supported by us ELF image. This should have been asserted by - // the `LoadAspect` method. - (IELF elf, bool is64bit, NativeArchitecture nativeArch) LoadELF (Stream stream, string? libraryName) + (bool is64bit, NativeArchitecture nativeArch) ValidateELF (IELF elf, string? libraryName) { - stream.Seek (0, SeekOrigin.Begin); - if (!ELFReader.TryLoad (stream, shouldOwnStream: false, out IELF? elf) || elf == null) { - Log.Debug ($"SharedLibrary: stream ('{libraryName}') failed to load as an ELF image."); - throw new InvalidOperationException ($"Failed to load ELF library '{libraryName}'."); - } - (bool is64, NativeArchitecture arch) = elf.Machine switch { Machine.ARM => (false, NativeArchitecture.Arm), Machine.Intel386 => (false, NativeArchitecture.X86), Machine.AArch64 => (true, NativeArchitecture.Arm64), Machine.AMD64 => (true, NativeArchitecture.X64), - _ => throw new NotSupportedException ($"Unsupported ELF architecture '{elf.Machine}'") + _ => throw new NotSupportedException ($"Unsupported ELF architecture '{elf.Machine}' for '{libraryName}'") }; - return (elf, is64, arch); + return (is64, arch); } (ulong offset, ulong size) FindAndroidPayload (IELF elf) diff --git a/tools/apput/src/Native/SharedLibraryAspectState.cs b/tools/apput/src/Native/SharedLibraryAspectState.cs new file mode 100644 index 00000000000..26b623bab64 --- /dev/null +++ b/tools/apput/src/Native/SharedLibraryAspectState.cs @@ -0,0 +1,14 @@ +using ELFSharp.ELF; + +namespace ApplicationUtility; + +class SharedLibraryAspectState : BasicAspectState +{ + public IELF? ElfImage { get; } + + public SharedLibraryAspectState (bool success, IELF? elf) + : base (success) + { + ElfImage = elf; + } +} diff --git a/tools/apput/src/Native/XamarinAppLibraryAspectState.cs b/tools/apput/src/Native/XamarinAppLibraryAspectState.cs index 02a9bd59f98..36fb5636926 100644 --- a/tools/apput/src/Native/XamarinAppLibraryAspectState.cs +++ b/tools/apput/src/Native/XamarinAppLibraryAspectState.cs @@ -1,12 +1,14 @@ namespace ApplicationUtility; -class XamarinAppLibraryAspectState : BasicAspectState +class XamarinAppLibraryAspectState : SharedLibraryAspectState { + public AnELF? LoadedELF { get; } public ulong FormatTag { get; } - public XamarinAppLibraryAspectState (bool success, ulong formatTag) - : base (success) + public XamarinAppLibraryAspectState (bool success, ulong formatTag, AnELF? elf) + : base (success, elf?.AnyELF) { FormatTag = formatTag; + LoadedELF = elf; } } diff --git a/tools/apput/src/Native/XamarinAppSharedLibrary.cs b/tools/apput/src/Native/XamarinAppSharedLibrary.cs index 6a5e8f49899..0e2393362cf 100644 --- a/tools/apput/src/Native/XamarinAppSharedLibrary.cs +++ b/tools/apput/src/Native/XamarinAppSharedLibrary.cs @@ -13,7 +13,7 @@ class XamarinAppSharedLibrary : SharedLibrary public ulong FormatTag { get; } XamarinAppSharedLibrary (Stream stream, string description, XamarinAppLibraryAspectState state) - : base (stream, description) + : base (stream, description, state) { FormatTag = state.FormatTag; } @@ -24,12 +24,10 @@ class XamarinAppSharedLibrary : SharedLibrary throw new ArgumentException ("Must be a shared library name", nameof (description)); } - if (!IsSupportedELFSharedLibrary (stream, description)) { - throw new InvalidOperationException ("Stream is not a supported ELF shared library"); - } + var libState = EnsureValidAspectState (state); // TODO: this needs to be versioned - return new XamarinAppSharedLibrary (stream, description, (XamarinAppLibraryAspectState)state); + return new XamarinAppSharedLibrary (stream, description, libState); } public static new IAspectState ProbeAspect (Stream stream, string? description) => IsXamarinAppSharedLibrary (stream, description); @@ -51,7 +49,7 @@ static XamarinAppLibraryAspectState IsXamarinAppSharedLibrary (Stream stream, st ulong formatTag = anElf.GetUInt64 (FormatTagSymbol); // TODO: check for presence of a handful of fields more - return GetState (success: true, formatTag); + return GetState (success: true, formatTag, anElf); XamarinAppLibraryAspectState LogMissingSymbolAndReturn (string name) { @@ -59,7 +57,7 @@ XamarinAppLibraryAspectState LogMissingSymbolAndReturn (string name) return GetErrorState (); } - XamarinAppLibraryAspectState GetState (bool success, ulong formatTag) => new XamarinAppLibraryAspectState (success, formatTag); - XamarinAppLibraryAspectState GetErrorState () => GetState (success: false, formatTag: 0); + XamarinAppLibraryAspectState GetState (bool success, ulong formatTag, AnELF? elf) => new XamarinAppLibraryAspectState (success, formatTag, elf); + XamarinAppLibraryAspectState GetErrorState () => GetState (success: false, formatTag: 0, elf: null); } } From 2aa7a9d3d65ab0fbb2cd516d3e7bd5e507979ba0 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 26 Sep 2025 16:48:53 +0200 Subject: [PATCH 22/32] Various odds and ends --- tools/apput/src/Android/AndroidManifest.cs | 1 + .../apput/src/AssemblyStore/AssemblyStore.cs | 19 ++- .../AssemblyStore/AssemblyStoreAspectState.cs | 2 - tools/apput/src/Common/Log.cs | 6 + tools/apput/src/Detector.cs | 12 +- tools/apput/src/Native/AnELF.cs | 46 +++---- .../DotNetAndroidWrapperSharedLibrary.cs | 121 ++++++++++++++++++ ...tAndroidWrapperSharedLibraryAspectState.cs | 12 ++ tools/apput/src/Native/ELF32.cs | 6 +- tools/apput/src/Native/ELF64.cs | 6 +- .../apput/src/Native/MonoAotSharedLibrary.cs | 1 + tools/apput/src/Native/SharedLibrary.cs | 74 +---------- .../src/Native/SharedLibraryAspectState.cs | 2 + tools/apput/src/Package/ApplicationPackage.cs | 7 + .../Reporters/ApplicationPackageReporter.cs | 27 ++++ tools/apput/src/Reporters/BaseReporter.cs | 23 ++++ 16 files changed, 256 insertions(+), 109 deletions(-) create mode 100644 tools/apput/src/Native/DotNetAndroidWrapperSharedLibrary.cs create mode 100644 tools/apput/src/Native/DotNetAndroidWrapperSharedLibraryAspectState.cs diff --git a/tools/apput/src/Android/AndroidManifest.cs b/tools/apput/src/Android/AndroidManifest.cs index 1268b3c4f88..2e1974d1a6f 100644 --- a/tools/apput/src/Android/AndroidManifest.cs +++ b/tools/apput/src/Android/AndroidManifest.cs @@ -5,6 +5,7 @@ namespace ApplicationUtility; +// TODO: implement support for AndroidManifest.xml in AAB packages. It's protobuf data, not binary/text XML public class AndroidManifest : IAspect { public string Description { get; } diff --git a/tools/apput/src/AssemblyStore/AssemblyStore.cs b/tools/apput/src/AssemblyStore/AssemblyStore.cs index c0f42b7d5b3..d2baafbb208 100644 --- a/tools/apput/src/AssemblyStore/AssemblyStore.cs +++ b/tools/apput/src/AssemblyStore/AssemblyStore.cs @@ -15,7 +15,7 @@ public class AssemblyStore : IAspect public static string AspectName { get; } = "Assembly Store"; public IDictionary Assemblies { get; private set; } = new Dictionary (StringComparer.Ordinal); - public AndroidTargetArch Architecture { get; private set; } = AndroidTargetArch.None; + public AndroidTargetArch Architecture { get; } public ulong NumberOfAssemblies => (ulong)(Assemblies?.Count ?? 0); AssemblyStoreAspectState storeState; @@ -25,6 +25,19 @@ public class AssemblyStore : IAspect { storeState = state; this.description = description; + + AssemblyStoreHeader? header = state.Format.Header; + if (header == null) { + throw new InvalidOperationException ("Internal error: state doesn't contain a valid store header."); + } + + Architecture = header.Version.ABI switch { + AssemblyStoreABI.Arm => AndroidTargetArch.Arm, + AssemblyStoreABI.Arm64 => AndroidTargetArch.Arm64, + AssemblyStoreABI.X86 => AndroidTargetArch.X86, + AssemblyStoreABI.X64 => AndroidTargetArch.X86_64, + _ => throw new InvalidOperationException ($"Internal error: unsupported assembly store ABI '{header.Version.ABI}'") + }; } bool Read () @@ -60,12 +73,12 @@ public static IAspectState ProbeAspect (Stream stream, string? description) Stream? storeStream = null; try { - IAspectState state = SharedLibrary.ProbeAspect (stream, description); + IAspectState state = DotNetAndroidWrapperSharedLibrary.ProbeAspect (stream, description); if (!state.Success) { return DoProbeAspect (stream, description); } - var library = (SharedLibrary)SharedLibrary.LoadAspect (stream, state, description); + var library = (DotNetAndroidWrapperSharedLibrary)DotNetAndroidWrapperSharedLibrary.LoadAspect (stream, state, description); if (!library.HasAndroidPayload) { Log.Debug ($"AssemblyStore: stream ('{description}') is an ELF shared library, without payload"); return new BasicAspectState (false); diff --git a/tools/apput/src/AssemblyStore/AssemblyStoreAspectState.cs b/tools/apput/src/AssemblyStore/AssemblyStoreAspectState.cs index f81e4ada7ac..f5ec96506b5 100644 --- a/tools/apput/src/AssemblyStore/AssemblyStoreAspectState.cs +++ b/tools/apput/src/AssemblyStore/AssemblyStoreAspectState.cs @@ -1,5 +1,3 @@ -using System.Collections.Generic; - namespace ApplicationUtility; class AssemblyStoreAspectState : BasicAspectState diff --git a/tools/apput/src/Common/Log.cs b/tools/apput/src/Common/Log.cs index 6ffef4d784e..0f5b852cc2b 100644 --- a/tools/apput/src/Common/Log.cs +++ b/tools/apput/src/Common/Log.cs @@ -91,6 +91,12 @@ public static void Warning (string message = "") Warning (tag: String.Empty, message); } + public static void Warning (string message, Exception ex) + { + Warning (tag: String.Empty, message); + Warning (tag: String.Empty, ex.ToString ()); + } + public static void Warning (string tag, string message) { if (message.Length > 0) { diff --git a/tools/apput/src/Detector.cs b/tools/apput/src/Detector.cs index 92bddde782c..c46755801c4 100644 --- a/tools/apput/src/Detector.cs +++ b/tools/apput/src/Detector.cs @@ -23,6 +23,7 @@ public class Detector typeof (NativeAotSharedLibrary), typeof (XamarinAppSharedLibrary), typeof (MonoAotSharedLibrary), + typeof (DotNetAndroidWrapperSharedLibrary), typeof (SharedLibrary), }; @@ -30,6 +31,7 @@ public class Detector typeof (NativeAotSharedLibrary), typeof (XamarinAppSharedLibrary), typeof (MonoAotSharedLibrary), + typeof (DotNetAndroidWrapperSharedLibrary), typeof (SharedLibrary), }; @@ -61,9 +63,13 @@ public class Detector static IAspect? TryFindAspect (List aspectTypes, Stream stream, string? description) { foreach (Type aspectType in aspectTypes) { - IAspect? aspect = TryProbeAndLoadAspect (aspectType, stream, description); - if (aspect != null) { - return aspect; + try { + IAspect? aspect = TryProbeAndLoadAspect (aspectType, stream, description); + if (aspect != null) { + return aspect; + } + } catch (Exception ex) { + Log.Warning ($"Failed to probe and load aspect '{aspectType}'", ex); } } diff --git a/tools/apput/src/Native/AnELF.cs b/tools/apput/src/Native/AnELF.cs index 0c2630ab0a3..c552bdb018f 100644 --- a/tools/apput/src/Native/AnELF.cs +++ b/tools/apput/src/Native/AnELF.cs @@ -17,16 +17,16 @@ abstract class AnELF const string SymtabSectionName = ".symtab"; const string RodataSectionName = ".rodata"; - ISymbolTable dynamicSymbolsSection; - ISection rodataSection; + ISymbolTable? dynamicSymbolsSection; + ISection? rodataSection; ISymbolTable? symbolsSection; string filePath; IELF elf; Stream elfStream; - protected ISymbolTable DynSymSection => dynamicSymbolsSection; + protected ISymbolTable? DynSymSection => dynamicSymbolsSection; protected ISymbolTable? SymSection => symbolsSection; - protected ISection RodataSection => rodataSection; + protected ISection? RodataSection => rodataSection; public IELF AnyELF => elf; protected Stream ELFStream => elfStream; @@ -36,7 +36,7 @@ abstract class AnELF public abstract bool Is64Bit { get; } public abstract string Bitness { get; } - protected AnELF (Stream stream, string filePath, IELF elf, ISymbolTable dynsymSection, ISection rodataSection, ISymbolTable? symSection) + protected AnELF (Stream stream, string filePath, IELF elf, ISymbolTable? dynsymSection, ISection? rodataSection, ISymbolTable? symSection) { this.filePath = filePath; this.elf = elf; @@ -61,14 +61,14 @@ protected AnELF (Stream stream, string filePath, IELF elf, ISymbolTable dynsymSe return symbol; } - protected static ISymbolEntry? GetSymbol (ISymbolTable symtab, string symbolName) + protected static ISymbolEntry? GetSymbol (ISymbolTable? symtab, string symbolName) { - return symtab.Entries.Where (entry => String.Compare (entry.Name, symbolName, StringComparison.Ordinal) == 0).FirstOrDefault (); + return symtab?.Entries.Where (entry => String.Compare (entry.Name, symbolName, StringComparison.Ordinal) == 0).FirstOrDefault (); } - protected static SymbolEntry? GetSymbol (SymbolTable symtab, T symbolValue) where T: struct + protected static SymbolEntry? GetSymbol (SymbolTable? symtab, T symbolValue) where T: struct { - return symtab.Entries.Where (entry => entry.Value.Equals (symbolValue)).FirstOrDefault (); + return symtab?.Entries.Where (entry => entry.Value.Equals (symbolValue)).FirstOrDefault (); } public bool HasSymbol (string symbolName) @@ -85,19 +85,22 @@ public byte[] GetData (string symbolName, out ISymbolEntry? symbolEntry) { Log.Debug ($"Looking for symbol: {symbolName}"); symbolEntry = GetSymbol (symbolName); - if (symbolEntry == null) + if (symbolEntry == null) { return EmptyArray; + } if (Is64Bit) { var symbol64 = symbolEntry as SymbolEntry; - if (symbol64 == null) + if (symbol64 == null) { throw new InvalidOperationException ($"Symbol '{symbolName}' is not a valid 64-bit symbol"); + } return GetData (symbol64); } var symbol32 = symbolEntry as SymbolEntry; - if (symbol32 == null) + if (symbol32 == null) { throw new InvalidOperationException ($"Symbol '{symbolName}' is not a valid 32-bit symbol"); + } return GetData (symbol32); } @@ -168,8 +171,9 @@ protected byte[] GetData (ISection section, ulong size, ulong offset) return EmptyArray; } - if (size == 0) + if (size == 0) { size = (ulong)data.Length - offset; + } var ret = new byte[size]; checked { @@ -280,20 +284,8 @@ public static bool TryLoad (Stream stream, string filePath, out AnELF? anElf) return false; } - ISymbolTable? symtab = GetSymbolTable (elf, DynsymSectionName); - if (symtab == null) { - Log.Warning ($"{filePath} does not contain dynamic symbol section '{DynsymSectionName}'"); - return false; - } - ISymbolTable dynsym = symtab; - - ISection? sec = GetSection (elf, RodataSectionName); - if (sec == null) { - Log.Warning ($"{filePath} does not contain read-only data section ('{RodataSectionName}')"); - return false; - } - ISection rodata = sec; - + ISymbolTable? dynsym = GetSymbolTable (elf, DynsymSectionName); + ISection? rodata = GetSection (elf, RodataSectionName); ISymbolTable? sym = GetSymbolTable (elf, SymtabSectionName); if (is64) { diff --git a/tools/apput/src/Native/DotNetAndroidWrapperSharedLibrary.cs b/tools/apput/src/Native/DotNetAndroidWrapperSharedLibrary.cs new file mode 100644 index 00000000000..a38b28db2c8 --- /dev/null +++ b/tools/apput/src/Native/DotNetAndroidWrapperSharedLibrary.cs @@ -0,0 +1,121 @@ +using System; +using System.IO; +using ELFSharp.ELF; +using ELFSharp.ELF.Sections; + +namespace ApplicationUtility; + +class DotNetAndroidWrapperSharedLibrary : SharedLibrary +{ + const string PayloadSectionName = "payload"; + const string DotNetPayloadMarkerSymbol = "dotnet_for_android_data_payload"; + + readonly ulong payloadOffset; + readonly ulong payloadSize; + + public bool HasAndroidPayload => payloadSize > 0; + + protected DotNetAndroidWrapperSharedLibrary (Stream stream, string libraryName, IAspectState state) + : base (stream, libraryName, state) + { + var libState = EnsureValidAspectState (state); + (payloadOffset, payloadSize) = FindAndroidPayload (ELF, libState.Is64Bit, libraryName); + } + + public new static IAspect LoadAspect (Stream stream, IAspectState? state, string? description) + { + if (String.IsNullOrEmpty (description)) { + throw new ArgumentException ("Must be a shared library name", nameof (description)); + } + + var libState = EnsureValidAspectState (state); + return new DotNetAndroidWrapperSharedLibrary (stream, description, libState); + } + + public static new IAspectState ProbeAspect (Stream stream, string? description) => IsDotNetAndroidWrapperSharedLibrary (stream, description); + + /// + /// If the library has .NET for Android payload section, this + /// method will read the data and write it to the + /// stream. All the data in the output stream will be overwritten. + /// + public void CopyAndroidPayload (Stream dest) + { + using Stream payload = OpenAndroidPayload (); + payload.CopyTo (dest); + } + + /// + /// Creates a stream referring to the Android payload data inside + /// the shared library. No data is read, the open stream is returned + /// to the user. Ownership of the stream is transferred to the caller. + /// + public Stream OpenAndroidPayload () + { + if (!HasAndroidPayload) { + throw new InvalidOperationException ("Payload section not found"); + } + + if (payloadOffset > Int64.MaxValue) { + throw new InvalidOperationException ($"Payload offset of {payloadOffset} is too large to support."); + } + + if (payloadSize > Int64.MaxValue) { + throw new InvalidOperationException ($"Payload offset of {payloadSize} is too large to support."); + } + + return new SubStream (LibraryStream, (long)payloadOffset, (long)payloadSize); + } + + static DotNetAndroidWrapperSharedLibraryAspectState IsDotNetAndroidWrapperSharedLibrary (Stream stream, string? description) + { + Log.Debug ($"Checking if '{description}' is a Mono AOT shared library"); + if (!IsSupportedELFSharedLibrary (stream, description, out IELF? elf) || elf == null) { + return GetErrorState (); + } + + if (!AnELF.TryLoad (stream, description ?? String.Empty, out AnELF? anElf) || anElf == null) { + Log.Debug ($"Library '{description}' failed to load"); + return GetErrorState (); + } + + if (!anElf.HasSymbol (DotNetPayloadMarkerSymbol)) { + Log.Debug ($"Symbol '{DotNetPayloadMarkerSymbol}' missing, not a .NET for Android wrapper shared library"); + return GetErrorState (); + } + + return new DotNetAndroidWrapperSharedLibraryAspectState (true, anElf); + + DotNetAndroidWrapperSharedLibraryAspectState GetErrorState () => new DotNetAndroidWrapperSharedLibraryAspectState (false, null); + } + + (ulong offset, ulong size) FindAndroidPayload (IELF elf, bool is64Bit, string libraryName) + { + if (!elf.TryGetSection (PayloadSectionName, out ISection? payloadSection)) { + Log.Debug ($"Shared library '{libraryName}' doesn't have the '{PayloadSectionName}' section."); + return (0, 0); + } + + ulong offset; + ulong size; + + if (is64Bit) { + (offset, size) = GetOffsetAndSize64 ((Section)payloadSection); + } else { + (offset, size) = GetOffsetAndSize32 ((Section)payloadSection); + } + + Log.Debug ($"Found payload section at offset {offset}, size of {size} bytes."); + return (offset, size); + + (ulong offset, ulong size) GetOffsetAndSize64 (Section payload) + { + return (payload.Offset, payload.Size); + } + + (ulong offset, ulong size) GetOffsetAndSize32 (Section payload) + { + return ((ulong)payload.Offset, (ulong)payload.Size); + } + } +} diff --git a/tools/apput/src/Native/DotNetAndroidWrapperSharedLibraryAspectState.cs b/tools/apput/src/Native/DotNetAndroidWrapperSharedLibraryAspectState.cs new file mode 100644 index 00000000000..bb058cb5e7e --- /dev/null +++ b/tools/apput/src/Native/DotNetAndroidWrapperSharedLibraryAspectState.cs @@ -0,0 +1,12 @@ +namespace ApplicationUtility; + +class DotNetAndroidWrapperSharedLibraryAspectState : SharedLibraryAspectState +{ + public AnELF? LoadedELF { get; } + + public DotNetAndroidWrapperSharedLibraryAspectState (bool success, AnELF? elf) + : base (success, elf?.AnyELF) + { + LoadedELF = elf; + } +} diff --git a/tools/apput/src/Native/ELF32.cs b/tools/apput/src/Native/ELF32.cs index 03a0d921f52..38036ed456f 100644 --- a/tools/apput/src/Native/ELF32.cs +++ b/tools/apput/src/Native/ELF32.cs @@ -11,12 +11,12 @@ class ELF32 : AnELF public override bool Is64Bit => false; public override string Bitness => "32"; - SymbolTable DynamicSymbols => (SymbolTable)DynSymSection; + SymbolTable? DynamicSymbols => (SymbolTable?)DynSymSection; SymbolTable? Symbols => (SymbolTable?)SymSection; - Section Rodata => (Section)RodataSection; + Section? Rodata => (Section?)RodataSection; ELF ELF => (ELF)AnyELF; - public ELF32 (Stream stream, string filePath, IELF elf, ISymbolTable dynsymSection, ISection rodataSection, ISymbolTable? symSection) + public ELF32 (Stream stream, string filePath, IELF elf, ISymbolTable? dynsymSection, ISection? rodataSection, ISymbolTable? symSection) : base (stream, filePath, elf, dynsymSection, rodataSection, symSection) {} diff --git a/tools/apput/src/Native/ELF64.cs b/tools/apput/src/Native/ELF64.cs index 67ba5193c71..3e1584fdc5c 100644 --- a/tools/apput/src/Native/ELF64.cs +++ b/tools/apput/src/Native/ELF64.cs @@ -11,12 +11,12 @@ class ELF64 : AnELF public override bool Is64Bit => true; public override string Bitness => "64"; - SymbolTable DynamicSymbols => (SymbolTable)DynSymSection; + SymbolTable? DynamicSymbols => (SymbolTable?)DynSymSection; SymbolTable? Symbols => (SymbolTable?)SymSection; - Section Rodata => (Section)RodataSection; + Section? Rodata => (Section?)RodataSection; ELF ELF => (ELF)AnyELF; - public ELF64 (Stream stream, string filePath, IELF elf, ISymbolTable dynsymSection, ISection rodataSection, ISymbolTable? symSection) + public ELF64 (Stream stream, string filePath, IELF elf, ISymbolTable? dynsymSection, ISection? rodataSection, ISymbolTable? symSection) : base (stream, filePath, elf, dynsymSection, rodataSection, symSection) {} diff --git a/tools/apput/src/Native/MonoAotSharedLibrary.cs b/tools/apput/src/Native/MonoAotSharedLibrary.cs index c61de908552..a5b2c92617c 100644 --- a/tools/apput/src/Native/MonoAotSharedLibrary.cs +++ b/tools/apput/src/Native/MonoAotSharedLibrary.cs @@ -32,6 +32,7 @@ static MonoAotSharedLibraryAspectState IsMonoAotSharedLibrary (Stream stream, st } if (!AnELF.TryLoad (stream, description ?? String.Empty, out AnELF? anElf) || anElf == null) { + Log.Debug ($"Library '{description}' failed to load"); return GetErrorState (); } diff --git a/tools/apput/src/Native/SharedLibrary.cs b/tools/apput/src/Native/SharedLibrary.cs index 2271980d943..29f7a415064 100644 --- a/tools/apput/src/Native/SharedLibrary.cs +++ b/tools/apput/src/Native/SharedLibrary.cs @@ -12,7 +12,6 @@ public class SharedLibrary : IAspect, IDisposable { const uint ELF_MAGIC = 0x464c457f; const string DebugLinkSectionName = ".gnu_debuglink"; - const string PayloadSectionName = "payload"; readonly string? androidIdent; readonly string? buildId; @@ -24,8 +23,6 @@ public class SharedLibrary : IAspect, IDisposable readonly string libraryName; readonly Stream libraryStream; readonly NativeArchitecture nativeArch = NativeArchitecture.Unknown; - readonly ulong payloadOffset; - readonly ulong payloadSize; readonly string? soname; bool disposed; @@ -38,12 +35,12 @@ public class SharedLibrary : IAspect, IDisposable public string? BuildID => buildId; public string? DebugLink => debugLink; public bool HasAndroidIdent => !String.IsNullOrEmpty (androidIdent); - public bool HasAndroidPayload => payloadSize > 0; public bool HasBuildID => !String.IsNullOrEmpty (buildId); public bool HasDebugInfo => hasDebugInfo; public bool HasDebugLink => !String.IsNullOrEmpty (debugLink); public bool HasSoname => !String.IsNullOrEmpty (soname); public bool Is64Bit => is64Bit; + public Stream LibraryStream => libraryStream; public string Name => libraryName; public string? Soname => soname; public NativeArchitecture TargetArchitecture => nativeArch; @@ -58,7 +55,6 @@ protected SharedLibrary (Stream stream, string libraryName, IAspectState state) this.libraryName = libraryName; elf = libState.ElfImage!; (is64Bit, nativeArch) = ValidateELF (libState.ElfImage!, libraryName); - (payloadOffset, payloadSize) = FindAndroidPayload (elf); libraryAlignment = DetectAlignment (elf, is64Bit); (hasDebugInfo, debugLink) = DetectDebugInfo (elf, libraryName); buildId = GetBuildID (elf, is64Bit); @@ -76,7 +72,11 @@ protected static T EnsureValidAspectState (IAspectState? state) where T: IAsp throw new InvalidOperationException ("Internal error: ProbeAspect failed to detect a valid shared library."); } - return (T)((object)libState); + try { + return (T)((object)libState); + } catch (Exception ex) { + throw new InvalidOperationException ($"Internal error: aspect should be of type '{typeof(T)}', found '{libState.GetType ()}' instead", ex); + } } public static IAspect LoadAspect (Stream stream, IAspectState? state, string? description) @@ -92,38 +92,6 @@ public static IAspect LoadAspect (Stream stream, IAspectState? state, string? de public static IAspectState ProbeAspect (Stream stream, string? description) => IsSupportedELFSharedLibrary (stream, description); - /// - /// If the library has .NET for Android payload section, this - /// method will read the data and write it to the - /// stream. All the data in the output stream will be overwritten. - /// - public void CopyAndroidPayload (Stream dest) - { - using Stream payload = OpenAndroidPayload (); - payload.CopyTo (dest); - } - - /// - /// Creates a stream referring to the Android payload data inside - /// the shared library. No data is read, the open stream is returned - /// to the user. Ownership of the stream is transferred to the caller. - /// - public Stream OpenAndroidPayload () - { - if (!HasAndroidPayload) { - throw new InvalidOperationException ("Payload section not found"); - } - - if (payloadOffset > Int64.MaxValue) { - throw new InvalidOperationException ($"Payload offset of {payloadOffset} is too large to support."); - } - - if (payloadSize > Int64.MaxValue) { - throw new InvalidOperationException ($"Payload offset of {payloadSize} is too large to support."); - } - - return new SubStream (libraryStream, (long)payloadOffset, (long)payloadSize); - } protected static bool IsSupportedELFSharedLibrary (Stream stream, string? description, out IELF? elf) { @@ -200,36 +168,6 @@ protected static IAspectState IsSupportedELFSharedLibrary (Stream stream, string return (is64, arch); } - (ulong offset, ulong size) FindAndroidPayload (IELF elf) - { - if (!elf.TryGetSection (PayloadSectionName, out ISection? payloadSection)) { - Log.Debug ($"SharedLibrary: shared library '{libraryName}' doesn't have the '{PayloadSectionName}' section."); - return (0, 0); - } - - ulong offset; - ulong size; - - if (is64Bit) { - (offset, size) = GetOffsetAndSize64 ((Section)payloadSection); - } else { - (offset, size) = GetOffsetAndSize32 ((Section)payloadSection); - } - - Log.Debug ($"SharedLibrary: found payload section at offset {offset}, size of {size} bytes."); - return (offset, size); - - (ulong offset, ulong size) GetOffsetAndSize64 (Section payload) - { - return (payload.Offset, payload.Size); - } - - (ulong offset, ulong size) GetOffsetAndSize32 (Section payload) - { - return ((ulong)payload.Offset, (ulong)payload.Size); - } - } - static (bool hasDebugInfo, string? debugLink) DetectDebugInfo (IELF elf, string libraryName) { bool hasDebugInfo = HasSection (elf, libraryName, ".debug_info", SectionType.ProgBits); diff --git a/tools/apput/src/Native/SharedLibraryAspectState.cs b/tools/apput/src/Native/SharedLibraryAspectState.cs index 26b623bab64..eeb48ff2d93 100644 --- a/tools/apput/src/Native/SharedLibraryAspectState.cs +++ b/tools/apput/src/Native/SharedLibraryAspectState.cs @@ -5,10 +5,12 @@ namespace ApplicationUtility; class SharedLibraryAspectState : BasicAspectState { public IELF? ElfImage { get; } + public bool Is64Bit { get; } public SharedLibraryAspectState (bool success, IELF? elf) : base (success) { ElfImage = elf; + Is64Bit = elf != null ? elf.Class == Class.Bit64 : false; } } diff --git a/tools/apput/src/Package/ApplicationPackage.cs b/tools/apput/src/Package/ApplicationPackage.cs index e1308d0f70e..77feae47034 100644 --- a/tools/apput/src/Package/ApplicationPackage.cs +++ b/tools/apput/src/Package/ApplicationPackage.cs @@ -252,6 +252,7 @@ void TryDetectWhetherIsSigned () void TryLoadAssemblyStores () { + var stores = new List (); foreach (AndroidTargetArch arch in Architectures) { string storePath = GetNativeLibFile (arch, $"libassemblies.{MonoAndroidHelper.ArchToAbi (arch)}.blob.so"); Log.Debug ($"Trying assembly store: {storePath}"); @@ -265,6 +266,12 @@ void TryLoadAssemblyStores () if (store == null) { continue; } + + stores.Add (store); + } + + if (stores.Count > 0) { + AssemblyStores = stores; } } diff --git a/tools/apput/src/Reporters/ApplicationPackageReporter.cs b/tools/apput/src/Reporters/ApplicationPackageReporter.cs index 6e0eed03692..9109f1ad0d0 100644 --- a/tools/apput/src/Reporters/ApplicationPackageReporter.cs +++ b/tools/apput/src/Reporters/ApplicationPackageReporter.cs @@ -1,3 +1,5 @@ +using Xamarin.Android.Tools; + namespace ApplicationUtility; [AspectReporter (typeof (PackageAPK))] @@ -42,5 +44,30 @@ protected override void DoReport () WriteSubsectionBanner (".NET for Android application information"); WriteItem ("Runtime", package.Runtime.ToString ()); + + if (package.AssemblyStores == null || package.AssemblyStores.Count == 0) { + WriteItem ("Assembly stores", "none"); + } else { + WriteLine (LabelColor, "Assembly stores"); + + foreach (AssemblyStore store in package.AssemblyStores) { + var color = store.Architecture == AndroidTargetArch.None ? InvalidValueColor : ValidValueColor; + + Write (LabelColor, " * "); + WriteLine (color, $"{store.Architecture} ({store.NumberOfAssemblies} {GetCountable (Countable.Assembly, store.NumberOfAssemblies)})"); + } + } + + if (package.SharedLibraries == null || package.SharedLibraries.Count == 0) { + // Very unlikely... + WriteItem ("Shared libraries", "none"); + } else { + WriteLine (LabelColor, "Shared libraries:"); + + foreach (SharedLibrary lib in package.SharedLibraries) { + Write (LabelColor, " * "); + WriteLine (ValidValueColor, $"{lib.Name}"); + } + } } } diff --git a/tools/apput/src/Reporters/BaseReporter.cs b/tools/apput/src/Reporters/BaseReporter.cs index 34410dcf9cc..7b6297238b0 100644 --- a/tools/apput/src/Reporters/BaseReporter.cs +++ b/tools/apput/src/Reporters/BaseReporter.cs @@ -8,9 +8,20 @@ namespace ApplicationUtility; abstract class BaseReporter : IReporter { + protected enum Countable + { + Assembly, + SharedLibrary + } + const string NativeArchitectureLabel = "Native target architecture"; const string NativeArchitecturesLabel = NativeArchitectureLabel + "s"; + static readonly Dictionary Countables = new () { + { Countable.Assembly, ("assembly", "assemblies") }, + { Countable.SharedLibrary, ("library", "libraries") }, + }; + protected const ConsoleColor LabelColor = ConsoleColor.Gray; protected const ConsoleColor ValidValueColor = ConsoleColor.Green; protected const ConsoleColor InvalidValueColor = ConsoleColor.Red; @@ -105,6 +116,18 @@ protected void Write (ConsoleColor color, string text) } } + protected string GetCountable (Countable countable, ulong count) + { + if (!Countables.TryGetValue (countable, out (string singular, string plural) forms)) { + throw new InvalidOperationException ($"Internal error: unsupported countable {countable}"); + } + + return count == 1 ? forms.singular : forms.plural; + } + + // Somehow I doubt we'll have more than Int64.MaxValue items of any kind... :) + protected string GetCountable (Countable countable, long count) => GetCountable (countable, (ulong)count); + protected string YesNo (bool yes) => yes ? "yes" : "no"; protected string ValueOrNone (string? s) => String.IsNullOrEmpty (s) ? "none" : s; } From d8f100b12b65f17bd7573ebc899cdb6bd4dee6fa Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 26 Sep 2025 16:53:28 +0200 Subject: [PATCH 23/32] TODOs --- tools/apput/src/Reporters/BaseReporter.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/apput/src/Reporters/BaseReporter.cs b/tools/apput/src/Reporters/BaseReporter.cs index 7b6297238b0..7806b432ffa 100644 --- a/tools/apput/src/Reporters/BaseReporter.cs +++ b/tools/apput/src/Reporters/BaseReporter.cs @@ -6,6 +6,8 @@ namespace ApplicationUtility; +// TODO: generate Markdown +// TODO: detect whether we can output colors abstract class BaseReporter : IReporter { protected enum Countable @@ -30,6 +32,8 @@ protected enum Countable protected abstract string AspectName { get; } protected abstract string ShortDescription { get; } + protected static readonly bool CanUseColor = !Console.IsOutputRedirected; + public void Report () { WriteLine (BannerColor, $"# {AspectName} ({ShortDescription})"); From 45778136f63b073fe2273d805cb611e9edc8baa8 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Tue, 7 Oct 2025 16:07:34 +0200 Subject: [PATCH 24/32] Add protobuf generated code to read AAB manifest --- .../src/Android/Aapt.Pb.Configuration.cs | 1413 ++ .../apput/src/Android/Aapt.Pb.Files.README.md | 2 + tools/apput/src/Android/Aapt.Pb.Resources.cs | 15266 ++++++++++++++++ tools/apput/src/apput.csproj | 1 + 4 files changed, 16682 insertions(+) create mode 100644 tools/apput/src/Android/Aapt.Pb.Configuration.cs create mode 100644 tools/apput/src/Android/Aapt.Pb.Files.README.md create mode 100644 tools/apput/src/Android/Aapt.Pb.Resources.cs diff --git a/tools/apput/src/Android/Aapt.Pb.Configuration.cs b/tools/apput/src/Android/Aapt.Pb.Configuration.cs new file mode 100644 index 00000000000..63f1429d45b --- /dev/null +++ b/tools/apput/src/Android/Aapt.Pb.Configuration.cs @@ -0,0 +1,1413 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: Configuration.proto +// +#pragma warning disable 1591, 0612, 3021, 8981 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Aapt.Pb { + + /// Holder for reflection information generated from Configuration.proto + public static partial class ConfigurationReflection { + + #region Descriptor + /// File descriptor for Configuration.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static ConfigurationReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "ChNDb25maWd1cmF0aW9uLnByb3RvEgdhYXB0LnBiIpcWCg1Db25maWd1cmF0", + "aW9uEgsKA21jYxgBIAEoDRILCgNtbmMYAiABKA0SDgoGbG9jYWxlGAMgASgJ", + "EkAKEGxheW91dF9kaXJlY3Rpb24YBCABKA4yJi5hYXB0LnBiLkNvbmZpZ3Vy", + "YXRpb24uTGF5b3V0RGlyZWN0aW9uEhQKDHNjcmVlbl93aWR0aBgFIAEoDRIV", + "Cg1zY3JlZW5faGVpZ2h0GAYgASgNEhcKD3NjcmVlbl93aWR0aF9kcBgHIAEo", + "DRIYChBzY3JlZW5faGVpZ2h0X2RwGAggASgNEiAKGHNtYWxsZXN0X3NjcmVl", + "bl93aWR0aF9kcBgJIAEoDRJDChJzY3JlZW5fbGF5b3V0X3NpemUYCiABKA4y", + "Jy5hYXB0LnBiLkNvbmZpZ3VyYXRpb24uU2NyZWVuTGF5b3V0U2l6ZRJDChJz", + "Y3JlZW5fbGF5b3V0X2xvbmcYCyABKA4yJy5hYXB0LnBiLkNvbmZpZ3VyYXRp", + "b24uU2NyZWVuTGF5b3V0TG9uZxI4CgxzY3JlZW5fcm91bmQYDCABKA4yIi5h", + "YXB0LnBiLkNvbmZpZ3VyYXRpb24uU2NyZWVuUm91bmQSPwoQd2lkZV9jb2xv", + "cl9nYW11dBgNIAEoDjIlLmFhcHQucGIuQ29uZmlndXJhdGlvbi5XaWRlQ29s", + "b3JHYW11dBInCgNoZHIYDiABKA4yGi5hYXB0LnBiLkNvbmZpZ3VyYXRpb24u", + "SGRyEjcKC29yaWVudGF0aW9uGA8gASgOMiIuYWFwdC5wYi5Db25maWd1cmF0", + "aW9uLk9yaWVudGF0aW9uEjcKDHVpX21vZGVfdHlwZRgQIAEoDjIhLmFhcHQu", + "cGIuQ29uZmlndXJhdGlvbi5VaU1vZGVUeXBlEjkKDXVpX21vZGVfbmlnaHQY", + "ESABKA4yIi5hYXB0LnBiLkNvbmZpZ3VyYXRpb24uVWlNb2RlTmlnaHQSDwoH", + "ZGVuc2l0eRgSIAEoDRI3Cgt0b3VjaHNjcmVlbhgTIAEoDjIiLmFhcHQucGIu", + "Q29uZmlndXJhdGlvbi5Ub3VjaHNjcmVlbhI2CgtrZXlzX2hpZGRlbhgUIAEo", + "DjIhLmFhcHQucGIuQ29uZmlndXJhdGlvbi5LZXlzSGlkZGVuEjEKCGtleWJv", + "YXJkGBUgASgOMh8uYWFwdC5wYi5Db25maWd1cmF0aW9uLktleWJvYXJkEjQK", + "Cm5hdl9oaWRkZW4YFiABKA4yIC5hYXB0LnBiLkNvbmZpZ3VyYXRpb24uTmF2", + "SGlkZGVuEjUKCm5hdmlnYXRpb24YFyABKA4yIS5hYXB0LnBiLkNvbmZpZ3Vy", + "YXRpb24uTmF2aWdhdGlvbhITCgtzZGtfdmVyc2lvbhgYIAEoDRJEChJncmFt", + "bWF0aWNhbF9nZW5kZXIYGiABKA4yKC5hYXB0LnBiLkNvbmZpZ3VyYXRpb24u", + "R3JhbW1hdGljYWxHZW5kZXISDwoHcHJvZHVjdBgZIAEoCSJhCg9MYXlvdXRE", + "aXJlY3Rpb24SGgoWTEFZT1VUX0RJUkVDVElPTl9VTlNFVBAAEhgKFExBWU9V", + "VF9ESVJFQ1RJT05fTFRSEAESGAoUTEFZT1VUX0RJUkVDVElPTl9SVEwQAiKq", + "AQoQU2NyZWVuTGF5b3V0U2l6ZRIcChhTQ1JFRU5fTEFZT1VUX1NJWkVfVU5T", + "RVQQABIcChhTQ1JFRU5fTEFZT1VUX1NJWkVfU01BTEwQARIdChlTQ1JFRU5f", + "TEFZT1VUX1NJWkVfTk9STUFMEAISHAoYU0NSRUVOX0xBWU9VVF9TSVpFX0xB", + "UkdFEAMSHQoZU0NSRUVOX0xBWU9VVF9TSVpFX1hMQVJHRRAEIm0KEFNjcmVl", + "bkxheW91dExvbmcSHAoYU0NSRUVOX0xBWU9VVF9MT05HX1VOU0VUEAASGwoX", + "U0NSRUVOX0xBWU9VVF9MT05HX0xPTkcQARIeChpTQ1JFRU5fTEFZT1VUX0xP", + "TkdfTk9UTE9ORxACIlgKC1NjcmVlblJvdW5kEhYKElNDUkVFTl9ST1VORF9V", + "TlNFVBAAEhYKElNDUkVFTl9ST1VORF9ST1VORBABEhkKFVNDUkVFTl9ST1VO", + "RF9OT1RST1VORBACImgKDldpZGVDb2xvckdhbXV0EhoKFldJREVfQ09MT1Jf", + "R0FNVVRfVU5TRVQQABIbChdXSURFX0NPTE9SX0dBTVVUX1dJREVDRxABEh0K", + "GVdJREVfQ09MT1JfR0FNVVRfTk9XSURFQ0cQAiIzCgNIZHISDQoJSERSX1VO", + "U0VUEAASDgoKSERSX0hJR0hEUhABEg0KCUhEUl9MT1dEUhACImgKC09yaWVu", + "dGF0aW9uEhUKEU9SSUVOVEFUSU9OX1VOU0VUEAASFAoQT1JJRU5UQVRJT05f", + "UE9SVBABEhQKEE9SSUVOVEFUSU9OX0xBTkQQAhIWChJPUklFTlRBVElPTl9T", + "UVVBUkUQAyLXAQoKVWlNb2RlVHlwZRIWChJVSV9NT0RFX1RZUEVfVU5TRVQQ", + "ABIXChNVSV9NT0RFX1RZUEVfTk9STUFMEAESFQoRVUlfTU9ERV9UWVBFX0RF", + "U0sQAhIUChBVSV9NT0RFX1RZUEVfQ0FSEAMSGwoXVUlfTU9ERV9UWVBFX1RF", + "TEVWSVNJT04QBBIaChZVSV9NT0RFX1RZUEVfQVBQTElBTkNFEAUSFgoSVUlf", + "TU9ERV9UWVBFX1dBVENIEAYSGgoWVUlfTU9ERV9UWVBFX1ZSSEVBRFNFVBAH", + "IlsKC1VpTW9kZU5pZ2h0EhcKE1VJX01PREVfTklHSFRfVU5TRVQQABIXChNV", + "SV9NT0RFX05JR0hUX05JR0hUEAESGgoWVUlfTU9ERV9OSUdIVF9OT1ROSUdI", + "VBACIm0KC1RvdWNoc2NyZWVuEhUKEVRPVUNIU0NSRUVOX1VOU0VUEAASFwoT", + "VE9VQ0hTQ1JFRU5fTk9UT1VDSBABEhYKElRPVUNIU0NSRUVOX1NUWUxVUxAC", + "EhYKElRPVUNIU0NSRUVOX0ZJTkdFUhADInYKCktleXNIaWRkZW4SFQoRS0VZ", + "U19ISURERU5fVU5TRVQQABIbChdLRVlTX0hJRERFTl9LRVlTRVhQT1NFRBAB", + "EhoKFktFWVNfSElEREVOX0tFWVNISURERU4QAhIYChRLRVlTX0hJRERFTl9L", + "RVlTU09GVBADImAKCEtleWJvYXJkEhIKDktFWUJPQVJEX1VOU0VUEAASEwoP", + "S0VZQk9BUkRfTk9LRVlTEAESEwoPS0VZQk9BUkRfUVdFUlRZEAISFgoSS0VZ", + "Qk9BUkRfVFdFTFZFS0VZEAMiVgoJTmF2SGlkZGVuEhQKEE5BVl9ISURERU5f", + "VU5TRVQQABIZChVOQVZfSElEREVOX05BVkVYUE9TRUQQARIYChROQVZfSElE", + "REVOX05BVkhJRERFThACIn0KCk5hdmlnYXRpb24SFAoQTkFWSUdBVElPTl9V", + "TlNFVBAAEhQKEE5BVklHQVRJT05fTk9OQVYQARITCg9OQVZJR0FUSU9OX0RQ", + "QUQQAhIYChROQVZJR0FUSU9OX1RSQUNLQkFMTBADEhQKEE5BVklHQVRJT05f", + "V0hFRUwQBCJ2ChFHcmFtbWF0aWNhbEdlbmRlchIUChBHUkFNX0dFTkRFUl9V", + "U0VUEAASFgoSR1JBTV9HRU5ERVJfTkVVVEVSEAESGAoUR1JBTV9HRU5ERVJf", + "RkVNSU5JTkUQAhIZChVHUkFNX0dFTkRFUl9NQVNDVUxJTkUQA0ISChBjb20u", + "YW5kcm9pZC5hYXB0YgZwcm90bzM=")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Configuration), global::Aapt.Pb.Configuration.Parser, new[]{ "Mcc", "Mnc", "Locale", "LayoutDirection", "ScreenWidth", "ScreenHeight", "ScreenWidthDp", "ScreenHeightDp", "SmallestScreenWidthDp", "ScreenLayoutSize", "ScreenLayoutLong", "ScreenRound", "WideColorGamut", "Hdr", "Orientation", "UiModeType", "UiModeNight", "Density", "Touchscreen", "KeysHidden", "Keyboard", "NavHidden", "Navigation", "SdkVersion", "GrammaticalGender", "Product" }, null, new[]{ typeof(global::Aapt.Pb.Configuration.Types.LayoutDirection), typeof(global::Aapt.Pb.Configuration.Types.ScreenLayoutSize), typeof(global::Aapt.Pb.Configuration.Types.ScreenLayoutLong), typeof(global::Aapt.Pb.Configuration.Types.ScreenRound), typeof(global::Aapt.Pb.Configuration.Types.WideColorGamut), typeof(global::Aapt.Pb.Configuration.Types.Hdr), typeof(global::Aapt.Pb.Configuration.Types.Orientation), typeof(global::Aapt.Pb.Configuration.Types.UiModeType), typeof(global::Aapt.Pb.Configuration.Types.UiModeNight), typeof(global::Aapt.Pb.Configuration.Types.Touchscreen), typeof(global::Aapt.Pb.Configuration.Types.KeysHidden), typeof(global::Aapt.Pb.Configuration.Types.Keyboard), typeof(global::Aapt.Pb.Configuration.Types.NavHidden), typeof(global::Aapt.Pb.Configuration.Types.Navigation), typeof(global::Aapt.Pb.Configuration.Types.GrammaticalGender) }, null, null) + })); + } + #endregion + + } + #region Messages + /// + /// A description of the requirements a device must have in order for a + /// resource to be matched and selected. + /// + public sealed partial class Configuration : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Configuration()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ConfigurationReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Configuration() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Configuration(Configuration other) : this() { + mcc_ = other.mcc_; + mnc_ = other.mnc_; + locale_ = other.locale_; + layoutDirection_ = other.layoutDirection_; + screenWidth_ = other.screenWidth_; + screenHeight_ = other.screenHeight_; + screenWidthDp_ = other.screenWidthDp_; + screenHeightDp_ = other.screenHeightDp_; + smallestScreenWidthDp_ = other.smallestScreenWidthDp_; + screenLayoutSize_ = other.screenLayoutSize_; + screenLayoutLong_ = other.screenLayoutLong_; + screenRound_ = other.screenRound_; + wideColorGamut_ = other.wideColorGamut_; + hdr_ = other.hdr_; + orientation_ = other.orientation_; + uiModeType_ = other.uiModeType_; + uiModeNight_ = other.uiModeNight_; + density_ = other.density_; + touchscreen_ = other.touchscreen_; + keysHidden_ = other.keysHidden_; + keyboard_ = other.keyboard_; + navHidden_ = other.navHidden_; + navigation_ = other.navigation_; + sdkVersion_ = other.sdkVersion_; + grammaticalGender_ = other.grammaticalGender_; + product_ = other.product_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Configuration Clone() { + return new Configuration(this); + } + + /// Field number for the "mcc" field. + public const int MccFieldNumber = 1; + private uint mcc_; + /// + /// Mobile country code. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint Mcc { + get { return mcc_; } + set { + mcc_ = value; + } + } + + /// Field number for the "mnc" field. + public const int MncFieldNumber = 2; + private uint mnc_; + /// + /// Mobile network code. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint Mnc { + get { return mnc_; } + set { + mnc_ = value; + } + } + + /// Field number for the "locale" field. + public const int LocaleFieldNumber = 3; + private string locale_ = ""; + /// + /// BCP-47 locale tag. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Locale { + get { return locale_; } + set { + locale_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "layout_direction" field. + public const int LayoutDirectionFieldNumber = 4; + private global::Aapt.Pb.Configuration.Types.LayoutDirection layoutDirection_ = global::Aapt.Pb.Configuration.Types.LayoutDirection.Unset; + /// + /// Left-to-right, right-to-left... + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Configuration.Types.LayoutDirection LayoutDirection { + get { return layoutDirection_; } + set { + layoutDirection_ = value; + } + } + + /// Field number for the "screen_width" field. + public const int ScreenWidthFieldNumber = 5; + private uint screenWidth_; + /// + /// Screen width in pixels. Prefer screen_width_dp. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint ScreenWidth { + get { return screenWidth_; } + set { + screenWidth_ = value; + } + } + + /// Field number for the "screen_height" field. + public const int ScreenHeightFieldNumber = 6; + private uint screenHeight_; + /// + /// Screen height in pixels. Prefer screen_height_dp. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint ScreenHeight { + get { return screenHeight_; } + set { + screenHeight_ = value; + } + } + + /// Field number for the "screen_width_dp" field. + public const int ScreenWidthDpFieldNumber = 7; + private uint screenWidthDp_; + /// + /// Screen width in density independent pixels (dp). + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint ScreenWidthDp { + get { return screenWidthDp_; } + set { + screenWidthDp_ = value; + } + } + + /// Field number for the "screen_height_dp" field. + public const int ScreenHeightDpFieldNumber = 8; + private uint screenHeightDp_; + /// + /// Screen height in density independent pixels (dp). + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint ScreenHeightDp { + get { return screenHeightDp_; } + set { + screenHeightDp_ = value; + } + } + + /// Field number for the "smallest_screen_width_dp" field. + public const int SmallestScreenWidthDpFieldNumber = 9; + private uint smallestScreenWidthDp_; + /// + /// The smallest screen dimension, regardless of orientation, in dp. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint SmallestScreenWidthDp { + get { return smallestScreenWidthDp_; } + set { + smallestScreenWidthDp_ = value; + } + } + + /// Field number for the "screen_layout_size" field. + public const int ScreenLayoutSizeFieldNumber = 10; + private global::Aapt.Pb.Configuration.Types.ScreenLayoutSize screenLayoutSize_ = global::Aapt.Pb.Configuration.Types.ScreenLayoutSize.Unset; + /// + /// Whether the device screen is classified as small, normal, large, xlarge. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Configuration.Types.ScreenLayoutSize ScreenLayoutSize { + get { return screenLayoutSize_; } + set { + screenLayoutSize_ = value; + } + } + + /// Field number for the "screen_layout_long" field. + public const int ScreenLayoutLongFieldNumber = 11; + private global::Aapt.Pb.Configuration.Types.ScreenLayoutLong screenLayoutLong_ = global::Aapt.Pb.Configuration.Types.ScreenLayoutLong.Unset; + /// + /// Whether the device screen is long. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Configuration.Types.ScreenLayoutLong ScreenLayoutLong { + get { return screenLayoutLong_; } + set { + screenLayoutLong_ = value; + } + } + + /// Field number for the "screen_round" field. + public const int ScreenRoundFieldNumber = 12; + private global::Aapt.Pb.Configuration.Types.ScreenRound screenRound_ = global::Aapt.Pb.Configuration.Types.ScreenRound.Unset; + /// + /// Whether the screen is round (Android Wear). + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Configuration.Types.ScreenRound ScreenRound { + get { return screenRound_; } + set { + screenRound_ = value; + } + } + + /// Field number for the "wide_color_gamut" field. + public const int WideColorGamutFieldNumber = 13; + private global::Aapt.Pb.Configuration.Types.WideColorGamut wideColorGamut_ = global::Aapt.Pb.Configuration.Types.WideColorGamut.Unset; + /// + /// Whether the screen supports wide color gamut. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Configuration.Types.WideColorGamut WideColorGamut { + get { return wideColorGamut_; } + set { + wideColorGamut_ = value; + } + } + + /// Field number for the "hdr" field. + public const int HdrFieldNumber = 14; + private global::Aapt.Pb.Configuration.Types.Hdr hdr_ = global::Aapt.Pb.Configuration.Types.Hdr.Unset; + /// + /// Whether the screen has high dynamic range. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Configuration.Types.Hdr Hdr { + get { return hdr_; } + set { + hdr_ = value; + } + } + + /// Field number for the "orientation" field. + public const int OrientationFieldNumber = 15; + private global::Aapt.Pb.Configuration.Types.Orientation orientation_ = global::Aapt.Pb.Configuration.Types.Orientation.Unset; + /// + /// Which orientation the device is in (portrait, landscape). + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Configuration.Types.Orientation Orientation { + get { return orientation_; } + set { + orientation_ = value; + } + } + + /// Field number for the "ui_mode_type" field. + public const int UiModeTypeFieldNumber = 16; + private global::Aapt.Pb.Configuration.Types.UiModeType uiModeType_ = global::Aapt.Pb.Configuration.Types.UiModeType.Unset; + /// + /// Which type of UI mode the device is in (television, car, etc.). + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Configuration.Types.UiModeType UiModeType { + get { return uiModeType_; } + set { + uiModeType_ = value; + } + } + + /// Field number for the "ui_mode_night" field. + public const int UiModeNightFieldNumber = 17; + private global::Aapt.Pb.Configuration.Types.UiModeNight uiModeNight_ = global::Aapt.Pb.Configuration.Types.UiModeNight.Unset; + /// + /// Whether the device is in night mode. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Configuration.Types.UiModeNight UiModeNight { + get { return uiModeNight_; } + set { + uiModeNight_ = value; + } + } + + /// Field number for the "density" field. + public const int DensityFieldNumber = 18; + private uint density_; + /// + /// The device's screen density in dots-per-inch (dpi). + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint Density { + get { return density_; } + set { + density_ = value; + } + } + + /// Field number for the "touchscreen" field. + public const int TouchscreenFieldNumber = 19; + private global::Aapt.Pb.Configuration.Types.Touchscreen touchscreen_ = global::Aapt.Pb.Configuration.Types.Touchscreen.Unset; + /// + /// Whether a touchscreen exists, supports a stylus, or finger. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Configuration.Types.Touchscreen Touchscreen { + get { return touchscreen_; } + set { + touchscreen_ = value; + } + } + + /// Field number for the "keys_hidden" field. + public const int KeysHiddenFieldNumber = 20; + private global::Aapt.Pb.Configuration.Types.KeysHidden keysHidden_ = global::Aapt.Pb.Configuration.Types.KeysHidden.Unset; + /// + /// Whether the keyboard hardware keys are currently hidden, exposed, or + /// if the keyboard is a software keyboard. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Configuration.Types.KeysHidden KeysHidden { + get { return keysHidden_; } + set { + keysHidden_ = value; + } + } + + /// Field number for the "keyboard" field. + public const int KeyboardFieldNumber = 21; + private global::Aapt.Pb.Configuration.Types.Keyboard keyboard_ = global::Aapt.Pb.Configuration.Types.Keyboard.Unset; + /// + /// The type of keyboard present (none, QWERTY, 12-key). + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Configuration.Types.Keyboard Keyboard { + get { return keyboard_; } + set { + keyboard_ = value; + } + } + + /// Field number for the "nav_hidden" field. + public const int NavHiddenFieldNumber = 22; + private global::Aapt.Pb.Configuration.Types.NavHidden navHidden_ = global::Aapt.Pb.Configuration.Types.NavHidden.Unset; + /// + /// Whether the navigation is exposed or hidden. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Configuration.Types.NavHidden NavHidden { + get { return navHidden_; } + set { + navHidden_ = value; + } + } + + /// Field number for the "navigation" field. + public const int NavigationFieldNumber = 23; + private global::Aapt.Pb.Configuration.Types.Navigation navigation_ = global::Aapt.Pb.Configuration.Types.Navigation.Unset; + /// + /// The type of navigation present on the device + /// (trackball, wheel, dpad, etc.). + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Configuration.Types.Navigation Navigation { + get { return navigation_; } + set { + navigation_ = value; + } + } + + /// Field number for the "sdk_version" field. + public const int SdkVersionFieldNumber = 24; + private uint sdkVersion_; + /// + /// The minimum SDK version of the device. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint SdkVersion { + get { return sdkVersion_; } + set { + sdkVersion_ = value; + } + } + + /// Field number for the "grammatical_gender" field. + public const int GrammaticalGenderFieldNumber = 26; + private global::Aapt.Pb.Configuration.Types.GrammaticalGender grammaticalGender_ = global::Aapt.Pb.Configuration.Types.GrammaticalGender.GramGenderUset; + /// + /// Grammatical gender. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Configuration.Types.GrammaticalGender GrammaticalGender { + get { return grammaticalGender_; } + set { + grammaticalGender_ = value; + } + } + + /// Field number for the "product" field. + public const int ProductFieldNumber = 25; + private string product_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Product { + get { return product_; } + set { + product_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Configuration); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Configuration other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Mcc != other.Mcc) return false; + if (Mnc != other.Mnc) return false; + if (Locale != other.Locale) return false; + if (LayoutDirection != other.LayoutDirection) return false; + if (ScreenWidth != other.ScreenWidth) return false; + if (ScreenHeight != other.ScreenHeight) return false; + if (ScreenWidthDp != other.ScreenWidthDp) return false; + if (ScreenHeightDp != other.ScreenHeightDp) return false; + if (SmallestScreenWidthDp != other.SmallestScreenWidthDp) return false; + if (ScreenLayoutSize != other.ScreenLayoutSize) return false; + if (ScreenLayoutLong != other.ScreenLayoutLong) return false; + if (ScreenRound != other.ScreenRound) return false; + if (WideColorGamut != other.WideColorGamut) return false; + if (Hdr != other.Hdr) return false; + if (Orientation != other.Orientation) return false; + if (UiModeType != other.UiModeType) return false; + if (UiModeNight != other.UiModeNight) return false; + if (Density != other.Density) return false; + if (Touchscreen != other.Touchscreen) return false; + if (KeysHidden != other.KeysHidden) return false; + if (Keyboard != other.Keyboard) return false; + if (NavHidden != other.NavHidden) return false; + if (Navigation != other.Navigation) return false; + if (SdkVersion != other.SdkVersion) return false; + if (GrammaticalGender != other.GrammaticalGender) return false; + if (Product != other.Product) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Mcc != 0) hash ^= Mcc.GetHashCode(); + if (Mnc != 0) hash ^= Mnc.GetHashCode(); + if (Locale.Length != 0) hash ^= Locale.GetHashCode(); + if (LayoutDirection != global::Aapt.Pb.Configuration.Types.LayoutDirection.Unset) hash ^= LayoutDirection.GetHashCode(); + if (ScreenWidth != 0) hash ^= ScreenWidth.GetHashCode(); + if (ScreenHeight != 0) hash ^= ScreenHeight.GetHashCode(); + if (ScreenWidthDp != 0) hash ^= ScreenWidthDp.GetHashCode(); + if (ScreenHeightDp != 0) hash ^= ScreenHeightDp.GetHashCode(); + if (SmallestScreenWidthDp != 0) hash ^= SmallestScreenWidthDp.GetHashCode(); + if (ScreenLayoutSize != global::Aapt.Pb.Configuration.Types.ScreenLayoutSize.Unset) hash ^= ScreenLayoutSize.GetHashCode(); + if (ScreenLayoutLong != global::Aapt.Pb.Configuration.Types.ScreenLayoutLong.Unset) hash ^= ScreenLayoutLong.GetHashCode(); + if (ScreenRound != global::Aapt.Pb.Configuration.Types.ScreenRound.Unset) hash ^= ScreenRound.GetHashCode(); + if (WideColorGamut != global::Aapt.Pb.Configuration.Types.WideColorGamut.Unset) hash ^= WideColorGamut.GetHashCode(); + if (Hdr != global::Aapt.Pb.Configuration.Types.Hdr.Unset) hash ^= Hdr.GetHashCode(); + if (Orientation != global::Aapt.Pb.Configuration.Types.Orientation.Unset) hash ^= Orientation.GetHashCode(); + if (UiModeType != global::Aapt.Pb.Configuration.Types.UiModeType.Unset) hash ^= UiModeType.GetHashCode(); + if (UiModeNight != global::Aapt.Pb.Configuration.Types.UiModeNight.Unset) hash ^= UiModeNight.GetHashCode(); + if (Density != 0) hash ^= Density.GetHashCode(); + if (Touchscreen != global::Aapt.Pb.Configuration.Types.Touchscreen.Unset) hash ^= Touchscreen.GetHashCode(); + if (KeysHidden != global::Aapt.Pb.Configuration.Types.KeysHidden.Unset) hash ^= KeysHidden.GetHashCode(); + if (Keyboard != global::Aapt.Pb.Configuration.Types.Keyboard.Unset) hash ^= Keyboard.GetHashCode(); + if (NavHidden != global::Aapt.Pb.Configuration.Types.NavHidden.Unset) hash ^= NavHidden.GetHashCode(); + if (Navigation != global::Aapt.Pb.Configuration.Types.Navigation.Unset) hash ^= Navigation.GetHashCode(); + if (SdkVersion != 0) hash ^= SdkVersion.GetHashCode(); + if (GrammaticalGender != global::Aapt.Pb.Configuration.Types.GrammaticalGender.GramGenderUset) hash ^= GrammaticalGender.GetHashCode(); + if (Product.Length != 0) hash ^= Product.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Mcc != 0) { + output.WriteRawTag(8); + output.WriteUInt32(Mcc); + } + if (Mnc != 0) { + output.WriteRawTag(16); + output.WriteUInt32(Mnc); + } + if (Locale.Length != 0) { + output.WriteRawTag(26); + output.WriteString(Locale); + } + if (LayoutDirection != global::Aapt.Pb.Configuration.Types.LayoutDirection.Unset) { + output.WriteRawTag(32); + output.WriteEnum((int) LayoutDirection); + } + if (ScreenWidth != 0) { + output.WriteRawTag(40); + output.WriteUInt32(ScreenWidth); + } + if (ScreenHeight != 0) { + output.WriteRawTag(48); + output.WriteUInt32(ScreenHeight); + } + if (ScreenWidthDp != 0) { + output.WriteRawTag(56); + output.WriteUInt32(ScreenWidthDp); + } + if (ScreenHeightDp != 0) { + output.WriteRawTag(64); + output.WriteUInt32(ScreenHeightDp); + } + if (SmallestScreenWidthDp != 0) { + output.WriteRawTag(72); + output.WriteUInt32(SmallestScreenWidthDp); + } + if (ScreenLayoutSize != global::Aapt.Pb.Configuration.Types.ScreenLayoutSize.Unset) { + output.WriteRawTag(80); + output.WriteEnum((int) ScreenLayoutSize); + } + if (ScreenLayoutLong != global::Aapt.Pb.Configuration.Types.ScreenLayoutLong.Unset) { + output.WriteRawTag(88); + output.WriteEnum((int) ScreenLayoutLong); + } + if (ScreenRound != global::Aapt.Pb.Configuration.Types.ScreenRound.Unset) { + output.WriteRawTag(96); + output.WriteEnum((int) ScreenRound); + } + if (WideColorGamut != global::Aapt.Pb.Configuration.Types.WideColorGamut.Unset) { + output.WriteRawTag(104); + output.WriteEnum((int) WideColorGamut); + } + if (Hdr != global::Aapt.Pb.Configuration.Types.Hdr.Unset) { + output.WriteRawTag(112); + output.WriteEnum((int) Hdr); + } + if (Orientation != global::Aapt.Pb.Configuration.Types.Orientation.Unset) { + output.WriteRawTag(120); + output.WriteEnum((int) Orientation); + } + if (UiModeType != global::Aapt.Pb.Configuration.Types.UiModeType.Unset) { + output.WriteRawTag(128, 1); + output.WriteEnum((int) UiModeType); + } + if (UiModeNight != global::Aapt.Pb.Configuration.Types.UiModeNight.Unset) { + output.WriteRawTag(136, 1); + output.WriteEnum((int) UiModeNight); + } + if (Density != 0) { + output.WriteRawTag(144, 1); + output.WriteUInt32(Density); + } + if (Touchscreen != global::Aapt.Pb.Configuration.Types.Touchscreen.Unset) { + output.WriteRawTag(152, 1); + output.WriteEnum((int) Touchscreen); + } + if (KeysHidden != global::Aapt.Pb.Configuration.Types.KeysHidden.Unset) { + output.WriteRawTag(160, 1); + output.WriteEnum((int) KeysHidden); + } + if (Keyboard != global::Aapt.Pb.Configuration.Types.Keyboard.Unset) { + output.WriteRawTag(168, 1); + output.WriteEnum((int) Keyboard); + } + if (NavHidden != global::Aapt.Pb.Configuration.Types.NavHidden.Unset) { + output.WriteRawTag(176, 1); + output.WriteEnum((int) NavHidden); + } + if (Navigation != global::Aapt.Pb.Configuration.Types.Navigation.Unset) { + output.WriteRawTag(184, 1); + output.WriteEnum((int) Navigation); + } + if (SdkVersion != 0) { + output.WriteRawTag(192, 1); + output.WriteUInt32(SdkVersion); + } + if (Product.Length != 0) { + output.WriteRawTag(202, 1); + output.WriteString(Product); + } + if (GrammaticalGender != global::Aapt.Pb.Configuration.Types.GrammaticalGender.GramGenderUset) { + output.WriteRawTag(208, 1); + output.WriteEnum((int) GrammaticalGender); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Mcc != 0) { + output.WriteRawTag(8); + output.WriteUInt32(Mcc); + } + if (Mnc != 0) { + output.WriteRawTag(16); + output.WriteUInt32(Mnc); + } + if (Locale.Length != 0) { + output.WriteRawTag(26); + output.WriteString(Locale); + } + if (LayoutDirection != global::Aapt.Pb.Configuration.Types.LayoutDirection.Unset) { + output.WriteRawTag(32); + output.WriteEnum((int) LayoutDirection); + } + if (ScreenWidth != 0) { + output.WriteRawTag(40); + output.WriteUInt32(ScreenWidth); + } + if (ScreenHeight != 0) { + output.WriteRawTag(48); + output.WriteUInt32(ScreenHeight); + } + if (ScreenWidthDp != 0) { + output.WriteRawTag(56); + output.WriteUInt32(ScreenWidthDp); + } + if (ScreenHeightDp != 0) { + output.WriteRawTag(64); + output.WriteUInt32(ScreenHeightDp); + } + if (SmallestScreenWidthDp != 0) { + output.WriteRawTag(72); + output.WriteUInt32(SmallestScreenWidthDp); + } + if (ScreenLayoutSize != global::Aapt.Pb.Configuration.Types.ScreenLayoutSize.Unset) { + output.WriteRawTag(80); + output.WriteEnum((int) ScreenLayoutSize); + } + if (ScreenLayoutLong != global::Aapt.Pb.Configuration.Types.ScreenLayoutLong.Unset) { + output.WriteRawTag(88); + output.WriteEnum((int) ScreenLayoutLong); + } + if (ScreenRound != global::Aapt.Pb.Configuration.Types.ScreenRound.Unset) { + output.WriteRawTag(96); + output.WriteEnum((int) ScreenRound); + } + if (WideColorGamut != global::Aapt.Pb.Configuration.Types.WideColorGamut.Unset) { + output.WriteRawTag(104); + output.WriteEnum((int) WideColorGamut); + } + if (Hdr != global::Aapt.Pb.Configuration.Types.Hdr.Unset) { + output.WriteRawTag(112); + output.WriteEnum((int) Hdr); + } + if (Orientation != global::Aapt.Pb.Configuration.Types.Orientation.Unset) { + output.WriteRawTag(120); + output.WriteEnum((int) Orientation); + } + if (UiModeType != global::Aapt.Pb.Configuration.Types.UiModeType.Unset) { + output.WriteRawTag(128, 1); + output.WriteEnum((int) UiModeType); + } + if (UiModeNight != global::Aapt.Pb.Configuration.Types.UiModeNight.Unset) { + output.WriteRawTag(136, 1); + output.WriteEnum((int) UiModeNight); + } + if (Density != 0) { + output.WriteRawTag(144, 1); + output.WriteUInt32(Density); + } + if (Touchscreen != global::Aapt.Pb.Configuration.Types.Touchscreen.Unset) { + output.WriteRawTag(152, 1); + output.WriteEnum((int) Touchscreen); + } + if (KeysHidden != global::Aapt.Pb.Configuration.Types.KeysHidden.Unset) { + output.WriteRawTag(160, 1); + output.WriteEnum((int) KeysHidden); + } + if (Keyboard != global::Aapt.Pb.Configuration.Types.Keyboard.Unset) { + output.WriteRawTag(168, 1); + output.WriteEnum((int) Keyboard); + } + if (NavHidden != global::Aapt.Pb.Configuration.Types.NavHidden.Unset) { + output.WriteRawTag(176, 1); + output.WriteEnum((int) NavHidden); + } + if (Navigation != global::Aapt.Pb.Configuration.Types.Navigation.Unset) { + output.WriteRawTag(184, 1); + output.WriteEnum((int) Navigation); + } + if (SdkVersion != 0) { + output.WriteRawTag(192, 1); + output.WriteUInt32(SdkVersion); + } + if (Product.Length != 0) { + output.WriteRawTag(202, 1); + output.WriteString(Product); + } + if (GrammaticalGender != global::Aapt.Pb.Configuration.Types.GrammaticalGender.GramGenderUset) { + output.WriteRawTag(208, 1); + output.WriteEnum((int) GrammaticalGender); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Mcc != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Mcc); + } + if (Mnc != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Mnc); + } + if (Locale.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Locale); + } + if (LayoutDirection != global::Aapt.Pb.Configuration.Types.LayoutDirection.Unset) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) LayoutDirection); + } + if (ScreenWidth != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(ScreenWidth); + } + if (ScreenHeight != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(ScreenHeight); + } + if (ScreenWidthDp != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(ScreenWidthDp); + } + if (ScreenHeightDp != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(ScreenHeightDp); + } + if (SmallestScreenWidthDp != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(SmallestScreenWidthDp); + } + if (ScreenLayoutSize != global::Aapt.Pb.Configuration.Types.ScreenLayoutSize.Unset) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ScreenLayoutSize); + } + if (ScreenLayoutLong != global::Aapt.Pb.Configuration.Types.ScreenLayoutLong.Unset) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ScreenLayoutLong); + } + if (ScreenRound != global::Aapt.Pb.Configuration.Types.ScreenRound.Unset) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ScreenRound); + } + if (WideColorGamut != global::Aapt.Pb.Configuration.Types.WideColorGamut.Unset) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) WideColorGamut); + } + if (Hdr != global::Aapt.Pb.Configuration.Types.Hdr.Unset) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Hdr); + } + if (Orientation != global::Aapt.Pb.Configuration.Types.Orientation.Unset) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Orientation); + } + if (UiModeType != global::Aapt.Pb.Configuration.Types.UiModeType.Unset) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) UiModeType); + } + if (UiModeNight != global::Aapt.Pb.Configuration.Types.UiModeNight.Unset) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) UiModeNight); + } + if (Density != 0) { + size += 2 + pb::CodedOutputStream.ComputeUInt32Size(Density); + } + if (Touchscreen != global::Aapt.Pb.Configuration.Types.Touchscreen.Unset) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) Touchscreen); + } + if (KeysHidden != global::Aapt.Pb.Configuration.Types.KeysHidden.Unset) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) KeysHidden); + } + if (Keyboard != global::Aapt.Pb.Configuration.Types.Keyboard.Unset) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) Keyboard); + } + if (NavHidden != global::Aapt.Pb.Configuration.Types.NavHidden.Unset) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) NavHidden); + } + if (Navigation != global::Aapt.Pb.Configuration.Types.Navigation.Unset) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) Navigation); + } + if (SdkVersion != 0) { + size += 2 + pb::CodedOutputStream.ComputeUInt32Size(SdkVersion); + } + if (GrammaticalGender != global::Aapt.Pb.Configuration.Types.GrammaticalGender.GramGenderUset) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) GrammaticalGender); + } + if (Product.Length != 0) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(Product); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Configuration other) { + if (other == null) { + return; + } + if (other.Mcc != 0) { + Mcc = other.Mcc; + } + if (other.Mnc != 0) { + Mnc = other.Mnc; + } + if (other.Locale.Length != 0) { + Locale = other.Locale; + } + if (other.LayoutDirection != global::Aapt.Pb.Configuration.Types.LayoutDirection.Unset) { + LayoutDirection = other.LayoutDirection; + } + if (other.ScreenWidth != 0) { + ScreenWidth = other.ScreenWidth; + } + if (other.ScreenHeight != 0) { + ScreenHeight = other.ScreenHeight; + } + if (other.ScreenWidthDp != 0) { + ScreenWidthDp = other.ScreenWidthDp; + } + if (other.ScreenHeightDp != 0) { + ScreenHeightDp = other.ScreenHeightDp; + } + if (other.SmallestScreenWidthDp != 0) { + SmallestScreenWidthDp = other.SmallestScreenWidthDp; + } + if (other.ScreenLayoutSize != global::Aapt.Pb.Configuration.Types.ScreenLayoutSize.Unset) { + ScreenLayoutSize = other.ScreenLayoutSize; + } + if (other.ScreenLayoutLong != global::Aapt.Pb.Configuration.Types.ScreenLayoutLong.Unset) { + ScreenLayoutLong = other.ScreenLayoutLong; + } + if (other.ScreenRound != global::Aapt.Pb.Configuration.Types.ScreenRound.Unset) { + ScreenRound = other.ScreenRound; + } + if (other.WideColorGamut != global::Aapt.Pb.Configuration.Types.WideColorGamut.Unset) { + WideColorGamut = other.WideColorGamut; + } + if (other.Hdr != global::Aapt.Pb.Configuration.Types.Hdr.Unset) { + Hdr = other.Hdr; + } + if (other.Orientation != global::Aapt.Pb.Configuration.Types.Orientation.Unset) { + Orientation = other.Orientation; + } + if (other.UiModeType != global::Aapt.Pb.Configuration.Types.UiModeType.Unset) { + UiModeType = other.UiModeType; + } + if (other.UiModeNight != global::Aapt.Pb.Configuration.Types.UiModeNight.Unset) { + UiModeNight = other.UiModeNight; + } + if (other.Density != 0) { + Density = other.Density; + } + if (other.Touchscreen != global::Aapt.Pb.Configuration.Types.Touchscreen.Unset) { + Touchscreen = other.Touchscreen; + } + if (other.KeysHidden != global::Aapt.Pb.Configuration.Types.KeysHidden.Unset) { + KeysHidden = other.KeysHidden; + } + if (other.Keyboard != global::Aapt.Pb.Configuration.Types.Keyboard.Unset) { + Keyboard = other.Keyboard; + } + if (other.NavHidden != global::Aapt.Pb.Configuration.Types.NavHidden.Unset) { + NavHidden = other.NavHidden; + } + if (other.Navigation != global::Aapt.Pb.Configuration.Types.Navigation.Unset) { + Navigation = other.Navigation; + } + if (other.SdkVersion != 0) { + SdkVersion = other.SdkVersion; + } + if (other.GrammaticalGender != global::Aapt.Pb.Configuration.Types.GrammaticalGender.GramGenderUset) { + GrammaticalGender = other.GrammaticalGender; + } + if (other.Product.Length != 0) { + Product = other.Product; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Mcc = input.ReadUInt32(); + break; + } + case 16: { + Mnc = input.ReadUInt32(); + break; + } + case 26: { + Locale = input.ReadString(); + break; + } + case 32: { + LayoutDirection = (global::Aapt.Pb.Configuration.Types.LayoutDirection) input.ReadEnum(); + break; + } + case 40: { + ScreenWidth = input.ReadUInt32(); + break; + } + case 48: { + ScreenHeight = input.ReadUInt32(); + break; + } + case 56: { + ScreenWidthDp = input.ReadUInt32(); + break; + } + case 64: { + ScreenHeightDp = input.ReadUInt32(); + break; + } + case 72: { + SmallestScreenWidthDp = input.ReadUInt32(); + break; + } + case 80: { + ScreenLayoutSize = (global::Aapt.Pb.Configuration.Types.ScreenLayoutSize) input.ReadEnum(); + break; + } + case 88: { + ScreenLayoutLong = (global::Aapt.Pb.Configuration.Types.ScreenLayoutLong) input.ReadEnum(); + break; + } + case 96: { + ScreenRound = (global::Aapt.Pb.Configuration.Types.ScreenRound) input.ReadEnum(); + break; + } + case 104: { + WideColorGamut = (global::Aapt.Pb.Configuration.Types.WideColorGamut) input.ReadEnum(); + break; + } + case 112: { + Hdr = (global::Aapt.Pb.Configuration.Types.Hdr) input.ReadEnum(); + break; + } + case 120: { + Orientation = (global::Aapt.Pb.Configuration.Types.Orientation) input.ReadEnum(); + break; + } + case 128: { + UiModeType = (global::Aapt.Pb.Configuration.Types.UiModeType) input.ReadEnum(); + break; + } + case 136: { + UiModeNight = (global::Aapt.Pb.Configuration.Types.UiModeNight) input.ReadEnum(); + break; + } + case 144: { + Density = input.ReadUInt32(); + break; + } + case 152: { + Touchscreen = (global::Aapt.Pb.Configuration.Types.Touchscreen) input.ReadEnum(); + break; + } + case 160: { + KeysHidden = (global::Aapt.Pb.Configuration.Types.KeysHidden) input.ReadEnum(); + break; + } + case 168: { + Keyboard = (global::Aapt.Pb.Configuration.Types.Keyboard) input.ReadEnum(); + break; + } + case 176: { + NavHidden = (global::Aapt.Pb.Configuration.Types.NavHidden) input.ReadEnum(); + break; + } + case 184: { + Navigation = (global::Aapt.Pb.Configuration.Types.Navigation) input.ReadEnum(); + break; + } + case 192: { + SdkVersion = input.ReadUInt32(); + break; + } + case 202: { + Product = input.ReadString(); + break; + } + case 208: { + GrammaticalGender = (global::Aapt.Pb.Configuration.Types.GrammaticalGender) input.ReadEnum(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Mcc = input.ReadUInt32(); + break; + } + case 16: { + Mnc = input.ReadUInt32(); + break; + } + case 26: { + Locale = input.ReadString(); + break; + } + case 32: { + LayoutDirection = (global::Aapt.Pb.Configuration.Types.LayoutDirection) input.ReadEnum(); + break; + } + case 40: { + ScreenWidth = input.ReadUInt32(); + break; + } + case 48: { + ScreenHeight = input.ReadUInt32(); + break; + } + case 56: { + ScreenWidthDp = input.ReadUInt32(); + break; + } + case 64: { + ScreenHeightDp = input.ReadUInt32(); + break; + } + case 72: { + SmallestScreenWidthDp = input.ReadUInt32(); + break; + } + case 80: { + ScreenLayoutSize = (global::Aapt.Pb.Configuration.Types.ScreenLayoutSize) input.ReadEnum(); + break; + } + case 88: { + ScreenLayoutLong = (global::Aapt.Pb.Configuration.Types.ScreenLayoutLong) input.ReadEnum(); + break; + } + case 96: { + ScreenRound = (global::Aapt.Pb.Configuration.Types.ScreenRound) input.ReadEnum(); + break; + } + case 104: { + WideColorGamut = (global::Aapt.Pb.Configuration.Types.WideColorGamut) input.ReadEnum(); + break; + } + case 112: { + Hdr = (global::Aapt.Pb.Configuration.Types.Hdr) input.ReadEnum(); + break; + } + case 120: { + Orientation = (global::Aapt.Pb.Configuration.Types.Orientation) input.ReadEnum(); + break; + } + case 128: { + UiModeType = (global::Aapt.Pb.Configuration.Types.UiModeType) input.ReadEnum(); + break; + } + case 136: { + UiModeNight = (global::Aapt.Pb.Configuration.Types.UiModeNight) input.ReadEnum(); + break; + } + case 144: { + Density = input.ReadUInt32(); + break; + } + case 152: { + Touchscreen = (global::Aapt.Pb.Configuration.Types.Touchscreen) input.ReadEnum(); + break; + } + case 160: { + KeysHidden = (global::Aapt.Pb.Configuration.Types.KeysHidden) input.ReadEnum(); + break; + } + case 168: { + Keyboard = (global::Aapt.Pb.Configuration.Types.Keyboard) input.ReadEnum(); + break; + } + case 176: { + NavHidden = (global::Aapt.Pb.Configuration.Types.NavHidden) input.ReadEnum(); + break; + } + case 184: { + Navigation = (global::Aapt.Pb.Configuration.Types.Navigation) input.ReadEnum(); + break; + } + case 192: { + SdkVersion = input.ReadUInt32(); + break; + } + case 202: { + Product = input.ReadString(); + break; + } + case 208: { + GrammaticalGender = (global::Aapt.Pb.Configuration.Types.GrammaticalGender) input.ReadEnum(); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the Configuration message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static partial class Types { + public enum LayoutDirection { + [pbr::OriginalName("LAYOUT_DIRECTION_UNSET")] Unset = 0, + [pbr::OriginalName("LAYOUT_DIRECTION_LTR")] Ltr = 1, + [pbr::OriginalName("LAYOUT_DIRECTION_RTL")] Rtl = 2, + } + + public enum ScreenLayoutSize { + [pbr::OriginalName("SCREEN_LAYOUT_SIZE_UNSET")] Unset = 0, + [pbr::OriginalName("SCREEN_LAYOUT_SIZE_SMALL")] Small = 1, + [pbr::OriginalName("SCREEN_LAYOUT_SIZE_NORMAL")] Normal = 2, + [pbr::OriginalName("SCREEN_LAYOUT_SIZE_LARGE")] Large = 3, + [pbr::OriginalName("SCREEN_LAYOUT_SIZE_XLARGE")] Xlarge = 4, + } + + public enum ScreenLayoutLong { + [pbr::OriginalName("SCREEN_LAYOUT_LONG_UNSET")] Unset = 0, + [pbr::OriginalName("SCREEN_LAYOUT_LONG_LONG")] Long = 1, + [pbr::OriginalName("SCREEN_LAYOUT_LONG_NOTLONG")] Notlong = 2, + } + + public enum ScreenRound { + [pbr::OriginalName("SCREEN_ROUND_UNSET")] Unset = 0, + [pbr::OriginalName("SCREEN_ROUND_ROUND")] Round = 1, + [pbr::OriginalName("SCREEN_ROUND_NOTROUND")] Notround = 2, + } + + public enum WideColorGamut { + [pbr::OriginalName("WIDE_COLOR_GAMUT_UNSET")] Unset = 0, + [pbr::OriginalName("WIDE_COLOR_GAMUT_WIDECG")] Widecg = 1, + [pbr::OriginalName("WIDE_COLOR_GAMUT_NOWIDECG")] Nowidecg = 2, + } + + public enum Hdr { + [pbr::OriginalName("HDR_UNSET")] Unset = 0, + [pbr::OriginalName("HDR_HIGHDR")] Highdr = 1, + [pbr::OriginalName("HDR_LOWDR")] Lowdr = 2, + } + + public enum Orientation { + [pbr::OriginalName("ORIENTATION_UNSET")] Unset = 0, + [pbr::OriginalName("ORIENTATION_PORT")] Port = 1, + [pbr::OriginalName("ORIENTATION_LAND")] Land = 2, + [pbr::OriginalName("ORIENTATION_SQUARE")] Square = 3, + } + + public enum UiModeType { + [pbr::OriginalName("UI_MODE_TYPE_UNSET")] Unset = 0, + [pbr::OriginalName("UI_MODE_TYPE_NORMAL")] Normal = 1, + [pbr::OriginalName("UI_MODE_TYPE_DESK")] Desk = 2, + [pbr::OriginalName("UI_MODE_TYPE_CAR")] Car = 3, + [pbr::OriginalName("UI_MODE_TYPE_TELEVISION")] Television = 4, + [pbr::OriginalName("UI_MODE_TYPE_APPLIANCE")] Appliance = 5, + [pbr::OriginalName("UI_MODE_TYPE_WATCH")] Watch = 6, + [pbr::OriginalName("UI_MODE_TYPE_VRHEADSET")] Vrheadset = 7, + } + + public enum UiModeNight { + [pbr::OriginalName("UI_MODE_NIGHT_UNSET")] Unset = 0, + [pbr::OriginalName("UI_MODE_NIGHT_NIGHT")] Night = 1, + [pbr::OriginalName("UI_MODE_NIGHT_NOTNIGHT")] Notnight = 2, + } + + public enum Touchscreen { + [pbr::OriginalName("TOUCHSCREEN_UNSET")] Unset = 0, + [pbr::OriginalName("TOUCHSCREEN_NOTOUCH")] Notouch = 1, + [pbr::OriginalName("TOUCHSCREEN_STYLUS")] Stylus = 2, + [pbr::OriginalName("TOUCHSCREEN_FINGER")] Finger = 3, + } + + public enum KeysHidden { + [pbr::OriginalName("KEYS_HIDDEN_UNSET")] Unset = 0, + [pbr::OriginalName("KEYS_HIDDEN_KEYSEXPOSED")] Keysexposed = 1, + [pbr::OriginalName("KEYS_HIDDEN_KEYSHIDDEN")] Keyshidden = 2, + [pbr::OriginalName("KEYS_HIDDEN_KEYSSOFT")] Keyssoft = 3, + } + + public enum Keyboard { + [pbr::OriginalName("KEYBOARD_UNSET")] Unset = 0, + [pbr::OriginalName("KEYBOARD_NOKEYS")] Nokeys = 1, + [pbr::OriginalName("KEYBOARD_QWERTY")] Qwerty = 2, + [pbr::OriginalName("KEYBOARD_TWELVEKEY")] Twelvekey = 3, + } + + public enum NavHidden { + [pbr::OriginalName("NAV_HIDDEN_UNSET")] Unset = 0, + [pbr::OriginalName("NAV_HIDDEN_NAVEXPOSED")] Navexposed = 1, + [pbr::OriginalName("NAV_HIDDEN_NAVHIDDEN")] Navhidden = 2, + } + + public enum Navigation { + [pbr::OriginalName("NAVIGATION_UNSET")] Unset = 0, + [pbr::OriginalName("NAVIGATION_NONAV")] Nonav = 1, + [pbr::OriginalName("NAVIGATION_DPAD")] Dpad = 2, + [pbr::OriginalName("NAVIGATION_TRACKBALL")] Trackball = 3, + [pbr::OriginalName("NAVIGATION_WHEEL")] Wheel = 4, + } + + public enum GrammaticalGender { + [pbr::OriginalName("GRAM_GENDER_USET")] GramGenderUset = 0, + [pbr::OriginalName("GRAM_GENDER_NEUTER")] GramGenderNeuter = 1, + [pbr::OriginalName("GRAM_GENDER_FEMININE")] GramGenderFeminine = 2, + [pbr::OriginalName("GRAM_GENDER_MASCULINE")] GramGenderMasculine = 3, + } + + } + #endregion + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/tools/apput/src/Android/Aapt.Pb.Files.README.md b/tools/apput/src/Android/Aapt.Pb.Files.README.md new file mode 100644 index 00000000000..b05523d88c3 --- /dev/null +++ b/tools/apput/src/Android/Aapt.Pb.Files.README.md @@ -0,0 +1,2 @@ +Aapt.Pb.Resources.cs generated from https://android.googlesource.com/platform/frameworks/base/+/54f29d4e33cc7ea12334ba8a6072a38f3f4d0ddb/tools/aapt2/Resources.proto +Aapt.Pb.Configuration.cs generated from https://android.googlesource.com/platform/frameworks/base/+/54f29d4e33cc7ea12334ba8a6072a38f3f4d0ddb/tools/aapt2/Configuration.proto diff --git a/tools/apput/src/Android/Aapt.Pb.Resources.cs b/tools/apput/src/Android/Aapt.Pb.Resources.cs new file mode 100644 index 00000000000..3cbe8a054c3 --- /dev/null +++ b/tools/apput/src/Android/Aapt.Pb.Resources.cs @@ -0,0 +1,15266 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: Resources.proto +// +#pragma warning disable 1591, 0612, 3021, 8981 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Aapt.Pb { + + /// Holder for reflection information generated from Resources.proto + public static partial class ResourcesReflection { + + #region Descriptor + /// File descriptor for Resources.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static ResourcesReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "Cg9SZXNvdXJjZXMucHJvdG8SB2FhcHQucGIaL2ZyYW1ld29ya3MvYmFzZS90", + "b29scy9hYXB0Mi9Db25maWd1cmF0aW9uLnByb3RvIhoKClN0cmluZ1Bvb2wS", + "DAoEZGF0YRgBIAEoDCI8Cg5Tb3VyY2VQb3NpdGlvbhITCgtsaW5lX251bWJl", + "chgBIAEoDRIVCg1jb2x1bW5fbnVtYmVyGAIgASgNIkUKBlNvdXJjZRIQCghw", + "YXRoX2lkeBgBIAEoDRIpCghwb3NpdGlvbhgCIAEoCzIXLmFhcHQucGIuU291", + "cmNlUG9zaXRpb24iMAoPVG9vbEZpbmdlcnByaW50EgwKBHRvb2wYASABKAkS", + "DwoHdmVyc2lvbhgCIAEoCSJPCg9EeW5hbWljUmVmVGFibGUSJgoKcGFja2Fn", + "ZV9pZBgBIAEoCzISLmFhcHQucGIuUGFja2FnZUlkEhQKDHBhY2thZ2VfbmFt", + "ZRgCIAEoCSLwAQoNUmVzb3VyY2VUYWJsZRIoCgtzb3VyY2VfcG9vbBgBIAEo", + "CzITLmFhcHQucGIuU3RyaW5nUG9vbBIhCgdwYWNrYWdlGAIgAygLMhAuYWFw", + "dC5wYi5QYWNrYWdlEikKC292ZXJsYXlhYmxlGAMgAygLMhQuYWFwdC5wYi5P", + "dmVybGF5YWJsZRIyChB0b29sX2ZpbmdlcnByaW50GAQgAygLMhguYWFwdC5w", + "Yi5Ub29sRmluZ2VycHJpbnQSMwoRZHluYW1pY19yZWZfdGFibGUYBSADKAsy", + "GC5hYXB0LnBiLkR5bmFtaWNSZWZUYWJsZSIXCglQYWNrYWdlSWQSCgoCaWQY", + "ASABKA0iZAoHUGFja2FnZRImCgpwYWNrYWdlX2lkGAEgASgLMhIuYWFwdC5w", + "Yi5QYWNrYWdlSWQSFAoMcGFja2FnZV9uYW1lGAIgASgJEhsKBHR5cGUYAyAD", + "KAsyDS5hYXB0LnBiLlR5cGUiFAoGVHlwZUlkEgoKAmlkGAEgASgNIlUKBFR5", + "cGUSIAoHdHlwZV9pZBgBIAEoCzIPLmFhcHQucGIuVHlwZUlkEgwKBG5hbWUY", + "AiABKAkSHQoFZW50cnkYAyADKAsyDi5hYXB0LnBiLkVudHJ5IqsBCgpWaXNp", + "YmlsaXR5EigKBWxldmVsGAEgASgOMhkuYWFwdC5wYi5WaXNpYmlsaXR5Lkxl", + "dmVsEh8KBnNvdXJjZRgCIAEoCzIPLmFhcHQucGIuU291cmNlEg8KB2NvbW1l", + "bnQYAyABKAkSEgoKc3RhZ2VkX2FwaRgEIAEoCCItCgVMZXZlbBILCgdVTktO", + "T1dOEAASCwoHUFJJVkFURRABEgoKBlBVQkxJQxACIjwKCEFsbG93TmV3Eh8K", + "BnNvdXJjZRgBIAEoCzIPLmFhcHQucGIuU291cmNlEg8KB2NvbW1lbnQYAiAB", + "KAkiSwoLT3ZlcmxheWFibGUSDAoEbmFtZRgBIAEoCRIfCgZzb3VyY2UYAiAB", + "KAsyDy5hYXB0LnBiLlNvdXJjZRINCgVhY3RvchgDIAEoCSKVAgoPT3Zlcmxh", + "eWFibGVJdGVtEh8KBnNvdXJjZRgBIAEoCzIPLmFhcHQucGIuU291cmNlEg8K", + "B2NvbW1lbnQYAiABKAkSLwoGcG9saWN5GAMgAygOMh8uYWFwdC5wYi5PdmVy", + "bGF5YWJsZUl0ZW0uUG9saWN5EhcKD292ZXJsYXlhYmxlX2lkeBgEIAEoDSKF", + "AQoGUG9saWN5EggKBE5PTkUQABIKCgZQVUJMSUMQARIKCgZTWVNURU0QAhIK", + "CgZWRU5ET1IQAxILCgdQUk9EVUNUEAQSDQoJU0lHTkFUVVJFEAUSBwoDT0RN", + "EAYSBwoDT0VNEAcSCQoFQUNUT1IQCBIUChBDT05GSUdfU0lHTkFUVVJFEAki", + "PgoIU3RhZ2VkSWQSHwoGc291cmNlGAEgASgLMg8uYWFwdC5wYi5Tb3VyY2US", + "EQoJc3RhZ2VkX2lkGAIgASgNIhUKB0VudHJ5SWQSCgoCaWQYASABKA0iyAIK", + "BUVudHJ5EiIKCGVudHJ5X2lkGAEgASgLMhAuYWFwdC5wYi5FbnRyeUlkEgwK", + "BG5hbWUYAiABKAkSJwoKdmlzaWJpbGl0eRgDIAEoCzITLmFhcHQucGIuVmlz", + "aWJpbGl0eRIkCglhbGxvd19uZXcYBCABKAsyES5hYXB0LnBiLkFsbG93TmV3", + "EjIKEG92ZXJsYXlhYmxlX2l0ZW0YBSABKAsyGC5hYXB0LnBiLk92ZXJsYXlh", + "YmxlSXRlbRIqCgxjb25maWdfdmFsdWUYBiADKAsyFC5hYXB0LnBiLkNvbmZp", + "Z1ZhbHVlEiQKCXN0YWdlZF9pZBgHIAEoCzIRLmFhcHQucGIuU3RhZ2VkSWQS", + "OAoaZmxhZ19kaXNhYmxlZF9jb25maWdfdmFsdWUYCCADKAsyFC5hYXB0LnBi", + "LkNvbmZpZ1ZhbHVlIloKC0NvbmZpZ1ZhbHVlEiYKBmNvbmZpZxgBIAEoCzIW", + "LmFhcHQucGIuQ29uZmlndXJhdGlvbhIdCgV2YWx1ZRgCIAEoCzIOLmFhcHQu", + "cGIuVmFsdWVKBAgDEAQioQEKBVZhbHVlEh8KBnNvdXJjZRgBIAEoCzIPLmFh", + "cHQucGIuU291cmNlEg8KB2NvbW1lbnQYAiABKAkSDAoEd2VhaxgDIAEoCBId", + "CgRpdGVtGAQgASgLMg0uYWFwdC5wYi5JdGVtSAASMAoOY29tcG91bmRfdmFs", + "dWUYBSABKAsyFi5hYXB0LnBiLkNvbXBvdW5kVmFsdWVIAEIHCgV2YWx1ZSLL", + "AgoESXRlbRIhCgNyZWYYASABKAsyEi5hYXB0LnBiLlJlZmVyZW5jZUgAEh4K", + "A3N0chgCIAEoCzIPLmFhcHQucGIuU3RyaW5nSAASJQoHcmF3X3N0chgDIAEo", + "CzISLmFhcHQucGIuUmF3U3RyaW5nSAASKwoKc3R5bGVkX3N0chgEIAEoCzIV", + "LmFhcHQucGIuU3R5bGVkU3RyaW5nSAASJgoEZmlsZRgFIAEoCzIWLmFhcHQu", + "cGIuRmlsZVJlZmVyZW5jZUgAEhkKAmlkGAYgASgLMgsuYWFwdC5wYi5JZEgA", + "EiIKBHByaW0YByABKAsyEi5hYXB0LnBiLlByaW1pdGl2ZUgAEhMKC2ZsYWdf", + "c3RhdHVzGAggASgNEhQKDGZsYWdfbmVnYXRlZBgJIAEoCBIRCglmbGFnX25h", + "bWUYCiABKAlCBwoFdmFsdWUirQIKDUNvbXBvdW5kVmFsdWUSIgoEYXR0chgB", + "IAEoCzISLmFhcHQucGIuQXR0cmlidXRlSAASHwoFc3R5bGUYAiABKAsyDi5h", + "YXB0LnBiLlN0eWxlSAASJwoJc3R5bGVhYmxlGAMgASgLMhIuYWFwdC5wYi5T", + "dHlsZWFibGVIABIfCgVhcnJheRgEIAEoCzIOLmFhcHQucGIuQXJyYXlIABIh", + "CgZwbHVyYWwYBSABKAsyDy5hYXB0LnBiLlBsdXJhbEgAEiMKBW1hY3JvGAYg", + "ASgLMhIuYWFwdC5wYi5NYWNyb0JvZHlIABITCgtmbGFnX3N0YXR1cxgHIAEo", + "DRIUCgxmbGFnX25lZ2F0ZWQYCCABKAgSEQoJZmxhZ19uYW1lGAkgASgJQgcK", + "BXZhbHVlIhgKB0Jvb2xlYW4SDQoFdmFsdWUYASABKAgi0AEKCVJlZmVyZW5j", + "ZRIlCgR0eXBlGAEgASgOMhcuYWFwdC5wYi5SZWZlcmVuY2UuVHlwZRIKCgJp", + "ZBgCIAEoDRIMCgRuYW1lGAMgASgJEg8KB3ByaXZhdGUYBCABKAgSJAoKaXNf", + "ZHluYW1pYxgFIAEoCzIQLmFhcHQucGIuQm9vbGVhbhISCgp0eXBlX2ZsYWdz", + "GAYgASgNEhEKCWFsbG93X3JhdxgHIAEoCCIkCgRUeXBlEg0KCVJFRkVSRU5D", + "RRAAEg0KCUFUVFJJQlVURRABIgQKAklkIhcKBlN0cmluZxINCgV2YWx1ZRgB", + "IAEoCSIaCglSYXdTdHJpbmcSDQoFdmFsdWUYASABKAkigwEKDFN0eWxlZFN0", + "cmluZxINCgV2YWx1ZRgBIAEoCRIoCgRzcGFuGAIgAygLMhouYWFwdC5wYi5T", + "dHlsZWRTdHJpbmcuU3Bhbho6CgRTcGFuEgsKA3RhZxgBIAEoCRISCgpmaXJz", + "dF9jaGFyGAIgASgNEhEKCWxhc3RfY2hhchgDIAEoDSKFAQoNRmlsZVJlZmVy", + "ZW5jZRIMCgRwYXRoGAEgASgJEikKBHR5cGUYAiABKA4yGy5hYXB0LnBiLkZp", + "bGVSZWZlcmVuY2UuVHlwZSI7CgRUeXBlEgsKB1VOS05PV04QABIHCgNQTkcQ", + "ARIOCgpCSU5BUllfWE1MEAISDQoJUFJPVE9fWE1MEAMigwQKCVByaW1pdGl2", + "ZRIxCgpudWxsX3ZhbHVlGAEgASgLMhsuYWFwdC5wYi5QcmltaXRpdmUuTnVs", + "bFR5cGVIABIzCgtlbXB0eV92YWx1ZRgCIAEoCzIcLmFhcHQucGIuUHJpbWl0", + "aXZlLkVtcHR5VHlwZUgAEhUKC2Zsb2F0X3ZhbHVlGAMgASgCSAASGQoPZGlt", + "ZW5zaW9uX3ZhbHVlGA0gASgNSAASGAoOZnJhY3Rpb25fdmFsdWUYDiABKA1I", + "ABIbChFpbnRfZGVjaW1hbF92YWx1ZRgGIAEoBUgAEh8KFWludF9oZXhhZGVj", + "aW1hbF92YWx1ZRgHIAEoDUgAEhcKDWJvb2xlYW5fdmFsdWUYCCABKAhIABIb", + "ChFjb2xvcl9hcmdiOF92YWx1ZRgJIAEoDUgAEhoKEGNvbG9yX3JnYjhfdmFs", + "dWUYCiABKA1IABIbChFjb2xvcl9hcmdiNF92YWx1ZRgLIAEoDUgAEhoKEGNv", + "bG9yX3JnYjRfdmFsdWUYDCABKA1IABIoChpkaW1lbnNpb25fdmFsdWVfZGVw", + "cmVjYXRlZBgEIAEoAkICGAFIABInChlmcmFjdGlvbl92YWx1ZV9kZXByZWNh", + "dGVkGAUgASgCQgIYAUgAGgoKCE51bGxUeXBlGgsKCUVtcHR5VHlwZUINCgtv", + "bmVvZl92YWx1ZSKQAwoJQXR0cmlidXRlEhQKDGZvcm1hdF9mbGFncxgBIAEo", + "DRIPCgdtaW5faW50GAIgASgFEg8KB21heF9pbnQYAyABKAUSKQoGc3ltYm9s", + "GAQgAygLMhkuYWFwdC5wYi5BdHRyaWJ1dGUuU3ltYm9sGnkKBlN5bWJvbBIf", + "CgZzb3VyY2UYASABKAsyDy5hYXB0LnBiLlNvdXJjZRIPCgdjb21tZW50GAIg", + "ASgJEiAKBG5hbWUYAyABKAsyEi5hYXB0LnBiLlJlZmVyZW5jZRINCgV2YWx1", + "ZRgEIAEoDRIMCgR0eXBlGAUgASgNIqQBCgtGb3JtYXRGbGFncxIICgROT05F", + "EAASCQoDQU5ZEP//AxINCglSRUZFUkVOQ0UQARIKCgZTVFJJTkcQAhILCgdJ", + "TlRFR0VSEAQSCwoHQk9PTEVBThAIEgkKBUNPTE9SEBASCQoFRkxPQVQQIBIN", + "CglESU1FTlNJT04QQBINCghGUkFDVElPThCAARIKCgRFTlVNEICABBILCgVG", + "TEFHUxCAgAgi8QEKBVN0eWxlEiIKBnBhcmVudBgBIAEoCzISLmFhcHQucGIu", + "UmVmZXJlbmNlEiYKDXBhcmVudF9zb3VyY2UYAiABKAsyDy5hYXB0LnBiLlNv", + "dXJjZRIjCgVlbnRyeRgDIAMoCzIULmFhcHQucGIuU3R5bGUuRW50cnkadwoF", + "RW50cnkSHwoGc291cmNlGAEgASgLMg8uYWFwdC5wYi5Tb3VyY2USDwoHY29t", + "bWVudBgCIAEoCRIfCgNrZXkYAyABKAsyEi5hYXB0LnBiLlJlZmVyZW5jZRIb", + "CgRpdGVtGAQgASgLMg0uYWFwdC5wYi5JdGVtIpEBCglTdHlsZWFibGUSJwoF", + "ZW50cnkYASADKAsyGC5hYXB0LnBiLlN0eWxlYWJsZS5FbnRyeRpbCgVFbnRy", + "eRIfCgZzb3VyY2UYASABKAsyDy5hYXB0LnBiLlNvdXJjZRIPCgdjb21tZW50", + "GAIgASgJEiAKBGF0dHIYAyABKAsyEi5hYXB0LnBiLlJlZmVyZW5jZSKKAQoF", + "QXJyYXkSJwoHZWxlbWVudBgBIAMoCzIWLmFhcHQucGIuQXJyYXkuRWxlbWVu", + "dBpYCgdFbGVtZW50Eh8KBnNvdXJjZRgBIAEoCzIPLmFhcHQucGIuU291cmNl", + "Eg8KB2NvbW1lbnQYAiABKAkSGwoEaXRlbRgDIAEoCzINLmFhcHQucGIuSXRl", + "bSLvAQoGUGx1cmFsEiQKBWVudHJ5GAEgAygLMhUuYWFwdC5wYi5QbHVyYWwu", + "RW50cnkafAoFRW50cnkSHwoGc291cmNlGAEgASgLMg8uYWFwdC5wYi5Tb3Vy", + "Y2USDwoHY29tbWVudBgCIAEoCRIkCgVhcml0eRgDIAEoDjIVLmFhcHQucGIu", + "UGx1cmFsLkFyaXR5EhsKBGl0ZW0YBCABKAsyDS5hYXB0LnBiLkl0ZW0iQQoF", + "QXJpdHkSCAoEWkVSTxAAEgcKA09ORRABEgcKA1RXTxACEgcKA0ZFVxADEggK", + "BE1BTlkQBBIJCgVPVEhFUhAFInIKB1htbE5vZGUSJgoHZWxlbWVudBgBIAEo", + "CzITLmFhcHQucGIuWG1sRWxlbWVudEgAEg4KBHRleHQYAiABKAlIABInCgZz", + "b3VyY2UYAyABKAsyFy5hYXB0LnBiLlNvdXJjZVBvc2l0aW9uQgYKBG5vZGUi", + "sgEKClhtbEVsZW1lbnQSNAoVbmFtZXNwYWNlX2RlY2xhcmF0aW9uGAEgAygL", + "MhUuYWFwdC5wYi5YbWxOYW1lc3BhY2USFQoNbmFtZXNwYWNlX3VyaRgCIAEo", + "CRIMCgRuYW1lGAMgASgJEigKCWF0dHJpYnV0ZRgEIAMoCzIVLmFhcHQucGIu", + "WG1sQXR0cmlidXRlEh8KBWNoaWxkGAUgAygLMhAuYWFwdC5wYi5YbWxOb2Rl", + "IlQKDFhtbE5hbWVzcGFjZRIOCgZwcmVmaXgYASABKAkSCwoDdXJpGAIgASgJ", + "EicKBnNvdXJjZRgDIAEoCzIXLmFhcHQucGIuU291cmNlUG9zaXRpb24ipgEK", + "DFhtbEF0dHJpYnV0ZRIVCg1uYW1lc3BhY2VfdXJpGAEgASgJEgwKBG5hbWUY", + "AiABKAkSDQoFdmFsdWUYAyABKAkSJwoGc291cmNlGAQgASgLMhcuYWFwdC5w", + "Yi5Tb3VyY2VQb3NpdGlvbhITCgtyZXNvdXJjZV9pZBgFIAEoDRIkCg1jb21w", + "aWxlZF9pdGVtGAYgASgLMg0uYWFwdC5wYi5JdGVtIucBCglNYWNyb0JvZHkS", + "EgoKcmF3X3N0cmluZxgBIAEoCRIqCgxzdHlsZV9zdHJpbmcYAiABKAsyFC5h", + "YXB0LnBiLlN0eWxlU3RyaW5nEj8KF3VudHJhbnNsYXRhYmxlX3NlY3Rpb25z", + "GAMgAygLMh4uYWFwdC5wYi5VbnRyYW5zbGF0YWJsZVNlY3Rpb24SMAoPbmFt", + "ZXNwYWNlX3N0YWNrGAQgAygLMhcuYWFwdC5wYi5OYW1lc3BhY2VBbGlhcxIn", + "CgZzb3VyY2UYBSABKAsyFy5hYXB0LnBiLlNvdXJjZVBvc2l0aW9uIkoKDk5h", + "bWVzcGFjZUFsaWFzEg4KBnByZWZpeBgBIAEoCRIUCgxwYWNrYWdlX25hbWUY", + "AiABKAkSEgoKaXNfcHJpdmF0ZRgDIAEoCCKCAQoLU3R5bGVTdHJpbmcSCwoD", + "c3RyGAEgASgJEigKBXNwYW5zGAIgAygLMhkuYWFwdC5wYi5TdHlsZVN0cmlu", + "Zy5TcGFuGjwKBFNwYW4SDAoEbmFtZRgBIAEoCRITCgtzdGFydF9pbmRleBgC", + "IAEoDRIRCgllbmRfaW5kZXgYAyABKA0iPwoVVW50cmFuc2xhdGFibGVTZWN0", + "aW9uEhMKC3N0YXJ0X2luZGV4GAEgASgEEhEKCWVuZF9pbmRleBgCIAEoBEIS", + "ChBjb20uYW5kcm9pZC5hYXB0YgZwcm90bzM=")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::Aapt.Pb.ConfigurationReflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.StringPool), global::Aapt.Pb.StringPool.Parser, new[]{ "Data" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.SourcePosition), global::Aapt.Pb.SourcePosition.Parser, new[]{ "LineNumber", "ColumnNumber" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Source), global::Aapt.Pb.Source.Parser, new[]{ "PathIdx", "Position" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.ToolFingerprint), global::Aapt.Pb.ToolFingerprint.Parser, new[]{ "Tool", "Version" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.DynamicRefTable), global::Aapt.Pb.DynamicRefTable.Parser, new[]{ "PackageId", "PackageName" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.ResourceTable), global::Aapt.Pb.ResourceTable.Parser, new[]{ "SourcePool", "Package", "Overlayable", "ToolFingerprint", "DynamicRefTable" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.PackageId), global::Aapt.Pb.PackageId.Parser, new[]{ "Id" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Package), global::Aapt.Pb.Package.Parser, new[]{ "PackageId", "PackageName", "Type" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.TypeId), global::Aapt.Pb.TypeId.Parser, new[]{ "Id" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Type), global::Aapt.Pb.Type.Parser, new[]{ "TypeId", "Name", "Entry" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Visibility), global::Aapt.Pb.Visibility.Parser, new[]{ "Level", "Source", "Comment", "StagedApi" }, null, new[]{ typeof(global::Aapt.Pb.Visibility.Types.Level) }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.AllowNew), global::Aapt.Pb.AllowNew.Parser, new[]{ "Source", "Comment" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Overlayable), global::Aapt.Pb.Overlayable.Parser, new[]{ "Name", "Source", "Actor" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.OverlayableItem), global::Aapt.Pb.OverlayableItem.Parser, new[]{ "Source", "Comment", "Policy", "OverlayableIdx" }, null, new[]{ typeof(global::Aapt.Pb.OverlayableItem.Types.Policy) }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.StagedId), global::Aapt.Pb.StagedId.Parser, new[]{ "Source", "StagedId_" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.EntryId), global::Aapt.Pb.EntryId.Parser, new[]{ "Id" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Entry), global::Aapt.Pb.Entry.Parser, new[]{ "EntryId", "Name", "Visibility", "AllowNew", "OverlayableItem", "ConfigValue", "StagedId", "FlagDisabledConfigValue" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.ConfigValue), global::Aapt.Pb.ConfigValue.Parser, new[]{ "Config", "Value" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Value), global::Aapt.Pb.Value.Parser, new[]{ "Source", "Comment", "Weak", "Item", "CompoundValue" }, new[]{ "Value" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Item), global::Aapt.Pb.Item.Parser, new[]{ "Ref", "Str", "RawStr", "StyledStr", "File", "Id", "Prim", "FlagStatus", "FlagNegated", "FlagName" }, new[]{ "Value" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.CompoundValue), global::Aapt.Pb.CompoundValue.Parser, new[]{ "Attr", "Style", "Styleable", "Array", "Plural", "Macro", "FlagStatus", "FlagNegated", "FlagName" }, new[]{ "Value" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Boolean), global::Aapt.Pb.Boolean.Parser, new[]{ "Value" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Reference), global::Aapt.Pb.Reference.Parser, new[]{ "Type", "Id", "Name", "Private", "IsDynamic", "TypeFlags", "AllowRaw" }, null, new[]{ typeof(global::Aapt.Pb.Reference.Types.Type) }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Id), global::Aapt.Pb.Id.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.String), global::Aapt.Pb.String.Parser, new[]{ "Value" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.RawString), global::Aapt.Pb.RawString.Parser, new[]{ "Value" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.StyledString), global::Aapt.Pb.StyledString.Parser, new[]{ "Value", "Span" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.StyledString.Types.Span), global::Aapt.Pb.StyledString.Types.Span.Parser, new[]{ "Tag", "FirstChar", "LastChar" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.FileReference), global::Aapt.Pb.FileReference.Parser, new[]{ "Path", "Type" }, null, new[]{ typeof(global::Aapt.Pb.FileReference.Types.Type) }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Primitive), global::Aapt.Pb.Primitive.Parser, new[]{ "NullValue", "EmptyValue", "FloatValue", "DimensionValue", "FractionValue", "IntDecimalValue", "IntHexadecimalValue", "BooleanValue", "ColorArgb8Value", "ColorRgb8Value", "ColorArgb4Value", "ColorRgb4Value", "DimensionValueDeprecated", "FractionValueDeprecated" }, new[]{ "OneofValue" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Primitive.Types.NullType), global::Aapt.Pb.Primitive.Types.NullType.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Primitive.Types.EmptyType), global::Aapt.Pb.Primitive.Types.EmptyType.Parser, null, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Attribute), global::Aapt.Pb.Attribute.Parser, new[]{ "FormatFlags", "MinInt", "MaxInt", "Symbol" }, null, new[]{ typeof(global::Aapt.Pb.Attribute.Types.FormatFlags) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Attribute.Types.Symbol), global::Aapt.Pb.Attribute.Types.Symbol.Parser, new[]{ "Source", "Comment", "Name", "Value", "Type" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Style), global::Aapt.Pb.Style.Parser, new[]{ "Parent", "ParentSource", "Entry" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Style.Types.Entry), global::Aapt.Pb.Style.Types.Entry.Parser, new[]{ "Source", "Comment", "Key", "Item" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Styleable), global::Aapt.Pb.Styleable.Parser, new[]{ "Entry" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Styleable.Types.Entry), global::Aapt.Pb.Styleable.Types.Entry.Parser, new[]{ "Source", "Comment", "Attr" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Array), global::Aapt.Pb.Array.Parser, new[]{ "Element" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Array.Types.Element), global::Aapt.Pb.Array.Types.Element.Parser, new[]{ "Source", "Comment", "Item" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Plural), global::Aapt.Pb.Plural.Parser, new[]{ "Entry" }, null, new[]{ typeof(global::Aapt.Pb.Plural.Types.Arity) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.Plural.Types.Entry), global::Aapt.Pb.Plural.Types.Entry.Parser, new[]{ "Source", "Comment", "Arity", "Item" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.XmlNode), global::Aapt.Pb.XmlNode.Parser, new[]{ "Element", "Text", "Source" }, new[]{ "Node" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.XmlElement), global::Aapt.Pb.XmlElement.Parser, new[]{ "NamespaceDeclaration", "NamespaceUri", "Name", "Attribute", "Child" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.XmlNamespace), global::Aapt.Pb.XmlNamespace.Parser, new[]{ "Prefix", "Uri", "Source" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.XmlAttribute), global::Aapt.Pb.XmlAttribute.Parser, new[]{ "NamespaceUri", "Name", "Value", "Source", "ResourceId", "CompiledItem" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.MacroBody), global::Aapt.Pb.MacroBody.Parser, new[]{ "RawString", "StyleString", "UntranslatableSections", "NamespaceStack", "Source" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.NamespaceAlias), global::Aapt.Pb.NamespaceAlias.Parser, new[]{ "Prefix", "PackageName", "IsPrivate" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.StyleString), global::Aapt.Pb.StyleString.Parser, new[]{ "Str", "Spans" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.StyleString.Types.Span), global::Aapt.Pb.StyleString.Types.Span.Parser, new[]{ "Name", "StartIndex", "EndIndex" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Aapt.Pb.UntranslatableSection), global::Aapt.Pb.UntranslatableSection.Parser, new[]{ "StartIndex", "EndIndex" }, null, null, null, null) + })); + } + #endregion + + } + #region Messages + /// + /// A string pool that wraps the binary form of the C++ class android::ResStringPool. + /// + public sealed partial class StringPool : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new StringPool()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public StringPool() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public StringPool(StringPool other) : this() { + data_ = other.data_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public StringPool Clone() { + return new StringPool(this); + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 1; + private pb::ByteString data_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pb::ByteString Data { + get { return data_; } + set { + data_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as StringPool); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(StringPool other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Data != other.Data) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Data.Length != 0) hash ^= Data.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Data.Length != 0) { + output.WriteRawTag(10); + output.WriteBytes(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Data.Length != 0) { + output.WriteRawTag(10); + output.WriteBytes(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Data.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(Data); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(StringPool other) { + if (other == null) { + return; + } + if (other.Data.Length != 0) { + Data = other.Data; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Data = input.ReadBytes(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Data = input.ReadBytes(); + break; + } + } + } + } + #endif + + } + + /// + /// The position of a declared entity within a file. + /// + public sealed partial class SourcePosition : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SourcePosition()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public SourcePosition() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public SourcePosition(SourcePosition other) : this() { + lineNumber_ = other.lineNumber_; + columnNumber_ = other.columnNumber_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public SourcePosition Clone() { + return new SourcePosition(this); + } + + /// Field number for the "line_number" field. + public const int LineNumberFieldNumber = 1; + private uint lineNumber_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint LineNumber { + get { return lineNumber_; } + set { + lineNumber_ = value; + } + } + + /// Field number for the "column_number" field. + public const int ColumnNumberFieldNumber = 2; + private uint columnNumber_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint ColumnNumber { + get { return columnNumber_; } + set { + columnNumber_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as SourcePosition); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(SourcePosition other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (LineNumber != other.LineNumber) return false; + if (ColumnNumber != other.ColumnNumber) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (LineNumber != 0) hash ^= LineNumber.GetHashCode(); + if (ColumnNumber != 0) hash ^= ColumnNumber.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (LineNumber != 0) { + output.WriteRawTag(8); + output.WriteUInt32(LineNumber); + } + if (ColumnNumber != 0) { + output.WriteRawTag(16); + output.WriteUInt32(ColumnNumber); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (LineNumber != 0) { + output.WriteRawTag(8); + output.WriteUInt32(LineNumber); + } + if (ColumnNumber != 0) { + output.WriteRawTag(16); + output.WriteUInt32(ColumnNumber); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (LineNumber != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(LineNumber); + } + if (ColumnNumber != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(ColumnNumber); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(SourcePosition other) { + if (other == null) { + return; + } + if (other.LineNumber != 0) { + LineNumber = other.LineNumber; + } + if (other.ColumnNumber != 0) { + ColumnNumber = other.ColumnNumber; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + LineNumber = input.ReadUInt32(); + break; + } + case 16: { + ColumnNumber = input.ReadUInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + LineNumber = input.ReadUInt32(); + break; + } + case 16: { + ColumnNumber = input.ReadUInt32(); + break; + } + } + } + } + #endif + + } + + /// + /// Developer friendly source file information for an entity in the resource table. + /// + public sealed partial class Source : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Source()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Source() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Source(Source other) : this() { + pathIdx_ = other.pathIdx_; + position_ = other.position_ != null ? other.position_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Source Clone() { + return new Source(this); + } + + /// Field number for the "path_idx" field. + public const int PathIdxFieldNumber = 1; + private uint pathIdx_; + /// + /// The index of the string path within the source string pool of a ResourceTable. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint PathIdx { + get { return pathIdx_; } + set { + pathIdx_ = value; + } + } + + /// Field number for the "position" field. + public const int PositionFieldNumber = 2; + private global::Aapt.Pb.SourcePosition position_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.SourcePosition Position { + get { return position_; } + set { + position_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Source); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Source other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (PathIdx != other.PathIdx) return false; + if (!object.Equals(Position, other.Position)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (PathIdx != 0) hash ^= PathIdx.GetHashCode(); + if (position_ != null) hash ^= Position.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (PathIdx != 0) { + output.WriteRawTag(8); + output.WriteUInt32(PathIdx); + } + if (position_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Position); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (PathIdx != 0) { + output.WriteRawTag(8); + output.WriteUInt32(PathIdx); + } + if (position_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Position); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (PathIdx != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(PathIdx); + } + if (position_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Position); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Source other) { + if (other == null) { + return; + } + if (other.PathIdx != 0) { + PathIdx = other.PathIdx; + } + if (other.position_ != null) { + if (position_ == null) { + Position = new global::Aapt.Pb.SourcePosition(); + } + Position.MergeFrom(other.Position); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + PathIdx = input.ReadUInt32(); + break; + } + case 18: { + if (position_ == null) { + Position = new global::Aapt.Pb.SourcePosition(); + } + input.ReadMessage(Position); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + PathIdx = input.ReadUInt32(); + break; + } + case 18: { + if (position_ == null) { + Position = new global::Aapt.Pb.SourcePosition(); + } + input.ReadMessage(Position); + break; + } + } + } + } + #endif + + } + + /// + /// The name and version fingerprint of a build tool. + /// + public sealed partial class ToolFingerprint : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ToolFingerprint()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[3]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ToolFingerprint() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ToolFingerprint(ToolFingerprint other) : this() { + tool_ = other.tool_; + version_ = other.version_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ToolFingerprint Clone() { + return new ToolFingerprint(this); + } + + /// Field number for the "tool" field. + public const int ToolFieldNumber = 1; + private string tool_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Tool { + get { return tool_; } + set { + tool_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "version" field. + public const int VersionFieldNumber = 2; + private string version_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Version { + get { return version_; } + set { + version_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ToolFingerprint); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ToolFingerprint other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Tool != other.Tool) return false; + if (Version != other.Version) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Tool.Length != 0) hash ^= Tool.GetHashCode(); + if (Version.Length != 0) hash ^= Version.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Tool.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Tool); + } + if (Version.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Version); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Tool.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Tool); + } + if (Version.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Version); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Tool.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Tool); + } + if (Version.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Version); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ToolFingerprint other) { + if (other == null) { + return; + } + if (other.Tool.Length != 0) { + Tool = other.Tool; + } + if (other.Version.Length != 0) { + Version = other.Version; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Tool = input.ReadString(); + break; + } + case 18: { + Version = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Tool = input.ReadString(); + break; + } + case 18: { + Version = input.ReadString(); + break; + } + } + } + } + #endif + + } + + /// + /// References to non local resources + /// + public sealed partial class DynamicRefTable : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DynamicRefTable()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[4]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public DynamicRefTable() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public DynamicRefTable(DynamicRefTable other) : this() { + packageId_ = other.packageId_ != null ? other.packageId_.Clone() : null; + packageName_ = other.packageName_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public DynamicRefTable Clone() { + return new DynamicRefTable(this); + } + + /// Field number for the "package_id" field. + public const int PackageIdFieldNumber = 1; + private global::Aapt.Pb.PackageId packageId_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.PackageId PackageId { + get { return packageId_; } + set { + packageId_ = value; + } + } + + /// Field number for the "package_name" field. + public const int PackageNameFieldNumber = 2; + private string packageName_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string PackageName { + get { return packageName_; } + set { + packageName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as DynamicRefTable); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(DynamicRefTable other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(PackageId, other.PackageId)) return false; + if (PackageName != other.PackageName) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (packageId_ != null) hash ^= PackageId.GetHashCode(); + if (PackageName.Length != 0) hash ^= PackageName.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (packageId_ != null) { + output.WriteRawTag(10); + output.WriteMessage(PackageId); + } + if (PackageName.Length != 0) { + output.WriteRawTag(18); + output.WriteString(PackageName); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (packageId_ != null) { + output.WriteRawTag(10); + output.WriteMessage(PackageId); + } + if (PackageName.Length != 0) { + output.WriteRawTag(18); + output.WriteString(PackageName); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (packageId_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(PackageId); + } + if (PackageName.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(PackageName); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(DynamicRefTable other) { + if (other == null) { + return; + } + if (other.packageId_ != null) { + if (packageId_ == null) { + PackageId = new global::Aapt.Pb.PackageId(); + } + PackageId.MergeFrom(other.PackageId); + } + if (other.PackageName.Length != 0) { + PackageName = other.PackageName; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (packageId_ == null) { + PackageId = new global::Aapt.Pb.PackageId(); + } + input.ReadMessage(PackageId); + break; + } + case 18: { + PackageName = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (packageId_ == null) { + PackageId = new global::Aapt.Pb.PackageId(); + } + input.ReadMessage(PackageId); + break; + } + case 18: { + PackageName = input.ReadString(); + break; + } + } + } + } + #endif + + } + + /// + /// Top level message representing a resource table. + /// + public sealed partial class ResourceTable : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ResourceTable()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[5]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ResourceTable() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ResourceTable(ResourceTable other) : this() { + sourcePool_ = other.sourcePool_ != null ? other.sourcePool_.Clone() : null; + package_ = other.package_.Clone(); + overlayable_ = other.overlayable_.Clone(); + toolFingerprint_ = other.toolFingerprint_.Clone(); + dynamicRefTable_ = other.dynamicRefTable_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ResourceTable Clone() { + return new ResourceTable(this); + } + + /// Field number for the "source_pool" field. + public const int SourcePoolFieldNumber = 1; + private global::Aapt.Pb.StringPool sourcePool_; + /// + /// The string pool containing source paths referenced throughout the resource table. This does + /// not end up in the final binary ARSC file. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.StringPool SourcePool { + get { return sourcePool_; } + set { + sourcePool_ = value; + } + } + + /// Field number for the "package" field. + public const int PackageFieldNumber = 2; + private static readonly pb::FieldCodec _repeated_package_codec + = pb::FieldCodec.ForMessage(18, global::Aapt.Pb.Package.Parser); + private readonly pbc::RepeatedField package_ = new pbc::RepeatedField(); + /// + /// Resource definitions corresponding to an Android package. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField Package { + get { return package_; } + } + + /// Field number for the "overlayable" field. + public const int OverlayableFieldNumber = 3; + private static readonly pb::FieldCodec _repeated_overlayable_codec + = pb::FieldCodec.ForMessage(26, global::Aapt.Pb.Overlayable.Parser); + private readonly pbc::RepeatedField overlayable_ = new pbc::RepeatedField(); + /// + /// The <overlayable> declarations within the resource table. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField Overlayable { + get { return overlayable_; } + } + + /// Field number for the "tool_fingerprint" field. + public const int ToolFingerprintFieldNumber = 4; + private static readonly pb::FieldCodec _repeated_toolFingerprint_codec + = pb::FieldCodec.ForMessage(34, global::Aapt.Pb.ToolFingerprint.Parser); + private readonly pbc::RepeatedField toolFingerprint_ = new pbc::RepeatedField(); + /// + /// The version fingerprints of the tools that built the resource table. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField ToolFingerprint { + get { return toolFingerprint_; } + } + + /// Field number for the "dynamic_ref_table" field. + public const int DynamicRefTableFieldNumber = 5; + private static readonly pb::FieldCodec _repeated_dynamicRefTable_codec + = pb::FieldCodec.ForMessage(42, global::Aapt.Pb.DynamicRefTable.Parser); + private readonly pbc::RepeatedField dynamicRefTable_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField DynamicRefTable { + get { return dynamicRefTable_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ResourceTable); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ResourceTable other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(SourcePool, other.SourcePool)) return false; + if(!package_.Equals(other.package_)) return false; + if(!overlayable_.Equals(other.overlayable_)) return false; + if(!toolFingerprint_.Equals(other.toolFingerprint_)) return false; + if(!dynamicRefTable_.Equals(other.dynamicRefTable_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (sourcePool_ != null) hash ^= SourcePool.GetHashCode(); + hash ^= package_.GetHashCode(); + hash ^= overlayable_.GetHashCode(); + hash ^= toolFingerprint_.GetHashCode(); + hash ^= dynamicRefTable_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (sourcePool_ != null) { + output.WriteRawTag(10); + output.WriteMessage(SourcePool); + } + package_.WriteTo(output, _repeated_package_codec); + overlayable_.WriteTo(output, _repeated_overlayable_codec); + toolFingerprint_.WriteTo(output, _repeated_toolFingerprint_codec); + dynamicRefTable_.WriteTo(output, _repeated_dynamicRefTable_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (sourcePool_ != null) { + output.WriteRawTag(10); + output.WriteMessage(SourcePool); + } + package_.WriteTo(ref output, _repeated_package_codec); + overlayable_.WriteTo(ref output, _repeated_overlayable_codec); + toolFingerprint_.WriteTo(ref output, _repeated_toolFingerprint_codec); + dynamicRefTable_.WriteTo(ref output, _repeated_dynamicRefTable_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (sourcePool_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(SourcePool); + } + size += package_.CalculateSize(_repeated_package_codec); + size += overlayable_.CalculateSize(_repeated_overlayable_codec); + size += toolFingerprint_.CalculateSize(_repeated_toolFingerprint_codec); + size += dynamicRefTable_.CalculateSize(_repeated_dynamicRefTable_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ResourceTable other) { + if (other == null) { + return; + } + if (other.sourcePool_ != null) { + if (sourcePool_ == null) { + SourcePool = new global::Aapt.Pb.StringPool(); + } + SourcePool.MergeFrom(other.SourcePool); + } + package_.Add(other.package_); + overlayable_.Add(other.overlayable_); + toolFingerprint_.Add(other.toolFingerprint_); + dynamicRefTable_.Add(other.dynamicRefTable_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (sourcePool_ == null) { + SourcePool = new global::Aapt.Pb.StringPool(); + } + input.ReadMessage(SourcePool); + break; + } + case 18: { + package_.AddEntriesFrom(input, _repeated_package_codec); + break; + } + case 26: { + overlayable_.AddEntriesFrom(input, _repeated_overlayable_codec); + break; + } + case 34: { + toolFingerprint_.AddEntriesFrom(input, _repeated_toolFingerprint_codec); + break; + } + case 42: { + dynamicRefTable_.AddEntriesFrom(input, _repeated_dynamicRefTable_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (sourcePool_ == null) { + SourcePool = new global::Aapt.Pb.StringPool(); + } + input.ReadMessage(SourcePool); + break; + } + case 18: { + package_.AddEntriesFrom(ref input, _repeated_package_codec); + break; + } + case 26: { + overlayable_.AddEntriesFrom(ref input, _repeated_overlayable_codec); + break; + } + case 34: { + toolFingerprint_.AddEntriesFrom(ref input, _repeated_toolFingerprint_codec); + break; + } + case 42: { + dynamicRefTable_.AddEntriesFrom(ref input, _repeated_dynamicRefTable_codec); + break; + } + } + } + } + #endif + + } + + /// + /// A package ID in the range [0x00, 0xff]. + /// + public sealed partial class PackageId : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new PackageId()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[6]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public PackageId() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public PackageId(PackageId other) : this() { + id_ = other.id_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public PackageId Clone() { + return new PackageId(this); + } + + /// Field number for the "id" field. + public const int IdFieldNumber = 1; + private uint id_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint Id { + get { return id_; } + set { + id_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as PackageId); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(PackageId other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Id != other.Id) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Id != 0) hash ^= Id.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Id != 0) { + output.WriteRawTag(8); + output.WriteUInt32(Id); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Id != 0) { + output.WriteRawTag(8); + output.WriteUInt32(Id); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Id != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Id); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(PackageId other) { + if (other == null) { + return; + } + if (other.Id != 0) { + Id = other.Id; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Id = input.ReadUInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Id = input.ReadUInt32(); + break; + } + } + } + } + #endif + + } + + /// + /// Defines resources for an Android package. + /// + public sealed partial class Package : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Package()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[7]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Package() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Package(Package other) : this() { + packageId_ = other.packageId_ != null ? other.packageId_.Clone() : null; + packageName_ = other.packageName_; + type_ = other.type_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Package Clone() { + return new Package(this); + } + + /// Field number for the "package_id" field. + public const int PackageIdFieldNumber = 1; + private global::Aapt.Pb.PackageId packageId_; + /// + /// The package ID of this package, in the range [0x00, 0xff]. + /// - ID 0x00 is reserved for shared libraries, or when the ID is assigned at run-time. + /// - ID 0x01 is reserved for the 'android' package (framework). + /// - ID range [0x02, 0x7f) is reserved for auto-assignment to shared libraries at run-time. + /// - ID 0x7f is reserved for the application package. + /// - IDs > 0x7f are reserved for the application as well and are treated as feature splits. + /// This may not be set if no ID was assigned. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.PackageId PackageId { + get { return packageId_; } + set { + packageId_ = value; + } + } + + /// Field number for the "package_name" field. + public const int PackageNameFieldNumber = 2; + private string packageName_ = ""; + /// + /// The Java compatible Android package name of the app. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string PackageName { + get { return packageName_; } + set { + packageName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "type" field. + public const int TypeFieldNumber = 3; + private static readonly pb::FieldCodec _repeated_type_codec + = pb::FieldCodec.ForMessage(26, global::Aapt.Pb.Type.Parser); + private readonly pbc::RepeatedField type_ = new pbc::RepeatedField(); + /// + /// The series of types defined by the package. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField Type { + get { return type_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Package); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Package other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(PackageId, other.PackageId)) return false; + if (PackageName != other.PackageName) return false; + if(!type_.Equals(other.type_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (packageId_ != null) hash ^= PackageId.GetHashCode(); + if (PackageName.Length != 0) hash ^= PackageName.GetHashCode(); + hash ^= type_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (packageId_ != null) { + output.WriteRawTag(10); + output.WriteMessage(PackageId); + } + if (PackageName.Length != 0) { + output.WriteRawTag(18); + output.WriteString(PackageName); + } + type_.WriteTo(output, _repeated_type_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (packageId_ != null) { + output.WriteRawTag(10); + output.WriteMessage(PackageId); + } + if (PackageName.Length != 0) { + output.WriteRawTag(18); + output.WriteString(PackageName); + } + type_.WriteTo(ref output, _repeated_type_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (packageId_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(PackageId); + } + if (PackageName.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(PackageName); + } + size += type_.CalculateSize(_repeated_type_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Package other) { + if (other == null) { + return; + } + if (other.packageId_ != null) { + if (packageId_ == null) { + PackageId = new global::Aapt.Pb.PackageId(); + } + PackageId.MergeFrom(other.PackageId); + } + if (other.PackageName.Length != 0) { + PackageName = other.PackageName; + } + type_.Add(other.type_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (packageId_ == null) { + PackageId = new global::Aapt.Pb.PackageId(); + } + input.ReadMessage(PackageId); + break; + } + case 18: { + PackageName = input.ReadString(); + break; + } + case 26: { + type_.AddEntriesFrom(input, _repeated_type_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (packageId_ == null) { + PackageId = new global::Aapt.Pb.PackageId(); + } + input.ReadMessage(PackageId); + break; + } + case 18: { + PackageName = input.ReadString(); + break; + } + case 26: { + type_.AddEntriesFrom(ref input, _repeated_type_codec); + break; + } + } + } + } + #endif + + } + + /// + /// A type ID in the range [0x01, 0xff]. + /// + public sealed partial class TypeId : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TypeId()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[8]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public TypeId() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public TypeId(TypeId other) : this() { + id_ = other.id_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public TypeId Clone() { + return new TypeId(this); + } + + /// Field number for the "id" field. + public const int IdFieldNumber = 1; + private uint id_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint Id { + get { return id_; } + set { + id_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as TypeId); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(TypeId other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Id != other.Id) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Id != 0) hash ^= Id.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Id != 0) { + output.WriteRawTag(8); + output.WriteUInt32(Id); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Id != 0) { + output.WriteRawTag(8); + output.WriteUInt32(Id); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Id != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Id); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(TypeId other) { + if (other == null) { + return; + } + if (other.Id != 0) { + Id = other.Id; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Id = input.ReadUInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Id = input.ReadUInt32(); + break; + } + } + } + } + #endif + + } + + /// + /// A set of resources grouped under a common type. Such types include string, layout, xml, dimen, + /// attr, etc. This maps to the second part of a resource identifier in Java (R.type.entry). + /// + public sealed partial class Type : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Type()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[9]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Type() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Type(Type other) : this() { + typeId_ = other.typeId_ != null ? other.typeId_.Clone() : null; + name_ = other.name_; + entry_ = other.entry_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Type Clone() { + return new Type(this); + } + + /// Field number for the "type_id" field. + public const int TypeIdFieldNumber = 1; + private global::Aapt.Pb.TypeId typeId_; + /// + /// The ID of the type. This may not be set if no ID was assigned. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.TypeId TypeId { + get { return typeId_; } + set { + typeId_ = value; + } + } + + /// Field number for the "name" field. + public const int NameFieldNumber = 2; + private string name_ = ""; + /// + /// The name of the type. This corresponds to the 'type' part of a full resource name of the form + /// package:type/entry. The set of legal type names is listed in Resource.cpp. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Name { + get { return name_; } + set { + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "entry" field. + public const int EntryFieldNumber = 3; + private static readonly pb::FieldCodec _repeated_entry_codec + = pb::FieldCodec.ForMessage(26, global::Aapt.Pb.Entry.Parser); + private readonly pbc::RepeatedField entry_ = new pbc::RepeatedField(); + /// + /// The entries defined for this type. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField Entry { + get { return entry_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Type); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Type other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(TypeId, other.TypeId)) return false; + if (Name != other.Name) return false; + if(!entry_.Equals(other.entry_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (typeId_ != null) hash ^= TypeId.GetHashCode(); + if (Name.Length != 0) hash ^= Name.GetHashCode(); + hash ^= entry_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (typeId_ != null) { + output.WriteRawTag(10); + output.WriteMessage(TypeId); + } + if (Name.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Name); + } + entry_.WriteTo(output, _repeated_entry_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (typeId_ != null) { + output.WriteRawTag(10); + output.WriteMessage(TypeId); + } + if (Name.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Name); + } + entry_.WriteTo(ref output, _repeated_entry_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (typeId_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(TypeId); + } + if (Name.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); + } + size += entry_.CalculateSize(_repeated_entry_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Type other) { + if (other == null) { + return; + } + if (other.typeId_ != null) { + if (typeId_ == null) { + TypeId = new global::Aapt.Pb.TypeId(); + } + TypeId.MergeFrom(other.TypeId); + } + if (other.Name.Length != 0) { + Name = other.Name; + } + entry_.Add(other.entry_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (typeId_ == null) { + TypeId = new global::Aapt.Pb.TypeId(); + } + input.ReadMessage(TypeId); + break; + } + case 18: { + Name = input.ReadString(); + break; + } + case 26: { + entry_.AddEntriesFrom(input, _repeated_entry_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (typeId_ == null) { + TypeId = new global::Aapt.Pb.TypeId(); + } + input.ReadMessage(TypeId); + break; + } + case 18: { + Name = input.ReadString(); + break; + } + case 26: { + entry_.AddEntriesFrom(ref input, _repeated_entry_codec); + break; + } + } + } + } + #endif + + } + + /// + /// The Visibility of a symbol/entry (public, private, undefined). + /// + public sealed partial class Visibility : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Visibility()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[10]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Visibility() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Visibility(Visibility other) : this() { + level_ = other.level_; + source_ = other.source_ != null ? other.source_.Clone() : null; + comment_ = other.comment_; + stagedApi_ = other.stagedApi_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Visibility Clone() { + return new Visibility(this); + } + + /// Field number for the "level" field. + public const int LevelFieldNumber = 1; + private global::Aapt.Pb.Visibility.Types.Level level_ = global::Aapt.Pb.Visibility.Types.Level.Unknown; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Visibility.Types.Level Level { + get { return level_; } + set { + level_ = value; + } + } + + /// Field number for the "source" field. + public const int SourceFieldNumber = 2; + private global::Aapt.Pb.Source source_; + /// + /// The path at which this entry's visibility was defined (eg. public.xml). + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Source Source { + get { return source_; } + set { + source_ = value; + } + } + + /// Field number for the "comment" field. + public const int CommentFieldNumber = 3; + private string comment_ = ""; + /// + /// The comment associated with the <public> tag. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Comment { + get { return comment_; } + set { + comment_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "staged_api" field. + public const int StagedApiFieldNumber = 4; + private bool stagedApi_; + /// + /// Indicates that the resource id may change across builds and that the public R.java identifier + /// for this resource should not be final. This is set to `true` for resources in `staging-group` + /// tags. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool StagedApi { + get { return stagedApi_; } + set { + stagedApi_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Visibility); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Visibility other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Level != other.Level) return false; + if (!object.Equals(Source, other.Source)) return false; + if (Comment != other.Comment) return false; + if (StagedApi != other.StagedApi) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Level != global::Aapt.Pb.Visibility.Types.Level.Unknown) hash ^= Level.GetHashCode(); + if (source_ != null) hash ^= Source.GetHashCode(); + if (Comment.Length != 0) hash ^= Comment.GetHashCode(); + if (StagedApi != false) hash ^= StagedApi.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Level != global::Aapt.Pb.Visibility.Types.Level.Unknown) { + output.WriteRawTag(8); + output.WriteEnum((int) Level); + } + if (source_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Source); + } + if (Comment.Length != 0) { + output.WriteRawTag(26); + output.WriteString(Comment); + } + if (StagedApi != false) { + output.WriteRawTag(32); + output.WriteBool(StagedApi); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Level != global::Aapt.Pb.Visibility.Types.Level.Unknown) { + output.WriteRawTag(8); + output.WriteEnum((int) Level); + } + if (source_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Source); + } + if (Comment.Length != 0) { + output.WriteRawTag(26); + output.WriteString(Comment); + } + if (StagedApi != false) { + output.WriteRawTag(32); + output.WriteBool(StagedApi); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Level != global::Aapt.Pb.Visibility.Types.Level.Unknown) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Level); + } + if (source_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Source); + } + if (Comment.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Comment); + } + if (StagedApi != false) { + size += 1 + 1; + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Visibility other) { + if (other == null) { + return; + } + if (other.Level != global::Aapt.Pb.Visibility.Types.Level.Unknown) { + Level = other.Level; + } + if (other.source_ != null) { + if (source_ == null) { + Source = new global::Aapt.Pb.Source(); + } + Source.MergeFrom(other.Source); + } + if (other.Comment.Length != 0) { + Comment = other.Comment; + } + if (other.StagedApi != false) { + StagedApi = other.StagedApi; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Level = (global::Aapt.Pb.Visibility.Types.Level) input.ReadEnum(); + break; + } + case 18: { + if (source_ == null) { + Source = new global::Aapt.Pb.Source(); + } + input.ReadMessage(Source); + break; + } + case 26: { + Comment = input.ReadString(); + break; + } + case 32: { + StagedApi = input.ReadBool(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Level = (global::Aapt.Pb.Visibility.Types.Level) input.ReadEnum(); + break; + } + case 18: { + if (source_ == null) { + Source = new global::Aapt.Pb.Source(); + } + input.ReadMessage(Source); + break; + } + case 26: { + Comment = input.ReadString(); + break; + } + case 32: { + StagedApi = input.ReadBool(); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the Visibility message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static partial class Types { + /// + /// The visibility of the resource outside of its package. + /// + public enum Level { + /// + /// No visibility was explicitly specified. This is typically treated as private. + /// The distinction is important when two separate R.java files are generated: a public and + /// private one. An unknown visibility, in this case, would cause the resource to be omitted + /// from either R.java. + /// + [pbr::OriginalName("UNKNOWN")] Unknown = 0, + /// + /// A resource was explicitly marked as private. This means the resource can not be accessed + /// outside of its package unless the @*package:type/entry notation is used (the asterisk being + /// the private accessor). If two R.java files are generated (private + public), the resource + /// will only be emitted to the private R.java file. + /// + [pbr::OriginalName("PRIVATE")] Private = 1, + /// + /// A resource was explicitly marked as public. This means the resource can be accessed + /// from any package, and is emitted into all R.java files, public and private. + /// + [pbr::OriginalName("PUBLIC")] Public = 2, + } + + } + #endregion + + } + + /// + /// Whether a resource comes from a compile-time overlay and is explicitly allowed to not overlay an + /// existing resource. + /// + public sealed partial class AllowNew : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new AllowNew()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[11]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public AllowNew() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public AllowNew(AllowNew other) : this() { + source_ = other.source_ != null ? other.source_.Clone() : null; + comment_ = other.comment_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public AllowNew Clone() { + return new AllowNew(this); + } + + /// Field number for the "source" field. + public const int SourceFieldNumber = 1; + private global::Aapt.Pb.Source source_; + /// + /// Where this was defined in source. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Source Source { + get { return source_; } + set { + source_ = value; + } + } + + /// Field number for the "comment" field. + public const int CommentFieldNumber = 2; + private string comment_ = ""; + /// + /// Any comment associated with the declaration. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Comment { + get { return comment_; } + set { + comment_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as AllowNew); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(AllowNew other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Source, other.Source)) return false; + if (Comment != other.Comment) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (source_ != null) hash ^= Source.GetHashCode(); + if (Comment.Length != 0) hash ^= Comment.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (source_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Source); + } + if (Comment.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Comment); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (source_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Source); + } + if (Comment.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Comment); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (source_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Source); + } + if (Comment.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Comment); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(AllowNew other) { + if (other == null) { + return; + } + if (other.source_ != null) { + if (source_ == null) { + Source = new global::Aapt.Pb.Source(); + } + Source.MergeFrom(other.Source); + } + if (other.Comment.Length != 0) { + Comment = other.Comment; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (source_ == null) { + Source = new global::Aapt.Pb.Source(); + } + input.ReadMessage(Source); + break; + } + case 18: { + Comment = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (source_ == null) { + Source = new global::Aapt.Pb.Source(); + } + input.ReadMessage(Source); + break; + } + case 18: { + Comment = input.ReadString(); + break; + } + } + } + } + #endif + + } + + /// + /// Represents a set of overlayable resources. + /// + public sealed partial class Overlayable : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Overlayable()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[12]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Overlayable() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Overlayable(Overlayable other) : this() { + name_ = other.name_; + source_ = other.source_ != null ? other.source_.Clone() : null; + actor_ = other.actor_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Overlayable Clone() { + return new Overlayable(this); + } + + /// Field number for the "name" field. + public const int NameFieldNumber = 1; + private string name_ = ""; + /// + /// The name of the <overlayable>. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Name { + get { return name_; } + set { + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "source" field. + public const int SourceFieldNumber = 2; + private global::Aapt.Pb.Source source_; + /// + /// The location of the <overlayable> declaration in the source. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Source Source { + get { return source_; } + set { + source_ = value; + } + } + + /// Field number for the "actor" field. + public const int ActorFieldNumber = 3; + private string actor_ = ""; + /// + /// The component responsible for enabling and disabling overlays targeting this <overlayable>. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Actor { + get { return actor_; } + set { + actor_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Overlayable); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Overlayable other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Name != other.Name) return false; + if (!object.Equals(Source, other.Source)) return false; + if (Actor != other.Actor) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Name.Length != 0) hash ^= Name.GetHashCode(); + if (source_ != null) hash ^= Source.GetHashCode(); + if (Actor.Length != 0) hash ^= Actor.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (source_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Source); + } + if (Actor.Length != 0) { + output.WriteRawTag(26); + output.WriteString(Actor); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (source_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Source); + } + if (Actor.Length != 0) { + output.WriteRawTag(26); + output.WriteString(Actor); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Name.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); + } + if (source_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Source); + } + if (Actor.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Actor); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Overlayable other) { + if (other == null) { + return; + } + if (other.Name.Length != 0) { + Name = other.Name; + } + if (other.source_ != null) { + if (source_ == null) { + Source = new global::Aapt.Pb.Source(); + } + Source.MergeFrom(other.Source); + } + if (other.Actor.Length != 0) { + Actor = other.Actor; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + if (source_ == null) { + Source = new global::Aapt.Pb.Source(); + } + input.ReadMessage(Source); + break; + } + case 26: { + Actor = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + if (source_ == null) { + Source = new global::Aapt.Pb.Source(); + } + input.ReadMessage(Source); + break; + } + case 26: { + Actor = input.ReadString(); + break; + } + } + } + } + #endif + + } + + /// + /// Represents an overlayable <item> declaration within an <overlayable> tag. + /// + public sealed partial class OverlayableItem : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OverlayableItem()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[13]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public OverlayableItem() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public OverlayableItem(OverlayableItem other) : this() { + source_ = other.source_ != null ? other.source_.Clone() : null; + comment_ = other.comment_; + policy_ = other.policy_.Clone(); + overlayableIdx_ = other.overlayableIdx_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public OverlayableItem Clone() { + return new OverlayableItem(this); + } + + /// Field number for the "source" field. + public const int SourceFieldNumber = 1; + private global::Aapt.Pb.Source source_; + /// + /// The location of the <item> declaration in source. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Source Source { + get { return source_; } + set { + source_ = value; + } + } + + /// Field number for the "comment" field. + public const int CommentFieldNumber = 2; + private string comment_ = ""; + /// + /// Any comment associated with the declaration. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Comment { + get { return comment_; } + set { + comment_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "policy" field. + public const int PolicyFieldNumber = 3; + private static readonly pb::FieldCodec _repeated_policy_codec + = pb::FieldCodec.ForEnum(26, x => (int) x, x => (global::Aapt.Pb.OverlayableItem.Types.Policy) x); + private readonly pbc::RepeatedField policy_ = new pbc::RepeatedField(); + /// + /// The policy defined by the enclosing <policy> tag of this <item>. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField Policy { + get { return policy_; } + } + + /// Field number for the "overlayable_idx" field. + public const int OverlayableIdxFieldNumber = 4; + private uint overlayableIdx_; + /// + /// The index into overlayable list that points to the <overlayable> tag that contains + /// this <item>. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint OverlayableIdx { + get { return overlayableIdx_; } + set { + overlayableIdx_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as OverlayableItem); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(OverlayableItem other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Source, other.Source)) return false; + if (Comment != other.Comment) return false; + if(!policy_.Equals(other.policy_)) return false; + if (OverlayableIdx != other.OverlayableIdx) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (source_ != null) hash ^= Source.GetHashCode(); + if (Comment.Length != 0) hash ^= Comment.GetHashCode(); + hash ^= policy_.GetHashCode(); + if (OverlayableIdx != 0) hash ^= OverlayableIdx.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (source_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Source); + } + if (Comment.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Comment); + } + policy_.WriteTo(output, _repeated_policy_codec); + if (OverlayableIdx != 0) { + output.WriteRawTag(32); + output.WriteUInt32(OverlayableIdx); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (source_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Source); + } + if (Comment.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Comment); + } + policy_.WriteTo(ref output, _repeated_policy_codec); + if (OverlayableIdx != 0) { + output.WriteRawTag(32); + output.WriteUInt32(OverlayableIdx); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (source_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Source); + } + if (Comment.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Comment); + } + size += policy_.CalculateSize(_repeated_policy_codec); + if (OverlayableIdx != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(OverlayableIdx); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(OverlayableItem other) { + if (other == null) { + return; + } + if (other.source_ != null) { + if (source_ == null) { + Source = new global::Aapt.Pb.Source(); + } + Source.MergeFrom(other.Source); + } + if (other.Comment.Length != 0) { + Comment = other.Comment; + } + policy_.Add(other.policy_); + if (other.OverlayableIdx != 0) { + OverlayableIdx = other.OverlayableIdx; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (source_ == null) { + Source = new global::Aapt.Pb.Source(); + } + input.ReadMessage(Source); + break; + } + case 18: { + Comment = input.ReadString(); + break; + } + case 26: + case 24: { + policy_.AddEntriesFrom(input, _repeated_policy_codec); + break; + } + case 32: { + OverlayableIdx = input.ReadUInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (source_ == null) { + Source = new global::Aapt.Pb.Source(); + } + input.ReadMessage(Source); + break; + } + case 18: { + Comment = input.ReadString(); + break; + } + case 26: + case 24: { + policy_.AddEntriesFrom(ref input, _repeated_policy_codec); + break; + } + case 32: { + OverlayableIdx = input.ReadUInt32(); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the OverlayableItem message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static partial class Types { + public enum Policy { + [pbr::OriginalName("NONE")] None = 0, + [pbr::OriginalName("PUBLIC")] Public = 1, + [pbr::OriginalName("SYSTEM")] System = 2, + [pbr::OriginalName("VENDOR")] Vendor = 3, + [pbr::OriginalName("PRODUCT")] Product = 4, + [pbr::OriginalName("SIGNATURE")] Signature = 5, + [pbr::OriginalName("ODM")] Odm = 6, + [pbr::OriginalName("OEM")] Oem = 7, + [pbr::OriginalName("ACTOR")] Actor = 8, + [pbr::OriginalName("CONFIG_SIGNATURE")] ConfigSignature = 9, + } + + } + #endregion + + } + + /// + /// The staged resource ID definition of a finalized resource. + /// + public sealed partial class StagedId : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new StagedId()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[14]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public StagedId() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public StagedId(StagedId other) : this() { + source_ = other.source_ != null ? other.source_.Clone() : null; + stagedId_ = other.stagedId_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public StagedId Clone() { + return new StagedId(this); + } + + /// Field number for the "source" field. + public const int SourceFieldNumber = 1; + private global::Aapt.Pb.Source source_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Source Source { + get { return source_; } + set { + source_ = value; + } + } + + /// Field number for the "staged_id" field. + public const int StagedId_FieldNumber = 2; + private uint stagedId_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint StagedId_ { + get { return stagedId_; } + set { + stagedId_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as StagedId); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(StagedId other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Source, other.Source)) return false; + if (StagedId_ != other.StagedId_) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (source_ != null) hash ^= Source.GetHashCode(); + if (StagedId_ != 0) hash ^= StagedId_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (source_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Source); + } + if (StagedId_ != 0) { + output.WriteRawTag(16); + output.WriteUInt32(StagedId_); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (source_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Source); + } + if (StagedId_ != 0) { + output.WriteRawTag(16); + output.WriteUInt32(StagedId_); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (source_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Source); + } + if (StagedId_ != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(StagedId_); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(StagedId other) { + if (other == null) { + return; + } + if (other.source_ != null) { + if (source_ == null) { + Source = new global::Aapt.Pb.Source(); + } + Source.MergeFrom(other.Source); + } + if (other.StagedId_ != 0) { + StagedId_ = other.StagedId_; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (source_ == null) { + Source = new global::Aapt.Pb.Source(); + } + input.ReadMessage(Source); + break; + } + case 16: { + StagedId_ = input.ReadUInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (source_ == null) { + Source = new global::Aapt.Pb.Source(); + } + input.ReadMessage(Source); + break; + } + case 16: { + StagedId_ = input.ReadUInt32(); + break; + } + } + } + } + #endif + + } + + /// + /// An entry ID in the range [0x0000, 0xffff]. + /// + public sealed partial class EntryId : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new EntryId()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[15]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public EntryId() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public EntryId(EntryId other) : this() { + id_ = other.id_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public EntryId Clone() { + return new EntryId(this); + } + + /// Field number for the "id" field. + public const int IdFieldNumber = 1; + private uint id_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint Id { + get { return id_; } + set { + id_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as EntryId); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(EntryId other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Id != other.Id) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Id != 0) hash ^= Id.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Id != 0) { + output.WriteRawTag(8); + output.WriteUInt32(Id); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Id != 0) { + output.WriteRawTag(8); + output.WriteUInt32(Id); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Id != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Id); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(EntryId other) { + if (other == null) { + return; + } + if (other.Id != 0) { + Id = other.Id; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Id = input.ReadUInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Id = input.ReadUInt32(); + break; + } + } + } + } + #endif + + } + + /// + /// An entry declaration. An entry has a full resource ID that is the combination of package ID, + /// type ID, and its own entry ID. An entry on its own has no value, but values are defined for + /// various configurations/variants. + /// + public sealed partial class Entry : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Entry()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[16]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Entry() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Entry(Entry other) : this() { + entryId_ = other.entryId_ != null ? other.entryId_.Clone() : null; + name_ = other.name_; + visibility_ = other.visibility_ != null ? other.visibility_.Clone() : null; + allowNew_ = other.allowNew_ != null ? other.allowNew_.Clone() : null; + overlayableItem_ = other.overlayableItem_ != null ? other.overlayableItem_.Clone() : null; + configValue_ = other.configValue_.Clone(); + stagedId_ = other.stagedId_ != null ? other.stagedId_.Clone() : null; + flagDisabledConfigValue_ = other.flagDisabledConfigValue_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Entry Clone() { + return new Entry(this); + } + + /// Field number for the "entry_id" field. + public const int EntryIdFieldNumber = 1; + private global::Aapt.Pb.EntryId entryId_; + /// + /// The ID of this entry. Together with the package ID and type ID, this forms a full resource ID + /// of the form 0xPPTTEEEE, where PP is the package ID, TT is the type ID, and EEEE is the entry + /// ID. + /// This may not be set if no ID was assigned. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.EntryId EntryId { + get { return entryId_; } + set { + entryId_ = value; + } + } + + /// Field number for the "name" field. + public const int NameFieldNumber = 2; + private string name_ = ""; + /// + /// The name of this entry. This corresponds to the 'entry' part of a full resource name of the + /// form package:type/entry. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Name { + get { return name_; } + set { + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "visibility" field. + public const int VisibilityFieldNumber = 3; + private global::Aapt.Pb.Visibility visibility_; + /// + /// The visibility of this entry (public, private, undefined). + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Visibility Visibility { + get { return visibility_; } + set { + visibility_ = value; + } + } + + /// Field number for the "allow_new" field. + public const int AllowNewFieldNumber = 4; + private global::Aapt.Pb.AllowNew allowNew_; + /// + /// Whether this resource, when originating from a compile-time overlay, is allowed to NOT overlay + /// any existing resources. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.AllowNew AllowNew { + get { return allowNew_; } + set { + allowNew_ = value; + } + } + + /// Field number for the "overlayable_item" field. + public const int OverlayableItemFieldNumber = 5; + private global::Aapt.Pb.OverlayableItem overlayableItem_; + /// + /// Whether this resource can be overlaid by a runtime resource overlay (RRO). + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.OverlayableItem OverlayableItem { + get { return overlayableItem_; } + set { + overlayableItem_ = value; + } + } + + /// Field number for the "config_value" field. + public const int ConfigValueFieldNumber = 6; + private static readonly pb::FieldCodec _repeated_configValue_codec + = pb::FieldCodec.ForMessage(50, global::Aapt.Pb.ConfigValue.Parser); + private readonly pbc::RepeatedField configValue_ = new pbc::RepeatedField(); + /// + /// The set of values defined for this entry, each corresponding to a different + /// configuration/variant. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField ConfigValue { + get { return configValue_; } + } + + /// Field number for the "staged_id" field. + public const int StagedIdFieldNumber = 7; + private global::Aapt.Pb.StagedId stagedId_; + /// + /// The staged resource ID of this finalized resource. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.StagedId StagedId { + get { return stagedId_; } + set { + stagedId_ = value; + } + } + + /// Field number for the "flag_disabled_config_value" field. + public const int FlagDisabledConfigValueFieldNumber = 8; + private static readonly pb::FieldCodec _repeated_flagDisabledConfigValue_codec + = pb::FieldCodec.ForMessage(66, global::Aapt.Pb.ConfigValue.Parser); + private readonly pbc::RepeatedField flagDisabledConfigValue_ = new pbc::RepeatedField(); + /// + /// The set of values defined for this entry which are behind disabled flags + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField FlagDisabledConfigValue { + get { return flagDisabledConfigValue_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Entry); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Entry other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(EntryId, other.EntryId)) return false; + if (Name != other.Name) return false; + if (!object.Equals(Visibility, other.Visibility)) return false; + if (!object.Equals(AllowNew, other.AllowNew)) return false; + if (!object.Equals(OverlayableItem, other.OverlayableItem)) return false; + if(!configValue_.Equals(other.configValue_)) return false; + if (!object.Equals(StagedId, other.StagedId)) return false; + if(!flagDisabledConfigValue_.Equals(other.flagDisabledConfigValue_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (entryId_ != null) hash ^= EntryId.GetHashCode(); + if (Name.Length != 0) hash ^= Name.GetHashCode(); + if (visibility_ != null) hash ^= Visibility.GetHashCode(); + if (allowNew_ != null) hash ^= AllowNew.GetHashCode(); + if (overlayableItem_ != null) hash ^= OverlayableItem.GetHashCode(); + hash ^= configValue_.GetHashCode(); + if (stagedId_ != null) hash ^= StagedId.GetHashCode(); + hash ^= flagDisabledConfigValue_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (entryId_ != null) { + output.WriteRawTag(10); + output.WriteMessage(EntryId); + } + if (Name.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Name); + } + if (visibility_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Visibility); + } + if (allowNew_ != null) { + output.WriteRawTag(34); + output.WriteMessage(AllowNew); + } + if (overlayableItem_ != null) { + output.WriteRawTag(42); + output.WriteMessage(OverlayableItem); + } + configValue_.WriteTo(output, _repeated_configValue_codec); + if (stagedId_ != null) { + output.WriteRawTag(58); + output.WriteMessage(StagedId); + } + flagDisabledConfigValue_.WriteTo(output, _repeated_flagDisabledConfigValue_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (entryId_ != null) { + output.WriteRawTag(10); + output.WriteMessage(EntryId); + } + if (Name.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Name); + } + if (visibility_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Visibility); + } + if (allowNew_ != null) { + output.WriteRawTag(34); + output.WriteMessage(AllowNew); + } + if (overlayableItem_ != null) { + output.WriteRawTag(42); + output.WriteMessage(OverlayableItem); + } + configValue_.WriteTo(ref output, _repeated_configValue_codec); + if (stagedId_ != null) { + output.WriteRawTag(58); + output.WriteMessage(StagedId); + } + flagDisabledConfigValue_.WriteTo(ref output, _repeated_flagDisabledConfigValue_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (entryId_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(EntryId); + } + if (Name.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); + } + if (visibility_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Visibility); + } + if (allowNew_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(AllowNew); + } + if (overlayableItem_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(OverlayableItem); + } + size += configValue_.CalculateSize(_repeated_configValue_codec); + if (stagedId_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(StagedId); + } + size += flagDisabledConfigValue_.CalculateSize(_repeated_flagDisabledConfigValue_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Entry other) { + if (other == null) { + return; + } + if (other.entryId_ != null) { + if (entryId_ == null) { + EntryId = new global::Aapt.Pb.EntryId(); + } + EntryId.MergeFrom(other.EntryId); + } + if (other.Name.Length != 0) { + Name = other.Name; + } + if (other.visibility_ != null) { + if (visibility_ == null) { + Visibility = new global::Aapt.Pb.Visibility(); + } + Visibility.MergeFrom(other.Visibility); + } + if (other.allowNew_ != null) { + if (allowNew_ == null) { + AllowNew = new global::Aapt.Pb.AllowNew(); + } + AllowNew.MergeFrom(other.AllowNew); + } + if (other.overlayableItem_ != null) { + if (overlayableItem_ == null) { + OverlayableItem = new global::Aapt.Pb.OverlayableItem(); + } + OverlayableItem.MergeFrom(other.OverlayableItem); + } + configValue_.Add(other.configValue_); + if (other.stagedId_ != null) { + if (stagedId_ == null) { + StagedId = new global::Aapt.Pb.StagedId(); + } + StagedId.MergeFrom(other.StagedId); + } + flagDisabledConfigValue_.Add(other.flagDisabledConfigValue_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (entryId_ == null) { + EntryId = new global::Aapt.Pb.EntryId(); + } + input.ReadMessage(EntryId); + break; + } + case 18: { + Name = input.ReadString(); + break; + } + case 26: { + if (visibility_ == null) { + Visibility = new global::Aapt.Pb.Visibility(); + } + input.ReadMessage(Visibility); + break; + } + case 34: { + if (allowNew_ == null) { + AllowNew = new global::Aapt.Pb.AllowNew(); + } + input.ReadMessage(AllowNew); + break; + } + case 42: { + if (overlayableItem_ == null) { + OverlayableItem = new global::Aapt.Pb.OverlayableItem(); + } + input.ReadMessage(OverlayableItem); + break; + } + case 50: { + configValue_.AddEntriesFrom(input, _repeated_configValue_codec); + break; + } + case 58: { + if (stagedId_ == null) { + StagedId = new global::Aapt.Pb.StagedId(); + } + input.ReadMessage(StagedId); + break; + } + case 66: { + flagDisabledConfigValue_.AddEntriesFrom(input, _repeated_flagDisabledConfigValue_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (entryId_ == null) { + EntryId = new global::Aapt.Pb.EntryId(); + } + input.ReadMessage(EntryId); + break; + } + case 18: { + Name = input.ReadString(); + break; + } + case 26: { + if (visibility_ == null) { + Visibility = new global::Aapt.Pb.Visibility(); + } + input.ReadMessage(Visibility); + break; + } + case 34: { + if (allowNew_ == null) { + AllowNew = new global::Aapt.Pb.AllowNew(); + } + input.ReadMessage(AllowNew); + break; + } + case 42: { + if (overlayableItem_ == null) { + OverlayableItem = new global::Aapt.Pb.OverlayableItem(); + } + input.ReadMessage(OverlayableItem); + break; + } + case 50: { + configValue_.AddEntriesFrom(ref input, _repeated_configValue_codec); + break; + } + case 58: { + if (stagedId_ == null) { + StagedId = new global::Aapt.Pb.StagedId(); + } + input.ReadMessage(StagedId); + break; + } + case 66: { + flagDisabledConfigValue_.AddEntriesFrom(ref input, _repeated_flagDisabledConfigValue_codec); + break; + } + } + } + } + #endif + + } + + /// + /// A Configuration/Value pair. + /// + public sealed partial class ConfigValue : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ConfigValue()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[17]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ConfigValue() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ConfigValue(ConfigValue other) : this() { + config_ = other.config_ != null ? other.config_.Clone() : null; + value_ = other.value_ != null ? other.value_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ConfigValue Clone() { + return new ConfigValue(this); + } + + /// Field number for the "config" field. + public const int ConfigFieldNumber = 1; + private global::Aapt.Pb.Configuration config_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Configuration Config { + get { return config_; } + set { + config_ = value; + } + } + + /// Field number for the "value" field. + public const int ValueFieldNumber = 2; + private global::Aapt.Pb.Value value_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Value Value { + get { return value_; } + set { + value_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ConfigValue); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ConfigValue other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Config, other.Config)) return false; + if (!object.Equals(Value, other.Value)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (config_ != null) hash ^= Config.GetHashCode(); + if (value_ != null) hash ^= Value.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (config_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Config); + } + if (value_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (config_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Config); + } + if (value_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (config_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Config); + } + if (value_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Value); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ConfigValue other) { + if (other == null) { + return; + } + if (other.config_ != null) { + if (config_ == null) { + Config = new global::Aapt.Pb.Configuration(); + } + Config.MergeFrom(other.Config); + } + if (other.value_ != null) { + if (value_ == null) { + Value = new global::Aapt.Pb.Value(); + } + Value.MergeFrom(other.Value); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (config_ == null) { + Config = new global::Aapt.Pb.Configuration(); + } + input.ReadMessage(Config); + break; + } + case 18: { + if (value_ == null) { + Value = new global::Aapt.Pb.Value(); + } + input.ReadMessage(Value); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (config_ == null) { + Config = new global::Aapt.Pb.Configuration(); + } + input.ReadMessage(Config); + break; + } + case 18: { + if (value_ == null) { + Value = new global::Aapt.Pb.Value(); + } + input.ReadMessage(Value); + break; + } + } + } + } + #endif + + } + + /// + /// The generic meta-data for every value in a resource table. + /// + public sealed partial class Value : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Value()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[18]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Value() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Value(Value other) : this() { + source_ = other.source_ != null ? other.source_.Clone() : null; + comment_ = other.comment_; + weak_ = other.weak_; + switch (other.ValueCase) { + case ValueOneofCase.Item: + Item = other.Item.Clone(); + break; + case ValueOneofCase.CompoundValue: + CompoundValue = other.CompoundValue.Clone(); + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Value Clone() { + return new Value(this); + } + + /// Field number for the "source" field. + public const int SourceFieldNumber = 1; + private global::Aapt.Pb.Source source_; + /// + /// Where the value was defined. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Source Source { + get { return source_; } + set { + source_ = value; + } + } + + /// Field number for the "comment" field. + public const int CommentFieldNumber = 2; + private string comment_ = ""; + /// + /// Any comment associated with the value. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Comment { + get { return comment_; } + set { + comment_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "weak" field. + public const int WeakFieldNumber = 3; + private bool weak_; + /// + /// Whether the value can be overridden. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Weak { + get { return weak_; } + set { + weak_ = value; + } + } + + /// Field number for the "item" field. + public const int ItemFieldNumber = 4; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Item Item { + get { return valueCase_ == ValueOneofCase.Item ? (global::Aapt.Pb.Item) value_ : null; } + set { + value_ = value; + valueCase_ = value == null ? ValueOneofCase.None : ValueOneofCase.Item; + } + } + + /// Field number for the "compound_value" field. + public const int CompoundValueFieldNumber = 5; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.CompoundValue CompoundValue { + get { return valueCase_ == ValueOneofCase.CompoundValue ? (global::Aapt.Pb.CompoundValue) value_ : null; } + set { + value_ = value; + valueCase_ = value == null ? ValueOneofCase.None : ValueOneofCase.CompoundValue; + } + } + + private object value_; + /// Enum of possible cases for the "value" oneof. + public enum ValueOneofCase { + None = 0, + Item = 4, + CompoundValue = 5, + } + private ValueOneofCase valueCase_ = ValueOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ValueOneofCase ValueCase { + get { return valueCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void ClearValue() { + valueCase_ = ValueOneofCase.None; + value_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Value); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Value other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Source, other.Source)) return false; + if (Comment != other.Comment) return false; + if (Weak != other.Weak) return false; + if (!object.Equals(Item, other.Item)) return false; + if (!object.Equals(CompoundValue, other.CompoundValue)) return false; + if (ValueCase != other.ValueCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (source_ != null) hash ^= Source.GetHashCode(); + if (Comment.Length != 0) hash ^= Comment.GetHashCode(); + if (Weak != false) hash ^= Weak.GetHashCode(); + if (valueCase_ == ValueOneofCase.Item) hash ^= Item.GetHashCode(); + if (valueCase_ == ValueOneofCase.CompoundValue) hash ^= CompoundValue.GetHashCode(); + hash ^= (int) valueCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (source_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Source); + } + if (Comment.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Comment); + } + if (Weak != false) { + output.WriteRawTag(24); + output.WriteBool(Weak); + } + if (valueCase_ == ValueOneofCase.Item) { + output.WriteRawTag(34); + output.WriteMessage(Item); + } + if (valueCase_ == ValueOneofCase.CompoundValue) { + output.WriteRawTag(42); + output.WriteMessage(CompoundValue); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (source_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Source); + } + if (Comment.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Comment); + } + if (Weak != false) { + output.WriteRawTag(24); + output.WriteBool(Weak); + } + if (valueCase_ == ValueOneofCase.Item) { + output.WriteRawTag(34); + output.WriteMessage(Item); + } + if (valueCase_ == ValueOneofCase.CompoundValue) { + output.WriteRawTag(42); + output.WriteMessage(CompoundValue); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (source_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Source); + } + if (Comment.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Comment); + } + if (Weak != false) { + size += 1 + 1; + } + if (valueCase_ == ValueOneofCase.Item) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Item); + } + if (valueCase_ == ValueOneofCase.CompoundValue) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(CompoundValue); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Value other) { + if (other == null) { + return; + } + if (other.source_ != null) { + if (source_ == null) { + Source = new global::Aapt.Pb.Source(); + } + Source.MergeFrom(other.Source); + } + if (other.Comment.Length != 0) { + Comment = other.Comment; + } + if (other.Weak != false) { + Weak = other.Weak; + } + switch (other.ValueCase) { + case ValueOneofCase.Item: + if (Item == null) { + Item = new global::Aapt.Pb.Item(); + } + Item.MergeFrom(other.Item); + break; + case ValueOneofCase.CompoundValue: + if (CompoundValue == null) { + CompoundValue = new global::Aapt.Pb.CompoundValue(); + } + CompoundValue.MergeFrom(other.CompoundValue); + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (source_ == null) { + Source = new global::Aapt.Pb.Source(); + } + input.ReadMessage(Source); + break; + } + case 18: { + Comment = input.ReadString(); + break; + } + case 24: { + Weak = input.ReadBool(); + break; + } + case 34: { + global::Aapt.Pb.Item subBuilder = new global::Aapt.Pb.Item(); + if (valueCase_ == ValueOneofCase.Item) { + subBuilder.MergeFrom(Item); + } + input.ReadMessage(subBuilder); + Item = subBuilder; + break; + } + case 42: { + global::Aapt.Pb.CompoundValue subBuilder = new global::Aapt.Pb.CompoundValue(); + if (valueCase_ == ValueOneofCase.CompoundValue) { + subBuilder.MergeFrom(CompoundValue); + } + input.ReadMessage(subBuilder); + CompoundValue = subBuilder; + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (source_ == null) { + Source = new global::Aapt.Pb.Source(); + } + input.ReadMessage(Source); + break; + } + case 18: { + Comment = input.ReadString(); + break; + } + case 24: { + Weak = input.ReadBool(); + break; + } + case 34: { + global::Aapt.Pb.Item subBuilder = new global::Aapt.Pb.Item(); + if (valueCase_ == ValueOneofCase.Item) { + subBuilder.MergeFrom(Item); + } + input.ReadMessage(subBuilder); + Item = subBuilder; + break; + } + case 42: { + global::Aapt.Pb.CompoundValue subBuilder = new global::Aapt.Pb.CompoundValue(); + if (valueCase_ == ValueOneofCase.CompoundValue) { + subBuilder.MergeFrom(CompoundValue); + } + input.ReadMessage(subBuilder); + CompoundValue = subBuilder; + break; + } + } + } + } + #endif + + } + + /// + /// An Item is an abstract type. It represents a value that can appear inline in many places, such + /// as XML attribute values or on the right hand side of style attribute definitions. The concrete + /// type is one of the types below. Only one can be set. + /// + public sealed partial class Item : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Item()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[19]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Item() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Item(Item other) : this() { + flagStatus_ = other.flagStatus_; + flagNegated_ = other.flagNegated_; + flagName_ = other.flagName_; + switch (other.ValueCase) { + case ValueOneofCase.Ref: + Ref = other.Ref.Clone(); + break; + case ValueOneofCase.Str: + Str = other.Str.Clone(); + break; + case ValueOneofCase.RawStr: + RawStr = other.RawStr.Clone(); + break; + case ValueOneofCase.StyledStr: + StyledStr = other.StyledStr.Clone(); + break; + case ValueOneofCase.File: + File = other.File.Clone(); + break; + case ValueOneofCase.Id: + Id = other.Id.Clone(); + break; + case ValueOneofCase.Prim: + Prim = other.Prim.Clone(); + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Item Clone() { + return new Item(this); + } + + /// Field number for the "ref" field. + public const int RefFieldNumber = 1; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Reference Ref { + get { return valueCase_ == ValueOneofCase.Ref ? (global::Aapt.Pb.Reference) value_ : null; } + set { + value_ = value; + valueCase_ = value == null ? ValueOneofCase.None : ValueOneofCase.Ref; + } + } + + /// Field number for the "str" field. + public const int StrFieldNumber = 2; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.String Str { + get { return valueCase_ == ValueOneofCase.Str ? (global::Aapt.Pb.String) value_ : null; } + set { + value_ = value; + valueCase_ = value == null ? ValueOneofCase.None : ValueOneofCase.Str; + } + } + + /// Field number for the "raw_str" field. + public const int RawStrFieldNumber = 3; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.RawString RawStr { + get { return valueCase_ == ValueOneofCase.RawStr ? (global::Aapt.Pb.RawString) value_ : null; } + set { + value_ = value; + valueCase_ = value == null ? ValueOneofCase.None : ValueOneofCase.RawStr; + } + } + + /// Field number for the "styled_str" field. + public const int StyledStrFieldNumber = 4; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.StyledString StyledStr { + get { return valueCase_ == ValueOneofCase.StyledStr ? (global::Aapt.Pb.StyledString) value_ : null; } + set { + value_ = value; + valueCase_ = value == null ? ValueOneofCase.None : ValueOneofCase.StyledStr; + } + } + + /// Field number for the "file" field. + public const int FileFieldNumber = 5; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.FileReference File { + get { return valueCase_ == ValueOneofCase.File ? (global::Aapt.Pb.FileReference) value_ : null; } + set { + value_ = value; + valueCase_ = value == null ? ValueOneofCase.None : ValueOneofCase.File; + } + } + + /// Field number for the "id" field. + public const int IdFieldNumber = 6; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Id Id { + get { return valueCase_ == ValueOneofCase.Id ? (global::Aapt.Pb.Id) value_ : null; } + set { + value_ = value; + valueCase_ = value == null ? ValueOneofCase.None : ValueOneofCase.Id; + } + } + + /// Field number for the "prim" field. + public const int PrimFieldNumber = 7; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Primitive Prim { + get { return valueCase_ == ValueOneofCase.Prim ? (global::Aapt.Pb.Primitive) value_ : null; } + set { + value_ = value; + valueCase_ = value == null ? ValueOneofCase.None : ValueOneofCase.Prim; + } + } + + /// Field number for the "flag_status" field. + public const int FlagStatusFieldNumber = 8; + private uint flagStatus_; + /// + /// The status of the flag the value is behind if any + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint FlagStatus { + get { return flagStatus_; } + set { + flagStatus_ = value; + } + } + + /// Field number for the "flag_negated" field. + public const int FlagNegatedFieldNumber = 9; + private bool flagNegated_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool FlagNegated { + get { return flagNegated_; } + set { + flagNegated_ = value; + } + } + + /// Field number for the "flag_name" field. + public const int FlagNameFieldNumber = 10; + private string flagName_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string FlagName { + get { return flagName_; } + set { + flagName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + private object value_; + /// Enum of possible cases for the "value" oneof. + public enum ValueOneofCase { + None = 0, + Ref = 1, + Str = 2, + RawStr = 3, + StyledStr = 4, + File = 5, + Id = 6, + Prim = 7, + } + private ValueOneofCase valueCase_ = ValueOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ValueOneofCase ValueCase { + get { return valueCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void ClearValue() { + valueCase_ = ValueOneofCase.None; + value_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Item); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Item other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Ref, other.Ref)) return false; + if (!object.Equals(Str, other.Str)) return false; + if (!object.Equals(RawStr, other.RawStr)) return false; + if (!object.Equals(StyledStr, other.StyledStr)) return false; + if (!object.Equals(File, other.File)) return false; + if (!object.Equals(Id, other.Id)) return false; + if (!object.Equals(Prim, other.Prim)) return false; + if (FlagStatus != other.FlagStatus) return false; + if (FlagNegated != other.FlagNegated) return false; + if (FlagName != other.FlagName) return false; + if (ValueCase != other.ValueCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (valueCase_ == ValueOneofCase.Ref) hash ^= Ref.GetHashCode(); + if (valueCase_ == ValueOneofCase.Str) hash ^= Str.GetHashCode(); + if (valueCase_ == ValueOneofCase.RawStr) hash ^= RawStr.GetHashCode(); + if (valueCase_ == ValueOneofCase.StyledStr) hash ^= StyledStr.GetHashCode(); + if (valueCase_ == ValueOneofCase.File) hash ^= File.GetHashCode(); + if (valueCase_ == ValueOneofCase.Id) hash ^= Id.GetHashCode(); + if (valueCase_ == ValueOneofCase.Prim) hash ^= Prim.GetHashCode(); + if (FlagStatus != 0) hash ^= FlagStatus.GetHashCode(); + if (FlagNegated != false) hash ^= FlagNegated.GetHashCode(); + if (FlagName.Length != 0) hash ^= FlagName.GetHashCode(); + hash ^= (int) valueCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (valueCase_ == ValueOneofCase.Ref) { + output.WriteRawTag(10); + output.WriteMessage(Ref); + } + if (valueCase_ == ValueOneofCase.Str) { + output.WriteRawTag(18); + output.WriteMessage(Str); + } + if (valueCase_ == ValueOneofCase.RawStr) { + output.WriteRawTag(26); + output.WriteMessage(RawStr); + } + if (valueCase_ == ValueOneofCase.StyledStr) { + output.WriteRawTag(34); + output.WriteMessage(StyledStr); + } + if (valueCase_ == ValueOneofCase.File) { + output.WriteRawTag(42); + output.WriteMessage(File); + } + if (valueCase_ == ValueOneofCase.Id) { + output.WriteRawTag(50); + output.WriteMessage(Id); + } + if (valueCase_ == ValueOneofCase.Prim) { + output.WriteRawTag(58); + output.WriteMessage(Prim); + } + if (FlagStatus != 0) { + output.WriteRawTag(64); + output.WriteUInt32(FlagStatus); + } + if (FlagNegated != false) { + output.WriteRawTag(72); + output.WriteBool(FlagNegated); + } + if (FlagName.Length != 0) { + output.WriteRawTag(82); + output.WriteString(FlagName); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (valueCase_ == ValueOneofCase.Ref) { + output.WriteRawTag(10); + output.WriteMessage(Ref); + } + if (valueCase_ == ValueOneofCase.Str) { + output.WriteRawTag(18); + output.WriteMessage(Str); + } + if (valueCase_ == ValueOneofCase.RawStr) { + output.WriteRawTag(26); + output.WriteMessage(RawStr); + } + if (valueCase_ == ValueOneofCase.StyledStr) { + output.WriteRawTag(34); + output.WriteMessage(StyledStr); + } + if (valueCase_ == ValueOneofCase.File) { + output.WriteRawTag(42); + output.WriteMessage(File); + } + if (valueCase_ == ValueOneofCase.Id) { + output.WriteRawTag(50); + output.WriteMessage(Id); + } + if (valueCase_ == ValueOneofCase.Prim) { + output.WriteRawTag(58); + output.WriteMessage(Prim); + } + if (FlagStatus != 0) { + output.WriteRawTag(64); + output.WriteUInt32(FlagStatus); + } + if (FlagNegated != false) { + output.WriteRawTag(72); + output.WriteBool(FlagNegated); + } + if (FlagName.Length != 0) { + output.WriteRawTag(82); + output.WriteString(FlagName); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (valueCase_ == ValueOneofCase.Ref) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Ref); + } + if (valueCase_ == ValueOneofCase.Str) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Str); + } + if (valueCase_ == ValueOneofCase.RawStr) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(RawStr); + } + if (valueCase_ == ValueOneofCase.StyledStr) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(StyledStr); + } + if (valueCase_ == ValueOneofCase.File) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(File); + } + if (valueCase_ == ValueOneofCase.Id) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Id); + } + if (valueCase_ == ValueOneofCase.Prim) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Prim); + } + if (FlagStatus != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(FlagStatus); + } + if (FlagNegated != false) { + size += 1 + 1; + } + if (FlagName.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(FlagName); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Item other) { + if (other == null) { + return; + } + if (other.FlagStatus != 0) { + FlagStatus = other.FlagStatus; + } + if (other.FlagNegated != false) { + FlagNegated = other.FlagNegated; + } + if (other.FlagName.Length != 0) { + FlagName = other.FlagName; + } + switch (other.ValueCase) { + case ValueOneofCase.Ref: + if (Ref == null) { + Ref = new global::Aapt.Pb.Reference(); + } + Ref.MergeFrom(other.Ref); + break; + case ValueOneofCase.Str: + if (Str == null) { + Str = new global::Aapt.Pb.String(); + } + Str.MergeFrom(other.Str); + break; + case ValueOneofCase.RawStr: + if (RawStr == null) { + RawStr = new global::Aapt.Pb.RawString(); + } + RawStr.MergeFrom(other.RawStr); + break; + case ValueOneofCase.StyledStr: + if (StyledStr == null) { + StyledStr = new global::Aapt.Pb.StyledString(); + } + StyledStr.MergeFrom(other.StyledStr); + break; + case ValueOneofCase.File: + if (File == null) { + File = new global::Aapt.Pb.FileReference(); + } + File.MergeFrom(other.File); + break; + case ValueOneofCase.Id: + if (Id == null) { + Id = new global::Aapt.Pb.Id(); + } + Id.MergeFrom(other.Id); + break; + case ValueOneofCase.Prim: + if (Prim == null) { + Prim = new global::Aapt.Pb.Primitive(); + } + Prim.MergeFrom(other.Prim); + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + global::Aapt.Pb.Reference subBuilder = new global::Aapt.Pb.Reference(); + if (valueCase_ == ValueOneofCase.Ref) { + subBuilder.MergeFrom(Ref); + } + input.ReadMessage(subBuilder); + Ref = subBuilder; + break; + } + case 18: { + global::Aapt.Pb.String subBuilder = new global::Aapt.Pb.String(); + if (valueCase_ == ValueOneofCase.Str) { + subBuilder.MergeFrom(Str); + } + input.ReadMessage(subBuilder); + Str = subBuilder; + break; + } + case 26: { + global::Aapt.Pb.RawString subBuilder = new global::Aapt.Pb.RawString(); + if (valueCase_ == ValueOneofCase.RawStr) { + subBuilder.MergeFrom(RawStr); + } + input.ReadMessage(subBuilder); + RawStr = subBuilder; + break; + } + case 34: { + global::Aapt.Pb.StyledString subBuilder = new global::Aapt.Pb.StyledString(); + if (valueCase_ == ValueOneofCase.StyledStr) { + subBuilder.MergeFrom(StyledStr); + } + input.ReadMessage(subBuilder); + StyledStr = subBuilder; + break; + } + case 42: { + global::Aapt.Pb.FileReference subBuilder = new global::Aapt.Pb.FileReference(); + if (valueCase_ == ValueOneofCase.File) { + subBuilder.MergeFrom(File); + } + input.ReadMessage(subBuilder); + File = subBuilder; + break; + } + case 50: { + global::Aapt.Pb.Id subBuilder = new global::Aapt.Pb.Id(); + if (valueCase_ == ValueOneofCase.Id) { + subBuilder.MergeFrom(Id); + } + input.ReadMessage(subBuilder); + Id = subBuilder; + break; + } + case 58: { + global::Aapt.Pb.Primitive subBuilder = new global::Aapt.Pb.Primitive(); + if (valueCase_ == ValueOneofCase.Prim) { + subBuilder.MergeFrom(Prim); + } + input.ReadMessage(subBuilder); + Prim = subBuilder; + break; + } + case 64: { + FlagStatus = input.ReadUInt32(); + break; + } + case 72: { + FlagNegated = input.ReadBool(); + break; + } + case 82: { + FlagName = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + global::Aapt.Pb.Reference subBuilder = new global::Aapt.Pb.Reference(); + if (valueCase_ == ValueOneofCase.Ref) { + subBuilder.MergeFrom(Ref); + } + input.ReadMessage(subBuilder); + Ref = subBuilder; + break; + } + case 18: { + global::Aapt.Pb.String subBuilder = new global::Aapt.Pb.String(); + if (valueCase_ == ValueOneofCase.Str) { + subBuilder.MergeFrom(Str); + } + input.ReadMessage(subBuilder); + Str = subBuilder; + break; + } + case 26: { + global::Aapt.Pb.RawString subBuilder = new global::Aapt.Pb.RawString(); + if (valueCase_ == ValueOneofCase.RawStr) { + subBuilder.MergeFrom(RawStr); + } + input.ReadMessage(subBuilder); + RawStr = subBuilder; + break; + } + case 34: { + global::Aapt.Pb.StyledString subBuilder = new global::Aapt.Pb.StyledString(); + if (valueCase_ == ValueOneofCase.StyledStr) { + subBuilder.MergeFrom(StyledStr); + } + input.ReadMessage(subBuilder); + StyledStr = subBuilder; + break; + } + case 42: { + global::Aapt.Pb.FileReference subBuilder = new global::Aapt.Pb.FileReference(); + if (valueCase_ == ValueOneofCase.File) { + subBuilder.MergeFrom(File); + } + input.ReadMessage(subBuilder); + File = subBuilder; + break; + } + case 50: { + global::Aapt.Pb.Id subBuilder = new global::Aapt.Pb.Id(); + if (valueCase_ == ValueOneofCase.Id) { + subBuilder.MergeFrom(Id); + } + input.ReadMessage(subBuilder); + Id = subBuilder; + break; + } + case 58: { + global::Aapt.Pb.Primitive subBuilder = new global::Aapt.Pb.Primitive(); + if (valueCase_ == ValueOneofCase.Prim) { + subBuilder.MergeFrom(Prim); + } + input.ReadMessage(subBuilder); + Prim = subBuilder; + break; + } + case 64: { + FlagStatus = input.ReadUInt32(); + break; + } + case 72: { + FlagNegated = input.ReadBool(); + break; + } + case 82: { + FlagName = input.ReadString(); + break; + } + } + } + } + #endif + + } + + /// + /// A CompoundValue is an abstract type. It represents a value that is a made of other values. + /// These can only usually appear as top-level resources. The concrete type is one of the types + /// below. Only one can be set. + /// + public sealed partial class CompoundValue : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CompoundValue()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[20]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public CompoundValue() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public CompoundValue(CompoundValue other) : this() { + flagStatus_ = other.flagStatus_; + flagNegated_ = other.flagNegated_; + flagName_ = other.flagName_; + switch (other.ValueCase) { + case ValueOneofCase.Attr: + Attr = other.Attr.Clone(); + break; + case ValueOneofCase.Style: + Style = other.Style.Clone(); + break; + case ValueOneofCase.Styleable: + Styleable = other.Styleable.Clone(); + break; + case ValueOneofCase.Array: + Array = other.Array.Clone(); + break; + case ValueOneofCase.Plural: + Plural = other.Plural.Clone(); + break; + case ValueOneofCase.Macro: + Macro = other.Macro.Clone(); + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public CompoundValue Clone() { + return new CompoundValue(this); + } + + /// Field number for the "attr" field. + public const int AttrFieldNumber = 1; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Attribute Attr { + get { return valueCase_ == ValueOneofCase.Attr ? (global::Aapt.Pb.Attribute) value_ : null; } + set { + value_ = value; + valueCase_ = value == null ? ValueOneofCase.None : ValueOneofCase.Attr; + } + } + + /// Field number for the "style" field. + public const int StyleFieldNumber = 2; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Style Style { + get { return valueCase_ == ValueOneofCase.Style ? (global::Aapt.Pb.Style) value_ : null; } + set { + value_ = value; + valueCase_ = value == null ? ValueOneofCase.None : ValueOneofCase.Style; + } + } + + /// Field number for the "styleable" field. + public const int StyleableFieldNumber = 3; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Styleable Styleable { + get { return valueCase_ == ValueOneofCase.Styleable ? (global::Aapt.Pb.Styleable) value_ : null; } + set { + value_ = value; + valueCase_ = value == null ? ValueOneofCase.None : ValueOneofCase.Styleable; + } + } + + /// Field number for the "array" field. + public const int ArrayFieldNumber = 4; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Array Array { + get { return valueCase_ == ValueOneofCase.Array ? (global::Aapt.Pb.Array) value_ : null; } + set { + value_ = value; + valueCase_ = value == null ? ValueOneofCase.None : ValueOneofCase.Array; + } + } + + /// Field number for the "plural" field. + public const int PluralFieldNumber = 5; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Plural Plural { + get { return valueCase_ == ValueOneofCase.Plural ? (global::Aapt.Pb.Plural) value_ : null; } + set { + value_ = value; + valueCase_ = value == null ? ValueOneofCase.None : ValueOneofCase.Plural; + } + } + + /// Field number for the "macro" field. + public const int MacroFieldNumber = 6; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.MacroBody Macro { + get { return valueCase_ == ValueOneofCase.Macro ? (global::Aapt.Pb.MacroBody) value_ : null; } + set { + value_ = value; + valueCase_ = value == null ? ValueOneofCase.None : ValueOneofCase.Macro; + } + } + + /// Field number for the "flag_status" field. + public const int FlagStatusFieldNumber = 7; + private uint flagStatus_; + /// + /// The status of the flag the value is behind if any + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint FlagStatus { + get { return flagStatus_; } + set { + flagStatus_ = value; + } + } + + /// Field number for the "flag_negated" field. + public const int FlagNegatedFieldNumber = 8; + private bool flagNegated_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool FlagNegated { + get { return flagNegated_; } + set { + flagNegated_ = value; + } + } + + /// Field number for the "flag_name" field. + public const int FlagNameFieldNumber = 9; + private string flagName_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string FlagName { + get { return flagName_; } + set { + flagName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + private object value_; + /// Enum of possible cases for the "value" oneof. + public enum ValueOneofCase { + None = 0, + Attr = 1, + Style = 2, + Styleable = 3, + Array = 4, + Plural = 5, + Macro = 6, + } + private ValueOneofCase valueCase_ = ValueOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ValueOneofCase ValueCase { + get { return valueCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void ClearValue() { + valueCase_ = ValueOneofCase.None; + value_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as CompoundValue); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(CompoundValue other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Attr, other.Attr)) return false; + if (!object.Equals(Style, other.Style)) return false; + if (!object.Equals(Styleable, other.Styleable)) return false; + if (!object.Equals(Array, other.Array)) return false; + if (!object.Equals(Plural, other.Plural)) return false; + if (!object.Equals(Macro, other.Macro)) return false; + if (FlagStatus != other.FlagStatus) return false; + if (FlagNegated != other.FlagNegated) return false; + if (FlagName != other.FlagName) return false; + if (ValueCase != other.ValueCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (valueCase_ == ValueOneofCase.Attr) hash ^= Attr.GetHashCode(); + if (valueCase_ == ValueOneofCase.Style) hash ^= Style.GetHashCode(); + if (valueCase_ == ValueOneofCase.Styleable) hash ^= Styleable.GetHashCode(); + if (valueCase_ == ValueOneofCase.Array) hash ^= Array.GetHashCode(); + if (valueCase_ == ValueOneofCase.Plural) hash ^= Plural.GetHashCode(); + if (valueCase_ == ValueOneofCase.Macro) hash ^= Macro.GetHashCode(); + if (FlagStatus != 0) hash ^= FlagStatus.GetHashCode(); + if (FlagNegated != false) hash ^= FlagNegated.GetHashCode(); + if (FlagName.Length != 0) hash ^= FlagName.GetHashCode(); + hash ^= (int) valueCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (valueCase_ == ValueOneofCase.Attr) { + output.WriteRawTag(10); + output.WriteMessage(Attr); + } + if (valueCase_ == ValueOneofCase.Style) { + output.WriteRawTag(18); + output.WriteMessage(Style); + } + if (valueCase_ == ValueOneofCase.Styleable) { + output.WriteRawTag(26); + output.WriteMessage(Styleable); + } + if (valueCase_ == ValueOneofCase.Array) { + output.WriteRawTag(34); + output.WriteMessage(Array); + } + if (valueCase_ == ValueOneofCase.Plural) { + output.WriteRawTag(42); + output.WriteMessage(Plural); + } + if (valueCase_ == ValueOneofCase.Macro) { + output.WriteRawTag(50); + output.WriteMessage(Macro); + } + if (FlagStatus != 0) { + output.WriteRawTag(56); + output.WriteUInt32(FlagStatus); + } + if (FlagNegated != false) { + output.WriteRawTag(64); + output.WriteBool(FlagNegated); + } + if (FlagName.Length != 0) { + output.WriteRawTag(74); + output.WriteString(FlagName); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (valueCase_ == ValueOneofCase.Attr) { + output.WriteRawTag(10); + output.WriteMessage(Attr); + } + if (valueCase_ == ValueOneofCase.Style) { + output.WriteRawTag(18); + output.WriteMessage(Style); + } + if (valueCase_ == ValueOneofCase.Styleable) { + output.WriteRawTag(26); + output.WriteMessage(Styleable); + } + if (valueCase_ == ValueOneofCase.Array) { + output.WriteRawTag(34); + output.WriteMessage(Array); + } + if (valueCase_ == ValueOneofCase.Plural) { + output.WriteRawTag(42); + output.WriteMessage(Plural); + } + if (valueCase_ == ValueOneofCase.Macro) { + output.WriteRawTag(50); + output.WriteMessage(Macro); + } + if (FlagStatus != 0) { + output.WriteRawTag(56); + output.WriteUInt32(FlagStatus); + } + if (FlagNegated != false) { + output.WriteRawTag(64); + output.WriteBool(FlagNegated); + } + if (FlagName.Length != 0) { + output.WriteRawTag(74); + output.WriteString(FlagName); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (valueCase_ == ValueOneofCase.Attr) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Attr); + } + if (valueCase_ == ValueOneofCase.Style) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Style); + } + if (valueCase_ == ValueOneofCase.Styleable) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Styleable); + } + if (valueCase_ == ValueOneofCase.Array) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Array); + } + if (valueCase_ == ValueOneofCase.Plural) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Plural); + } + if (valueCase_ == ValueOneofCase.Macro) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Macro); + } + if (FlagStatus != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(FlagStatus); + } + if (FlagNegated != false) { + size += 1 + 1; + } + if (FlagName.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(FlagName); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(CompoundValue other) { + if (other == null) { + return; + } + if (other.FlagStatus != 0) { + FlagStatus = other.FlagStatus; + } + if (other.FlagNegated != false) { + FlagNegated = other.FlagNegated; + } + if (other.FlagName.Length != 0) { + FlagName = other.FlagName; + } + switch (other.ValueCase) { + case ValueOneofCase.Attr: + if (Attr == null) { + Attr = new global::Aapt.Pb.Attribute(); + } + Attr.MergeFrom(other.Attr); + break; + case ValueOneofCase.Style: + if (Style == null) { + Style = new global::Aapt.Pb.Style(); + } + Style.MergeFrom(other.Style); + break; + case ValueOneofCase.Styleable: + if (Styleable == null) { + Styleable = new global::Aapt.Pb.Styleable(); + } + Styleable.MergeFrom(other.Styleable); + break; + case ValueOneofCase.Array: + if (Array == null) { + Array = new global::Aapt.Pb.Array(); + } + Array.MergeFrom(other.Array); + break; + case ValueOneofCase.Plural: + if (Plural == null) { + Plural = new global::Aapt.Pb.Plural(); + } + Plural.MergeFrom(other.Plural); + break; + case ValueOneofCase.Macro: + if (Macro == null) { + Macro = new global::Aapt.Pb.MacroBody(); + } + Macro.MergeFrom(other.Macro); + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + global::Aapt.Pb.Attribute subBuilder = new global::Aapt.Pb.Attribute(); + if (valueCase_ == ValueOneofCase.Attr) { + subBuilder.MergeFrom(Attr); + } + input.ReadMessage(subBuilder); + Attr = subBuilder; + break; + } + case 18: { + global::Aapt.Pb.Style subBuilder = new global::Aapt.Pb.Style(); + if (valueCase_ == ValueOneofCase.Style) { + subBuilder.MergeFrom(Style); + } + input.ReadMessage(subBuilder); + Style = subBuilder; + break; + } + case 26: { + global::Aapt.Pb.Styleable subBuilder = new global::Aapt.Pb.Styleable(); + if (valueCase_ == ValueOneofCase.Styleable) { + subBuilder.MergeFrom(Styleable); + } + input.ReadMessage(subBuilder); + Styleable = subBuilder; + break; + } + case 34: { + global::Aapt.Pb.Array subBuilder = new global::Aapt.Pb.Array(); + if (valueCase_ == ValueOneofCase.Array) { + subBuilder.MergeFrom(Array); + } + input.ReadMessage(subBuilder); + Array = subBuilder; + break; + } + case 42: { + global::Aapt.Pb.Plural subBuilder = new global::Aapt.Pb.Plural(); + if (valueCase_ == ValueOneofCase.Plural) { + subBuilder.MergeFrom(Plural); + } + input.ReadMessage(subBuilder); + Plural = subBuilder; + break; + } + case 50: { + global::Aapt.Pb.MacroBody subBuilder = new global::Aapt.Pb.MacroBody(); + if (valueCase_ == ValueOneofCase.Macro) { + subBuilder.MergeFrom(Macro); + } + input.ReadMessage(subBuilder); + Macro = subBuilder; + break; + } + case 56: { + FlagStatus = input.ReadUInt32(); + break; + } + case 64: { + FlagNegated = input.ReadBool(); + break; + } + case 74: { + FlagName = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + global::Aapt.Pb.Attribute subBuilder = new global::Aapt.Pb.Attribute(); + if (valueCase_ == ValueOneofCase.Attr) { + subBuilder.MergeFrom(Attr); + } + input.ReadMessage(subBuilder); + Attr = subBuilder; + break; + } + case 18: { + global::Aapt.Pb.Style subBuilder = new global::Aapt.Pb.Style(); + if (valueCase_ == ValueOneofCase.Style) { + subBuilder.MergeFrom(Style); + } + input.ReadMessage(subBuilder); + Style = subBuilder; + break; + } + case 26: { + global::Aapt.Pb.Styleable subBuilder = new global::Aapt.Pb.Styleable(); + if (valueCase_ == ValueOneofCase.Styleable) { + subBuilder.MergeFrom(Styleable); + } + input.ReadMessage(subBuilder); + Styleable = subBuilder; + break; + } + case 34: { + global::Aapt.Pb.Array subBuilder = new global::Aapt.Pb.Array(); + if (valueCase_ == ValueOneofCase.Array) { + subBuilder.MergeFrom(Array); + } + input.ReadMessage(subBuilder); + Array = subBuilder; + break; + } + case 42: { + global::Aapt.Pb.Plural subBuilder = new global::Aapt.Pb.Plural(); + if (valueCase_ == ValueOneofCase.Plural) { + subBuilder.MergeFrom(Plural); + } + input.ReadMessage(subBuilder); + Plural = subBuilder; + break; + } + case 50: { + global::Aapt.Pb.MacroBody subBuilder = new global::Aapt.Pb.MacroBody(); + if (valueCase_ == ValueOneofCase.Macro) { + subBuilder.MergeFrom(Macro); + } + input.ReadMessage(subBuilder); + Macro = subBuilder; + break; + } + case 56: { + FlagStatus = input.ReadUInt32(); + break; + } + case 64: { + FlagNegated = input.ReadBool(); + break; + } + case 74: { + FlagName = input.ReadString(); + break; + } + } + } + } + #endif + + } + + /// + /// Message holding a boolean, so it can be optionally encoded. + /// + public sealed partial class Boolean : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Boolean()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[21]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Boolean() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Boolean(Boolean other) : this() { + value_ = other.value_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Boolean Clone() { + return new Boolean(this); + } + + /// Field number for the "value" field. + public const int ValueFieldNumber = 1; + private bool value_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Value { + get { return value_; } + set { + value_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Boolean); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Boolean other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Value != other.Value) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Value != false) hash ^= Value.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Value != false) { + output.WriteRawTag(8); + output.WriteBool(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Value != false) { + output.WriteRawTag(8); + output.WriteBool(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Value != false) { + size += 1 + 1; + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Boolean other) { + if (other == null) { + return; + } + if (other.Value != false) { + Value = other.Value; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Value = input.ReadBool(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Value = input.ReadBool(); + break; + } + } + } + } + #endif + + } + + /// + /// A value that is a reference to another resource. This reference can be by name or resource ID. + /// + public sealed partial class Reference : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Reference()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[22]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Reference() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Reference(Reference other) : this() { + type_ = other.type_; + id_ = other.id_; + name_ = other.name_; + private_ = other.private_; + isDynamic_ = other.isDynamic_ != null ? other.isDynamic_.Clone() : null; + typeFlags_ = other.typeFlags_; + allowRaw_ = other.allowRaw_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Reference Clone() { + return new Reference(this); + } + + /// Field number for the "type" field. + public const int TypeFieldNumber = 1; + private global::Aapt.Pb.Reference.Types.Type type_ = global::Aapt.Pb.Reference.Types.Type.Reference; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Reference.Types.Type Type { + get { return type_; } + set { + type_ = value; + } + } + + /// Field number for the "id" field. + public const int IdFieldNumber = 2; + private uint id_; + /// + /// The resource ID (0xPPTTEEEE) of the resource being referred. This is optional. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint Id { + get { return id_; } + set { + id_ = value; + } + } + + /// Field number for the "name" field. + public const int NameFieldNumber = 3; + private string name_ = ""; + /// + /// The name of the resource being referred. This is optional if the resource ID is set. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Name { + get { return name_; } + set { + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "private" field. + public const int PrivateFieldNumber = 4; + private bool private_; + /// + /// Whether this reference is referencing a private resource (@*package:type/entry). + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Private { + get { return private_; } + set { + private_ = value; + } + } + + /// Field number for the "is_dynamic" field. + public const int IsDynamicFieldNumber = 5; + private global::Aapt.Pb.Boolean isDynamic_; + /// + /// Whether this reference is dynamic. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Boolean IsDynamic { + get { return isDynamic_; } + set { + isDynamic_ = value; + } + } + + /// Field number for the "type_flags" field. + public const int TypeFlagsFieldNumber = 6; + private uint typeFlags_; + /// + /// The type flags used when compiling the reference. Used for substituting the contents of macros. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint TypeFlags { + get { return typeFlags_; } + set { + typeFlags_ = value; + } + } + + /// Field number for the "allow_raw" field. + public const int AllowRawFieldNumber = 7; + private bool allowRaw_; + /// + /// Whether raw string values would have been accepted in place of this reference definition. Used + /// for substituting the contents of macros. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool AllowRaw { + get { return allowRaw_; } + set { + allowRaw_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Reference); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Reference other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Type != other.Type) return false; + if (Id != other.Id) return false; + if (Name != other.Name) return false; + if (Private != other.Private) return false; + if (!object.Equals(IsDynamic, other.IsDynamic)) return false; + if (TypeFlags != other.TypeFlags) return false; + if (AllowRaw != other.AllowRaw) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Type != global::Aapt.Pb.Reference.Types.Type.Reference) hash ^= Type.GetHashCode(); + if (Id != 0) hash ^= Id.GetHashCode(); + if (Name.Length != 0) hash ^= Name.GetHashCode(); + if (Private != false) hash ^= Private.GetHashCode(); + if (isDynamic_ != null) hash ^= IsDynamic.GetHashCode(); + if (TypeFlags != 0) hash ^= TypeFlags.GetHashCode(); + if (AllowRaw != false) hash ^= AllowRaw.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Type != global::Aapt.Pb.Reference.Types.Type.Reference) { + output.WriteRawTag(8); + output.WriteEnum((int) Type); + } + if (Id != 0) { + output.WriteRawTag(16); + output.WriteUInt32(Id); + } + if (Name.Length != 0) { + output.WriteRawTag(26); + output.WriteString(Name); + } + if (Private != false) { + output.WriteRawTag(32); + output.WriteBool(Private); + } + if (isDynamic_ != null) { + output.WriteRawTag(42); + output.WriteMessage(IsDynamic); + } + if (TypeFlags != 0) { + output.WriteRawTag(48); + output.WriteUInt32(TypeFlags); + } + if (AllowRaw != false) { + output.WriteRawTag(56); + output.WriteBool(AllowRaw); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Type != global::Aapt.Pb.Reference.Types.Type.Reference) { + output.WriteRawTag(8); + output.WriteEnum((int) Type); + } + if (Id != 0) { + output.WriteRawTag(16); + output.WriteUInt32(Id); + } + if (Name.Length != 0) { + output.WriteRawTag(26); + output.WriteString(Name); + } + if (Private != false) { + output.WriteRawTag(32); + output.WriteBool(Private); + } + if (isDynamic_ != null) { + output.WriteRawTag(42); + output.WriteMessage(IsDynamic); + } + if (TypeFlags != 0) { + output.WriteRawTag(48); + output.WriteUInt32(TypeFlags); + } + if (AllowRaw != false) { + output.WriteRawTag(56); + output.WriteBool(AllowRaw); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Type != global::Aapt.Pb.Reference.Types.Type.Reference) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type); + } + if (Id != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Id); + } + if (Name.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); + } + if (Private != false) { + size += 1 + 1; + } + if (isDynamic_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(IsDynamic); + } + if (TypeFlags != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(TypeFlags); + } + if (AllowRaw != false) { + size += 1 + 1; + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Reference other) { + if (other == null) { + return; + } + if (other.Type != global::Aapt.Pb.Reference.Types.Type.Reference) { + Type = other.Type; + } + if (other.Id != 0) { + Id = other.Id; + } + if (other.Name.Length != 0) { + Name = other.Name; + } + if (other.Private != false) { + Private = other.Private; + } + if (other.isDynamic_ != null) { + if (isDynamic_ == null) { + IsDynamic = new global::Aapt.Pb.Boolean(); + } + IsDynamic.MergeFrom(other.IsDynamic); + } + if (other.TypeFlags != 0) { + TypeFlags = other.TypeFlags; + } + if (other.AllowRaw != false) { + AllowRaw = other.AllowRaw; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Type = (global::Aapt.Pb.Reference.Types.Type) input.ReadEnum(); + break; + } + case 16: { + Id = input.ReadUInt32(); + break; + } + case 26: { + Name = input.ReadString(); + break; + } + case 32: { + Private = input.ReadBool(); + break; + } + case 42: { + if (isDynamic_ == null) { + IsDynamic = new global::Aapt.Pb.Boolean(); + } + input.ReadMessage(IsDynamic); + break; + } + case 48: { + TypeFlags = input.ReadUInt32(); + break; + } + case 56: { + AllowRaw = input.ReadBool(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Type = (global::Aapt.Pb.Reference.Types.Type) input.ReadEnum(); + break; + } + case 16: { + Id = input.ReadUInt32(); + break; + } + case 26: { + Name = input.ReadString(); + break; + } + case 32: { + Private = input.ReadBool(); + break; + } + case 42: { + if (isDynamic_ == null) { + IsDynamic = new global::Aapt.Pb.Boolean(); + } + input.ReadMessage(IsDynamic); + break; + } + case 48: { + TypeFlags = input.ReadUInt32(); + break; + } + case 56: { + AllowRaw = input.ReadBool(); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the Reference message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static partial class Types { + public enum Type { + /// + /// A plain reference (@package:type/entry). + /// + [pbr::OriginalName("REFERENCE")] Reference = 0, + /// + /// A reference to a theme attribute (?package:type/entry). + /// + [pbr::OriginalName("ATTRIBUTE")] Attribute = 1, + } + + } + #endregion + + } + + /// + /// A value that represents an ID. This is just a placeholder, as ID values are used to occupy a + /// resource ID (0xPPTTEEEE) as a unique identifier. Their value is unimportant. + /// + public sealed partial class Id : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Id()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[23]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Id() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Id(Id other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Id Clone() { + return new Id(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Id); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Id other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Id other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + } + } + } + #endif + + } + + /// + /// A value that is a string. + /// + public sealed partial class String : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new String()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[24]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public String() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public String(String other) : this() { + value_ = other.value_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public String Clone() { + return new String(this); + } + + /// Field number for the "value" field. + public const int ValueFieldNumber = 1; + private string value_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Value { + get { return value_; } + set { + value_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as String); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(String other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Value != other.Value) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Value.Length != 0) hash ^= Value.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Value.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Value.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Value.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Value); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(String other) { + if (other == null) { + return; + } + if (other.Value.Length != 0) { + Value = other.Value; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Value = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Value = input.ReadString(); + break; + } + } + } + } + #endif + + } + + /// + /// A value that is a raw string, which is unescaped/uninterpreted. This is typically used to + /// represent the value of a style attribute before the attribute is compiled and the set of + /// allowed values is known. + /// + public sealed partial class RawString : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new RawString()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[25]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public RawString() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public RawString(RawString other) : this() { + value_ = other.value_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public RawString Clone() { + return new RawString(this); + } + + /// Field number for the "value" field. + public const int ValueFieldNumber = 1; + private string value_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Value { + get { return value_; } + set { + value_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as RawString); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(RawString other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Value != other.Value) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Value.Length != 0) hash ^= Value.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Value.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Value.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Value.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Value); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(RawString other) { + if (other == null) { + return; + } + if (other.Value.Length != 0) { + Value = other.Value; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Value = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Value = input.ReadString(); + break; + } + } + } + } + #endif + + } + + /// + /// A string with styling information, like html tags that specify boldness, italics, etc. + /// + public sealed partial class StyledString : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new StyledString()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[26]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public StyledString() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public StyledString(StyledString other) : this() { + value_ = other.value_; + span_ = other.span_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public StyledString Clone() { + return new StyledString(this); + } + + /// Field number for the "value" field. + public const int ValueFieldNumber = 1; + private string value_ = ""; + /// + /// The raw text of the string. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Value { + get { return value_; } + set { + value_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "span" field. + public const int SpanFieldNumber = 2; + private static readonly pb::FieldCodec _repeated_span_codec + = pb::FieldCodec.ForMessage(18, global::Aapt.Pb.StyledString.Types.Span.Parser); + private readonly pbc::RepeatedField span_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField Span { + get { return span_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as StyledString); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(StyledString other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Value != other.Value) return false; + if(!span_.Equals(other.span_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Value.Length != 0) hash ^= Value.GetHashCode(); + hash ^= span_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Value.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Value); + } + span_.WriteTo(output, _repeated_span_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Value.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Value); + } + span_.WriteTo(ref output, _repeated_span_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Value.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Value); + } + size += span_.CalculateSize(_repeated_span_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(StyledString other) { + if (other == null) { + return; + } + if (other.Value.Length != 0) { + Value = other.Value; + } + span_.Add(other.span_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Value = input.ReadString(); + break; + } + case 18: { + span_.AddEntriesFrom(input, _repeated_span_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Value = input.ReadString(); + break; + } + case 18: { + span_.AddEntriesFrom(ref input, _repeated_span_codec); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the StyledString message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static partial class Types { + /// + /// A Span marks a region of the string text that is styled. + /// + public sealed partial class Span : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Span()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.StyledString.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Span() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Span(Span other) : this() { + tag_ = other.tag_; + firstChar_ = other.firstChar_; + lastChar_ = other.lastChar_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Span Clone() { + return new Span(this); + } + + /// Field number for the "tag" field. + public const int TagFieldNumber = 1; + private string tag_ = ""; + /// + /// The name of the tag, and its attributes, encoded as follows: + /// tag_name;attr1=value1;attr2=value2;[...] + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Tag { + get { return tag_; } + set { + tag_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "first_char" field. + public const int FirstCharFieldNumber = 2; + private uint firstChar_; + /// + /// The first character position this span applies to, in UTF-16 offset. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint FirstChar { + get { return firstChar_; } + set { + firstChar_ = value; + } + } + + /// Field number for the "last_char" field. + public const int LastCharFieldNumber = 3; + private uint lastChar_; + /// + /// The last character position this span applies to, in UTF-16 offset. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint LastChar { + get { return lastChar_; } + set { + lastChar_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Span); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Span other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Tag != other.Tag) return false; + if (FirstChar != other.FirstChar) return false; + if (LastChar != other.LastChar) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Tag.Length != 0) hash ^= Tag.GetHashCode(); + if (FirstChar != 0) hash ^= FirstChar.GetHashCode(); + if (LastChar != 0) hash ^= LastChar.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Tag.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Tag); + } + if (FirstChar != 0) { + output.WriteRawTag(16); + output.WriteUInt32(FirstChar); + } + if (LastChar != 0) { + output.WriteRawTag(24); + output.WriteUInt32(LastChar); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Tag.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Tag); + } + if (FirstChar != 0) { + output.WriteRawTag(16); + output.WriteUInt32(FirstChar); + } + if (LastChar != 0) { + output.WriteRawTag(24); + output.WriteUInt32(LastChar); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Tag.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Tag); + } + if (FirstChar != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(FirstChar); + } + if (LastChar != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(LastChar); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Span other) { + if (other == null) { + return; + } + if (other.Tag.Length != 0) { + Tag = other.Tag; + } + if (other.FirstChar != 0) { + FirstChar = other.FirstChar; + } + if (other.LastChar != 0) { + LastChar = other.LastChar; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Tag = input.ReadString(); + break; + } + case 16: { + FirstChar = input.ReadUInt32(); + break; + } + case 24: { + LastChar = input.ReadUInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Tag = input.ReadString(); + break; + } + case 16: { + FirstChar = input.ReadUInt32(); + break; + } + case 24: { + LastChar = input.ReadUInt32(); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + /// + /// A value that is a reference to an external entity, like an XML file or a PNG. + /// + public sealed partial class FileReference : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FileReference()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[27]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public FileReference() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public FileReference(FileReference other) : this() { + path_ = other.path_; + type_ = other.type_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public FileReference Clone() { + return new FileReference(this); + } + + /// Field number for the "path" field. + public const int PathFieldNumber = 1; + private string path_ = ""; + /// + /// Path to a file within the APK (typically res/type-config/entry.ext). + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Path { + get { return path_; } + set { + path_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "type" field. + public const int TypeFieldNumber = 2; + private global::Aapt.Pb.FileReference.Types.Type type_ = global::Aapt.Pb.FileReference.Types.Type.Unknown; + /// + /// The type of file this path points to. For UAM bundle, this cannot be + /// BINARY_XML. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.FileReference.Types.Type Type { + get { return type_; } + set { + type_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as FileReference); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(FileReference other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Path != other.Path) return false; + if (Type != other.Type) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Path.Length != 0) hash ^= Path.GetHashCode(); + if (Type != global::Aapt.Pb.FileReference.Types.Type.Unknown) hash ^= Type.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Path.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Path); + } + if (Type != global::Aapt.Pb.FileReference.Types.Type.Unknown) { + output.WriteRawTag(16); + output.WriteEnum((int) Type); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Path.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Path); + } + if (Type != global::Aapt.Pb.FileReference.Types.Type.Unknown) { + output.WriteRawTag(16); + output.WriteEnum((int) Type); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Path.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Path); + } + if (Type != global::Aapt.Pb.FileReference.Types.Type.Unknown) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(FileReference other) { + if (other == null) { + return; + } + if (other.Path.Length != 0) { + Path = other.Path; + } + if (other.Type != global::Aapt.Pb.FileReference.Types.Type.Unknown) { + Type = other.Type; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Path = input.ReadString(); + break; + } + case 16: { + Type = (global::Aapt.Pb.FileReference.Types.Type) input.ReadEnum(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Path = input.ReadString(); + break; + } + case 16: { + Type = (global::Aapt.Pb.FileReference.Types.Type) input.ReadEnum(); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the FileReference message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static partial class Types { + public enum Type { + [pbr::OriginalName("UNKNOWN")] Unknown = 0, + [pbr::OriginalName("PNG")] Png = 1, + [pbr::OriginalName("BINARY_XML")] BinaryXml = 2, + [pbr::OriginalName("PROTO_XML")] ProtoXml = 3, + } + + } + #endregion + + } + + /// + /// A value that represents a primitive data type (float, int, boolean, etc.). + /// Refer to Res_value in ResourceTypes.h for info on types and formatting + /// + public sealed partial class Primitive : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Primitive()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[28]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Primitive() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Primitive(Primitive other) : this() { + switch (other.OneofValueCase) { + case OneofValueOneofCase.NullValue: + NullValue = other.NullValue.Clone(); + break; + case OneofValueOneofCase.EmptyValue: + EmptyValue = other.EmptyValue.Clone(); + break; + case OneofValueOneofCase.FloatValue: + FloatValue = other.FloatValue; + break; + case OneofValueOneofCase.DimensionValue: + DimensionValue = other.DimensionValue; + break; + case OneofValueOneofCase.FractionValue: + FractionValue = other.FractionValue; + break; + case OneofValueOneofCase.IntDecimalValue: + IntDecimalValue = other.IntDecimalValue; + break; + case OneofValueOneofCase.IntHexadecimalValue: + IntHexadecimalValue = other.IntHexadecimalValue; + break; + case OneofValueOneofCase.BooleanValue: + BooleanValue = other.BooleanValue; + break; + case OneofValueOneofCase.ColorArgb8Value: + ColorArgb8Value = other.ColorArgb8Value; + break; + case OneofValueOneofCase.ColorRgb8Value: + ColorRgb8Value = other.ColorRgb8Value; + break; + case OneofValueOneofCase.ColorArgb4Value: + ColorArgb4Value = other.ColorArgb4Value; + break; + case OneofValueOneofCase.ColorRgb4Value: + ColorRgb4Value = other.ColorRgb4Value; + break; + case OneofValueOneofCase.DimensionValueDeprecated: + DimensionValueDeprecated = other.DimensionValueDeprecated; + break; + case OneofValueOneofCase.FractionValueDeprecated: + FractionValueDeprecated = other.FractionValueDeprecated; + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Primitive Clone() { + return new Primitive(this); + } + + /// Field number for the "null_value" field. + public const int NullValueFieldNumber = 1; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Primitive.Types.NullType NullValue { + get { return oneofValueCase_ == OneofValueOneofCase.NullValue ? (global::Aapt.Pb.Primitive.Types.NullType) oneofValue_ : null; } + set { + oneofValue_ = value; + oneofValueCase_ = value == null ? OneofValueOneofCase.None : OneofValueOneofCase.NullValue; + } + } + + /// Field number for the "empty_value" field. + public const int EmptyValueFieldNumber = 2; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Primitive.Types.EmptyType EmptyValue { + get { return oneofValueCase_ == OneofValueOneofCase.EmptyValue ? (global::Aapt.Pb.Primitive.Types.EmptyType) oneofValue_ : null; } + set { + oneofValue_ = value; + oneofValueCase_ = value == null ? OneofValueOneofCase.None : OneofValueOneofCase.EmptyValue; + } + } + + /// Field number for the "float_value" field. + public const int FloatValueFieldNumber = 3; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public float FloatValue { + get { return oneofValueCase_ == OneofValueOneofCase.FloatValue ? (float) oneofValue_ : 0F; } + set { + oneofValue_ = value; + oneofValueCase_ = OneofValueOneofCase.FloatValue; + } + } + + /// Field number for the "dimension_value" field. + public const int DimensionValueFieldNumber = 13; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint DimensionValue { + get { return oneofValueCase_ == OneofValueOneofCase.DimensionValue ? (uint) oneofValue_ : 0; } + set { + oneofValue_ = value; + oneofValueCase_ = OneofValueOneofCase.DimensionValue; + } + } + + /// Field number for the "fraction_value" field. + public const int FractionValueFieldNumber = 14; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint FractionValue { + get { return oneofValueCase_ == OneofValueOneofCase.FractionValue ? (uint) oneofValue_ : 0; } + set { + oneofValue_ = value; + oneofValueCase_ = OneofValueOneofCase.FractionValue; + } + } + + /// Field number for the "int_decimal_value" field. + public const int IntDecimalValueFieldNumber = 6; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int IntDecimalValue { + get { return oneofValueCase_ == OneofValueOneofCase.IntDecimalValue ? (int) oneofValue_ : 0; } + set { + oneofValue_ = value; + oneofValueCase_ = OneofValueOneofCase.IntDecimalValue; + } + } + + /// Field number for the "int_hexadecimal_value" field. + public const int IntHexadecimalValueFieldNumber = 7; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint IntHexadecimalValue { + get { return oneofValueCase_ == OneofValueOneofCase.IntHexadecimalValue ? (uint) oneofValue_ : 0; } + set { + oneofValue_ = value; + oneofValueCase_ = OneofValueOneofCase.IntHexadecimalValue; + } + } + + /// Field number for the "boolean_value" field. + public const int BooleanValueFieldNumber = 8; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool BooleanValue { + get { return oneofValueCase_ == OneofValueOneofCase.BooleanValue ? (bool) oneofValue_ : false; } + set { + oneofValue_ = value; + oneofValueCase_ = OneofValueOneofCase.BooleanValue; + } + } + + /// Field number for the "color_argb8_value" field. + public const int ColorArgb8ValueFieldNumber = 9; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint ColorArgb8Value { + get { return oneofValueCase_ == OneofValueOneofCase.ColorArgb8Value ? (uint) oneofValue_ : 0; } + set { + oneofValue_ = value; + oneofValueCase_ = OneofValueOneofCase.ColorArgb8Value; + } + } + + /// Field number for the "color_rgb8_value" field. + public const int ColorRgb8ValueFieldNumber = 10; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint ColorRgb8Value { + get { return oneofValueCase_ == OneofValueOneofCase.ColorRgb8Value ? (uint) oneofValue_ : 0; } + set { + oneofValue_ = value; + oneofValueCase_ = OneofValueOneofCase.ColorRgb8Value; + } + } + + /// Field number for the "color_argb4_value" field. + public const int ColorArgb4ValueFieldNumber = 11; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint ColorArgb4Value { + get { return oneofValueCase_ == OneofValueOneofCase.ColorArgb4Value ? (uint) oneofValue_ : 0; } + set { + oneofValue_ = value; + oneofValueCase_ = OneofValueOneofCase.ColorArgb4Value; + } + } + + /// Field number for the "color_rgb4_value" field. + public const int ColorRgb4ValueFieldNumber = 12; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint ColorRgb4Value { + get { return oneofValueCase_ == OneofValueOneofCase.ColorRgb4Value ? (uint) oneofValue_ : 0; } + set { + oneofValue_ = value; + oneofValueCase_ = OneofValueOneofCase.ColorRgb4Value; + } + } + + /// Field number for the "dimension_value_deprecated" field. + public const int DimensionValueDeprecatedFieldNumber = 4; + [global::System.ObsoleteAttribute] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public float DimensionValueDeprecated { + get { return oneofValueCase_ == OneofValueOneofCase.DimensionValueDeprecated ? (float) oneofValue_ : 0F; } + set { + oneofValue_ = value; + oneofValueCase_ = OneofValueOneofCase.DimensionValueDeprecated; + } + } + + /// Field number for the "fraction_value_deprecated" field. + public const int FractionValueDeprecatedFieldNumber = 5; + [global::System.ObsoleteAttribute] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public float FractionValueDeprecated { + get { return oneofValueCase_ == OneofValueOneofCase.FractionValueDeprecated ? (float) oneofValue_ : 0F; } + set { + oneofValue_ = value; + oneofValueCase_ = OneofValueOneofCase.FractionValueDeprecated; + } + } + + private object oneofValue_; + /// Enum of possible cases for the "oneof_value" oneof. + public enum OneofValueOneofCase { + None = 0, + NullValue = 1, + EmptyValue = 2, + FloatValue = 3, + DimensionValue = 13, + FractionValue = 14, + IntDecimalValue = 6, + IntHexadecimalValue = 7, + BooleanValue = 8, + ColorArgb8Value = 9, + ColorRgb8Value = 10, + ColorArgb4Value = 11, + ColorRgb4Value = 12, + DimensionValueDeprecated = 4, + FractionValueDeprecated = 5, + } + private OneofValueOneofCase oneofValueCase_ = OneofValueOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public OneofValueOneofCase OneofValueCase { + get { return oneofValueCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void ClearOneofValue() { + oneofValueCase_ = OneofValueOneofCase.None; + oneofValue_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Primitive); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Primitive other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(NullValue, other.NullValue)) return false; + if (!object.Equals(EmptyValue, other.EmptyValue)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(FloatValue, other.FloatValue)) return false; + if (DimensionValue != other.DimensionValue) return false; + if (FractionValue != other.FractionValue) return false; + if (IntDecimalValue != other.IntDecimalValue) return false; + if (IntHexadecimalValue != other.IntHexadecimalValue) return false; + if (BooleanValue != other.BooleanValue) return false; + if (ColorArgb8Value != other.ColorArgb8Value) return false; + if (ColorRgb8Value != other.ColorRgb8Value) return false; + if (ColorArgb4Value != other.ColorArgb4Value) return false; + if (ColorRgb4Value != other.ColorRgb4Value) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(DimensionValueDeprecated, other.DimensionValueDeprecated)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(FractionValueDeprecated, other.FractionValueDeprecated)) return false; + if (OneofValueCase != other.OneofValueCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (oneofValueCase_ == OneofValueOneofCase.NullValue) hash ^= NullValue.GetHashCode(); + if (oneofValueCase_ == OneofValueOneofCase.EmptyValue) hash ^= EmptyValue.GetHashCode(); + if (oneofValueCase_ == OneofValueOneofCase.FloatValue) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(FloatValue); + if (oneofValueCase_ == OneofValueOneofCase.DimensionValue) hash ^= DimensionValue.GetHashCode(); + if (oneofValueCase_ == OneofValueOneofCase.FractionValue) hash ^= FractionValue.GetHashCode(); + if (oneofValueCase_ == OneofValueOneofCase.IntDecimalValue) hash ^= IntDecimalValue.GetHashCode(); + if (oneofValueCase_ == OneofValueOneofCase.IntHexadecimalValue) hash ^= IntHexadecimalValue.GetHashCode(); + if (oneofValueCase_ == OneofValueOneofCase.BooleanValue) hash ^= BooleanValue.GetHashCode(); + if (oneofValueCase_ == OneofValueOneofCase.ColorArgb8Value) hash ^= ColorArgb8Value.GetHashCode(); + if (oneofValueCase_ == OneofValueOneofCase.ColorRgb8Value) hash ^= ColorRgb8Value.GetHashCode(); + if (oneofValueCase_ == OneofValueOneofCase.ColorArgb4Value) hash ^= ColorArgb4Value.GetHashCode(); + if (oneofValueCase_ == OneofValueOneofCase.ColorRgb4Value) hash ^= ColorRgb4Value.GetHashCode(); + if (oneofValueCase_ == OneofValueOneofCase.DimensionValueDeprecated) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(DimensionValueDeprecated); + if (oneofValueCase_ == OneofValueOneofCase.FractionValueDeprecated) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(FractionValueDeprecated); + hash ^= (int) oneofValueCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (oneofValueCase_ == OneofValueOneofCase.NullValue) { + output.WriteRawTag(10); + output.WriteMessage(NullValue); + } + if (oneofValueCase_ == OneofValueOneofCase.EmptyValue) { + output.WriteRawTag(18); + output.WriteMessage(EmptyValue); + } + if (oneofValueCase_ == OneofValueOneofCase.FloatValue) { + output.WriteRawTag(29); + output.WriteFloat(FloatValue); + } + if (oneofValueCase_ == OneofValueOneofCase.DimensionValueDeprecated) { + output.WriteRawTag(37); + output.WriteFloat(DimensionValueDeprecated); + } + if (oneofValueCase_ == OneofValueOneofCase.FractionValueDeprecated) { + output.WriteRawTag(45); + output.WriteFloat(FractionValueDeprecated); + } + if (oneofValueCase_ == OneofValueOneofCase.IntDecimalValue) { + output.WriteRawTag(48); + output.WriteInt32(IntDecimalValue); + } + if (oneofValueCase_ == OneofValueOneofCase.IntHexadecimalValue) { + output.WriteRawTag(56); + output.WriteUInt32(IntHexadecimalValue); + } + if (oneofValueCase_ == OneofValueOneofCase.BooleanValue) { + output.WriteRawTag(64); + output.WriteBool(BooleanValue); + } + if (oneofValueCase_ == OneofValueOneofCase.ColorArgb8Value) { + output.WriteRawTag(72); + output.WriteUInt32(ColorArgb8Value); + } + if (oneofValueCase_ == OneofValueOneofCase.ColorRgb8Value) { + output.WriteRawTag(80); + output.WriteUInt32(ColorRgb8Value); + } + if (oneofValueCase_ == OneofValueOneofCase.ColorArgb4Value) { + output.WriteRawTag(88); + output.WriteUInt32(ColorArgb4Value); + } + if (oneofValueCase_ == OneofValueOneofCase.ColorRgb4Value) { + output.WriteRawTag(96); + output.WriteUInt32(ColorRgb4Value); + } + if (oneofValueCase_ == OneofValueOneofCase.DimensionValue) { + output.WriteRawTag(104); + output.WriteUInt32(DimensionValue); + } + if (oneofValueCase_ == OneofValueOneofCase.FractionValue) { + output.WriteRawTag(112); + output.WriteUInt32(FractionValue); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (oneofValueCase_ == OneofValueOneofCase.NullValue) { + output.WriteRawTag(10); + output.WriteMessage(NullValue); + } + if (oneofValueCase_ == OneofValueOneofCase.EmptyValue) { + output.WriteRawTag(18); + output.WriteMessage(EmptyValue); + } + if (oneofValueCase_ == OneofValueOneofCase.FloatValue) { + output.WriteRawTag(29); + output.WriteFloat(FloatValue); + } + if (oneofValueCase_ == OneofValueOneofCase.DimensionValueDeprecated) { + output.WriteRawTag(37); + output.WriteFloat(DimensionValueDeprecated); + } + if (oneofValueCase_ == OneofValueOneofCase.FractionValueDeprecated) { + output.WriteRawTag(45); + output.WriteFloat(FractionValueDeprecated); + } + if (oneofValueCase_ == OneofValueOneofCase.IntDecimalValue) { + output.WriteRawTag(48); + output.WriteInt32(IntDecimalValue); + } + if (oneofValueCase_ == OneofValueOneofCase.IntHexadecimalValue) { + output.WriteRawTag(56); + output.WriteUInt32(IntHexadecimalValue); + } + if (oneofValueCase_ == OneofValueOneofCase.BooleanValue) { + output.WriteRawTag(64); + output.WriteBool(BooleanValue); + } + if (oneofValueCase_ == OneofValueOneofCase.ColorArgb8Value) { + output.WriteRawTag(72); + output.WriteUInt32(ColorArgb8Value); + } + if (oneofValueCase_ == OneofValueOneofCase.ColorRgb8Value) { + output.WriteRawTag(80); + output.WriteUInt32(ColorRgb8Value); + } + if (oneofValueCase_ == OneofValueOneofCase.ColorArgb4Value) { + output.WriteRawTag(88); + output.WriteUInt32(ColorArgb4Value); + } + if (oneofValueCase_ == OneofValueOneofCase.ColorRgb4Value) { + output.WriteRawTag(96); + output.WriteUInt32(ColorRgb4Value); + } + if (oneofValueCase_ == OneofValueOneofCase.DimensionValue) { + output.WriteRawTag(104); + output.WriteUInt32(DimensionValue); + } + if (oneofValueCase_ == OneofValueOneofCase.FractionValue) { + output.WriteRawTag(112); + output.WriteUInt32(FractionValue); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (oneofValueCase_ == OneofValueOneofCase.NullValue) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(NullValue); + } + if (oneofValueCase_ == OneofValueOneofCase.EmptyValue) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(EmptyValue); + } + if (oneofValueCase_ == OneofValueOneofCase.FloatValue) { + size += 1 + 4; + } + if (oneofValueCase_ == OneofValueOneofCase.DimensionValue) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(DimensionValue); + } + if (oneofValueCase_ == OneofValueOneofCase.FractionValue) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(FractionValue); + } + if (oneofValueCase_ == OneofValueOneofCase.IntDecimalValue) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntDecimalValue); + } + if (oneofValueCase_ == OneofValueOneofCase.IntHexadecimalValue) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(IntHexadecimalValue); + } + if (oneofValueCase_ == OneofValueOneofCase.BooleanValue) { + size += 1 + 1; + } + if (oneofValueCase_ == OneofValueOneofCase.ColorArgb8Value) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(ColorArgb8Value); + } + if (oneofValueCase_ == OneofValueOneofCase.ColorRgb8Value) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(ColorRgb8Value); + } + if (oneofValueCase_ == OneofValueOneofCase.ColorArgb4Value) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(ColorArgb4Value); + } + if (oneofValueCase_ == OneofValueOneofCase.ColorRgb4Value) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(ColorRgb4Value); + } + if (oneofValueCase_ == OneofValueOneofCase.DimensionValueDeprecated) { + size += 1 + 4; + } + if (oneofValueCase_ == OneofValueOneofCase.FractionValueDeprecated) { + size += 1 + 4; + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Primitive other) { + if (other == null) { + return; + } + switch (other.OneofValueCase) { + case OneofValueOneofCase.NullValue: + if (NullValue == null) { + NullValue = new global::Aapt.Pb.Primitive.Types.NullType(); + } + NullValue.MergeFrom(other.NullValue); + break; + case OneofValueOneofCase.EmptyValue: + if (EmptyValue == null) { + EmptyValue = new global::Aapt.Pb.Primitive.Types.EmptyType(); + } + EmptyValue.MergeFrom(other.EmptyValue); + break; + case OneofValueOneofCase.FloatValue: + FloatValue = other.FloatValue; + break; + case OneofValueOneofCase.DimensionValue: + DimensionValue = other.DimensionValue; + break; + case OneofValueOneofCase.FractionValue: + FractionValue = other.FractionValue; + break; + case OneofValueOneofCase.IntDecimalValue: + IntDecimalValue = other.IntDecimalValue; + break; + case OneofValueOneofCase.IntHexadecimalValue: + IntHexadecimalValue = other.IntHexadecimalValue; + break; + case OneofValueOneofCase.BooleanValue: + BooleanValue = other.BooleanValue; + break; + case OneofValueOneofCase.ColorArgb8Value: + ColorArgb8Value = other.ColorArgb8Value; + break; + case OneofValueOneofCase.ColorRgb8Value: + ColorRgb8Value = other.ColorRgb8Value; + break; + case OneofValueOneofCase.ColorArgb4Value: + ColorArgb4Value = other.ColorArgb4Value; + break; + case OneofValueOneofCase.ColorRgb4Value: + ColorRgb4Value = other.ColorRgb4Value; + break; + case OneofValueOneofCase.DimensionValueDeprecated: + DimensionValueDeprecated = other.DimensionValueDeprecated; + break; + case OneofValueOneofCase.FractionValueDeprecated: + FractionValueDeprecated = other.FractionValueDeprecated; + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + global::Aapt.Pb.Primitive.Types.NullType subBuilder = new global::Aapt.Pb.Primitive.Types.NullType(); + if (oneofValueCase_ == OneofValueOneofCase.NullValue) { + subBuilder.MergeFrom(NullValue); + } + input.ReadMessage(subBuilder); + NullValue = subBuilder; + break; + } + case 18: { + global::Aapt.Pb.Primitive.Types.EmptyType subBuilder = new global::Aapt.Pb.Primitive.Types.EmptyType(); + if (oneofValueCase_ == OneofValueOneofCase.EmptyValue) { + subBuilder.MergeFrom(EmptyValue); + } + input.ReadMessage(subBuilder); + EmptyValue = subBuilder; + break; + } + case 29: { + FloatValue = input.ReadFloat(); + break; + } + case 37: { + DimensionValueDeprecated = input.ReadFloat(); + break; + } + case 45: { + FractionValueDeprecated = input.ReadFloat(); + break; + } + case 48: { + IntDecimalValue = input.ReadInt32(); + break; + } + case 56: { + IntHexadecimalValue = input.ReadUInt32(); + break; + } + case 64: { + BooleanValue = input.ReadBool(); + break; + } + case 72: { + ColorArgb8Value = input.ReadUInt32(); + break; + } + case 80: { + ColorRgb8Value = input.ReadUInt32(); + break; + } + case 88: { + ColorArgb4Value = input.ReadUInt32(); + break; + } + case 96: { + ColorRgb4Value = input.ReadUInt32(); + break; + } + case 104: { + DimensionValue = input.ReadUInt32(); + break; + } + case 112: { + FractionValue = input.ReadUInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + global::Aapt.Pb.Primitive.Types.NullType subBuilder = new global::Aapt.Pb.Primitive.Types.NullType(); + if (oneofValueCase_ == OneofValueOneofCase.NullValue) { + subBuilder.MergeFrom(NullValue); + } + input.ReadMessage(subBuilder); + NullValue = subBuilder; + break; + } + case 18: { + global::Aapt.Pb.Primitive.Types.EmptyType subBuilder = new global::Aapt.Pb.Primitive.Types.EmptyType(); + if (oneofValueCase_ == OneofValueOneofCase.EmptyValue) { + subBuilder.MergeFrom(EmptyValue); + } + input.ReadMessage(subBuilder); + EmptyValue = subBuilder; + break; + } + case 29: { + FloatValue = input.ReadFloat(); + break; + } + case 37: { + DimensionValueDeprecated = input.ReadFloat(); + break; + } + case 45: { + FractionValueDeprecated = input.ReadFloat(); + break; + } + case 48: { + IntDecimalValue = input.ReadInt32(); + break; + } + case 56: { + IntHexadecimalValue = input.ReadUInt32(); + break; + } + case 64: { + BooleanValue = input.ReadBool(); + break; + } + case 72: { + ColorArgb8Value = input.ReadUInt32(); + break; + } + case 80: { + ColorRgb8Value = input.ReadUInt32(); + break; + } + case 88: { + ColorArgb4Value = input.ReadUInt32(); + break; + } + case 96: { + ColorRgb4Value = input.ReadUInt32(); + break; + } + case 104: { + DimensionValue = input.ReadUInt32(); + break; + } + case 112: { + FractionValue = input.ReadUInt32(); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the Primitive message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static partial class Types { + public sealed partial class NullType : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NullType()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.Primitive.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public NullType() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public NullType(NullType other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public NullType Clone() { + return new NullType(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as NullType); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(NullType other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(NullType other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + } + } + } + #endif + + } + + public sealed partial class EmptyType : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new EmptyType()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.Primitive.Descriptor.NestedTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public EmptyType() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public EmptyType(EmptyType other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public EmptyType Clone() { + return new EmptyType(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as EmptyType); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(EmptyType other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(EmptyType other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + } + } + } + #endif + + } + + } + #endregion + + } + + /// + /// A value that represents an XML attribute and what values it accepts. + /// + public sealed partial class Attribute : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Attribute()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.ResourcesReflection.Descriptor.MessageTypes[29]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Attribute() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Attribute(Attribute other) : this() { + formatFlags_ = other.formatFlags_; + minInt_ = other.minInt_; + maxInt_ = other.maxInt_; + symbol_ = other.symbol_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Attribute Clone() { + return new Attribute(this); + } + + /// Field number for the "format_flags" field. + public const int FormatFlagsFieldNumber = 1; + private uint formatFlags_; + /// + /// A bitmask of types that this XML attribute accepts. Corresponds to the flags in the + /// enum FormatFlags. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint FormatFlags { + get { return formatFlags_; } + set { + formatFlags_ = value; + } + } + + /// Field number for the "min_int" field. + public const int MinIntFieldNumber = 2; + private int minInt_; + /// + /// The smallest integer allowed for this XML attribute. Only makes sense if the format includes + /// FormatFlags::INTEGER. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int MinInt { + get { return minInt_; } + set { + minInt_ = value; + } + } + + /// Field number for the "max_int" field. + public const int MaxIntFieldNumber = 3; + private int maxInt_; + /// + /// The largest integer allowed for this XML attribute. Only makes sense if the format includes + /// FormatFlags::INTEGER. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int MaxInt { + get { return maxInt_; } + set { + maxInt_ = value; + } + } + + /// Field number for the "symbol" field. + public const int SymbolFieldNumber = 4; + private static readonly pb::FieldCodec _repeated_symbol_codec + = pb::FieldCodec.ForMessage(34, global::Aapt.Pb.Attribute.Types.Symbol.Parser); + private readonly pbc::RepeatedField symbol_ = new pbc::RepeatedField(); + /// + /// The set of enums/flags defined in this attribute. Only makes sense if the format includes + /// either FormatFlags::ENUM or FormatFlags::FLAGS. Having both is an error. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField Symbol { + get { return symbol_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Attribute); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Attribute other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (FormatFlags != other.FormatFlags) return false; + if (MinInt != other.MinInt) return false; + if (MaxInt != other.MaxInt) return false; + if(!symbol_.Equals(other.symbol_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (FormatFlags != 0) hash ^= FormatFlags.GetHashCode(); + if (MinInt != 0) hash ^= MinInt.GetHashCode(); + if (MaxInt != 0) hash ^= MaxInt.GetHashCode(); + hash ^= symbol_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (FormatFlags != 0) { + output.WriteRawTag(8); + output.WriteUInt32(FormatFlags); + } + if (MinInt != 0) { + output.WriteRawTag(16); + output.WriteInt32(MinInt); + } + if (MaxInt != 0) { + output.WriteRawTag(24); + output.WriteInt32(MaxInt); + } + symbol_.WriteTo(output, _repeated_symbol_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (FormatFlags != 0) { + output.WriteRawTag(8); + output.WriteUInt32(FormatFlags); + } + if (MinInt != 0) { + output.WriteRawTag(16); + output.WriteInt32(MinInt); + } + if (MaxInt != 0) { + output.WriteRawTag(24); + output.WriteInt32(MaxInt); + } + symbol_.WriteTo(ref output, _repeated_symbol_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (FormatFlags != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(FormatFlags); + } + if (MinInt != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(MinInt); + } + if (MaxInt != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(MaxInt); + } + size += symbol_.CalculateSize(_repeated_symbol_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Attribute other) { + if (other == null) { + return; + } + if (other.FormatFlags != 0) { + FormatFlags = other.FormatFlags; + } + if (other.MinInt != 0) { + MinInt = other.MinInt; + } + if (other.MaxInt != 0) { + MaxInt = other.MaxInt; + } + symbol_.Add(other.symbol_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + FormatFlags = input.ReadUInt32(); + break; + } + case 16: { + MinInt = input.ReadInt32(); + break; + } + case 24: { + MaxInt = input.ReadInt32(); + break; + } + case 34: { + symbol_.AddEntriesFrom(input, _repeated_symbol_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + FormatFlags = input.ReadUInt32(); + break; + } + case 16: { + MinInt = input.ReadInt32(); + break; + } + case 24: { + MaxInt = input.ReadInt32(); + break; + } + case 34: { + symbol_.AddEntriesFrom(ref input, _repeated_symbol_codec); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the Attribute message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static partial class Types { + /// + /// Bitmask of formats allowed for an attribute. + /// + public enum FormatFlags { + /// + /// Proto3 requires a default of 0. + /// + [pbr::OriginalName("NONE")] None = 0, + /// + /// Allows any type except ENUM and FLAGS. + /// + [pbr::OriginalName("ANY")] Any = 65535, + /// + /// Allows Reference values. + /// + [pbr::OriginalName("REFERENCE")] Reference = 1, + /// + /// Allows String/StyledString values. + /// + [pbr::OriginalName("STRING")] String = 2, + /// + /// Allows any integer BinaryPrimitive values. + /// + [pbr::OriginalName("INTEGER")] Integer = 4, + /// + /// Allows any boolean BinaryPrimitive values. + /// + [pbr::OriginalName("BOOLEAN")] Boolean = 8, + /// + /// Allows any color BinaryPrimitive values. + /// + [pbr::OriginalName("COLOR")] Color = 16, + /// + /// Allows any float BinaryPrimitive values. + /// + [pbr::OriginalName("FLOAT")] Float = 32, + /// + /// Allows any dimension BinaryPrimitive values. + /// + [pbr::OriginalName("DIMENSION")] Dimension = 64, + /// + /// Allows any fraction BinaryPrimitive values. + /// + [pbr::OriginalName("FRACTION")] Fraction = 128, + /// + /// Allows enums that are defined in the Attribute's symbols. + /// + [pbr::OriginalName("ENUM")] Enum = 65536, + /// + /// ENUM and FLAGS cannot BOTH be set. + /// + [pbr::OriginalName("FLAGS")] Flags = 131072, + } + + /// + /// A Symbol used to represent an enum or a flag. + /// + public sealed partial class Symbol : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Symbol()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Aapt.Pb.Attribute.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Symbol() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Symbol(Symbol other) : this() { + source_ = other.source_ != null ? other.source_.Clone() : null; + comment_ = other.comment_; + name_ = other.name_ != null ? other.name_.Clone() : null; + value_ = other.value_; + type_ = other.type_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Symbol Clone() { + return new Symbol(this); + } + + /// Field number for the "source" field. + public const int SourceFieldNumber = 1; + private global::Aapt.Pb.Source source_; + /// + /// Where the enum/flag item was defined. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Source Source { + get { return source_; } + set { + source_ = value; + } + } + + /// Field number for the "comment" field. + public const int CommentFieldNumber = 2; + private string comment_ = ""; + /// + /// Any comments associated with the enum or flag. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Comment { + get { return comment_; } + set { + comment_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "name" field. + public const int NameFieldNumber = 3; + private global::Aapt.Pb.Reference name_; + /// + /// The name of the enum/flag as a reference. Enums/flag items are generated as ID resource + /// values. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Aapt.Pb.Reference Name { + get { return name_; } + set { + name_ = value; + } + } + + /// Field number for the "value" field. + public const int ValueFieldNumber = 4; + private uint value_; + /// + /// The value of the enum/flag. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint Value { + get { return value_; } + set { + value_ = value; + } + } + + /// Field number for the "type" field. + public const int TypeFieldNumber = 5; + private uint type_; + /// + /// The data type of the enum/flag as defined in android::Res_value. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public uint Type { + get { return type_; } + set { + type_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Symbol); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Symbol other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Source, other.Source)) return false; + if (Comment != other.Comment) return false; + if (!object.Equals(Name, other.Name)) return false; + if (Value != other.Value) return false; + if (Type != other.Type) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (source_ != null) hash ^= Source.GetHashCode(); + if (Comment.Length != 0) hash ^= Comment.GetHashCode(); + if (name_ != null) hash ^= Name.GetHashCode(); + if (Value != 0) hash ^= Value.GetHashCode(); + if (Type != 0) hash ^= Type.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (source_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Source); + } + if (Comment.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Comment); + } + if (name_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Name); + } + if (Value != 0) { + output.WriteRawTag(32); + output.WriteUInt32(Value); + } + if (Type != 0) { + output.WriteRawTag(40); + output.WriteUInt32(Type); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (source_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Source); + } + if (Comment.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Comment); + } + if (name_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Name); + } + if (Value != 0) { + output.WriteRawTag(32); + output.WriteUInt32(Value); + } + if (Type != 0) { + output.WriteRawTag(40); + output.WriteUInt32(Type); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (source_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Source); + } + if (Comment.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Comment); + } + if (name_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Name); + } + if (Value != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Value); + } + if (Type != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Type); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Symbol other) { + if (other == null) { + return; + } + if (other.source_ != null) { + if (source_ == null) { + Source = new global::Aapt.Pb.Source(); + } + Source.MergeFrom(other.Source); + } + if (other.Comment.Length != 0) { + Comment = other.Comment; + } + if (other.name_ != null) { + if (name_ == null) { + Name = new global::Aapt.Pb.Reference(); + } + Name.MergeFrom(other.Name); + } + if (other.Value != 0) { + Value = other.Value; + } + if (other.Type != 0) { + Type = other.Type; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (source_ == null) { + Source = new global::Aapt.Pb.Source(); + } + input.ReadMessage(Source); + break; + } + case 18: { + Comment = input.ReadString(); + break; + } + case 26: { + if (name_ == null) { + Name = new global::Aapt.Pb.Reference(); + } + input.ReadMessage(Name); + break; + } + case 32: { + Value = input.ReadUInt32(); + break; + } + case 40: { + Type = input.ReadUInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (source_ == null) { + Source = new global::Aapt.Pb.Source(); + } + input.ReadMessage(Source); + break; + } + case 18: { + Comment = input.ReadString(); + break; + } + case 26: { + if (name_ == null) { + Name = new global::Aapt.Pb.Reference(); + } + input.ReadMessage(Name); + break; + } + case 32: { + Value = input.ReadUInt32(); + break; + } + case 40: { + Type = input.ReadUInt32(); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + /// + /// A value that represents a style. + /// + public sealed partial class Style : pb::IMessage