diff --git a/libs/androidfw/Util.cpp b/libs/androidfw/Util.cpp
index 59c9d64..be9edc4 100644
--- a/libs/androidfw/Util.cpp
+++ b/libs/androidfw/Util.cpp
@@ -68,6 +68,107 @@
   return utf8;
 }
 
+std::string Utf8ToModifiedUtf8(const std::string& utf8) {
+  // Java uses Modified UTF-8 which only supports the 1, 2, and 3 byte formats of UTF-8. To encode
+  // 4 byte UTF-8 codepoints, Modified UTF-8 allows the use of surrogate pairs in the same format
+  // of CESU-8 surrogate pairs. Calculate the size of the utf8 string with all 4 byte UTF-8
+  // codepoints replaced with 2 3 byte surrogate pairs
+  size_t modified_size = 0;
+  const size_t size = utf8.size();
+  for (size_t i = 0; i < size; i++) {
+    if (((uint8_t)utf8[i] >> 4) == 0xF) {
+      modified_size += 6;
+      i += 3;
+    } else {
+      modified_size++;
+    }
+  }
+
+  // Early out if no 4 byte codepoints are found
+  if (size == modified_size) {
+    return utf8;
+  }
+
+  std::string output;
+  output.reserve(modified_size);
+  for (size_t i = 0; i < size; i++) {
+    if (((uint8_t)utf8[i] >> 4) == 0xF) {
+      int32_t codepoint = utf32_from_utf8_at(utf8.data(), size, i, nullptr);
+
+      // Calculate the high and low surrogates as UTF-16 would
+      int32_t high = ((codepoint - 0x10000) / 0x400) + 0xD800;
+      int32_t low = ((codepoint - 0x10000) % 0x400) + 0xDC00;
+
+      // Encode each surrogate in UTF-8
+      output.push_back((char)(0xE4 | ((high >> 12) & 0xF)));
+      output.push_back((char)(0x80 | ((high >> 6) & 0x3F)));
+      output.push_back((char)(0x80 | (high & 0x3F)));
+      output.push_back((char)(0xE4 | ((low >> 12) & 0xF)));
+      output.push_back((char)(0x80 | ((low >> 6) & 0x3F)));
+      output.push_back((char)(0x80 | (low & 0x3F)));
+      i += 3;
+    } else {
+      output.push_back(utf8[i]);
+    }
+  }
+
+  return output;
+}
+
+std::string ModifiedUtf8ToUtf8(const std::string& modified_utf8) {
+  // The UTF-8 representation will have a byte length less than or equal to the Modified UTF-8
+  // representation.
+  std::string output;
+  output.reserve(modified_utf8.size());
+
+  size_t index = 0;
+  const size_t modified_size = modified_utf8.size();
+  while (index < modified_size) {
+    size_t next_index;
+    int32_t high_surrogate =
+        utf32_from_utf8_at(modified_utf8.data(), modified_size, index, &next_index);
+    if (high_surrogate < 0) {
+      return {};
+    }
+
+    // Check that the first codepoint is within the high surrogate range
+    if (high_surrogate >= 0xD800 && high_surrogate <= 0xDB7F) {
+      int32_t low_surrogate =
+          utf32_from_utf8_at(modified_utf8.data(), modified_size, next_index, &next_index);
+      if (low_surrogate < 0) {
+        return {};
+      }
+
+      // Check that the second codepoint is within the low surrogate range
+      if (low_surrogate >= 0xDC00 && low_surrogate <= 0xDFFF) {
+        const char32_t codepoint =
+            (char32_t)(((high_surrogate - 0xD800) * 0x400) + (low_surrogate - 0xDC00) + 0x10000);
+
+        // The decoded codepoint should represent a 4 byte, UTF-8 character
+        const size_t utf8_length = (size_t)utf32_to_utf8_length(&codepoint, 1);
+        if (utf8_length != 4) {
+          return {};
+        }
+
+        // Encode the UTF-8 representation of the codepoint into the string
+        char* start = &output[output.size()];
+        output.resize(output.size() + utf8_length);
+        utf32_to_utf8((char32_t*)&codepoint, 1, start, utf8_length + 1);
+
+        index = next_index;
+        continue;
+      }
+    }
+
+    // Append non-surrogate pairs to the output string
+    for (size_t i = index; i < next_index; i++) {
+      output.push_back(modified_utf8[i]);
+    }
+    index = next_index;
+  }
+  return output;
+}
+
 static std::vector<std::string> SplitAndTransform(
     const StringPiece& str, char sep, const std::function<char(char)>& f) {
   std::vector<std::string> parts;
@@ -90,6 +191,29 @@
   return SplitAndTransform(str, sep, ::tolower);
 }
 
+std::unique_ptr<uint8_t[]> Copy(const BigBuffer& buffer) {
+  std::unique_ptr<uint8_t[]> data = std::unique_ptr<uint8_t[]>(new uint8_t[buffer.size()]);
+  uint8_t* p = data.get();
+  for (const auto& block : buffer) {
+    memcpy(p, block.buffer.get(), block.size);
+    p += block.size;
+  }
+  return data;
+}
+
+StringPiece16 GetString16(const android::ResStringPool& pool, size_t idx) {
+  if (auto str = pool.stringAt(idx); str.ok()) {
+    return *str;
+  }
+  return StringPiece16();
+}
+
+std::string GetString(const android::ResStringPool& pool, size_t idx) {
+  if (auto str = pool.string8At(idx); str.ok()) {
+    return ModifiedUtf8ToUtf8(str->to_string());
+  }
+  return Utf16ToUtf8(GetString16(pool, idx));
+}
 
 } // namespace util
 } // namespace android
