Fix segfault with sparse encoding

The native code that underlies `Resources#getIdentifier()` did not take
sparse encoding into account when calculating offsets, resulting in
either garbage or SEGV_MAPERR whenever a resource is first encountered
in a sparsely encoded configuration.

Bug: 197976367
Test: atest libandroidfw_tests --host
Change-Id: Ib7550fe2e05005550f59129a06be5712b74bc9c8
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index d17c328..446e580 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -384,7 +384,16 @@
         return base::unexpected(IOError::PAGES_MISSING);
       }
 
-      auto offset = dtohl(entry_offset_ptr.value());
+      uint32_t offset;
+      uint16_t res_idx;
+      if (type->flags & ResTable_type::FLAG_SPARSE) {
+        auto sparse_entry = entry_offset_ptr.convert<ResTable_sparseTypeEntry>();
+        offset = dtohs(sparse_entry->offset) * 4u;
+        res_idx  = dtohs(sparse_entry->idx);
+      } else {
+        offset = dtohl(entry_offset_ptr.value());
+        res_idx = entry_idx;
+      }
       if (offset != ResTable_type::NO_ENTRY) {
         auto entry = type.offset(dtohl(type->entriesStart) + offset).convert<ResTable_entry>();
         if (!entry) {
@@ -394,7 +403,7 @@
         if (dtohl(entry->key.index) == static_cast<uint32_t>(*key_idx)) {
           // The package ID will be overridden by the caller (due to runtime assignment of package
           // IDs for shared libraries).
-          return make_resid(0x00, *type_idx + type_id_offset_ + 1, entry_idx);
+          return make_resid(0x00, *type_idx + type_id_offset_ + 1, res_idx);
         }
       }
     }