diff options
Diffstat (limited to 'cmds')
25 files changed, 272 insertions, 125 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..814800bcd9e5 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"; @@ -617,10 +615,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 +648,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 6ef6845c75f2..18ec5a407b24 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-*", @@ -54,7 +56,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", @@ -115,6 +116,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 1b2d905aec0a..083bbf01bf5b 100644 --- a/cmds/idmap2/idmap2d/Idmap2Service.cpp +++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp @@ -234,7 +234,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/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..21862a3635d5 100644 --- a/cmds/idmap2/include/idmap2/ResourceMapping.h +++ b/cmds/idmap2/include/idmap2/ResourceMapping.h @@ -69,7 +69,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..8ec749602c4a 100644 --- a/cmds/idmap2/include/idmap2/ResourceUtils.h +++ b/cmds/idmap2/include/idmap2/ResourceUtils.h @@ -40,6 +40,12 @@ 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; }; namespace utils { 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/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..8ebe5aa46e73 100644 --- a/cmds/idmap2/libidmap2/ResourceMapping.cpp +++ b/cmds/idmap2/libidmap2/ResourceMapping.cpp @@ -160,7 +160,7 @@ Result<ResourceMapping> ResourceMapping::FromContainers(const TargetResourceCont Result<Unit> ResourceMapping::AddMapping( ResourceId target_resource, - const std::variant<OverlayData::ResourceIdValue, TargetValue>& value) { + const std::variant<OverlayData::ResourceIdValue, TargetValueWithConfig>& value) { if (target_map_.find(target_resource) != target_map_.end()) { return Error(R"(target resource id "0x%08x" mapped to multiple values)", target_resource); } @@ -176,8 +176,8 @@ 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 overlay_value = std::get<TargetValueWithConfig>(value); + target_map_.insert(std::make_pair(target_resource, overlay_value.value)); } 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/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/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp index 738b9cf237c9..ee9a424b3050 100644 --- a/cmds/idmap2/tests/IdmapTests.cpp +++ b/cmds/idmap2/tests/IdmapTests.cpp @@ -261,8 +261,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, "") + .SetResourceValue("string/str1", Res_value::TYPE_REFERENCE, 0x7f010000, "") + .SetResourceValue("string/str2", Res_value::TYPE_STRING, "foobar", "") .Build(); ASSERT_TRUE(frro); @@ -288,12 +289,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_EQ(target_inline_entries.size(), 3U); ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], R::target::integer::int1, Res_value::TYPE_INT_DEC, 2U); ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[1], R::target::string::str1, Res_value::TYPE_REFERENCE, 0x7f010000); + ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[2], R::target::string::str2, + Res_value::TYPE_STRING, + (uint32_t) (string_pool.indexOfString(u"foobar", 6)).value_or(-1)); } TEST(IdmapTests, FailCreateIdmapInvalidName) { 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/ResourceMappingTests.cpp b/cmds/idmap2/tests/ResourceMappingTests.cpp index 32b3d1326d92..ca9a444bcb05 100644 --- a/cmds/idmap2/tests/ResourceMappingTests.cpp +++ b/cmds/idmap2/tests/ResourceMappingTests.cpp @@ -194,8 +194,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 +210,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/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); } |