Skip to content

Commit 7e7f0ba

Browse files
[Xamarin.Android.Build.Tasks] fix signing for App Bundles with multi-dex (#4038)
Fixes: #3993 After 16.4 shipped, we started getting reports that App Bundle signing was broken. Google Play was not accepting the file: You uploaded an APK or Android App Bundle with invalid or missing signing information for some of its files. You need to create a valid signed APK or Android App Bundle. Both @pjcollins and myself tested this, but it worked for us? Finally we discovered the issue only occurred when multi-dex was enabled! I was able to reproduce the issue and do a diff of the file contents of good and bad `.aab` files. These two files were present in the broken App Bundle: +1969-12-31 18:00:00 ..... 1480 716 base\root\META-INF\MSFTSIG.SF +1969-12-31 18:00:00 ..... 8546 5469 base\root\META-INF\MSFTSIG.RSA These definitely look signing related! In c4f032a, I ported some Java code from Android Studio to C# that allowed Kotlin libraries to function. Specifically files such as: META-INF/services/kotlinx.coroutines.internal.MainDispatcherFactory META-INF/services/kotlinx.coroutines.CoroutineExceptionHandler Needed to be present in the APK. This inadvertently added files like `META-INF\MSFTSIG.SF` also! I checked the latest source I was review before from Android Studio: https://android.googlesource.com/platform/tools/base/+/refs/heads/master/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/tasks/ExtractJavaResourcesTask.java#199 https://android.googlesource.com/platform/tools/base/+/refs/heads/master/sdk-common/src/main/java/com/android/ide/common/packaging/PackagingUtils.java#24 I see nothing accounting for these files... For now I think we should ignore: * For files under `META-INF` * Ignore `.SF`, `.MF`, and `.RSA` files I updated a test to validate these changes.
1 parent d5b5419 commit 7e7f0ba

File tree

2 files changed

+27
-10
lines changed

2 files changed

+27
-10
lines changed

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/PackagingUtilsTests.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,18 @@ void AssertIsNotValid (string path)
1717
}
1818

1919
[Test]
20-
public void JarManifest ()
20+
public void SigningFiles ()
2121
{
2222
AssertIsNotValid ("META-INF/MANIFEST.MF");
23+
AssertIsNotValid ("META-INF/MANIFEST.SF");
24+
AssertIsNotValid ("META-INF/MSFTSIG.SF");
25+
AssertIsNotValid ("META-INF/MSFTSIG.RSA");
26+
AssertIsNotValid ("META-INF/GOOG.RSA");
27+
AssertIsNotValid ("META-INF\\MANIFEST.MF");
28+
AssertIsNotValid ("META-INF\\MANIFEST.SF");
29+
AssertIsNotValid ("META-INF\\MSFTSIG.SF");
30+
AssertIsNotValid ("META-INF\\MSFTSIG.RSA");
31+
AssertIsNotValid ("META-INF\\GOOG.RSA");
2332
}
2433

2534
[Test]

src/Xamarin.Android.Build.Tasks/Utilities/PackagingUtils.cs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,6 @@ namespace Xamarin.Android.Tasks
2828
/// </summary>
2929
internal class PackagingUtils
3030
{
31-
static readonly string [] InvalidEntryPaths = new []{
32-
// http://hg.openjdk.java.net/jdk8u/jdk8u-dev/jdk/file/0fc878b99541/src/share/classes/java/util/jar/JarFile.java#l91
33-
"META-INF/MANIFEST.MF",
34-
};
35-
3631
static readonly Regex pathRegex = new Regex (@"\\|\/", RegexOptions.Compiled);
3732

3833
/// <summary>
@@ -42,9 +37,6 @@ internal class PackagingUtils
4237
/// <returns>true if the entry is valid for packaging.</returns>
4338
public static bool CheckEntryForPackaging (string entryName)
4439
{
45-
if (InvalidEntryPaths.Contains (entryName))
46-
return false;
47-
4840
var segments = pathRegex.Split (entryName);
4941
for (int i = 0; i < segments.Length - 1; i++) {
5042
if (!CheckFolderForPackaging (segments [i])) {
@@ -55,7 +47,9 @@ public static bool CheckEntryForPackaging (string entryName)
5547
var fileName = segments [segments.Length - 1];
5648
if (string.IsNullOrEmpty (fileName))
5749
return false;
58-
return CheckFileForPackaging (fileName, Path.GetExtension (fileName));
50+
var extension = Path.GetExtension (fileName);
51+
return CheckSignatureFile (segments [0], extension) &&
52+
CheckFileForPackaging (fileName, extension);
5953
}
6054

6155
/// <summary>
@@ -71,6 +65,20 @@ static bool CheckFolderForPackaging (string folderName)
7165
!folderName.StartsWith ("_");
7266
}
7367

68+
/// <summary>
69+
/// Checks for signing related files such as META-INF/MANIFEST.MF or META-INF/GOOG.RSA
70+
/// </summary>
71+
/// <param name="folderName">the name of the folder.</param>
72+
/// <param name="extension">the extension of the file (including '.')</param>
73+
/// <returns></returns>
74+
static bool CheckSignatureFile (string folderName, string extension)
75+
{
76+
return folderName != "META-INF" ||
77+
!EqualsIgnoreCase (".SF", extension) &&
78+
!EqualsIgnoreCase (".MF", extension) &&
79+
!EqualsIgnoreCase (".RSA", extension);
80+
}
81+
7482
/// <summary>
7583
/// Checks a file to make sure it should be packaged as standard resources.
7684
/// </summary>

0 commit comments

Comments
 (0)