private void LoadTable() { if (table != null) return; var raw = Load(); table = new Table(new MemoryStream(raw)); }
public void LoadTableTestFull() { var resources = new Table(new MemoryStream(TestResource.android_jar_resources)); var index = resources.Strings.IndexOf("name", -1); var pkg = resources.Packages[0]; var index2 = pkg.KeyStrings.IndexOf("name", -1); }
/// <summary> /// Default ctor /// </summary> public TableEntryNode(int entryIndex, Table.TypeSpec typeSpec, Table.Entry entry) { this.entryIndex = entryIndex; this.typeSpec = typeSpec; this.entry = entry; Text = string.Format("[{0:X4}] {1}", entryIndex, entry.Key); }
/// <summary> /// Creation ctor /// </summary> internal Package(Table table, int id, string name) : base(ChunkTypes.RES_TABLE_PACKAGE_TYPE) { this.table = table; this.id = id; this.name = name; keyStrings = new StringPool(); typeStrings = new StringPool(); }
/// <summary> /// Default ctor /// </summary> internal DescriptorProviderSet(AttrsXmlParser parser, LayoutXmlParser layoutParser, Table resources) { this.parser = parser; this.layoutParser = layoutParser; if (resources != null) { var pkg = resources.Packages.FirstOrDefault(); var typeSpec = (pkg != null) ? pkg.TypeSpecs.FirstOrDefault(x => x.Name == "attr") : null; parser.AttrTypeSpec = typeSpec; } }
/// <summary> /// Default ctor /// </summary> public AssemblyCompiler(CompilationMode mode, List<AssemblyDefinition> assemblies, List<AssemblyDefinition> references, Table resources, NameConverter nameConverter, bool generateDebugInfo, AssemblyClassLoader assemblyClassLoader, HashSet<string> rootClassNames, XModule module) { this.mode = mode; this.assemblies = assemblies; this.references = references; this.resources = resources; this.generateDebugInfo = generateDebugInfo; this.assemblyClassLoader = assemblyClassLoader; this.rootClassNames = rootClassNames; this.module = module; targetPackage = new Target.Dex.DexTargetPackage(nameConverter, this); }
/// <summary> /// Default ctor /// </summary> internal Package(Table table, ResReader reader) : base(reader, ChunkTypes.RES_TABLE_PACKAGE_TYPE) { this.table = table; id = reader.ReadInt32(); name = reader.ReadFixedLenghtUnicodeString(128); var typeStringsOffset = reader.ReadInt32(); var lastPublicType = reader.ReadInt32(); var keyStringsOffset = reader.ReadInt32(); var lastPublicKey = reader.ReadInt32(); // Record offset var dataOffset = reader.Position; // Data typeStrings = new StringPool(reader); keyStrings = new StringPool(reader); TypeSpec currentTypeSpec = null; while (reader.Position - dataOffset < DataSize) { var chunkType = reader.PeekChunkType(); if (chunkType == ChunkTypes.RES_TABLE_TYPE_SPEC_TYPE) { currentTypeSpec = Read(reader, () => new TypeSpec(this, reader)); typeSpecs.Add(currentTypeSpec); } else if (chunkType == ChunkTypes.RES_TABLE_TYPE_TYPE) { if (currentTypeSpec == null) { throw new IOException("Invalid chunk sequence: content read before typeSpec."); } var parent = currentTypeSpec; var type = Read(reader, () => new Type(parent, reader)); currentTypeSpec.Add(type); } else { throw new IOException("Unexpected chunk type (" + chunkType + ")."); } } }
/// <summary> /// TODO: the list of parameters has gotten way to long. /// </summary> public AssemblyCompiler(CompilationMode mode, List<AssemblyDefinition> assemblies, List<AssemblyDefinition> references, Table resources, NameConverter nameConverter, bool generateDebugInfo, AssemblyClassLoader assemblyClassLoader, Func<AssemblyDefinition, string> assemblyToFilename, DexMethodBodyCompilerCache ccache, HashSet<string> rootClassNames, XModule module, bool generateSetNextInstructionCode) { this.mode = mode; this.assemblies = assemblies; this.references = references; this.resources = resources; this.generateDebugInfo = generateDebugInfo; this.assemblyClassLoader = assemblyClassLoader; this.assemblyToFilename = assemblyToFilename; this.rootClassNames = rootClassNames; this.module = module; this.generateSetNextInstructionCode = generateDebugInfo && generateSetNextInstructionCode; targetPackage = new Target.Dex.DexTargetPackage(nameConverter, this); methodBodyCompilerCache = ccache; StopAtFirstError = true; }
/// <summary> /// Default ctor /// </summary> public ResourceIdMap(Table frameworkResources, XmlTree manifest) { var package = frameworkResources.Packages.First(); var resourceNames = package.KeyStrings; for (var i = 0; i < resourceNames.Count; i++) { var name = XName.Get(resourceNames[i], AndroidSchema); idMap.Add(name, new Entry(MakeId(0, 0, i))); } // Find attribute types manifest.VisitAttributes(a => { Entry entry; if (idMap.TryGetValue(a.XName, out entry)) { entry.ValueType = a.TypedValue.Type; } }); }
/// <summary> /// Default ctor /// </summary> public CreateResourceIdsCode(Table resourceTable, List<Tuple<string, ResourceType>> resources, List<StyleableDeclaration> styleableDeclarations) { this.resourceTable = resourceTable; this.resources = resources; this.styleableDeclarations = styleableDeclarations; }
private static string CreateTypeSpecName(Table.TypeSpec typeSpec) { var name = Utility.NameConverter.UpperCamelCase(typeSpec.Name); //if (!name.EndsWith("s")) // name += "s"; return name; }
/// <summary> /// Lookup the value of a resource id with given name. /// </summary> private static int FindResourceId(Table resourceTable, string name) { foreach (var typeSpec in resourceTable.Packages[0].TypeSpecs) { if (typeSpec.EntryCount == 0) continue; var index = 0; foreach (var entry in typeSpec.Entries) { if (entry.Key == name) { var resId = 0x7F000000 | ((typeSpec.Id) << 16) | index; return resId; } index++; } } throw new ArgumentException(string.Format("Unknown resource name '{0}'", name)); }
/// <summary> /// Compile an assembly into a dex file. /// </summary> private static void CompileAssembly(CommandLineOptions options, NameConverter nsConverter) { // Load resource type usage info file var usedTypeNames = LoadResourceTypeUsageInformation(options); // Load assemblies List<AssemblyDefinition> assemblies = new List<AssemblyDefinition>(); List<AssemblyDefinition> references= new List<AssemblyDefinition>(); var dxJarCompiler = options.EnableDxJarCompilation ? new DxClassfileMethodBodyCompiler(options.OutputFolder, options.DebugInfo) : null; Action<ClassSource> jarLoaded = dxJarCompiler != null ? dxJarCompiler.PreloadJar : (Action<ClassSource>)null; var module = new XModule(); var classLoader = new AssemblyClassLoader(module.OnClassLoaded); var resolver = new AssemblyResolver(options.ReferenceFolders, classLoader, module.OnAssemblyLoaded); // initialize compiler cache in background. var ccache = options.EnableCompilerCache ? new DexMethodBodyCompilerCache(options.OutputFolder, resolver.GetFileName) : new DexMethodBodyCompilerCache(); var readerParameters = new ReaderParameters { AssemblyResolver = resolver, SymbolReaderProvider = new SafeSymbolReaderProvider(), ReadSymbols = true, ReadingMode = ReadingMode.Immediate }; // load assemblies var toLoad = options.Assemblies.Select(path => new {path, target = assemblies}) .Concat(options.References.Select(path => new {path, target = references})) // Some micro optimizations... // Our startup is IO bound until we have loaded first assembly from disk. // So just load from smallest to largest. .Select(load => new { load.path, load.target, length = new FileInfo(resolver.ResolvePath(load.path)).Length}) .OrderBy(load=>load.length) .ToList(); using (AssemblyCompiler.Profile("for loading assemblies")) { toLoad.AsParallel().ForAll( //toLoad.ForEach( load => { var assm = resolver.Load(load.path, readerParameters); lock (load.target) load.target.Add(assm); }); } // Load resources Table table; using (var stream = new FileStream(options.InputResources, FileMode.Open, FileAccess.Read)) { table = new Table(stream); } // Create compiler var compiler = new AssemblyCompiler(options.CompilationMode, assemblies, references, table, nsConverter, options.DebugInfo, classLoader, resolver.GetFileName, ccache, usedTypeNames, module, options.GenerateSetNextInstructionCode); compiler.DxClassfileMethodBodyCompiler = dxJarCompiler; using (AssemblyCompiler.Profile("total compilation time", true)) compiler.Compile(); ccache.PrintStatistics(); using (AssemblyCompiler.Profile("saving results")) compiler.Save(options.OutputFolder, options.FreeAppsKeyPath); }
/// <summary> /// Compile the given resources into a suitable output folder. /// </summary> internal bool Compile(List<Tuple<string, ResourceType>> resources, List<string> appWidgetProviderCodeFiles, List<string> references, List<string> referenceFolders, string baseApkPath) { // Remove temp folder if (Directory.Exists(tempFolder)) { Directory.Delete(tempFolder, true); } // Ensure temp\res folder exists var resFolder = Path.Combine(tempFolder, "res"); Directory.CreateDirectory(resFolder); var tempApkPath = Path.Combine(tempFolder, "temp.apk"); // Compile each resource foreach (var resource in resources.Where(x => x.Item2 != ResourceType.Manifest)) { CopyResourceToFolder(tempFolder, resource.Item1, resource.Item2); } // Extract resources out of library project references var resolver = new AssemblyResolver(referenceFolders, null, null); foreach (var path in references) { ExtractLibraryProjectResources(resFolder, path, resolver); } // Select manifest path var manifestPath = resources.Where(x => x.Item2 == ResourceType.Manifest).Select(x => x.Item1).FirstOrDefault(); // Ensure files exists for the appwidgetproviders CreateAppWidgetProviderFiles(tempFolder, manifestPath, appWidgetProviderCodeFiles); // Create system ID's resource CreateSystemIdsResource(tempFolder); // Run aapt var args = new[] { "p", "-f", "-S", resFolder, "-M", GetManifestPath(tempFolder, manifestPath, packageName), "-I", baseApkPath, "-F", tempApkPath }; var runner = new ProcessRunner(Locations.Aapt, args); var exitCode = runner.Run(); if (exitCode != 0) { ProcessAaptErrors(runner.Output, tempFolder, resources); return false; } // Unpack compiled resources to base folder. Table resourceTable = null; using (var apk = new ApkFile(tempApkPath)) { foreach (var name in apk.FileNames) { // Extract var data = apk.Load(name); // Save var path = Path.Combine(baseFolder, name); Directory.CreateDirectory(Path.GetDirectoryName(path)); File.WriteAllBytes(path, data); // Is resource table? yes -> load it if (name == "resources.arsc") { resourceTable = new Table(new MemoryStream(data)); } } } // Create R.cs if (!string.IsNullOrEmpty(generatedCodeFolder)) { var codeBuilder = new CreateResourceIdsCode(resourceTable, resources, valuesResourceProcessor.StyleableDeclarations); codeBuilder.Generate(generatedCodeFolder, packageName, generatedCodeNamespace, generatedCodeLanguage, lastModified); } // Create resource type usage info file if (!string.IsNullOrEmpty(resourceTypeUsageInformationPath)) { // Ensure folder exists var folder = Path.GetDirectoryName(resourceTypeUsageInformationPath); if (!Directory.Exists(folder)) Directory.CreateDirectory(folder); // Create file File.WriteAllLines(resourceTypeUsageInformationPath, layoutProcessor.CustomClassNames); } return true; }
/// <summary> /// Compile an assembly into a dex file. /// </summary> private static void CompileAssembly(CommandLineOptions options, NameConverter nsConverter) { // Load resource type usage info file var usedTypeNames = LoadResourceTypeUsageInformation(options); // Load assemblies var assemblies = new List<AssemblyDefinition>(); var module = new XModule(); var classLoader = new AssemblyClassLoader(module.OnClassLoaded); var resolver = new AssemblyResolver(options.ReferenceFolders, classLoader, module.OnAssemblyLoaded); var readerParameters = new ReaderParameters(ReadingMode.Immediate) { AssemblyResolver = resolver, SymbolReaderProvider = new SafeSymbolReaderProvider(), ReadSymbols = true }; foreach (var asmPath in options.Assemblies) { var asm = resolver.Load(asmPath, readerParameters); module.OnAssemblyLoaded(asm); classLoader.LoadAssembly(asm); assemblies.Add(asm); } // Load references var references = new List<AssemblyDefinition>(); foreach (var refPath in options.References) { var asm = resolver.Load(refPath, readerParameters); module.OnAssemblyLoaded(asm); classLoader.LoadAssembly(asm); references.Add(asm); } // Load resources Table table; using (var stream = new FileStream(options.InputResources, FileMode.Open, FileAccess.Read)) { table = new Table(stream); } // Create compiler var compiler = new AssemblyCompiler(options.CompilationMode, assemblies, references, table, nsConverter, options.DebugInfo, classLoader, usedTypeNames, module); compiler.Compile(); compiler.Save(options.OutputFolder, options.FreeAppsKeyPath); }
/// <summary> /// Default ctor /// </summary> public TableEntryInstanceNode(Table.Type type, Table.EntryInstance instance) { this.type = type; this.instance = instance; Text = type.Configuration.ToString(); }
/// <summary> /// Default ctor /// </summary> public TableTypeSpecNode(Table.TypeSpec typeSpec) { spec = typeSpec; Text = typeSpec.Name; }
public void LoadTableTest() { var arsc = new Table(new MemoryStream(TestResource.resources)); }