diff options
Diffstat (limited to 'cmds')
35 files changed, 707 insertions, 324 deletions
diff --git a/cmds/am/src/com/android/commands/am/Instrument.java b/cmds/am/src/com/android/commands/am/Instrument.java index 7ff4bc4bcf76..2604497dcb63 100644 --- a/cmds/am/src/com/android/commands/am/Instrument.java +++ b/cmds/am/src/com/android/commands/am/Instrument.java @@ -425,7 +425,8 @@ public class Instrument { if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg); return cn; } else { - List<InstrumentationInfo> infos = mPm.queryInstrumentation(null, 0).getList(); + List<InstrumentationInfo> infos = mPm.queryInstrumentationAsUser( + null, 0, userId).getList(); final int numInfos = infos == null ? 0: infos.size(); ArrayList<ComponentName> cns = new ArrayList<>(); diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 33739f39aaa4..8be8cdacfc84 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -71,8 +71,6 @@ static const char PRODUCT_BOOTANIMATION_DARK_FILE[] = "/product/media/bootanimat static const char PRODUCT_BOOTANIMATION_FILE[] = "/product/media/bootanimation.zip"; static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip"; static const char APEX_BOOTANIMATION_FILE[] = "/apex/com.android.bootanimation/etc/bootanimation.zip"; -static const char PRODUCT_ENCRYPTED_BOOTANIMATION_FILE[] = "/product/media/bootanimation-encrypted.zip"; -static const char SYSTEM_ENCRYPTED_BOOTANIMATION_FILE[] = "/system/media/bootanimation-encrypted.zip"; static const char OEM_SHUTDOWNANIMATION_FILE[] = "/oem/media/shutdownanimation.zip"; static const char PRODUCT_SHUTDOWNANIMATION_FILE[] = "/product/media/shutdownanimation.zip"; static const char SYSTEM_SHUTDOWNANIMATION_FILE[] = "/system/media/shutdownanimation.zip"; @@ -494,28 +492,13 @@ ui::Size BootAnimation::limitSurfaceSize(int width, int height) const { status_t BootAnimation::readyToRun() { mAssets.addDefaultAssets(); - mDisplayToken = SurfaceComposerClient::getInternalDisplayToken(); - if (mDisplayToken == nullptr) + const std::vector<PhysicalDisplayId> ids = SurfaceComposerClient::getPhysicalDisplayIds(); + if (ids.empty()) { + SLOGE("Failed to get ID for any displays\n"); return NAME_NOT_FOUND; + } - DisplayMode displayMode; - const status_t error = - SurfaceComposerClient::getActiveDisplayMode(mDisplayToken, &displayMode); - if (error != NO_ERROR) - return error; - - mMaxWidth = android::base::GetIntProperty("ro.surface_flinger.max_graphics_width", 0); - mMaxHeight = android::base::GetIntProperty("ro.surface_flinger.max_graphics_height", 0); - ui::Size resolution = displayMode.resolution; - resolution = limitSurfaceSize(resolution.width, resolution.height); - // create the native surface - sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"), - resolution.getWidth(), resolution.getHeight(), PIXEL_FORMAT_RGB_565, - ISurfaceComposerClient::eOpaque); - - SurfaceComposerClient::Transaction t; - - // this guest property specifies multi-display IDs to show the boot animation + // this system property specifies multi-display IDs to show the boot animation // multiple ids can be set with comma (,) as separator, for example: // setprop persist.boot.animation.displays 19260422155234049,19261083906282754 Vector<PhysicalDisplayId> physicalDisplayIds; @@ -542,9 +525,44 @@ status_t BootAnimation::readyToRun() { stream.ignore(); } + // the first specified display id is used to retrieve mDisplayToken + for (const auto id : physicalDisplayIds) { + if (std::find(ids.begin(), ids.end(), id) != ids.end()) { + if (const auto token = SurfaceComposerClient::getPhysicalDisplayToken(id)) { + mDisplayToken = token; + break; + } + } + } + } + + // If the system property is not present or invalid, display 0 is used + if (mDisplayToken == nullptr) { + mDisplayToken = SurfaceComposerClient::getPhysicalDisplayToken(ids.front()); + if (mDisplayToken == nullptr) { + return NAME_NOT_FOUND; + } + } + + DisplayMode displayMode; + const status_t error = + SurfaceComposerClient::getActiveDisplayMode(mDisplayToken, &displayMode); + if (error != NO_ERROR) { + return error; + } + + mMaxWidth = android::base::GetIntProperty("ro.surface_flinger.max_graphics_width", 0); + mMaxHeight = android::base::GetIntProperty("ro.surface_flinger.max_graphics_height", 0); + ui::Size resolution = displayMode.resolution; + resolution = limitSurfaceSize(resolution.width, resolution.height); + // create the native surface + sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"), + resolution.getWidth(), resolution.getHeight(), PIXEL_FORMAT_RGB_565, + ISurfaceComposerClient::eOpaque); + + SurfaceComposerClient::Transaction t; + if (isValid) { // In the case of multi-display, boot animation shows on the specified displays - // in addition to the primary display - const auto ids = SurfaceComposerClient::getPhysicalDisplayIds(); for (const auto id : physicalDisplayIds) { if (std::find(ids.begin(), ids.end(), id) != ids.end()) { if (const auto token = SurfaceComposerClient::getPhysicalDisplayToken(id)) { @@ -572,8 +590,9 @@ status_t BootAnimation::readyToRun() { eglQuerySurface(display, surface, EGL_WIDTH, &w); eglQuerySurface(display, surface, EGL_HEIGHT, &h); - if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) + if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) { return NO_INIT; + } mDisplay = display; mContext = context; @@ -617,10 +636,6 @@ void BootAnimation::resizeSurface(int newWidth, int newHeight) { mWidth = limitedSize.width; mHeight = limitedSize.height; - SurfaceComposerClient::Transaction t; - t.setSize(mFlingerSurfaceControl, mWidth, mHeight); - t.apply(); - EGLConfig config = getEglConfig(mDisplay); EGLSurface surface = eglCreateWindowSurface(mDisplay, config, mFlingerSurface.get(), nullptr); if (eglMakeCurrent(mDisplay, surface, surface, mContext) == EGL_FALSE) { @@ -654,23 +669,6 @@ bool BootAnimation::findBootAnimationFileInternal(const std::vector<std::string> } void BootAnimation::findBootAnimationFile() { - // If the device has encryption turned on or is in process - // of being encrypted we show the encrypted boot animation. - char decrypt[PROPERTY_VALUE_MAX]; - property_get("vold.decrypt", decrypt, ""); - - bool encryptedAnimation = atoi(decrypt) != 0 || - !strcmp("trigger_restart_min_framework", decrypt); - - if (!mShuttingDown && encryptedAnimation) { - static const std::vector<std::string> encryptedBootFiles = { - PRODUCT_ENCRYPTED_BOOTANIMATION_FILE, SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, - }; - if (findBootAnimationFileInternal(encryptedBootFiles)) { - return; - } - } - const bool playDarkAnim = android::base::GetIntProperty("ro.boot.theme", 0) == 1; static const std::vector<std::string> bootFiles = { APEX_BOOTANIMATION_FILE, playDarkAnim ? PRODUCT_BOOTANIMATION_DARK_FILE : PRODUCT_BOOTANIMATION_FILE, diff --git a/cmds/bootanimation/FORMAT.md b/cmds/bootanimation/FORMAT.md index 64814c8a25e2..988685e23443 100644 --- a/cmds/bootanimation/FORMAT.md +++ b/cmds/bootanimation/FORMAT.md @@ -4,7 +4,6 @@ The system selects a boot animation zipfile from the following locations, in order: - /system/media/bootanimation-encrypted.zip (if getprop("vold.decrypt") = '1') /system/media/bootanimation.zip /oem/media/bootanimation.zip diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp index aa2113f931c3..4f8faca59e4c 100644 --- a/cmds/idmap2/Android.bp +++ b/cmds/idmap2/Android.bp @@ -23,6 +23,7 @@ package { cc_defaults { name: "idmap2_defaults", + cpp_std: "gnu++2b", tidy: true, tidy_checks: [ "modernize-*", @@ -31,6 +32,7 @@ cc_defaults { "android-*", "misc-*", "readability-*", + "-readability-identifier-length", ], tidy_checks_as_errors: [ "modernize-*", @@ -55,7 +57,6 @@ cc_defaults { "-readability-convert-member-functions-to-static", "-readability-duplicate-include", "-readability-else-after-return", - "-readability-identifier-length", "-readability-named-parameter", "-readability-redundant-access-specifiers", "-readability-uppercase-literal-suffix", @@ -116,6 +117,7 @@ cc_library { "libidmap2/proto/*.proto", ], host_supported: true, + tidy: false, proto: { type: "lite", export_proto_headers: true, diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp index e2638106994c..44311648da80 100644 --- a/cmds/idmap2/idmap2d/Idmap2Service.cpp +++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp @@ -235,7 +235,13 @@ Status Idmap2Service::createFabricatedOverlay( } for (const auto& res : overlay.entries) { - builder.SetResourceValue(res.resourceName, res.dataType, res.data); + if (res.dataType == Res_value::TYPE_STRING) { + builder.SetResourceValue(res.resourceName, res.dataType, res.stringData.value(), + res.configuration.value_or(std::string())); + } else { + builder.SetResourceValue(res.resourceName, res.dataType, res.data, + res.configuration.value_or(std::string())); + } } // Generate the file path of the fabricated overlay and ensure it does not collide with an diff --git a/cmds/idmap2/idmap2d/aidl/core/android/os/FabricatedOverlayInternalEntry.aidl b/cmds/idmap2/idmap2d/aidl/core/android/os/FabricatedOverlayInternalEntry.aidl index 6c2af274ae32..c773e112997d 100644 --- a/cmds/idmap2/idmap2d/aidl/core/android/os/FabricatedOverlayInternalEntry.aidl +++ b/cmds/idmap2/idmap2d/aidl/core/android/os/FabricatedOverlayInternalEntry.aidl @@ -23,4 +23,6 @@ parcelable FabricatedOverlayInternalEntry { @utf8InCpp String resourceName; int dataType; int data; + @nullable @utf8InCpp String stringData; + @nullable @utf8InCpp String configuration; }
\ No newline at end of file diff --git a/cmds/idmap2/include/idmap2/FabricatedOverlay.h b/cmds/idmap2/include/idmap2/FabricatedOverlay.h index 375671881e5f..05b0618131c9 100644 --- a/cmds/idmap2/include/idmap2/FabricatedOverlay.h +++ b/cmds/idmap2/include/idmap2/FabricatedOverlay.h @@ -39,7 +39,11 @@ struct FabricatedOverlay { Builder& SetOverlayable(const std::string& name); Builder& SetResourceValue(const std::string& resource_name, uint8_t data_type, - uint32_t data_value); + uint32_t data_value, const std::string& configuration); + + Builder& SetResourceValue(const std::string& resource_name, uint8_t data_type, + const std::string& data_string_value, + const std::string& configuration); WARN_UNUSED Result<FabricatedOverlay> Build(); @@ -48,6 +52,8 @@ struct FabricatedOverlay { std::string resource_name; DataType data_type; DataValue data_value; + std::string data_string_value; + std::string configuration; }; std::string package_name_; @@ -62,18 +68,21 @@ struct FabricatedOverlay { private: struct SerializedData { - std::unique_ptr<uint8_t[]> data; - size_t data_size; - uint32_t crc; - }; + std::unique_ptr<uint8_t[]> pb_data; + size_t pb_data_size; + uint32_t pb_crc; + std::string sp_data; + }; Result<SerializedData*> InitializeData() const; Result<uint32_t> GetCrc() const; explicit FabricatedOverlay(pb::FabricatedOverlay&& overlay, + std::string&& string_pool_data_, std::optional<uint32_t> crc_from_disk = {}); pb::FabricatedOverlay overlay_pb_; + std::string string_pool_data_; std::optional<uint32_t> crc_from_disk_; mutable std::optional<SerializedData> data_; diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h index 58aff42b1e98..03e714a3847e 100644 --- a/cmds/idmap2/include/idmap2/Idmap.h +++ b/cmds/idmap2/include/idmap2/Idmap.h @@ -21,42 +21,51 @@ * header := magic version target_crc overlay_crc fulfilled_policies * enforce_overlayable target_path overlay_path overlay_name * debug_info - * data := data_header target_entry* target_inline_entry* overlay_entry* - * string_pool - * data_header := target_entry_count target_inline_entry_count overlay_entry_count + * data := data_header target_entry* target_inline_entry* + target_inline_entry_value* config* overlay_entry* string_pool + * data_header := target_entry_count target_inline_entry_count + target_inline_entry_value_count config_count overlay_entry_count * string_pool_index * target_entry := target_id overlay_id - * target_inline_entry := target_id Res_value::size padding(1) Res_value::type + * target_inline_entry := target_id start_value_index value_count + * target_inline_entry_value := config_index Res_value::size padding(1) Res_value::type + * Res_value::value + * config := target_id Res_value::size padding(1) Res_value::type * Res_value::value * overlay_entry := overlay_id target_id * - * debug_info := string - * enforce_overlayable := <uint32_t> - * fulfilled_policies := <uint32_t> - * magic := <uint32_t> - * overlay_crc := <uint32_t> - * overlay_entry_count := <uint32_t> - * overlay_id := <uint32_t> - * overlay_package_id := <uint8_t> - * overlay_name := string - * overlay_path := string - * padding(n) := <uint8_t>[n] - * Res_value::size := <uint16_t> - * Res_value::type := <uint8_t> - * Res_value::value := <uint32_t> - * string := <uint32_t> <uint8_t>+ padding(n) - * string_pool := string - * string_pool_index := <uint32_t> - * string_pool_length := <uint32_t> - * target_crc := <uint32_t> - * target_entry_count := <uint32_t> - * target_inline_entry_count := <uint32_t> - * target_id := <uint32_t> - * target_package_id := <uint8_t> - * target_path := string - * value_type := <uint8_t> - * value_data := <uint32_t> - * version := <uint32_t> + * debug_info := string + * enforce_overlayable := <uint32_t> + * fulfilled_policies := <uint32_t> + * magic := <uint32_t> + * overlay_crc := <uint32_t> + * overlay_entry_count := <uint32_t> + * overlay_id := <uint32_t> + * overlay_package_id := <uint8_t> + * overlay_name := string + * overlay_path := string + * padding(n) := <uint8_t>[n] + * Res_value::size := <uint16_t> + * Res_value::type := <uint8_t> + * Res_value::value := <uint32_t> + * string := <uint32_t> <uint8_t>+ padding(n) + * string_pool := string + * string_pool_index := <uint32_t> + * string_pool_length := <uint32_t> + * target_crc := <uint32_t> + * target_entry_count := <uint32_t> + * target_inline_entry_count := <uint32_t> + * target_inline_entry_value_count := <uint32_t> + * config_count := <uint32_t> + * config_index := <uint32_t> + * start_value_index := <uint32_t> + * value_count := <uint32_t> + * target_id := <uint32_t> + * target_package_id := <uint8_t> + * target_path := string + * value_type := <uint8_t> + * value_data := <uint32_t> + * version := <uint32_t> */ #ifndef IDMAP2_INCLUDE_IDMAP2_IDMAP_H_ @@ -70,6 +79,7 @@ #include "android-base/macros.h" #include "androidfw/ResourceTypes.h" #include "androidfw/StringPiece.h" +#include "androidfw/ConfigDescription.h" #include "idmap2/ResourceContainer.h" #include "idmap2/ResourceMapping.h" @@ -165,19 +175,27 @@ class IdmapData { public: static std::unique_ptr<const Header> FromBinaryStream(std::istream& stream); - inline uint32_t GetTargetEntryCount() const { + [[nodiscard]] inline uint32_t GetTargetEntryCount() const { return target_entry_count; } - inline uint32_t GetTargetInlineEntryCount() const { + [[nodiscard]] inline uint32_t GetTargetInlineEntryCount() const { return target_entry_inline_count; } - inline uint32_t GetOverlayEntryCount() const { + [[nodiscard]] inline uint32_t GetTargetInlineEntryValueCount() const { + return target_entry_inline_value_count; + } + + [[nodiscard]] inline uint32_t GetConfigCount() const { + return config_count; + } + + [[nodiscard]] inline uint32_t GetOverlayEntryCount() const { return overlay_entry_count; } - inline uint32_t GetStringPoolIndexOffset() const { + [[nodiscard]] inline uint32_t GetStringPoolIndexOffset() const { return string_pool_index_offset; } @@ -186,6 +204,8 @@ class IdmapData { private: uint32_t target_entry_count; uint32_t target_entry_inline_count; + uint32_t target_entry_inline_value_count; + uint32_t config_count; uint32_t overlay_entry_count; uint32_t string_pool_index_offset; Header() = default; @@ -202,7 +222,7 @@ class IdmapData { struct TargetInlineEntry { ResourceId target_id; - TargetValue value; + std::map<ConfigDescription, TargetValue> values; }; struct OverlayEntry { @@ -227,11 +247,11 @@ class IdmapData { return target_inline_entries_; } - const std::vector<OverlayEntry>& GetOverlayEntries() const { + [[nodiscard]] const std::vector<OverlayEntry>& GetOverlayEntries() const { return overlay_entries_; } - const std::string& GetStringPoolData() const { + [[nodiscard]] const std::string& GetStringPoolData() const { return string_pool_data_; } diff --git a/cmds/idmap2/include/idmap2/ResourceContainer.h b/cmds/idmap2/include/idmap2/ResourceContainer.h index c3ba4640bd77..2452ff0784ce 100644 --- a/cmds/idmap2/include/idmap2/ResourceContainer.h +++ b/cmds/idmap2/include/idmap2/ResourceContainer.h @@ -66,7 +66,7 @@ struct OverlayData { struct Value { std::string resource_name; - std::variant<ResourceIdValue, TargetValue> value; + std::variant<ResourceIdValue, TargetValueWithConfig> value; }; struct InlineStringPoolData { diff --git a/cmds/idmap2/include/idmap2/ResourceMapping.h b/cmds/idmap2/include/idmap2/ResourceMapping.h index 5a0a384f75a3..4bad2fa392a2 100644 --- a/cmds/idmap2/include/idmap2/ResourceMapping.h +++ b/cmds/idmap2/include/idmap2/ResourceMapping.h @@ -33,7 +33,8 @@ using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask; namespace android::idmap2 { -using TargetResourceMap = std::map<ResourceId, std::variant<ResourceId, TargetValue>>; +using ConfigMap = std::unordered_map<std::string, TargetValue>; +using TargetResourceMap = std::map<ResourceId, std::variant<ResourceId, ConfigMap>>; using OverlayResourceMap = std::map<ResourceId, ResourceId>; class ResourceMapping { @@ -69,7 +70,8 @@ class ResourceMapping { // If `allow_rewriting_` is true, then the overlay-to-target map will be populated if the target // resource id is mapped to an overlay resource id. Result<Unit> AddMapping(ResourceId target_resource, - const std::variant<OverlayData::ResourceIdValue, TargetValue>& value); + const std::variant<OverlayData::ResourceIdValue, + TargetValueWithConfig>& value); TargetResourceMap target_map_; OverlayResourceMap overlay_map_; diff --git a/cmds/idmap2/include/idmap2/ResourceUtils.h b/cmds/idmap2/include/idmap2/ResourceUtils.h index a0202dfee473..af4dd8960cc3 100644 --- a/cmds/idmap2/include/idmap2/ResourceUtils.h +++ b/cmds/idmap2/include/idmap2/ResourceUtils.h @@ -40,6 +40,16 @@ using DataValue = uint32_t; // Res_value::data struct TargetValue { DataType data_type; DataValue data_value; + std::string data_string_value; +}; + +struct TargetValueWithConfig { + TargetValue value; + std::string config; + + [[nodiscard]] std::pair<std::string, TargetValue> to_pair() const { + return std::make_pair(config, value); + } }; namespace utils { diff --git a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp index 3bbe9d91deb6..4b271a1ff96f 100644 --- a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp +++ b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp @@ -70,12 +70,35 @@ void BinaryStreamVisitor::visit(const IdmapData& data) { } static constexpr uint16_t kValueSize = 8U; + std::vector<std::pair<ConfigDescription, TargetValue>> target_values; + target_values.reserve(data.GetHeader()->GetTargetInlineEntryValueCount()); for (const auto& target_entry : data.GetTargetInlineEntries()) { Write32(target_entry.target_id); + Write32(target_values.size()); + Write32(target_entry.values.size()); + target_values.insert( + target_values.end(), target_entry.values.begin(), target_entry.values.end()); + } + + std::vector<ConfigDescription> configs; + configs.reserve(data.GetHeader()->GetConfigCount()); + for (const auto& target_entry_value : target_values) { + auto config_it = find(configs.begin(), configs.end(), target_entry_value.first); + if (config_it != configs.end()) { + Write32(config_it - configs.begin()); + } else { + Write32(configs.size()); + configs.push_back(target_entry_value.first); + } Write16(kValueSize); Write8(0U); // padding - Write8(target_entry.value.data_type); - Write32(target_entry.value.data_value); + Write8(target_entry_value.second.data_type); + Write32(target_entry_value.second.data_value); + } + + for( auto& cd : configs) { + cd.swapHtoD(); + stream_.write(reinterpret_cast<char*>(&cd), sizeof(cd)); } for (const auto& overlay_entry : data.GetOverlayEntries()) { @@ -89,6 +112,8 @@ void BinaryStreamVisitor::visit(const IdmapData& data) { void BinaryStreamVisitor::visit(const IdmapData::Header& header) { Write32(header.GetTargetEntryCount()); Write32(header.GetTargetInlineEntryCount()); + Write32(header.GetTargetInlineEntryValueCount()); + Write32(header.GetConfigCount()); Write32(header.GetOverlayEntryCount()); Write32(header.GetStringPoolIndexOffset()); } diff --git a/cmds/idmap2/libidmap2/FabricatedOverlay.cpp b/cmds/idmap2/libidmap2/FabricatedOverlay.cpp index 8352dbb7b619..bde9b0be4361 100644 --- a/cmds/idmap2/libidmap2/FabricatedOverlay.cpp +++ b/cmds/idmap2/libidmap2/FabricatedOverlay.cpp @@ -17,8 +17,9 @@ #include "idmap2/FabricatedOverlay.h" #include <androidfw/ResourceUtils.h> +#include <androidfw/StringPool.h> #include <google/protobuf/io/coded_stream.h> -#include <google/protobuf/io/zero_copy_stream_impl_lite.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> #include <utils/ByteOrder.h> #include <zlib.h> @@ -30,6 +31,8 @@ namespace android::idmap2 { +constexpr auto kBufferSize = 1024; + namespace { bool Read32(std::istream& stream, uint32_t* out) { uint32_t value; @@ -47,8 +50,11 @@ void Write32(std::ostream& stream, uint32_t value) { } // namespace FabricatedOverlay::FabricatedOverlay(pb::FabricatedOverlay&& overlay, + std::string&& string_pool_data, std::optional<uint32_t> crc_from_disk) - : overlay_pb_(std::forward<pb::FabricatedOverlay>(overlay)), crc_from_disk_(crc_from_disk) { + : overlay_pb_(std::forward<pb::FabricatedOverlay>(overlay)), + string_pool_data_(std::move(string_pool_data)), + crc_from_disk_(crc_from_disk) { } FabricatedOverlay::Builder::Builder(const std::string& package_name, const std::string& name, @@ -64,13 +70,26 @@ FabricatedOverlay::Builder& FabricatedOverlay::Builder::SetOverlayable(const std } FabricatedOverlay::Builder& FabricatedOverlay::Builder::SetResourceValue( - const std::string& resource_name, uint8_t data_type, uint32_t data_value) { - entries_.emplace_back(Entry{resource_name, data_type, data_value}); + const std::string& resource_name, uint8_t data_type, uint32_t data_value, + const std::string& configuration) { + entries_.emplace_back(Entry{resource_name, data_type, data_value, "", configuration}); + return *this; +} + +FabricatedOverlay::Builder& FabricatedOverlay::Builder::SetResourceValue( + const std::string& resource_name, uint8_t data_type, const std::string& data_string_value, + const std::string& configuration) { + entries_.emplace_back(Entry{resource_name, data_type, 0, data_string_value, configuration}); return *this; } Result<FabricatedOverlay> FabricatedOverlay::Builder::Build() { - std::map<std::string, std::map<std::string, std::map<std::string, TargetValue>>> entries; + using ConfigMap = std::map<std::string, TargetValue>; + using EntryMap = std::map<std::string, ConfigMap>; + using TypeMap = std::map<std::string, EntryMap>; + using PackageMap = std::map<std::string, TypeMap>; + PackageMap package_map; + android::StringPool string_pool; for (const auto& res_entry : entries_) { StringPiece package_substr; StringPiece type_name; @@ -90,11 +109,10 @@ Result<FabricatedOverlay> FabricatedOverlay::Builder::Build() { return Error("resource name '%s' missing entry name", res_entry.resource_name.c_str()); } - auto package = entries.find(package_name); - if (package == entries.end()) { - package = entries - .insert(std::make_pair( - package_name, std::map<std::string, std::map<std::string, TargetValue>>())) + auto package = package_map.find(package_name); + if (package == package_map.end()) { + package = package_map + .insert(std::make_pair(package_name, TypeMap())) .first; } @@ -102,16 +120,22 @@ Result<FabricatedOverlay> FabricatedOverlay::Builder::Build() { if (type == package->second.end()) { type = package->second - .insert(std::make_pair(type_name.to_string(), std::map<std::string, TargetValue>())) + .insert(std::make_pair(type_name.to_string(), EntryMap())) .first; } auto entry = type->second.find(entry_name.to_string()); if (entry == type->second.end()) { - entry = type->second.insert(std::make_pair(entry_name.to_string(), TargetValue())).first; + entry = type->second.insert(std::make_pair(entry_name.to_string(), ConfigMap())).first; } - entry->second = TargetValue{res_entry.data_type, res_entry.data_value}; + auto value = entry->second.find(res_entry.configuration); + if (value == entry->second.end()) { + value = entry->second.insert(std::make_pair(res_entry.configuration, TargetValue())).first; + } + + value->second = TargetValue{res_entry.data_type, res_entry.data_value, + res_entry.data_string_value}; } pb::FabricatedOverlay overlay_pb; @@ -120,25 +144,35 @@ Result<FabricatedOverlay> FabricatedOverlay::Builder::Build() { overlay_pb.set_target_package_name(target_package_name_); overlay_pb.set_target_overlayable(target_overlayable_); - for (const auto& package : entries) { + for (auto& package : package_map) { auto package_pb = overlay_pb.add_packages(); package_pb->set_name(package.first); - for (const auto& type : package.second) { + for (auto& type : package.second) { auto type_pb = package_pb->add_types(); type_pb->set_name(type.first); - for (const auto& entry : type.second) { - auto entry_pb = type_pb->add_entries(); - entry_pb->set_name(entry.first); - pb::ResourceValue* value = entry_pb->mutable_res_value(); - value->set_data_type(entry.second.data_type); - value->set_data_value(entry.second.data_value); + for (auto& entry : type.second) { + for (const auto& value: entry.second) { + auto entry_pb = type_pb->add_entries(); + entry_pb->set_name(entry.first); + entry_pb->set_configuration(value.first); + pb::ResourceValue* pb_value = entry_pb->mutable_res_value(); + pb_value->set_data_type(value.second.data_type); + if (value.second.data_type == Res_value::TYPE_STRING) { + auto ref = string_pool.MakeRef(value.second.data_string_value); + pb_value->set_data_value(ref.index()); + } else { + pb_value->set_data_value(value.second.data_value); + } + } } } } - return FabricatedOverlay(std::move(overlay_pb)); + android::BigBuffer string_buffer(kBufferSize); + android::StringPool::FlattenUtf8(&string_buffer, string_pool, nullptr); + return FabricatedOverlay(std::move(overlay_pb), string_buffer.to_string()); } Result<FabricatedOverlay> FabricatedOverlay::FromBinaryStream(std::istream& stream) { @@ -156,48 +190,67 @@ Result<FabricatedOverlay> FabricatedOverlay::FromBinaryStream(std::istream& stre return Error("Failed to read fabricated overlay version."); } - if (version != 1) { + if (version != 1 && version != 2) { return Error("Invalid fabricated overlay version '%u'.", version); } uint32_t crc; if (!Read32(stream, &crc)) { - return Error("Failed to read fabricated overlay version."); + return Error("Failed to read fabricated overlay crc."); } pb::FabricatedOverlay overlay{}; - if (!overlay.ParseFromIstream(&stream)) { - return Error("Failed read fabricated overlay proto."); + std::string sp_data; + if (version == 2) { + uint32_t sp_size; + if (!Read32(stream, &sp_size)) { + return Error("Failed read string pool size."); + } + std::string buf(sp_size, '\0'); + if (!stream.read(buf.data(), sp_size)) { + return Error("Failed to read string pool."); + } + sp_data = buf; + + if (!overlay.ParseFromIstream(&stream)) { + return Error("Failed read fabricated overlay proto."); + } + } else { + if (!overlay.ParseFromIstream(&stream)) { + return Error("Failed read fabricated overlay proto."); + } } // If the proto version is the latest version, then the contents of the proto must be the same // when the proto is re-serialized; otherwise, the crc must be calculated because migrating the // proto to the latest version will likely change the contents of the fabricated overlay. - return FabricatedOverlay(std::move(overlay), version == kFabricatedOverlayCurrentVersion + return FabricatedOverlay(std::move(overlay), std::move(sp_data), + version == kFabricatedOverlayCurrentVersion ? std::optional<uint32_t>(crc) : std::nullopt); } Result<FabricatedOverlay::SerializedData*> FabricatedOverlay::InitializeData() const { if (!data_.has_value()) { - auto size = overlay_pb_.ByteSizeLong(); - auto data = std::unique_ptr<uint8_t[]>(new uint8_t[size]); + auto pb_size = overlay_pb_.ByteSizeLong(); + auto pb_data = std::unique_ptr<uint8_t[]>(new uint8_t[pb_size]); // Ensure serialization is deterministic - google::protobuf::io::ArrayOutputStream array_stream(data.get(), size); + google::protobuf::io::ArrayOutputStream array_stream(pb_data.get(), pb_size); google::protobuf::io::CodedOutputStream output_stream(&array_stream); output_stream.SetSerializationDeterministic(true); overlay_pb_.SerializeWithCachedSizes(&output_stream); - if (output_stream.HadError() || size != output_stream.ByteCount()) { + if (output_stream.HadError() || pb_size != output_stream.ByteCount()) { return Error("Failed to serialize fabricated overlay."); } // Calculate the crc using the proto data and the version. - uint32_t crc = crc32(0L, Z_NULL, 0); - crc = crc32(crc, reinterpret_cast<const uint8_t*>(&kFabricatedOverlayCurrentVersion), + uint32_t pb_crc = crc32(0L, Z_NULL, 0); + pb_crc = crc32(pb_crc, reinterpret_cast<const uint8_t*>(&kFabricatedOverlayCurrentVersion), sizeof(uint32_t)); - crc = crc32(crc, data.get(), size); - data_ = SerializedData{std::move(data), size, crc}; + pb_crc = crc32(pb_crc, pb_data.get(), pb_size); + + data_ = SerializedData{std::move(pb_data), pb_size, pb_crc, string_pool_data_}; } return &(*data_); } @@ -209,7 +262,7 @@ Result<uint32_t> FabricatedOverlay::GetCrc() const { if (!data) { return data.GetError(); } - return (*data)->crc; + return (*data)->pb_crc; } Result<Unit> FabricatedOverlay::ToBinaryStream(std::ostream& stream) const { @@ -220,8 +273,13 @@ Result<Unit> FabricatedOverlay::ToBinaryStream(std::ostream& stream) const { Write32(stream, kFabricatedOverlayMagic); Write32(stream, kFabricatedOverlayCurrentVersion); - Write32(stream, (*data)->crc); - stream.write(reinterpret_cast<const char*>((*data)->data.get()), (*data)->data_size); + Write32(stream, (*data)->pb_crc); + Write32(stream, (*data)->sp_data.length()); + stream.write((*data)->sp_data.data(), (*data)->sp_data.length()); + if (stream.bad()) { + return Error("Failed to write string pool data."); + } + stream.write(reinterpret_cast<const char*>((*data)->pb_data.get()), (*data)->pb_data_size); if (stream.bad()) { return Error("Failed to write serialized fabricated overlay."); } @@ -283,11 +341,20 @@ Result<OverlayData> FabContainer::GetOverlayData(const OverlayManifestInfo& info entry.name().c_str()); const auto& res_value = entry.res_value(); result.pairs.emplace_back(OverlayData::Value{ - name, TargetValue{.data_type = static_cast<uint8_t>(res_value.data_type()), - .data_value = res_value.data_value()}}); + name, TargetValueWithConfig{.config = entry.configuration(), .value = TargetValue{ + .data_type = static_cast<uint8_t>(res_value.data_type()), + .data_value = res_value.data_value()}}}); } } } + const uint32_t string_pool_data_length = overlay_.string_pool_data_.length(); + result.string_pool_data = OverlayData::InlineStringPoolData{ + .data = std::unique_ptr<uint8_t[]>(new uint8_t[string_pool_data_length]), + .data_length = string_pool_data_length, + .string_pool_offset = 0, + }; + memcpy(result.string_pool_data->data.get(), overlay_.string_pool_data_.data(), + string_pool_data_length); return result; } diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp index 06650f681b24..813dff1c141c 100644 --- a/cmds/idmap2/libidmap2/Idmap.cpp +++ b/cmds/idmap2/libidmap2/Idmap.cpp @@ -77,8 +77,7 @@ bool WARN_UNUSED ReadString(std::istream& stream, std::string* out) { return false; } uint32_t padding_size = CalculatePadding(size); - std::string padding(padding_size, '\0'); - if (!stream.read(padding.data(), padding_size)) { + if (padding_size != 0 && !stream.seekg(padding_size, std::ios_base::cur)) { return false; } *out = buf; @@ -186,6 +185,8 @@ std::unique_ptr<const IdmapData::Header> IdmapData::Header::FromBinaryStream(std std::unique_ptr<IdmapData::Header> idmap_data_header(new IdmapData::Header()); if (!Read32(stream, &idmap_data_header->target_entry_count) || !Read32(stream, &idmap_data_header->target_entry_inline_count) || + !Read32(stream, &idmap_data_header->target_entry_inline_value_count) || + !Read32(stream, &idmap_data_header->config_count) || !Read32(stream, &idmap_data_header->overlay_entry_count) || !Read32(stream, &idmap_data_header->string_pool_index_offset)) { return nullptr; @@ -207,20 +208,59 @@ std::unique_ptr<const IdmapData> IdmapData::FromBinaryStream(std::istream& strea if (!Read32(stream, &target_entry.target_id) || !Read32(stream, &target_entry.overlay_id)) { return nullptr; } - data->target_entries_.push_back(target_entry); + data->target_entries_.emplace_back(target_entry); } // Read the mapping of target resource id to inline overlay values. - uint8_t unused1; - uint16_t unused2; + std::vector<std::tuple<TargetInlineEntry, uint32_t, uint32_t>> target_inline_entries; for (size_t i = 0; i < data->header_->GetTargetInlineEntryCount(); i++) { TargetInlineEntry target_entry{}; - if (!Read32(stream, &target_entry.target_id) || !Read16(stream, &unused2) || - !Read8(stream, &unused1) || !Read8(stream, &target_entry.value.data_type) || - !Read32(stream, &target_entry.value.data_value)) { + uint32_t entry_offset; + uint32_t entry_count; + if (!Read32(stream, &target_entry.target_id) || !Read32(stream, &entry_offset) + || !Read32(stream, &entry_count)) { return nullptr; } - data->target_inline_entries_.push_back(target_entry); + target_inline_entries.emplace_back(target_entry, entry_offset, entry_count); + } + + // Read the inline overlay resource values + std::vector<std::pair<uint32_t, TargetValue>> target_values; + uint8_t unused1; + uint16_t unused2; + for (size_t i = 0; i < data->header_->GetTargetInlineEntryValueCount(); i++) { + uint32_t config_index; + if (!Read32(stream, &config_index)) { + return nullptr; + } + TargetValue value; + if (!Read16(stream, &unused2) + || !Read8(stream, &unused1) + || !Read8(stream, &value.data_type) + || !Read32(stream, &value.data_value)) { + return nullptr; + } + target_values.emplace_back(config_index, value); + } + + // Read the configurations + std::vector<ConfigDescription> configurations; + for (size_t i = 0; i < data->header_->GetConfigCount(); i++) { + ConfigDescription cd; + if (!stream.read(reinterpret_cast<char*>(&cd), sizeof(ConfigDescription))) { + return nullptr; + } + configurations.emplace_back(cd); + } + + // Construct complete target inline entries + for (auto [target_entry, entry_offset, entry_count] : target_inline_entries) { + for(size_t i = 0; i < entry_count; i++) { + const auto& target_value = target_values[entry_offset + i]; + const auto& config = configurations[target_value.first]; + target_entry.values[config] = target_value.second; + } + data->target_inline_entries_.emplace_back(target_entry); } // Read the mapping of overlay resource id to target resource id. @@ -278,12 +318,21 @@ Result<std::unique_ptr<const IdmapData>> IdmapData::FromResourceMapping( std::unique_ptr<IdmapData> data(new IdmapData()); data->string_pool_data_ = resource_mapping.GetStringPoolData().to_string(); + uint32_t inline_value_count = 0; + std::set<std::string> config_set; for (const auto& mapping : resource_mapping.GetTargetToOverlayMap()) { if (auto overlay_resource = std::get_if<ResourceId>(&mapping.second)) { data->target_entries_.push_back({mapping.first, *overlay_resource}); } else { - data->target_inline_entries_.push_back( - {mapping.first, std::get<TargetValue>(mapping.second)}); + std::map<ConfigDescription, TargetValue> values; + for (const auto& [config, value] : std::get<ConfigMap>(mapping.second)) { + config_set.insert(config); + ConfigDescription cd; + ConfigDescription::Parse(config, &cd); + values[cd] = value; + inline_value_count++; + } + data->target_inline_entries_.push_back({mapping.first, values}); } } @@ -295,6 +344,8 @@ Result<std::unique_ptr<const IdmapData>> IdmapData::FromResourceMapping( data_header->target_entry_count = static_cast<uint32_t>(data->target_entries_.size()); data_header->target_entry_inline_count = static_cast<uint32_t>(data->target_inline_entries_.size()); + data_header->target_entry_inline_value_count = inline_value_count; + data_header->config_count = config_set.size(); data_header->overlay_entry_count = static_cast<uint32_t>(data->overlay_entries_.size()); data_header->string_pool_index_offset = resource_mapping.GetStringPoolOffset(); data->header_ = std::move(data_header); diff --git a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp index d10a2785aaba..a44fa756aa1c 100644 --- a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp +++ b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp @@ -94,14 +94,17 @@ void PrettyPrintVisitor::visit(const IdmapData& data) { } for (auto& target_entry : data.GetTargetInlineEntries()) { - stream_ << TAB << base::StringPrintf("0x%08x -> ", target_entry.target_id) - << utils::DataTypeToString(target_entry.value.data_type); - - if (target_entry.value.data_type == Res_value::TYPE_STRING) { - auto str = string_pool.stringAt(target_entry.value.data_value - string_pool_offset); - stream_ << " \"" << str.value_or(StringPiece16(u"")) << "\""; - } else { - stream_ << " " << base::StringPrintf("0x%08x", target_entry.value.data_value); + for(auto iter = target_entry.values.begin(); iter != target_entry.values.end(); ++iter) { + auto value = iter->second; + stream_ << TAB << base::StringPrintf("0x%08x -> ", target_entry.target_id) + << utils::DataTypeToString(value.data_type); + + if (value.data_type == Res_value::TYPE_STRING) { + auto str = string_pool.stringAt(value.data_value - string_pool_offset); + stream_ << " \"" << str.value_or(StringPiece16(u"")) << "\""; + } else { + stream_ << " " << base::StringPrintf("0x%08x", value.data_value); + } } std::string target_name = kUnknownResourceName; diff --git a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp index 779538c617f4..3531cd7c2f36 100644 --- a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp +++ b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp @@ -89,22 +89,30 @@ void RawPrintVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) { print(target_entry.target_id, "target id"); } + pad(sizeof(Res_value::size) + sizeof(Res_value::res0)); - print(target_entry.value.data_type, "type: %s", - utils::DataTypeToString(target_entry.value.data_type).data()); + for (auto& target_entry_value : target_entry.values) { + auto value = target_entry_value.second; - Result<std::string> overlay_name(Error("")); - if (overlay_ != nullptr && - (target_entry.value.data_value == Res_value::TYPE_REFERENCE || - target_entry.value.data_value == Res_value::TYPE_DYNAMIC_REFERENCE)) { - overlay_name = overlay_->GetResourceName(target_entry.value.data_value); - } + print(target_entry_value.first.to_string(), false, "config: %s", + target_entry_value.first.toString().string()); - if (overlay_name) { - print(target_entry.value.data_value, "data: %s", overlay_name->c_str()); - } else { - print(target_entry.value.data_value, "data"); + print(value.data_type, "type: %s", + utils::DataTypeToString(value.data_type).data()); + + Result<std::string> overlay_name(Error("")); + if (overlay_ != nullptr && + (value.data_value == Res_value::TYPE_REFERENCE || + value.data_value == Res_value::TYPE_DYNAMIC_REFERENCE)) { + overlay_name = overlay_->GetResourceName(value.data_value); + } + + if (overlay_name) { + print(value.data_value, "data: %s", overlay_name->c_str()); + } else { + print(value.data_value, "data"); + } } } @@ -138,6 +146,8 @@ void RawPrintVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) { void RawPrintVisitor::visit(const IdmapData::Header& header) { print(header.GetTargetEntryCount(), "target entry count"); print(header.GetTargetInlineEntryCount(), "target inline entry count"); + print(header.GetTargetInlineEntryValueCount(), "target inline entry value count"); + print(header.GetConfigCount(), "config count"); print(header.GetOverlayEntryCount(), "overlay entry count"); print(header.GetStringPoolIndexOffset(), "string pool index offset"); } diff --git a/cmds/idmap2/libidmap2/ResourceContainer.cpp b/cmds/idmap2/libidmap2/ResourceContainer.cpp index a62472c8f11e..0e3590486c6f 100644 --- a/cmds/idmap2/libidmap2/ResourceContainer.cpp +++ b/cmds/idmap2/libidmap2/ResourceContainer.cpp @@ -226,8 +226,10 @@ Result<OverlayData> CreateResourceMapping(ResourceId id, const ZipAssetsProvider *target_resource, OverlayData::ResourceIdValue{overlay_resource->data, rewrite_id}}); } else { overlay_data.pairs.emplace_back( - OverlayData::Value{*target_resource, TargetValue{.data_type = overlay_resource->dataType, - .data_value = overlay_resource->data}}); + OverlayData::Value{*target_resource, TargetValueWithConfig{ + .config = std::string(), + .value = TargetValue{.data_type = overlay_resource->dataType, + .data_value = overlay_resource->data}}}); } } diff --git a/cmds/idmap2/libidmap2/ResourceMapping.cpp b/cmds/idmap2/libidmap2/ResourceMapping.cpp index 3bbbf248c87d..bb31c11d629c 100644 --- a/cmds/idmap2/libidmap2/ResourceMapping.cpp +++ b/cmds/idmap2/libidmap2/ResourceMapping.cpp @@ -160,15 +160,14 @@ Result<ResourceMapping> ResourceMapping::FromContainers(const TargetResourceCont Result<Unit> ResourceMapping::AddMapping( ResourceId target_resource, - const std::variant<OverlayData::ResourceIdValue, TargetValue>& value) { - if (target_map_.find(target_resource) != target_map_.end()) { - return Error(R"(target resource id "0x%08x" mapped to multiple values)", target_resource); - } - + const std::variant<OverlayData::ResourceIdValue, TargetValueWithConfig>& value) { // TODO(141485591): Ensure that the overlay type is compatible with the target type. If the // runtime types are not compatible, it could cause runtime crashes when the resource is resolved. if (auto overlay_resource = std::get_if<OverlayData::ResourceIdValue>(&value)) { + if (target_map_.find(target_resource) != target_map_.end()) { + return Error(R"(target resource id "0x%08x" mapped to multiple values)", target_resource); + } target_map_.insert(std::make_pair(target_resource, overlay_resource->overlay_id)); if (overlay_resource->rewrite_id) { // An overlay resource can override multiple target resources at once. Rewrite the overlay @@ -176,8 +175,18 @@ Result<Unit> ResourceMapping::AddMapping( overlay_map_.insert(std::make_pair(overlay_resource->overlay_id, target_resource)); } } else { - auto overlay_value = std::get<TargetValue>(value); - target_map_.insert(std::make_pair(target_resource, overlay_value)); + auto[iter, inserted] = target_map_.try_emplace(target_resource, ConfigMap()); + auto& resource_value = iter->second; + if (!inserted && std::holds_alternative<ResourceId>(resource_value)) { + return Error(R"(target resource id "0x%08x" mapped to multiple values)", target_resource); + } + auto& config_map = std::get<ConfigMap>(resource_value); + const auto& config_value = std::get<TargetValueWithConfig>(value); + if (config_map.find(config_value.config) != config_map.end()) { + return Error(R"(target resource id "0x%08x" mapped to multiple values with the same config)", + target_resource); + } + config_map.insert(config_value.to_pair()); } return Unit{}; diff --git a/cmds/idmap2/libidmap2/proto/fabricated_v1.proto b/cmds/idmap2/libidmap2/proto/fabricated_v1.proto index a392b2b6d856..c7a79b31e151 100644 --- a/cmds/idmap2/libidmap2/proto/fabricated_v1.proto +++ b/cmds/idmap2/libidmap2/proto/fabricated_v1.proto @@ -46,6 +46,7 @@ message ResourceEntry { oneof value { ResourceValue res_value = 2; } + string configuration = 3; } message ResourceValue { diff --git a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp index bf6332742787..f1eeab9c803b 100644 --- a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp +++ b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp @@ -84,8 +84,10 @@ TEST(BinaryStreamVisitorTests, CreateBinaryStreamViaBinaryStreamVisitor) { const auto& target_inline_entries2 = data2->GetTargetInlineEntries(); ASSERT_EQ(target_inline_entries1.size(), target_inline_entries2.size()); ASSERT_EQ(target_inline_entries1[0].target_id, target_inline_entries2[0].target_id); - ASSERT_EQ(target_inline_entries1[0].value.data_type, target_inline_entries2[0].value.data_type); - ASSERT_EQ(target_inline_entries1[0].value.data_value, target_inline_entries2[0].value.data_value); + ASSERT_EQ(target_inline_entries1[0].values.begin()->second.data_type, + target_inline_entries2[0].values.begin()->second.data_type); + ASSERT_EQ(target_inline_entries1[0].values.begin()->second.data_value, + target_inline_entries2[0].values.begin()->second.data_value); const auto& overlay_entries1 = data1->GetOverlayEntries(); const auto& overlay_entries2 = data2->GetOverlayEntries(); diff --git a/cmds/idmap2/tests/FabricatedOverlayTests.cpp b/cmds/idmap2/tests/FabricatedOverlayTests.cpp index 468ea0c634c1..e804c879ee82 100644 --- a/cmds/idmap2/tests/FabricatedOverlayTests.cpp +++ b/cmds/idmap2/tests/FabricatedOverlayTests.cpp @@ -43,9 +43,17 @@ TEST(FabricatedOverlayTests, OverlayInfo) { TEST(FabricatedOverlayTests, SetResourceValue) { auto overlay = FabricatedOverlay::Builder("com.example.overlay", "SandTheme", "com.example.target") - .SetResourceValue("com.example.target:integer/int1", Res_value::TYPE_INT_DEC, 1U) - .SetResourceValue("com.example.target.split:integer/int2", Res_value::TYPE_INT_DEC, 2U) - .SetResourceValue("string/int3", Res_value::TYPE_REFERENCE, 0x7f010000) + .SetResourceValue( + "com.example.target:integer/int1", Res_value::TYPE_INT_DEC, 1U, "port") + .SetResourceValue( + "com.example.target.split:integer/int2", Res_value::TYPE_INT_DEC, 2U, "land") + .SetResourceValue( + "string/int3", Res_value::TYPE_REFERENCE, 0x7f010000, "xxhdpi-v7") + .SetResourceValue( + "com.example.target:string/string1", + Res_value::TYPE_STRING, + "foobar", + "en-rUS-normal-xxhdpi-v21") .Build(); ASSERT_TRUE(overlay); auto container = FabricatedOverlayContainer::FromOverlay(std::move(*overlay)); @@ -59,42 +67,54 @@ TEST(FabricatedOverlayTests, SetResourceValue) { auto pairs = container->GetOverlayData(*info); ASSERT_TRUE(pairs); - EXPECT_FALSE(pairs->string_pool_data.has_value()); - ASSERT_EQ(3U, pairs->pairs.size()); + ASSERT_EQ(4U, pairs->pairs.size()); + auto string_pool = ResStringPool(pairs->string_pool_data->data.get(), + pairs->string_pool_data->data_length, false); auto& it = pairs->pairs[0]; ASSERT_EQ("com.example.target:integer/int1", it.resource_name); - auto entry = std::get_if<TargetValue>(&it.value); + auto entry = std::get_if<TargetValueWithConfig>(&it.value); ASSERT_NE(nullptr, entry); - ASSERT_EQ(1U, entry->data_value); - ASSERT_EQ(Res_value::TYPE_INT_DEC, entry->data_type); + ASSERT_EQ(1U, entry->value.data_value); + ASSERT_EQ(Res_value::TYPE_INT_DEC, entry->value.data_type); + ASSERT_EQ("port", entry->config); it = pairs->pairs[1]; ASSERT_EQ("com.example.target:string/int3", it.resource_name); - entry = std::get_if<TargetValue>(&it.value); + entry = std::get_if<TargetValueWithConfig>(&it.value); ASSERT_NE(nullptr, entry); - ASSERT_EQ(0x7f010000, entry->data_value); - ASSERT_EQ(Res_value::TYPE_REFERENCE, entry->data_type); + ASSERT_EQ(0x7f010000, entry->value.data_value); + ASSERT_EQ(Res_value::TYPE_REFERENCE, entry->value.data_type); + ASSERT_EQ("xxhdpi-v7", entry->config); it = pairs->pairs[2]; + ASSERT_EQ("com.example.target:string/string1", it.resource_name); + entry = std::get_if<TargetValueWithConfig>(&it.value); + ASSERT_NE(nullptr, entry); + ASSERT_EQ(Res_value::TYPE_STRING, entry->value.data_type); + ASSERT_EQ(std::string("foobar"), string_pool.string8At(entry->value.data_value).value_or("")); + ASSERT_EQ("en-rUS-normal-xxhdpi-v21", entry->config); + + it = pairs->pairs[3]; ASSERT_EQ("com.example.target.split:integer/int2", it.resource_name); - entry = std::get_if<TargetValue>(&it.value); + entry = std::get_if<TargetValueWithConfig>(&it.value); ASSERT_NE(nullptr, entry); - ASSERT_EQ(2U, entry->data_value); - ASSERT_EQ(Res_value::TYPE_INT_DEC, entry->data_type); + ASSERT_EQ(2U, entry->value.data_value); + ASSERT_EQ(Res_value::TYPE_INT_DEC, entry->value.data_type); + ASSERT_EQ("land", entry->config); } TEST(FabricatedOverlayTests, SetResourceValueBadArgs) { { auto builder = FabricatedOverlay::Builder("com.example.overlay", "SandTheme", "com.example.target") - .SetResourceValue("int1", Res_value::TYPE_INT_DEC, 1U); + .SetResourceValue("int1", Res_value::TYPE_INT_DEC, 1U, ""); ASSERT_FALSE(builder.Build()); } { auto builder = FabricatedOverlay::Builder("com.example.overlay", "SandTheme", "com.example.target") - .SetResourceValue("com.example.target:int2", Res_value::TYPE_INT_DEC, 1U); + .SetResourceValue("com.example.target:int2", Res_value::TYPE_INT_DEC, 1U, ""); ASSERT_FALSE(builder.Build()); } } @@ -103,7 +123,9 @@ TEST(FabricatedOverlayTests, SerializeAndDeserialize) { auto overlay = FabricatedOverlay::Builder("com.example.overlay", "SandTheme", "com.example.target") .SetOverlayable("TestResources") - .SetResourceValue("com.example.target:integer/int1", Res_value::TYPE_INT_DEC, 1U) + .SetResourceValue("com.example.target:integer/int1", Res_value::TYPE_INT_DEC, 1U, "") + .SetResourceValue( + "com.example.target:string/string1", Res_value::TYPE_STRING, "foobar", "") .Build(); ASSERT_TRUE(overlay); TemporaryFile tf; @@ -126,14 +148,23 @@ TEST(FabricatedOverlayTests, SerializeAndDeserialize) { auto pairs = (*container)->GetOverlayData(*info); ASSERT_TRUE(pairs) << pairs.GetErrorMessage(); - EXPECT_EQ(1U, pairs->pairs.size()); + EXPECT_EQ(2U, pairs->pairs.size()); + auto string_pool = ResStringPool(pairs->string_pool_data->data.get(), + pairs->string_pool_data->data_length, false); auto& it = pairs->pairs[0]; ASSERT_EQ("com.example.target:integer/int1", it.resource_name); - auto entry = std::get_if<TargetValue>(&it.value); + auto entry = std::get_if<TargetValueWithConfig>(&it.value); + ASSERT_NE(nullptr, entry); + EXPECT_EQ(1U, entry->value.data_value); + EXPECT_EQ(Res_value::TYPE_INT_DEC, entry->value.data_type); + + it = pairs->pairs[1]; + ASSERT_EQ("com.example.target:string/string1", it.resource_name); + entry = std::get_if<TargetValueWithConfig>(&it.value); ASSERT_NE(nullptr, entry); - EXPECT_EQ(1U, entry->data_value); - EXPECT_EQ(Res_value::TYPE_INT_DEC, entry->data_type); + ASSERT_EQ(Res_value::TYPE_STRING, entry->value.data_type); + ASSERT_EQ(std::string("foobar"), string_pool.string8At(entry->value.data_value).value_or("")); } } // namespace android::idmap2 diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp index e1b782972d3c..5a7fcd519cfd 100644 --- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp +++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp @@ -46,7 +46,6 @@ using ::android::base::StringPrintf; using ::android::util::ExecuteBinary; -using ::testing::NotNull; namespace android::idmap2 { @@ -95,8 +94,8 @@ TEST_F(Idmap2BinaryTests, Create) { "--overlay-name", TestConstants::OVERLAY_NAME_DEFAULT, "--idmap-path", GetIdmapPath()}); // clang-format on - ASSERT_THAT(result, NotNull()); - ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr_str; + ASSERT_TRUE((bool)result); + ASSERT_EQ(result.status, EXIT_SUCCESS) << result.stderr_str; struct stat st; ASSERT_EQ(stat(GetIdmapPath().c_str(), &st), 0); @@ -122,33 +121,33 @@ TEST_F(Idmap2BinaryTests, Dump) { "--overlay-name", TestConstants::OVERLAY_NAME_DEFAULT, "--idmap-path", GetIdmapPath()}); // clang-format on - ASSERT_THAT(result, NotNull()); - ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr_str; + ASSERT_TRUE((bool)result); + ASSERT_EQ(result.status, EXIT_SUCCESS) << result.stderr_str; // clang-format off result = ExecuteBinary({"idmap2", "dump", "--idmap-path", GetIdmapPath()}); // clang-format on - ASSERT_THAT(result, NotNull()); - ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr_str; + ASSERT_TRUE((bool)result); + ASSERT_EQ(result.status, EXIT_SUCCESS) << result.stderr_str; - ASSERT_NE(result->stdout_str.find(StringPrintf("0x%08x -> 0x%08x", R::target::integer::int1, + ASSERT_NE(result.stdout_str.find(StringPrintf("0x%08x -> 0x%08x", R::target::integer::int1, R::overlay::integer::int1)), std::string::npos) - << result->stdout_str; - ASSERT_NE(result->stdout_str.find(StringPrintf("0x%08x -> 0x%08x", R::target::string::str1, + << result.stdout_str; + ASSERT_NE(result.stdout_str.find(StringPrintf("0x%08x -> 0x%08x", R::target::string::str1, R::overlay::string::str1)), std::string::npos) - << result->stdout_str; - ASSERT_NE(result->stdout_str.find(StringPrintf("0x%08x -> 0x%08x", R::target::string::str3, + << result.stdout_str; + ASSERT_NE(result.stdout_str.find(StringPrintf("0x%08x -> 0x%08x", R::target::string::str3, R::overlay::string::str3)), std::string::npos) - << result->stdout_str; - ASSERT_NE(result->stdout_str.find(StringPrintf("0x%08x -> 0x%08x", R::target::string::str4, + << result.stdout_str; + ASSERT_NE(result.stdout_str.find(StringPrintf("0x%08x -> 0x%08x", R::target::string::str4, R::overlay::string::str4)), std::string::npos) - << result->stdout_str; + << result.stdout_str; // clang-format off result = ExecuteBinary({"idmap2", @@ -156,9 +155,9 @@ TEST_F(Idmap2BinaryTests, Dump) { "--verbose", "--idmap-path", GetIdmapPath()}); // clang-format on - ASSERT_THAT(result, NotNull()); - ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr_str; - ASSERT_NE(result->stdout_str.find("00000000: 504d4449 magic"), std::string::npos); + ASSERT_TRUE((bool)result); + ASSERT_EQ(result.status, EXIT_SUCCESS) << result.stderr_str; + ASSERT_NE(result.stdout_str.find("00000000: 504d4449 magic"), std::string::npos); // clang-format off result = ExecuteBinary({"idmap2", @@ -166,8 +165,8 @@ TEST_F(Idmap2BinaryTests, Dump) { "--verbose", "--idmap-path", GetTestDataPath() + "/DOES-NOT-EXIST"}); // clang-format on - ASSERT_THAT(result, NotNull()); - ASSERT_NE(result->status, EXIT_SUCCESS); + ASSERT_TRUE((bool)result); + ASSERT_NE(result.status, EXIT_SUCCESS); unlink(GetIdmapPath().c_str()); } @@ -183,8 +182,8 @@ TEST_F(Idmap2BinaryTests, Lookup) { "--overlay-name", TestConstants::OVERLAY_NAME_DEFAULT, "--idmap-path", GetIdmapPath()}); // clang-format on - ASSERT_THAT(result, NotNull()); - ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr_str; + ASSERT_TRUE((bool)result); + ASSERT_EQ(result.status, EXIT_SUCCESS) << result.stderr_str; // clang-format off result = ExecuteBinary({"idmap2", @@ -193,10 +192,10 @@ TEST_F(Idmap2BinaryTests, Lookup) { "--config", "", "--resid", StringPrintf("0x%08x", R::target::string::str1)}); // clang-format on - ASSERT_THAT(result, NotNull()); - ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr_str; - ASSERT_NE(result->stdout_str.find("overlay-1"), std::string::npos); - ASSERT_EQ(result->stdout_str.find("overlay-1-sv"), std::string::npos); + ASSERT_TRUE((bool)result); + ASSERT_EQ(result.status, EXIT_SUCCESS) << result.stderr_str; + ASSERT_NE(result.stdout_str.find("overlay-1"), std::string::npos); + ASSERT_EQ(result.stdout_str.find("overlay-1-sv"), std::string::npos); // clang-format off result = ExecuteBinary({"idmap2", @@ -205,10 +204,10 @@ TEST_F(Idmap2BinaryTests, Lookup) { "--config", "", "--resid", "test.target:string/str1"}); // clang-format on - ASSERT_THAT(result, NotNull()); - ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr_str; - ASSERT_NE(result->stdout_str.find("overlay-1"), std::string::npos); - ASSERT_EQ(result->stdout_str.find("overlay-1-sv"), std::string::npos); + ASSERT_TRUE((bool)result); + ASSERT_EQ(result.status, EXIT_SUCCESS) << result.stderr_str; + ASSERT_NE(result.stdout_str.find("overlay-1"), std::string::npos); + ASSERT_EQ(result.stdout_str.find("overlay-1-sv"), std::string::npos); // clang-format off result = ExecuteBinary({"idmap2", @@ -217,9 +216,9 @@ TEST_F(Idmap2BinaryTests, Lookup) { "--config", "sv", "--resid", "test.target:string/str1"}); // clang-format on - ASSERT_THAT(result, NotNull()); - ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr_str; - ASSERT_NE(result->stdout_str.find("overlay-1-sv"), std::string::npos); + ASSERT_TRUE((bool)result); + ASSERT_EQ(result.status, EXIT_SUCCESS) << result.stderr_str; + ASSERT_NE(result.stdout_str.find("overlay-1-sv"), std::string::npos); unlink(GetIdmapPath().c_str()); } @@ -234,8 +233,8 @@ TEST_F(Idmap2BinaryTests, InvalidCommandLineOptions) { auto result = ExecuteBinary({"idmap2", "create"}); // clang-format on - ASSERT_THAT(result, NotNull()); - ASSERT_NE(result->status, EXIT_SUCCESS); + ASSERT_TRUE((bool)result); + ASSERT_NE(result.status, EXIT_SUCCESS); // missing argument to option // clang-format off @@ -246,8 +245,8 @@ TEST_F(Idmap2BinaryTests, InvalidCommandLineOptions) { "--overlay-name", TestConstants::OVERLAY_NAME_DEFAULT, "--idmap-path"}); // clang-format on - ASSERT_THAT(result, NotNull()); - ASSERT_NE(result->status, EXIT_SUCCESS); + ASSERT_TRUE((bool)result); + ASSERT_NE(result.status, EXIT_SUCCESS); // invalid target apk path // clang-format off @@ -258,8 +257,8 @@ TEST_F(Idmap2BinaryTests, InvalidCommandLineOptions) { "--overlay-name", TestConstants::OVERLAY_NAME_DEFAULT, "--idmap-path", GetIdmapPath()}); // clang-format on - ASSERT_THAT(result, NotNull()); - ASSERT_NE(result->status, EXIT_SUCCESS); + ASSERT_TRUE((bool)result); + ASSERT_NE(result.status, EXIT_SUCCESS); // unknown policy // clang-format off @@ -271,8 +270,8 @@ TEST_F(Idmap2BinaryTests, InvalidCommandLineOptions) { "--idmap-path", GetIdmapPath(), "--policy", "this-does-not-exist"}); // clang-format on - ASSERT_THAT(result, NotNull()); - ASSERT_NE(result->status, EXIT_SUCCESS); + ASSERT_TRUE((bool)result); + ASSERT_NE(result.status, EXIT_SUCCESS); } } // namespace android::idmap2 diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp index 738b9cf237c9..7b7dc17deea4 100644 --- a/cmds/idmap2/tests/IdmapTests.cpp +++ b/cmds/idmap2/tests/IdmapTests.cpp @@ -47,10 +47,11 @@ namespace android::idmap2 { ASSERT_EQ((entry).target_id, (target_resid)); \ ASSERT_EQ((entry).overlay_id, (overlay_resid)) -#define ASSERT_TARGET_INLINE_ENTRY(entry, target_resid, expected_type, expected_value) \ - ASSERT_EQ((entry).target_id, target_resid); \ - ASSERT_EQ((entry).value.data_type, (expected_type)); \ - ASSERT_EQ((entry).value.data_value, (expected_value)) +#define ASSERT_TARGET_INLINE_ENTRY(entry, target_resid, ex_config, expected_type, expected_value) \ + ASSERT_EQ((entry).target_id, target_resid); \ + ASSERT_EQ((entry).values.begin()->first.to_string(), (ex_config)); \ + ASSERT_EQ((entry).values.begin()->second.data_type, (expected_type)); \ + ASSERT_EQ((entry).values.begin()->second.data_value, (expected_value)) #define ASSERT_OVERLAY_ENTRY(entry, overlay_resid, target_resid) \ ASSERT_EQ((entry).overlay_id, (overlay_resid)); \ @@ -67,7 +68,7 @@ TEST(IdmapTests, CreateIdmapHeaderFromBinaryStream) { std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream); ASSERT_THAT(header, NotNull()); ASSERT_EQ(header->GetMagic(), 0x504d4449U); - ASSERT_EQ(header->GetVersion(), 0x08U); + ASSERT_EQ(header->GetVersion(), 0x09U); ASSERT_EQ(header->GetTargetCrc(), 0x1234U); ASSERT_EQ(header->GetOverlayCrc(), 0x5678U); ASSERT_EQ(header->GetFulfilledPolicies(), 0x11); @@ -122,8 +123,8 @@ TEST(IdmapTests, CreateIdmapDataFromBinaryStream) { const auto& target_inline_entries = data->GetTargetInlineEntries(); ASSERT_EQ(target_inline_entries.size(), 1U); - ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], 0x7f040000, Res_value::TYPE_INT_HEX, - 0x12345678); + ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], 0x7f040000, "land-xxhdpi-v7", + Res_value::TYPE_INT_HEX, 0x12345678); const auto& overlay_entries = data->GetOverlayEntries(); ASSERT_EQ(target_entries.size(), 3U); @@ -142,7 +143,7 @@ TEST(IdmapTests, CreateIdmapFromBinaryStream) { ASSERT_THAT(idmap->GetHeader(), NotNull()); ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U); - ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x08U); + ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x09U); ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x1234U); ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x5678U); ASSERT_EQ(idmap->GetHeader()->GetFulfilledPolicies(), kIdmapRawDataPolicies); @@ -165,8 +166,8 @@ TEST(IdmapTests, CreateIdmapFromBinaryStream) { const auto& target_inline_entries = data->GetTargetInlineEntries(); ASSERT_EQ(target_inline_entries.size(), 1U); - ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], 0x7f040000, Res_value::TYPE_INT_HEX, - 0x12345678); + ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], 0x7f040000, "land-xxhdpi-v7", + Res_value::TYPE_INT_HEX, 0x12345678); const auto& overlay_entries = data->GetOverlayEntries(); ASSERT_EQ(target_entries.size(), 3U); @@ -203,7 +204,7 @@ TEST(IdmapTests, CreateIdmapHeaderFromApkAssets) { ASSERT_THAT(idmap->GetHeader(), NotNull()); ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U); - ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x08U); + ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x09U); ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), android::idmap2::TestConstants::TARGET_CRC); ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), android::idmap2::TestConstants::OVERLAY_CRC); ASSERT_EQ(idmap->GetHeader()->GetFulfilledPolicies(), PolicyFlags::PUBLIC); @@ -261,8 +262,9 @@ TEST(IdmapTests, FabricatedOverlay) { auto frro = FabricatedOverlay::Builder("com.example.overlay", "SandTheme", "test.target") .SetOverlayable("TestResources") - .SetResourceValue("integer/int1", Res_value::TYPE_INT_DEC, 2U) - .SetResourceValue("string/str1", Res_value::TYPE_REFERENCE, 0x7f010000) + .SetResourceValue("integer/int1", Res_value::TYPE_INT_DEC, 2U, "land-xxhdpi-v7") + .SetResourceValue("string/str1", Res_value::TYPE_REFERENCE, 0x7f010000, "land") + .SetResourceValue("string/str2", Res_value::TYPE_STRING, "foobar", "xxhdpi-v7") .Build(); ASSERT_TRUE(frro); @@ -288,12 +290,19 @@ TEST(IdmapTests, FabricatedOverlay) { ASSERT_EQ(data->GetTargetEntries().size(), 0U); ASSERT_EQ(data->GetOverlayEntries().size(), 0U); + auto string_pool_data = data->GetStringPoolData(); + auto string_pool = ResStringPool(string_pool_data.data(), string_pool_data.size(), false); + + const auto& target_inline_entries = data->GetTargetInlineEntries(); - ASSERT_EQ(target_inline_entries.size(), 2U); - ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], R::target::integer::int1, + ASSERT_EQ(target_inline_entries.size(), 3U); + ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], R::target::integer::int1, "land-xxhdpi-v7", Res_value::TYPE_INT_DEC, 2U); - ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[1], R::target::string::str1, + ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[1], R::target::string::str1, "land", Res_value::TYPE_REFERENCE, 0x7f010000); + ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[2], R::target::string::str2, "xxhdpi-v7", + Res_value::TYPE_STRING, + (uint32_t) (string_pool.indexOfString(u"foobar", 6)).value_or(-1)); } TEST(IdmapTests, FailCreateIdmapInvalidName) { @@ -434,9 +443,9 @@ TEST(IdmapTests, CreateIdmapDataInlineResources) { constexpr size_t overlay_string_pool_size = 10U; const auto& target_inline_entries = data->GetTargetInlineEntries(); ASSERT_EQ(target_inline_entries.size(), 2U); - ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], R::target::integer::int1, + ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], R::target::integer::int1, std::string(), Res_value::TYPE_INT_DEC, 73U); // -> 73 - ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[1], R::target::string::str1, + ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[1], R::target::string::str1, std::string(), Res_value::TYPE_STRING, overlay_string_pool_size + 0U); // -> "Hello World" diff --git a/cmds/idmap2/tests/R.h b/cmds/idmap2/tests/R.h index 89219c9c8213..ad998b9a7a4c 100644 --- a/cmds/idmap2/tests/R.h +++ b/cmds/idmap2/tests/R.h @@ -41,6 +41,7 @@ namespace R::target { constexpr ResourceId policy_system = 0x7f02000c; constexpr ResourceId policy_system_vendor = 0x7f02000d; constexpr ResourceId str1 = 0x7f02000e; + constexpr ResourceId str2 = 0x7f02000f; constexpr ResourceId str3 = 0x7f020010; constexpr ResourceId str4 = 0x7f020011; } // namespace string diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp index a6371cb74f2e..7112eeb9ea0c 100644 --- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp +++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp @@ -64,7 +64,7 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) { (*idmap)->accept(&visitor); ASSERT_CONTAINS_REGEX(ADDRESS "504d4449 magic\n", stream.str()); - ASSERT_CONTAINS_REGEX(ADDRESS "00000008 version\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "00000009 version\n", stream.str()); ASSERT_CONTAINS_REGEX( StringPrintf(ADDRESS "%s target crc\n", android::idmap2::TestConstants::TARGET_CRC_STRING), stream.str()); @@ -75,6 +75,8 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) { ASSERT_CONTAINS_REGEX(ADDRESS "00000001 enforce overlayable\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000004 target entry count", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000000 target inline entry count", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "00000000 target inline entry value count", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "00000000 config count", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000004 overlay entry count", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "0000000a string pool index offset", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 target id: integer/int1", stream.str()); @@ -111,7 +113,7 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitorWithoutAccessToApks) { (*idmap)->accept(&visitor); ASSERT_CONTAINS_REGEX(ADDRESS "504d4449 magic\n", stream.str()); - ASSERT_CONTAINS_REGEX(ADDRESS "00000008 version\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "00000009 version\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00001234 target crc\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00005678 overlay crc\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000011 fulfilled policies: public|signature\n", stream.str()); @@ -124,17 +126,25 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitorWithoutAccessToApks) { ASSERT_CONTAINS_REGEX(ADDRESS "........ overlay name: OverlayName\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000003 target entry count\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000001 target inline entry count\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "00000001 target inline entry value count", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "00000001 config count", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000003 overlay entry count\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000000 string pool index offset\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 target id\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 overlay id\n", stream.str()); - ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 target id\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "7f030000 target id\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "7f030000 overlay id\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "7f030002 target id\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "7f030001 overlay id\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "7f040000 target id\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "0000000e config: land-xxhdpi-v7 size\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "........ config: land-xxhdpi-v7\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS " 11 type: integer\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "12345678 data\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 overlay id\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "7f030002 target id\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000004 string pool size\n", stream.str()); - ASSERT_CONTAINS_REGEX("000000a4: ........ string pool\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "........ string pool\n", stream.str()); } } // namespace android::idmap2 diff --git a/cmds/idmap2/tests/ResourceMappingTests.cpp b/cmds/idmap2/tests/ResourceMappingTests.cpp index 32b3d1326d92..016d427e7452 100644 --- a/cmds/idmap2/tests/ResourceMappingTests.cpp +++ b/cmds/idmap2/tests/ResourceMappingTests.cpp @@ -111,19 +111,20 @@ Result<Unit> MappingExists(const ResourceMapping& mapping, const ResourceId& tar return Error("Failed to find mapping for target resource"); } - auto actual_overlay_value = std::get_if<TargetValue>(&entry_map->second); - if (actual_overlay_value == nullptr) { + auto config_map = std::get_if<ConfigMap>(&entry_map->second); + if (config_map == nullptr || config_map->empty()) { return Error("Target resource is not mapped to an inline value"); } + auto actual_overlay_value = config_map->begin()->second; - if (actual_overlay_value->data_type != type) { + if (actual_overlay_value.data_type != type) { return Error(R"(Expected type: "0x%02x" Actual type: "0x%02x")", type, - actual_overlay_value->data_type); + actual_overlay_value.data_type); } - if (actual_overlay_value->data_value != value) { + if (actual_overlay_value.data_value != value) { return Error(R"(Expected value: "0x%08x" Actual value: "0x%08x")", type, - actual_overlay_value->data_value); + actual_overlay_value.data_value); } return Result<Unit>({}); @@ -194,8 +195,9 @@ TEST(ResourceMappingTests, InlineResources) { TEST(ResourceMappingTests, FabricatedOverlay) { auto frro = FabricatedOverlay::Builder("com.example.overlay", "SandTheme", "test.target") .SetOverlayable("TestResources") - .SetResourceValue("integer/int1", Res_value::TYPE_INT_DEC, 2U) - .SetResourceValue("string/str1", Res_value::TYPE_REFERENCE, 0x7f010000) + .SetResourceValue("integer/int1", Res_value::TYPE_INT_DEC, 2U, "") + .SetResourceValue("string/str1", Res_value::TYPE_REFERENCE, 0x7f010000, "") + .SetResourceValue("string/str2", Res_value::TYPE_STRING, "foobar", "") .Build(); ASSERT_TRUE(frro); @@ -209,9 +211,14 @@ TEST(ResourceMappingTests, FabricatedOverlay) { ASSERT_TRUE(resources) << resources.GetErrorMessage(); auto& res = *resources; - ASSERT_EQ(res.GetTargetToOverlayMap().size(), 2U); + auto string_pool_data = res.GetStringPoolData(); + auto string_pool = ResStringPool(string_pool_data.data(), string_pool_data.size(), false); + + ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U); ASSERT_EQ(res.GetOverlayToTargetMap().size(), 0U); ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_REFERENCE, 0x7f010000)); + ASSERT_RESULT(MappingExists(res, R::target::string::str2, Res_value::TYPE_STRING, + (uint32_t) (string_pool.indexOfString(u"foobar", 6)).value_or(-1))); ASSERT_RESULT(MappingExists(res, R::target::integer::int1, Res_value::TYPE_INT_DEC, 2U)); } diff --git a/cmds/idmap2/tests/ResultTests.cpp b/cmds/idmap2/tests/ResultTests.cpp index f2f8854cec3a..f9c4fa3c798b 100644 --- a/cmds/idmap2/tests/ResultTests.cpp +++ b/cmds/idmap2/tests/ResultTests.cpp @@ -259,7 +259,8 @@ TEST(ResultTests, CascadeError) { } struct NoCopyContainer { - uint32_t value; // NOLINT(misc-non-private-member-variables-in-classes) + uint32_t value = 0; // NOLINT(misc-non-private-member-variables-in-classes) + NoCopyContainer() = default; NoCopyContainer(const NoCopyContainer&) = delete; NoCopyContainer& operator=(const NoCopyContainer&) = delete; }; @@ -268,7 +269,7 @@ Result<std::unique_ptr<NoCopyContainer>> CreateNoCopyContainer(bool succeed) { if (!succeed) { return Error("foo"); } - std::unique_ptr<NoCopyContainer> p(new NoCopyContainer{0U}); + std::unique_ptr<NoCopyContainer> p(new NoCopyContainer{}); p->value = 42U; return std::move(p); } diff --git a/cmds/idmap2/tests/TestHelpers.h b/cmds/idmap2/tests/TestHelpers.h index 6b5f3a8a98eb..cdc0b8fbb87e 100644 --- a/cmds/idmap2/tests/TestHelpers.h +++ b/cmds/idmap2/tests/TestHelpers.h @@ -30,7 +30,7 @@ const unsigned char kIdmapRawData[] = { 0x49, 0x44, 0x4d, 0x50, // 0x4: version - 0x08, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, // 0x8: target crc 0x34, 0x12, 0x00, 0x00, @@ -76,66 +76,123 @@ const unsigned char kIdmapRawData[] = { // 0x58: target_inline_entry_count 0x01, 0x00, 0x00, 0x00, - // 0x5c: overlay_entry_count + // 0x5c: target_inline_entry_value_count + 0x01, 0x00, 0x00, 0x00, + + // 0x60: config_count + 0x01, 0x00, 0x00, 0x00, + + // 0x64: overlay_entry_count 0x03, 0x00, 0x00, 0x00, - // 0x60: string_pool_offset + // 0x68: string_pool_offset 0x00, 0x00, 0x00, 0x00, // TARGET ENTRIES - // 0x64: target id (0x7f020000) + // 0x6c: target id (0x7f020000) 0x00, 0x00, 0x02, 0x7f, - // 0x68: overlay_id (0x7f020000) + // 0x70: overlay_id (0x7f020000) 0x00, 0x00, 0x02, 0x7f, - // 0x6c: target id (0x7f030000) + // 0x74: target id (0x7f030000) 0x00, 0x00, 0x03, 0x7f, - // 0x70: overlay_id (0x7f030000) + // 0x78: overlay_id (0x7f030000) 0x00, 0x00, 0x03, 0x7f, - // 0x74: target id (0x7f030002) + // 0x7c: target id (0x7f030002) 0x02, 0x00, 0x03, 0x7f, - // 0x78: overlay_id (0x7f030001) + // 0x80: overlay_id (0x7f030001) 0x01, 0x00, 0x03, 0x7f, // INLINE TARGET ENTRIES - // 0x7c: target_id + // 0x84: target_id 0x00, 0x00, 0x04, 0x7f, - // 0x80: Res_value::size (value ignored by idmap) + // 0x88: start value index + 0x00, 0x00, 0x00, 0x00, + + // 0x8c: value count + 0x01, 0x00, 0x00, 0x00, + + // INLINE TARGET ENTRY VALUES + + // 0x90: config index + 0x00, 0x00, 0x00, 0x00, + + // 0x94: Res_value::size (value ignored by idmap) 0x08, 0x00, - // 0x82: Res_value::res0 (value ignored by idmap) + // 0x98: Res_value::res0 (value ignored by idmap) 0x00, - // 0x83: Res_value::dataType (TYPE_INT_HEX) + // 0x9c: Res_value::dataType (TYPE_INT_HEX) 0x11, - // 0x84: Res_value::data + // 0xa0: Res_value::data 0x78, 0x56, 0x34, 0x12, + // CONFIGURATIONS + + // 0xa4: ConfigDescription + // size + 0x40, 0x00, 0x00, 0x00, + // 0xa8: imsi + 0x00, 0x00, 0x00, 0x00, + // 0xac: locale + 0x00, 0x00, 0x00, 0x00, + // 0xb0: screenType + 0x02, 0x00, 0xe0, 0x01, + // 0xb4: input + 0x00, 0x00, 0x00, 0x00, + // 0xb8: screenSize + 0x00, 0x00, 0x00, 0x00, + // 0xbc: version + 0x07, 0x00, 0x00, 0x00, + // 0xc0: screenConfig + 0x00, 0x00, 0x00, 0x00, + // 0xc4: screenSizeDp + 0x00, 0x00, 0x00, 0x00, + // 0xc8: localeScript + 0x00, 0x00, 0x00, 0x00, + // 0xcc: localVariant(1) + 0x00, 0x00, 0x00, 0x00, + // 0xd0: localVariant(2) + 0x00, 0x00, 0x00, 0x00, + // 0xd4: screenConfig2 + 0x00, 0x00, 0x00, 0x00, + // 0xd8: localeScriptWasComputed + 0x00, + // 0xd9: localeNumberingSystem(1) + 0x00, 0x00, 0x00, 0x00, + // 0xdd: localeNumberingSystem(2) + 0x00, 0x00, 0x00, 0x00, + + // 0xe1: padding + 0x00, 0x00, 0x00, + + // OVERLAY ENTRIES - // 0x88: 0x7f020000 -> 0x7f020000 + // 0xe4: 0x7f020000 -> 0x7f020000 0x00, 0x00, 0x02, 0x7f, 0x00, 0x00, 0x02, 0x7f, - // 0x90: 0x7f030000 -> 0x7f030000 + // 0xec: 0x7f030000 -> 0x7f030000 0x00, 0x00, 0x03, 0x7f, 0x00, 0x00, 0x03, 0x7f, - // 0x98: 0x7f030001 -> 0x7f030002 + // 0xf4: 0x7f030001 -> 0x7f030002 0x01, 0x00, 0x03, 0x7f, 0x02, 0x00, 0x03, 0x7f, - // 0xa0: string pool + // 0xfc: string pool // string length, 0x04, 0x00, 0x00, 0x00, - // 0xa4 string contents "test" + // 0x100 string contents "test" 0x74, 0x65, 0x73, 0x74}; -const unsigned int kIdmapRawDataLen = 0xa8; +constexpr unsigned int kIdmapRawDataLen = std::size(kIdmapRawData); const unsigned int kIdmapRawDataOffset = 0x54; const unsigned int kIdmapRawDataTargetCrc = 0x1234; const unsigned int kIdmapRawOverlayCrc = 0x5678; diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp index 7e6a521ca46c..d7222d248911 100644 --- a/cmds/screencap/screencap.cpp +++ b/cmds/screencap/screencap.cpp @@ -45,17 +45,23 @@ using namespace android; #define COLORSPACE_SRGB 1 #define COLORSPACE_DISPLAY_P3 2 -static void usage(const char* pname, DisplayId displayId) +static void usage(const char* pname, std::optional<PhysicalDisplayId> displayId) { + std::string defaultDisplayStr = ""; + if (!displayId) { + defaultDisplayStr = ""; + } else { + defaultDisplayStr = " (default: " + to_string(*displayId) + ")"; + } fprintf(stderr, "usage: %s [-hp] [-d display-id] [FILENAME]\n" " -h: this message\n" " -p: save the file as a png.\n" - " -d: specify the display ID to capture (default: %s)\n" + " -d: specify the display ID to capture%s\n" " see \"dumpsys SurfaceFlinger --display-id\" for valid display IDs.\n" "If FILENAME ends with .png it will be saved as a png.\n" "If FILENAME is not given, the results will be printed to stdout.\n", - pname, to_string(displayId).c_str()); + pname, defaultDisplayStr.c_str()); } static int32_t flinger2bitmapFormat(PixelFormat f) @@ -121,12 +127,12 @@ static status_t notifyMediaScanner(const char* fileName) { int main(int argc, char** argv) { - std::optional<DisplayId> displayId = SurfaceComposerClient::getInternalDisplayId(); - if (!displayId) { - fprintf(stderr, "Failed to get ID for internal display\n"); + const std::vector<PhysicalDisplayId> ids = SurfaceComposerClient::getPhysicalDisplayIds(); + if (ids.empty()) { + fprintf(stderr, "Failed to get ID for any displays.\n"); return 1; } - + std::optional<PhysicalDisplayId> displayId; const char* pname = argv[0]; bool png = false; int c; @@ -136,18 +142,34 @@ int main(int argc, char** argv) png = true; break; case 'd': - displayId = DisplayId::fromValue(atoll(optarg)); + displayId = DisplayId::fromValue<PhysicalDisplayId>(atoll(optarg)); if (!displayId) { - fprintf(stderr, "Invalid display ID\n"); + fprintf(stderr, "Invalid display ID: %s\n", optarg); return 1; } break; case '?': case 'h': - usage(pname, *displayId); + if (ids.size() == 1) { + displayId = ids.front(); + } + usage(pname, displayId); return 1; } } + + if (!displayId) { // no diplsay id is specified + displayId = ids.front(); + if (ids.size() > 1) { + fprintf(stderr, + "[Warning] Multiple displays were found, but no display id was specified! " + "Defaulting to the first display found, however this default is not guaranteed " + "to be consistent across captures. A display id should be specified.\n"); + fprintf(stderr, "A display ID can be specified with the [-d display-id] option.\n"); + fprintf(stderr, "See \"dumpsys SurfaceFlinger --display-id\" for valid display IDs.\n"); + } + } + argc -= optind; argv += optind; @@ -169,7 +191,7 @@ int main(int argc, char** argv) } if (fd == -1) { - usage(pname, *displayId); + usage(pname, displayId); return 1; } @@ -193,7 +215,7 @@ int main(int argc, char** argv) } ScreenCaptureResults captureResults = captureListener->waitForResults(); - if (captureResults.result != NO_ERROR) { + if (!captureResults.fenceResult.ok()) { close(fd); return 1; } diff --git a/cmds/telecom/src/com/android/commands/telecom/Telecom.java b/cmds/telecom/src/com/android/commands/telecom/Telecom.java index d464e266ac36..13c7946a033f 100644 --- a/cmds/telecom/src/com/android/commands/telecom/Telecom.java +++ b/cmds/telecom/src/com/android/commands/telecom/Telecom.java @@ -54,7 +54,7 @@ public final class Telecom extends BaseCommand { (new Telecom()).run(args); } - + private static final String CALLING_PACKAGE = Telecom.class.getPackageName(); private static final String COMMAND_SET_PHONE_ACCOUNT_ENABLED = "set-phone-account-enabled"; private static final String COMMAND_SET_PHONE_ACCOUNT_DISABLED = "set-phone-account-disabled"; private static final String COMMAND_REGISTER_PHONE_ACCOUNT = "register-phone-account"; @@ -297,7 +297,7 @@ public final class Telecom extends BaseCommand { final String label = nextArgRequired(); PhoneAccount account = PhoneAccount.builder(handle, label) .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER).build(); - mTelecomService.registerPhoneAccount(account); + mTelecomService.registerPhoneAccount(account, CALLING_PACKAGE); System.out.println("Success - " + handle + " registered."); } @@ -327,7 +327,7 @@ public final class Telecom extends BaseCommand { .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL) .build(); - mTelecomService.registerPhoneAccount(account); + mTelecomService.registerPhoneAccount(account, CALLING_PACKAGE); System.out.println("Success - " + handle + " registered."); } @@ -369,7 +369,7 @@ public final class Telecom extends BaseCommand { private void runUnregisterPhoneAccount() throws RemoteException { final PhoneAccountHandle handle = getPhoneAccountHandleFromArgs(); - mTelecomService.unregisterPhoneAccount(handle); + mTelecomService.unregisterPhoneAccount(handle, CALLING_PACKAGE); System.out.println("Success - " + handle + " unregistered."); } @@ -406,11 +406,11 @@ public final class Telecom extends BaseCommand { } private void runGetDefaultDialer() throws RemoteException { - System.out.println(mTelecomService.getDefaultDialerPackage()); + System.out.println(mTelecomService.getDefaultDialerPackage(CALLING_PACKAGE)); } private void runGetSystemDialer() throws RemoteException { - System.out.println(mTelecomService.getSystemDialerPackage()); + System.out.println(mTelecomService.getSystemDialerPackage(CALLING_PACKAGE)); } private void runWaitOnHandler() throws RemoteException { diff --git a/cmds/uinput/jni/com_android_commands_uinput_Device.cpp b/cmds/uinput/jni/com_android_commands_uinput_Device.cpp index 06fa2aac2c7e..3f4163dc54ec 100644 --- a/cmds/uinput/jni/com_android_commands_uinput_Device.cpp +++ b/cmds/uinput/jni/com_android_commands_uinput_Device.cpp @@ -99,6 +99,7 @@ JNIEnv* DeviceCallback::getJNIEnv() { std::unique_ptr<UinputDevice> UinputDevice::open(int32_t id, const char* name, int32_t vid, int32_t pid, uint16_t bus, uint32_t ffEffectsMax, + const char* port, std::unique_ptr<DeviceCallback> callback) { android::base::unique_fd fd(::open(UINPUT_PATH, O_RDWR | O_NONBLOCK | O_CLOEXEC)); if (!fd.ok()) { @@ -131,6 +132,9 @@ std::unique_ptr<UinputDevice> UinputDevice::open(int32_t id, const char* name, i return nullptr; } + // set the physical port. + ::ioctl(fd, UI_SET_PHYS, port); + if (::ioctl(fd, UI_DEV_CREATE) != 0) { ALOGE("Unable to create uinput device: %s.", strerror(errno)); return nullptr; @@ -240,17 +244,19 @@ std::vector<int32_t> toVector(JNIEnv* env, jintArray javaArray) { } static jlong openUinputDevice(JNIEnv* env, jclass /* clazz */, jstring rawName, jint id, jint vid, - jint pid, jint bus, jint ffEffectsMax, jobject callback) { + jint pid, jint bus, jint ffEffectsMax, jstring rawPort, + jobject callback) { ScopedUtfChars name(env, rawName); if (name.c_str() == nullptr) { return 0; } + ScopedUtfChars port(env, rawPort); std::unique_ptr<uinput::DeviceCallback> cb = std::make_unique<uinput::DeviceCallback>(env, callback); std::unique_ptr<uinput::UinputDevice> d = - uinput::UinputDevice::open(id, name.c_str(), vid, pid, bus, ffEffectsMax, + uinput::UinputDevice::open(id, name.c_str(), vid, pid, bus, ffEffectsMax, port.c_str(), std::move(cb)); return reinterpret_cast<jlong>(d.release()); } @@ -303,7 +309,7 @@ static void setAbsInfo(JNIEnv* env, jclass /* clazz */, jint handle, jint axisCo static JNINativeMethod sMethods[] = { {"nativeOpenUinputDevice", - "(Ljava/lang/String;IIIII" + "(Ljava/lang/String;IIIIILjava/lang/String;" "Lcom/android/commands/uinput/Device$DeviceCallback;)J", reinterpret_cast<void*>(openUinputDevice)}, {"nativeInjectEvent", "(JIII)V", reinterpret_cast<void*>(injectEvent)}, diff --git a/cmds/uinput/jni/com_android_commands_uinput_Device.h b/cmds/uinput/jni/com_android_commands_uinput_Device.h index 5a9a06cfb32e..6da3d7968ed0 100644 --- a/cmds/uinput/jni/com_android_commands_uinput_Device.h +++ b/cmds/uinput/jni/com_android_commands_uinput_Device.h @@ -48,6 +48,7 @@ class UinputDevice { public: static std::unique_ptr<UinputDevice> open(int32_t id, const char* name, int32_t vid, int32_t pid, uint16_t bus, uint32_t ff_effects_max, + const char* port, std::unique_ptr<DeviceCallback> callback); virtual ~UinputDevice(); diff --git a/cmds/uinput/src/com/android/commands/uinput/Device.java b/cmds/uinput/src/com/android/commands/uinput/Device.java index 62bee7b964bd..732b33d60c15 100644 --- a/cmds/uinput/src/com/android/commands/uinput/Device.java +++ b/cmds/uinput/src/com/android/commands/uinput/Device.java @@ -61,7 +61,7 @@ public class Device { } private static native long nativeOpenUinputDevice(String name, int id, int vid, int pid, - int bus, int ffEffectsMax, DeviceCallback callback); + int bus, int ffEffectsMax, String port, DeviceCallback callback); private static native void nativeCloseUinputDevice(long ptr); private static native void nativeInjectEvent(long ptr, int type, int code, int value); private static native void nativeConfigure(int handle, int code, int[] configs); @@ -69,7 +69,7 @@ public class Device { public Device(int id, String name, int vid, int pid, int bus, SparseArray<int[]> configuration, int ffEffectsMax, - SparseArray<InputAbsInfo> absInfo) { + SparseArray<InputAbsInfo> absInfo, String port) { mId = id; mThread = new HandlerThread("UinputDeviceHandler"); mThread.start(); @@ -88,6 +88,11 @@ public class Device { } else { args.arg1 = id + ":" + vid + ":" + pid; } + if (port != null) { + args.arg2 = port; + } else { + args.arg2 = "uinput:" + id + ":" + vid + ":" + pid; + } mHandler.obtainMessage(MSG_OPEN_UINPUT_DEVICE, args).sendToTarget(); mTimeToSend = SystemClock.uptimeMillis(); @@ -142,7 +147,7 @@ public class Device { case MSG_OPEN_UINPUT_DEVICE: SomeArgs args = (SomeArgs) msg.obj; mPtr = nativeOpenUinputDevice((String) args.arg1, args.argi1, args.argi2, - args.argi3, args.argi4, args.argi5, + args.argi3, args.argi4, args.argi5, (String) args.arg2, new DeviceCallback()); break; case MSG_INJECT_EVENT: diff --git a/cmds/uinput/src/com/android/commands/uinput/Event.java b/cmds/uinput/src/com/android/commands/uinput/Event.java index c4ba05054eda..4b090f5a713c 100644 --- a/cmds/uinput/src/com/android/commands/uinput/Event.java +++ b/cmds/uinput/src/com/android/commands/uinput/Event.java @@ -25,6 +25,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; +import java.util.stream.IntStream; import src.com.android.commands.uinput.InputAbsInfo; @@ -64,6 +65,7 @@ public class Event { private SparseArray<int[]> mConfiguration; private int mDuration; private int mFfEffectsMax = 0; + private String mInputport; private SparseArray<InputAbsInfo> mAbsInfo; public int getId() { @@ -110,6 +112,10 @@ public class Event { return mAbsInfo; } + public String getPort() { + return mInputport; + } + /** * Convert an event to String. */ @@ -124,6 +130,7 @@ public class Event { + ", configuration=" + mConfiguration + ", duration=" + mDuration + ", ff_effects_max=" + mFfEffectsMax + + ", port=" + mInputport + "}"; } @@ -178,6 +185,10 @@ public class Event { mEvent.mAbsInfo = absInfo; } + public void setInputport(String port) { + mEvent.mInputport = port; + } + public Event build() { if (mEvent.mId == -1) { throw new IllegalStateException("No event id"); @@ -262,6 +273,9 @@ public class Event { case "duration": eb.setDuration(readInt()); break; + case "port": + eb.setInputport(mReader.nextString()); + break; default: mReader.skipValue(); } @@ -325,7 +339,7 @@ public class Event { mReader.beginArray(); while (mReader.hasNext()) { int type = 0; - int[] data = null; + IntStream data = null; mReader.beginObject(); while (mReader.hasNext()) { String name = mReader.nextName(); @@ -334,8 +348,7 @@ public class Event { type = readInt(); break; case "data": - data = readIntList().stream() - .mapToInt(Integer::intValue).toArray(); + data = readIntList().stream().mapToInt(Integer::intValue); break; default: consumeRemainingElements(); @@ -346,7 +359,9 @@ public class Event { } mReader.endObject(); if (data != null) { - configuration.put(type, data); + final int[] existing = configuration.get(type); + configuration.put(type, existing == null ? data.toArray() + : IntStream.concat(IntStream.of(existing), data).toArray()); } } mReader.endArray(); diff --git a/cmds/uinput/src/com/android/commands/uinput/Uinput.java b/cmds/uinput/src/com/android/commands/uinput/Uinput.java index f7601a2f7c07..740578e878ac 100644 --- a/cmds/uinput/src/com/android/commands/uinput/Uinput.java +++ b/cmds/uinput/src/com/android/commands/uinput/Uinput.java @@ -123,7 +123,7 @@ public class Uinput { } int id = e.getId(); Device d = new Device(id, e.getName(), e.getVendorId(), e.getProductId(), e.getBus(), - e.getConfiguration(), e.getFfEffectsMax(), e.getAbsInfo()); + e.getConfiguration(), e.getFfEffectsMax(), e.getAbsInfo(), e.getPort()); mDevices.append(id, d); } |