Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7768b376 authored by Ryan Mitchell's avatar Ryan Mitchell Committed by android-build-merger
Browse files

Merge "Allow non-references to be copied between AssetManagers" into qt-dev

am: 4108c7fc

Change-Id: I237510de38a281f474a5080cba5aa448f5ccd537
parents c79afdb2 4108c7fc
Loading
Loading
Loading
Loading
+38 −30
Original line number Diff line number Diff line
@@ -1319,7 +1319,7 @@ void Theme::SetTo(const Theme& o) {
    typedef std::map<int, int> SourceToDestinationRuntimePackageMap;
    std::map<ApkAssetsCookie, SourceToDestinationRuntimePackageMap> src_asset_cookie_id_map;

    // Determine which ApkAssets are loaded in both theme AssetManagers
    // Determine which ApkAssets are loaded in both theme AssetManagers.
    std::vector<const ApkAssets*> src_assets = o.asset_manager_->GetApkAssets();
    for (size_t i = 0; i < src_assets.size(); i++) {
      const ApkAssets* src_asset = src_assets[i];
@@ -1328,7 +1328,7 @@ void Theme::SetTo(const Theme& o) {
      for (size_t j = 0; j < dest_assets.size(); j++) {
        const ApkAssets* dest_asset = dest_assets[j];

        // Map the runtime package of the source apk asset to the destination apk asset
        // Map the runtime package of the source apk asset to the destination apk asset.
        if (src_asset->GetPath() == dest_asset->GetPath()) {
          const std::vector<std::unique_ptr<const LoadedPackage>>& src_packages =
              src_asset->GetLoadedArsc()->GetPackages();
@@ -1353,15 +1353,14 @@ void Theme::SetTo(const Theme& o) {
            package_map[src_package_id] = dest_package_id;
          }

          src_to_dest_asset_cookies.insert(std::pair<ApkAssetsCookie, ApkAssetsCookie>(i, j));
          src_asset_cookie_id_map.insert(
              std::pair<ApkAssetsCookie, SourceToDestinationRuntimePackageMap>(i, package_map));
          src_to_dest_asset_cookies.insert(std::make_pair(i, j));
          src_asset_cookie_id_map.insert(std::make_pair(i, package_map));
          break;
        }
      }
    }

    // Reset the data in the destination theme
    // Reset the data in the destination theme.
    for (size_t p = 0; p < packages_.size(); p++) {
      if (packages_[p] != nullptr) {
        packages_[p].reset();
@@ -1387,16 +1386,17 @@ void Theme::SetTo(const Theme& o) {
            continue;
          }

          // If the attribute value represents an attribute or reference, the package id of the
          // value needs to be rewritten to the package id of the value in the destination
          uint32_t attribue_data = entry.value.data;
          if ((entry.value.dataType == Res_value::TYPE_ATTRIBUTE
          bool is_reference = (entry.value.dataType == Res_value::TYPE_ATTRIBUTE
                               || entry.value.dataType == Res_value::TYPE_REFERENCE
                               || entry.value.dataType == Res_value::TYPE_DYNAMIC_ATTRIBUTE
                               || entry.value.dataType == Res_value::TYPE_DYNAMIC_REFERENCE)
              && attribue_data != 0x0) {
                              && entry.value.data != 0x0;

            // Determine the package id of the reference in the destination AssetManager
          // If the attribute value represents an attribute or reference, the package id of the
          // value needs to be rewritten to the package id of the value in the destination.
          uint32_t attribute_data = entry.value.data;
          if (is_reference) {
            // Determine the package id of the reference in the destination AssetManager.
            auto value_package_map = src_asset_cookie_id_map.find(entry.cookie);
            if (value_package_map == src_asset_cookie_id_map.end()) {
              continue;
@@ -1408,14 +1408,28 @@ void Theme::SetTo(const Theme& o) {
              continue;
            }

            attribue_data = fix_package_id(entry.value.data, value_dest_package->second);
            attribute_data = fix_package_id(entry.value.data, value_dest_package->second);
          }

          // Find the cookie of the value in the destination. If the source apk is not loaded in the
          // destination, only copy resources that do not reference resources in the source.
          ApkAssetsCookie data_dest_cookie;
          auto value_dest_cookie = src_to_dest_asset_cookies.find(entry.cookie);
          if (value_dest_cookie != src_to_dest_asset_cookies.end()) {
            data_dest_cookie = value_dest_cookie->second;
          } else {
            if (is_reference || entry.value.dataType == Res_value::TYPE_STRING) {
              continue;
            } else {
              data_dest_cookie = 0x0;
            }
          }

          // The package id of the attribute needs to be rewritten to the package id of the
          // attribute in the destination
          // attribute in the destination.
          int attribute_dest_package_id = p;
          if (attribute_dest_package_id != 0x01) {
            // Find the cookie of the attribute resource id
            // Find the cookie of the attribute resource id in the source AssetManager
            FindEntryResult attribute_entry_result;
            ApkAssetsCookie attribute_cookie =
                o.asset_manager_->FindEntry(make_resid(p, t, e), 0 /* density_override */ ,
@@ -1423,7 +1437,7 @@ void Theme::SetTo(const Theme& o) {
                                            true /* ignore_configuration */,
                                            &attribute_entry_result);

            // Determine the package id of the attribute in the destination AssetManager
            // Determine the package id of the attribute in the destination AssetManager.
            auto attribute_package_map = src_asset_cookie_id_map.find(attribute_cookie);
            if (attribute_package_map == src_asset_cookie_id_map.end()) {
              continue;
@@ -1436,13 +1450,13 @@ void Theme::SetTo(const Theme& o) {
            attribute_dest_package_id = attribute_dest_package->second;
          }

          // Lazily instantiate the destination package
          // Lazily instantiate the destination package.
          std::unique_ptr<Package>& dest_package = packages_[attribute_dest_package_id];
          if (dest_package == nullptr) {
            dest_package.reset(new Package());
          }

          // Lazily instantiate and resize the destination type
          // Lazily instantiate and resize the destination type.
          util::unique_cptr<ThemeType>& dest_type = dest_package->types[t];
          if (dest_type == nullptr || dest_type->entry_count < type->entry_count) {
            const size_t type_alloc_size = sizeof(ThemeType)
@@ -1450,7 +1464,7 @@ void Theme::SetTo(const Theme& o) {
            void* dest_data = malloc(type_alloc_size);
            memset(dest_data, 0, type->entry_count * sizeof(ThemeEntry));

            // Copy the existing destination type values if the type is resized
            // Copy the existing destination type values if the type is resized.
            if (dest_type != nullptr) {
              memcpy(dest_data, type, sizeof(ThemeType)
                                      + (dest_type->entry_count * sizeof(ThemeEntry)));
@@ -1460,15 +1474,9 @@ void Theme::SetTo(const Theme& o) {
            dest_type->entry_count = type->entry_count;
          }

          // Find the cookie of the value in the destination
          auto value_dest_cookie = src_to_dest_asset_cookies.find(entry.cookie);
          if (value_dest_cookie == src_to_dest_asset_cookies.end()) {
            continue;
          }

          dest_type->entries[e].cookie = value_dest_cookie->second;
          dest_type->entries[e].cookie = data_dest_cookie;
          dest_type->entries[e].value.dataType = entry.value.dataType;
          dest_type->entries[e].value.data = attribue_data;
          dest_type->entries[e].value.data = attribute_data;
          dest_type->entries[e].type_spec_flags = entry.type_spec_flags;
        }
      }
+53 −20
Original line number Diff line number Diff line
@@ -282,48 +282,81 @@ TEST_F(ThemeTest, CopyThemeSameAssetManager) {
}

TEST_F(ThemeTest, OnlyCopySameAssetsThemeWhenAssetManagersDiffer) {
  AssetManager2 assetmanager_one;
  assetmanager_one.SetApkAssets({system_assets_.get(), lib_one_assets_.get(), style_assets_.get(),
  AssetManager2 assetmanager_dst;
  assetmanager_dst.SetApkAssets({system_assets_.get(), lib_one_assets_.get(), style_assets_.get(),
                                 libclient_assets_.get()});

  AssetManager2 assetmanager_two;
  assetmanager_two.SetApkAssets({system_assets_.get(), lib_two_assets_.get(), lib_one_assets_.get(),
  AssetManager2 assetmanager_src;
  assetmanager_src.SetApkAssets({system_assets_.get(), lib_two_assets_.get(), lib_one_assets_.get(),
                                 style_assets_.get()});

  auto theme_one = assetmanager_one.NewTheme();
  ASSERT_TRUE(theme_one->ApplyStyle(app::R::style::StyleOne));
  auto theme_dst = assetmanager_dst.NewTheme();
  ASSERT_TRUE(theme_dst->ApplyStyle(app::R::style::StyleOne));

  auto theme_two = assetmanager_two.NewTheme();
  ASSERT_TRUE(theme_two->ApplyStyle(R::style::Theme_One));
  ASSERT_TRUE(theme_two->ApplyStyle(app::R::style::StyleTwo));
  ASSERT_TRUE(theme_two->ApplyStyle(fix_package_id(lib_one::R::style::Theme, 0x03),
  auto theme_src = assetmanager_src.NewTheme();
  ASSERT_TRUE(theme_src->ApplyStyle(R::style::Theme_One));
  ASSERT_TRUE(theme_src->ApplyStyle(app::R::style::StyleTwo));
  ASSERT_TRUE(theme_src->ApplyStyle(fix_package_id(lib_one::R::style::Theme, 0x03),
                                    false /*force*/));
  ASSERT_TRUE(theme_two->ApplyStyle(fix_package_id(lib_two::R::style::Theme, 0x02),
  ASSERT_TRUE(theme_src->ApplyStyle(fix_package_id(lib_two::R::style::Theme, 0x02),
                                    false /*force*/));

  theme_one->SetTo(*theme_two);
  theme_dst->SetTo(*theme_src);

  Res_value value;
  uint32_t flags;

  // System resources (present in destination asset manager)
  EXPECT_EQ(0, theme_one->GetAttribute(R::attr::foreground, &value, &flags));
  // System resources (present in destination asset manager).
  EXPECT_EQ(0, theme_dst->GetAttribute(R::attr::foreground, &value, &flags));

  // The cookie of the style asset is 3 in the source and 2 in the destination.
  // Check that the cookie has been rewritten to the destination values
  EXPECT_EQ(2, theme_one->GetAttribute(app::R::attr::attr_one, &value, &flags));
  // Check that the cookie has been rewritten to the destination values.
  EXPECT_EQ(2, theme_dst->GetAttribute(app::R::attr::attr_one, &value, &flags));

  // The cookie of the lib_one asset is 2 in the source and 1 in the destination.
  // The package id of the lib_one package is 0x03 in the source and 0x02 in the destination
  // Check that the cookie and packages have been rewritten to the destination values
  EXPECT_EQ(1, theme_one->GetAttribute(fix_package_id(lib_one::R::attr::attr1, 0x02), &value,
  // Check that the cookie and packages have been rewritten to the destination values.
  EXPECT_EQ(1, theme_dst->GetAttribute(fix_package_id(lib_one::R::attr::attr1, 0x02), &value,
                                       &flags));
  EXPECT_EQ(1, theme_one->GetAttribute(fix_package_id(lib_one::R::attr::attr2, 0x02), &value,
  EXPECT_EQ(1, theme_dst->GetAttribute(fix_package_id(lib_one::R::attr::attr2, 0x02), &value,
                                       &flags));

  // attr2 references an attribute in lib_one. Check that the resolution of the attribute value is
  // correct after the value of attr2 had its package id rewritten to the destination package id
  // correct after the value of attr2 had its package id rewritten to the destination package id.
  EXPECT_EQ(700, value.data);
}

TEST_F(ThemeTest, CopyNonReferencesWhenPackagesDiffer) {
  AssetManager2 assetmanager_dst;
  assetmanager_dst.SetApkAssets({system_assets_.get()});

  AssetManager2 assetmanager_src;
  assetmanager_src.SetApkAssets({system_assets_.get(), style_assets_.get()});

  auto theme_dst = assetmanager_dst.NewTheme();
  auto theme_src = assetmanager_src.NewTheme();
  ASSERT_TRUE(theme_src->ApplyStyle(app::R::style::StyleSeven));
  theme_dst->SetTo(*theme_src);

  Res_value value;
  uint32_t flags;

  // Allow inline resource values to be copied even if the source apk asset is not present in the
  // destination.
  EXPECT_EQ(0, theme_dst->GetAttribute(0x0101021b /* android:versionCode */, &value, &flags));

  // Do not copy strings since the data is an index into the values string pool of the source apk
  // asset.
  EXPECT_EQ(-1, theme_dst->GetAttribute(0x01010001 /* android:label */, &value, &flags));

  // Do not copy values that reference another resource if the resource is not present in the
  // destination.
  EXPECT_EQ(-1, theme_dst->GetAttribute(0x01010002 /* android:icon */, &value, &flags));
  EXPECT_EQ(-1, theme_dst->GetAttribute(0x010100d1 /* android:tag */, &value, &flags));

  // Allow @empty to and @null to be copied.
  EXPECT_EQ(0, theme_dst->GetAttribute(0x010100d0 /* android:id */, &value, &flags));
  EXPECT_EQ(0, theme_dst->GetAttribute(0x01010000 /* android:theme */, &value, &flags));
}

}  // namespace android
+1 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ struct R {
      StyleFour = 0x7f020003u,
      StyleFive = 0x7f020004u,
      StyleSix = 0x7f020005u,
      StyleSeven = 0x7f020006u,
    };
  };
};
+3 −1
Original line number Diff line number Diff line
@@ -2,5 +2,7 @@

set -e

PATH_TO_FRAMEWORK_RES=${ANDROID_BUILD_TOP}/prebuilts/sdk/current/public/android.jar

aapt2 compile -o compiled.flata --dir res
aapt2 link -o styles.apk --manifest AndroidManifest.xml compiled.flata
aapt2 link -o styles.apk --manifest AndroidManifest.xml -I $PATH_TO_FRAMEWORK_RES compiled.flata
+10 −0
Original line number Diff line number Diff line
@@ -79,4 +79,14 @@
        <item name="attr_three">3</item>
    </style>

    <public type="style" name="StyleSeven" id="0x7f020006" />
    <style name="StyleSeven" >
        <item name="android:versionCode">3</item>
        <item name="android:label">"string"</item>
        <item name="android:icon">?attr/attr_one</item>
        <item name="android:tag">@string/string_one</item>
        <item name="android:id">@null</item>
        <item name="android:theme">@empty</item>
    </style>

</resources>
Loading