summaryrefslogtreecommitdiff
path: root/cmds
diff options
context:
space:
mode:
Diffstat (limited to 'cmds')
-rw-r--r--cmds/am/src/com/android/commands/am/Instrument.java3
-rw-r--r--cmds/bootanimation/BootAnimation.cpp90
-rw-r--r--cmds/bootanimation/FORMAT.md1
-rw-r--r--cmds/idmap2/Android.bp4
-rw-r--r--cmds/idmap2/idmap2d/Idmap2Service.cpp8
-rw-r--r--cmds/idmap2/idmap2d/aidl/core/android/os/FabricatedOverlayInternalEntry.aidl2
-rw-r--r--cmds/idmap2/include/idmap2/FabricatedOverlay.h19
-rw-r--r--cmds/idmap2/include/idmap2/Idmap.h96
-rw-r--r--cmds/idmap2/include/idmap2/ResourceContainer.h2
-rw-r--r--cmds/idmap2/include/idmap2/ResourceMapping.h6
-rw-r--r--cmds/idmap2/include/idmap2/ResourceUtils.h10
-rw-r--r--cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp29
-rw-r--r--cmds/idmap2/libidmap2/FabricatedOverlay.cpp147
-rw-r--r--cmds/idmap2/libidmap2/Idmap.cpp73
-rw-r--r--cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp19
-rw-r--r--cmds/idmap2/libidmap2/RawPrintVisitor.cpp34
-rw-r--r--cmds/idmap2/libidmap2/ResourceContainer.cpp6
-rw-r--r--cmds/idmap2/libidmap2/ResourceMapping.cpp23
-rw-r--r--cmds/idmap2/libidmap2/proto/fabricated_v1.proto1
-rw-r--r--cmds/idmap2/tests/BinaryStreamVisitorTests.cpp6
-rw-r--r--cmds/idmap2/tests/FabricatedOverlayTests.cpp73
-rw-r--r--cmds/idmap2/tests/Idmap2BinaryTests.cpp81
-rw-r--r--cmds/idmap2/tests/IdmapTests.cpp45
-rw-r--r--cmds/idmap2/tests/R.h1
-rw-r--r--cmds/idmap2/tests/RawPrintVisitorTests.cpp18
-rw-r--r--cmds/idmap2/tests/ResourceMappingTests.cpp25
-rw-r--r--cmds/idmap2/tests/ResultTests.cpp5
-rw-r--r--cmds/idmap2/tests/TestHelpers.h97
-rw-r--r--cmds/screencap/screencap.cpp46
-rw-r--r--cmds/telecom/src/com/android/commands/telecom/Telecom.java12
-rw-r--r--cmds/uinput/jni/com_android_commands_uinput_Device.cpp12
-rw-r--r--cmds/uinput/jni/com_android_commands_uinput_Device.h1
-rw-r--r--cmds/uinput/src/com/android/commands/uinput/Device.java11
-rw-r--r--cmds/uinput/src/com/android/commands/uinput/Event.java23
-rw-r--r--cmds/uinput/src/com/android/commands/uinput/Uinput.java2
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);
}