public static void Main(string [] args) { var(path1, path2) = ProcessArguments(args); var desc1 = ApkDescription.Load(path1, SaveDescription1); if (path2 != null) { var desc2 = ApkDescription.Load(path2, SaveDescription2); desc1.Compare(desc2, entriesPattern, Flat); if (ApkRegressionThreshold != 0) { if ((desc2.PackageSize - desc1.PackageSize) > ApkRegressionThreshold) { Error($"PackageSize increase {desc2.PackageSize - desc1.PackageSize:#,0} is {desc2.PackageSize - desc1.PackageSize - ApkRegressionThreshold:#,0} bytes more than the threshold {ApkRegressionThreshold:#,0}. apk1 size: {desc1.PackageSize:#,0} bytes, apk2 size: {desc2.PackageSize:#,0} bytes."); RegressionCount++; } else if (DecreaseIsRegression && (desc1.PackageSize - desc2.PackageSize) > ApkRegressionThreshold) { Error($"PackageSize decrease {desc1.PackageSize - desc2.PackageSize:#,0} is {desc1.PackageSize - desc2.PackageSize - ApkRegressionThreshold:#,0} bytes more than the threshold {ApkRegressionThreshold:#,0}. apk1 size: {desc1.PackageSize:#,0} bytes, apk2 size: {desc2.PackageSize:#,0} bytes."); RegressionCount++; } } } if (RegressionCount > 0) { Error($"Size regression occured, {RegressionCount:#,0} check(s) failed."); Environment.Exit(3); } }
public static ApkDescription Load(string path) { if (!File.Exists(path)) { Program.Error($"File '{path}' does not exist."); Environment.Exit(2); } var extension = Path.GetExtension(path); switch (extension.ToLower()) { case ".apk": case ".aab": var nd = new ApkDescription(); nd.LoadApk(path); return(nd); case ".apkdesc": case ".aabdesc": return(LoadDescription(path)); default: Program.Error($"Unknown file extension '{extension}'"); Environment.Exit(3); return(null); } }
public static void Main(string [] args) { var(path1, path2) = ProcessArguments(args); var desc1 = ApkDescription.Load(path1); if (path2 != null) { var desc2 = ApkDescription.Load(path2); desc1.Compare(desc2); } }
public void Compare(ApkDescription other) { var keys = Entries.Keys.Union(other.Entries.Keys); var differences = new Dictionary <string, long> (); var singles = new HashSet <string> (); Program.ColorWriteLine("Size difference in bytes ([*1] apk1 only, [*2] apk2 only):", ConsoleColor.Yellow); foreach (var key in Entries.Keys) { if (other.Entries.ContainsKey(key)) { differences [key] = other.Entries [key].Size - Entries [key].Size; } else { differences [key] = -Entries [key].Size; singles.Add(key); } } foreach (var key in other.Entries.Keys) { if (Entries.ContainsKey(key)) { continue; } differences [key] = other.Entries [key].Size; singles.Add(key); } foreach (var diff in differences.OrderByDescending(v => v.Value)) { if (diff.Value == 0) { continue; } PrintDifference(diff.Key, diff.Value, singles.Contains(diff.Key) ? $" *{(diff.Value > 0 ? 2 : 1)}" : null); } Program.ColorWriteLine("Summary:", ConsoleColor.Green); if (Program.Verbose) { Program.ColorWriteLine($" apk1: {PackageSize,12} {PackagePath}\n apk2: {other.PackageSize,12} {other.PackagePath}", ConsoleColor.Gray); } PrintDifference("Package size difference", other.PackageSize - PackageSize); }
void CompareSymbols(string file, string other, string padding) { var sym1 = ParseNMOutput(RunNMCmd(file)); var sym2 = ParseNMOutput(RunNMCmd(other)); Program.ColorWriteLine($"{padding} Symbol size difference", ConsoleColor.Yellow); var differences = new Dictionary <string, long> (); var singles = new HashSet <string> (); foreach (var entry in sym1) { var key = entry.Key; if (sym2.ContainsKey(key)) { var otherEntry = sym2 [key]; differences [key] = otherEntry.Size - sym1 [key].Size; } else { differences [key] = -sym1 [key].Size; singles.Add(key); } } foreach (var key in sym2.Keys) { if (sym1.ContainsKey(key)) { continue; } differences [key] = sym2 [key].Size; singles.Add(key); } foreach (var diff in differences.OrderByDescending(v => v.Value)) { if (diff.Value == 0) { continue; } var single = singles.Contains(diff.Key); ApkDescription.PrintDifference(diff.Key, diff.Value, single ? $" *{(diff.Value > 0 ? 2 : 1)}" : null, padding); } }
public override void Compare(string file, string other, string padding) { using (var dex1 = new DexFile(file, padding)) { using (var dex2 = new DexFile(other, padding)) { if (dex1.linkSize != dex2.linkSize) { ApkDescription.PrintDifference("link section size", dex2.linkSize - dex1.linkSize, "", padding); } if (dex1.stringIdsSize != dex2.stringIdsSize) { ApkDescription.PrintDifference("strings count", dex2.stringIdsSize - dex1.stringIdsSize, "", padding); } if (dex1.typeIdsSize != dex2.typeIdsSize) { ApkDescription.PrintDifference("types count", dex2.typeIdsSize - dex1.typeIdsSize, "", padding); } if (dex1.protoIdsSize != dex2.protoIdsSize) { ApkDescription.PrintDifference("prototypes count", dex2.protoIdsSize - dex1.protoIdsSize, "", padding); } if (dex1.fieldIdsSize != dex2.fieldIdsSize) { ApkDescription.PrintDifference("fields count", dex2.fieldIdsSize - dex1.fieldIdsSize, "", padding); } if (dex1.methodIdsSize != dex2.methodIdsSize) { ApkDescription.PrintDifference("methods count", dex2.methodIdsSize - dex1.methodIdsSize, "", padding); } if (dex1.classDefsSize != dex2.classDefsSize) { ApkDescription.PrintDifference("classes count", dex2.classDefsSize - dex1.classDefsSize, "", padding); } if (dex1.dataSize != dex2.dataSize) { ApkDescription.PrintDifference("data section size", dex2.dataSize - dex1.dataSize, "", padding); } } } }