AAPT2: Fix windows unicode path issues

Mingw64 was being difficult, so instead of defining a wmain entrypoint,
the command line parameters are parsed manually using built-in Windows
methods that support Unicode. The results are converted to UTF8 and
handled just like the rest of the linux/mac version of the code.

This also removes dependencies on std::istream in favour of a
FileInputStream which calls the appropriate unicode version of
open to read a file.

No speed regressions found on Linux or MacOS.

Bug: 62336414
Bug: 63830502
Test: manual
Change-Id: I597da51e33729ed1b98bf246e7e773337fd3fee8
diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp
index b64cd8c..8536edb 100644
--- a/tools/aapt2/cmd/Compile.cpp
+++ b/tools/aapt2/cmd/Compile.cpp
@@ -16,11 +16,11 @@
 
 #include <dirent.h>
 
-#include <fstream>
 #include <string>
 
 #include "android-base/errors.h"
 #include "android-base/file.h"
+#include "android-base/utf8.h"
 #include "androidfw/StringPiece.h"
 #include "google/protobuf/io/coded_stream.h"
 #include "google/protobuf/io/zero_copy_stream_impl_lite.h"
@@ -38,6 +38,7 @@
 #include "flatten/Archive.h"
 #include "flatten/XmlFlattener.h"
 #include "io/BigBufferOutputStream.h"
+#include "io/FileInputStream.h"
 #include "io/Util.h"
 #include "proto/ProtoSerialize.h"
 #include "util/Files.h"
@@ -46,8 +47,9 @@
 #include "xml/XmlDom.h"
 #include "xml/XmlPullParser.h"
 
-using android::StringPiece;
-using google::protobuf::io::CopyingOutputStreamAdaptor;
+using ::aapt::io::FileInputStream;
+using ::android::StringPiece;
+using ::google::protobuf::io::CopyingOutputStreamAdaptor;
 
 namespace aapt {
 
@@ -57,19 +59,14 @@
   std::string name;
   std::string extension;
 
-  // Original config str. We keep this because when we parse the config, we may
-  // add on
-  // version qualifiers. We want to preserve the original input so the output is
-  // easily
+  // Original config str. We keep this because when we parse the config, we may add on
+  // version qualifiers. We want to preserve the original input so the output is easily
   // computed before hand.
   std::string config_str;
   ConfigDescription config;
 };
 
-/**
- * Resource file paths are expected to look like:
- * [--/res/]type[-config]/name
- */
+// Resource file paths are expected to look like: [--/res/]type[-config]/name
 static Maybe<ResourcePathData> ExtractResourcePathData(const std::string& path,
                                                        std::string* out_error) {
   std::vector<std::string> parts = util::Split(path, file::sDirSep);
@@ -137,9 +134,7 @@
   return util::StartsWith(filename, ".");
 }
 
-/**
- * Walks the res directory structure, looking for resource files.
- */
+// Walks the res directory structure, looking for resource files.
 static bool LoadInputFilesFromDir(IAaptContext* context, const CompileOptions& options,
                                   std::vector<ResourcePathData>* out_path_data) {
   const std::string& root_dir = options.res_dir.value();
@@ -195,22 +190,20 @@
                          const std::string& output_path) {
   ResourceTable table;
   {
-    std::ifstream fin(path_data.source.path, std::ifstream::binary);
-    if (!fin) {
+    FileInputStream fin(path_data.source.path);
+    if (fin.HadError()) {
       context->GetDiagnostics()->Error(DiagMessage(path_data.source)
-                                       << "failed to open file: "
-                                       << android::base::SystemErrorCodeToString(errno));
+                                       << "failed to open file: " << fin.GetError());
       return false;
     }
 
     // Parse the values file from XML.
-    xml::XmlPullParser xml_parser(fin);
+    xml::XmlPullParser xml_parser(&fin);
 
     ResourceParserOptions parser_options;
     parser_options.error_on_positional_arguments = !options.legacy_mode;
 
-    // If the filename includes donottranslate, then the default translatable is
-    // false.
+    // If the filename includes donottranslate, then the default translatable is false.
     parser_options.translatable = path_data.name.find("donottranslate") == std::string::npos;
 
     ResourceParser res_parser(context->GetDiagnostics(), &table, path_data.source, path_data.config,
@@ -218,8 +211,6 @@
     if (!res_parser.Parse(&xml_parser)) {
       return false;
     }
-
-    fin.close();
   }
 
   if (options.pseudolocalize) {
@@ -239,8 +230,7 @@
   // Assign an ID to any package that has resources.
   for (auto& pkg : table.packages) {
     if (!pkg->id) {
-      // If no package ID was set while parsing (public identifiers), auto
-      // assign an ID.
+      // If no package ID was set while parsing (public identifiers), auto assign an ID.
       pkg->id = context->GetPackageId();
     }
   }
@@ -367,7 +357,7 @@
   return true;
 }
 
-static bool IsValidFile(IAaptContext* context, const StringPiece& input_path) {
+static bool IsValidFile(IAaptContext* context, const std::string& input_path) {
   const file::FileType file_type = file::GetFileType(input_path);
   if (file_type != file::FileType::kRegular && file_type != file::FileType::kSymlink) {
     if (file_type == file::FileType::kDirectory) {
@@ -393,17 +383,14 @@
 
   std::unique_ptr<xml::XmlResource> xmlres;
   {
-    std::ifstream fin(path_data.source.path, std::ifstream::binary);
-    if (!fin) {
+    FileInputStream fin(path_data.source.path);
+    if (fin.HadError()) {
       context->GetDiagnostics()->Error(DiagMessage(path_data.source)
-                                       << "failed to open file: "
-                                       << android::base::SystemErrorCodeToString(errno));
+                                       << "failed to open file: " << fin.GetError());
       return false;
     }
 
     xmlres = xml::Inflate(&fin, context->GetDiagnostics(), path_data.source);
-
-    fin.close();
   }
 
   if (!xmlres) {
@@ -432,12 +419,9 @@
     return false;
   }
 
-  // Make sure CopyingOutputStreamAdaptor is deleted before we call
-  // writer->FinishEntry().
+  // Make sure CopyingOutputStreamAdaptor is deleted before we call writer->FinishEntry().
   {
-    // Wrap our IArchiveWriter with an adaptor that implements the
-    // ZeroCopyOutputStream
-    // interface.
+    // Wrap our IArchiveWriter with an adaptor that implements the ZeroCopyOutputStream interface.
     CopyingOutputStreamAdaptor copying_adaptor(writer);
     CompiledFileOutputStream output_stream(&copying_adaptor);