Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 48 additions & 18 deletions src/Xamarin.Android.Build.Tasks/Utilities/Aapt2Daemon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
using System.IO;
using System.Text;
using System.Threading;
using System.Reflection;
using Microsoft.Build.Framework;
using TPL = System.Threading.Tasks;
using Xamarin.Android.Tools;

namespace Xamarin.Android.Tasks
{
Expand Down Expand Up @@ -144,6 +146,33 @@ public void Stop ()
pendingJobs.CompleteAdding ();
}

private bool SetConsoleInputEncoding (Encoding encoding)
{
try {
if (Console.InputEncoding != encoding) {
Console.InputEncoding = encoding;
return true;
}
} catch (IOException) {
//In a DesignTime Build on VS Windows sometimes this exception is raised.
//We should catch it, but there is nothing we can do about it.
}
return false;
}

private bool SetProcessInputEncoding (ProcessStartInfo info, Encoding encoding)
{
Type type = info.GetType ();
PropertyInfo prop = type.GetRuntimeProperty ("StandardInputEncoding");
if (prop == null)
prop = type.GetProperty ("StandardInputEncoding", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if(prop?.CanWrite ?? false) {
prop.SetValue (info, encoding, null);
return true;
}
return false;
}

private void Aapt2DaemonStart ()
{
ProcessStartInfo info = new ProcessStartInfo (Aapt2)
Expand All @@ -158,23 +187,24 @@ private void Aapt2DaemonStart ()
WorkingDirectory = Path.GetTempPath (),
StandardErrorEncoding = Encoding.UTF8,
StandardOutputEncoding = Encoding.UTF8,
// We need to FORCE the StandardInput to be UTF8 so we can use
// accented characters. Also DONT INCLUDE A BOM!!
// otherwise aapt2 will try to interpret the BOM as an argument.
// Cant use this cos its netstandard 2.1 only
// and we are using netstandard 2.0
//StandardInputEncoding = Encoding.UTF8,
//StandardInputEncoding = MonoAndroidHelper.UTF8withoutBOM,
};
// We need to FORCE the StandardInput to be UTF8 so we can use
// accented characters. Also DONT INCLUDE A BOM!!
// otherwise aapt2 will try to interpret the BOM as an argument.
Process aapt2;
lock (lockObject) {
Encoding current = Console.InputEncoding;
Encoding currentEncoding = Console.InputEncoding;
lock (lockObject) {
try {
Console.InputEncoding = new UTF8Encoding (false);
if (!SetProcessInputEncoding (info, MonoAndroidHelper.UTF8withoutBOM))
SetConsoleInputEncoding (MonoAndroidHelper.UTF8withoutBOM);
aapt2 = new Process ();
aapt2.StartInfo = info;
aapt2.Start ();
} finally {
Console.InputEncoding = current;
SetConsoleInputEncoding (currentEncoding);
}
}
try {
Expand All @@ -183,15 +213,15 @@ private void Aapt2DaemonStart ()
bool errored = false;
try {
// try to write Unicode UTF8 to aapt2
StreamWriter writer = aapt2.StandardInput;
foreach (var arg in job.Commands)
{
writer.WriteLine (arg);
using (StreamWriter writer = new StreamWriter (aapt2.StandardInput.BaseStream, MonoAndroidHelper.UTF8withoutBOM, bufferSize: 1024, leaveOpen: true)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this change fix the problem on its own? Or does the encoding have to also be set when the process is started?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok so on my machine it fixes it on its own, on CI it does not. So its not 100% effective, so I've left it in for the case where the Console.InputEncoding call fails and we need a back up.

foreach (var arg in job.Commands) {
writer.WriteLine (arg);
}
writer.WriteLine ();
writer.Flush ();
}
writer.WriteLine ();
writer.Flush ();
string line;

Queue<string> stdError = new Queue<string> ();
while ((line = aapt2.StandardError.ReadLine ()) != null) {
if (string.Compare (line, "Done", StringComparison.OrdinalIgnoreCase) == 0) {
Expand All @@ -201,8 +231,8 @@ private void Aapt2DaemonStart ()
errored = true;
continue;
}
// we have to queue the output because the "Done"/"Error" lines are
//written after all the messages. So to process the warnings/errors
// we have to queue the output because the "Done"/"Error" lines are
//written after all the messages. So to process the warnings/errors
// correctly we need to do this after we know if worked or failed.
stdError.Enqueue (line);
}
Expand Down Expand Up @@ -256,4 +286,4 @@ bool IsAapt2Warning (string singleLine)
return false;
}
}
}
}