Merge "TouchpadInputMapper: rotate pointer movement with display"
diff --git a/cmds/installd/installd.rc b/cmds/installd/installd.rc
index 240aa49..5b08c77 100644
--- a/cmds/installd/installd.rc
+++ b/cmds/installd/installd.rc
@@ -1,6 +1,7 @@
service installd /system/bin/installd
class main
+ capabilities CHOWN DAC_OVERRIDE DAC_READ_SEARCH FOWNER FSETID KILL SETGID SETUID SYS_ADMIN
on early-boot
mkdir /config/sdcardfs/extensions/1055
diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h
index 5fa9fda..09933d3 100644
--- a/include/input/InputDevice.h
+++ b/include/input/InputDevice.h
@@ -24,7 +24,6 @@
#include <vector>
#include <android/os/IInputConstants.h>
-#include "android/hardware/input/InputDeviceCountryCode.h"
namespace android {
@@ -236,9 +235,7 @@
void initialize(int32_t id, int32_t generation, int32_t controllerNumber,
const InputDeviceIdentifier& identifier, const std::string& alias,
- bool isExternal, bool hasMic,
- hardware::input::InputDeviceCountryCode countryCode =
- hardware::input::InputDeviceCountryCode::INVALID);
+ bool isExternal, bool hasMic);
inline int32_t getId() const { return mId; }
inline int32_t getControllerNumber() const { return mControllerNumber; }
@@ -250,7 +247,6 @@
}
inline bool isExternal() const { return mIsExternal; }
inline bool hasMic() const { return mHasMic; }
- inline hardware::input::InputDeviceCountryCode getCountryCode() const { return mCountryCode; }
inline uint32_t getSources() const { return mSources; }
const MotionRange* getMotionRange(int32_t axis, uint32_t source) const;
@@ -310,7 +306,6 @@
std::string mAlias;
bool mIsExternal;
bool mHasMic;
- hardware::input::InputDeviceCountryCode mCountryCode;
std::optional<KeyboardLayoutInfo> mKeyboardLayoutInfo;
uint32_t mSources;
int32_t mKeyboardType;
diff --git a/libs/binder/rust/src/parcel.rs b/libs/binder/rust/src/parcel.rs
index 53a24af..e4c568e 100644
--- a/libs/binder/rust/src/parcel.rs
+++ b/libs/binder/rust/src/parcel.rs
@@ -566,9 +566,6 @@
impl<'a> ReadableSubParcel<'a> {
/// Read a type that implements [`Deserialize`] from the sub-parcel.
pub fn read<D: Deserialize>(&self) -> Result<D> {
- // The caller should have checked this,
- // but it can't hurt to double-check
- assert!(self.has_more_data());
D::deserialize(&self.parcel)
}
diff --git a/libs/binder/rust/src/parcel/parcelable.rs b/libs/binder/rust/src/parcel/parcelable.rs
index c241e4d..6f4c375 100644
--- a/libs/binder/rust/src/parcel/parcelable.rs
+++ b/libs/binder/rust/src/parcel/parcelable.rs
@@ -23,7 +23,7 @@
use std::convert::{TryFrom, TryInto};
use std::ffi::c_void;
use std::mem::{self, ManuallyDrop, MaybeUninit};
-use std::os::raw::{c_char, c_ulong};
+use std::os::raw::c_char;
use std::ptr;
use std::slice;
@@ -103,12 +103,8 @@
unsafe extern "C" fn serialize_element<T: Serialize>(
parcel: *mut sys::AParcel,
array: *const c_void,
- index: c_ulong,
+ index: usize,
) -> status_t {
- // c_ulong and usize are the same, but we need the explicitly sized version
- // so the function signature matches what bindgen generates.
- let index = index as usize;
-
let slice: &[T] = slice::from_raw_parts(array.cast(), index + 1);
let mut parcel = match BorrowedParcel::from_raw(parcel) {
@@ -158,12 +154,8 @@
unsafe extern "C" fn deserialize_element<T: Deserialize>(
parcel: *const sys::AParcel,
array: *mut c_void,
- index: c_ulong,
+ index: usize,
) -> status_t {
- // c_ulong and usize are the same, but we need the explicitly sized version
- // so the function signature matches what bindgen generates.
- let index = index as usize;
-
let vec = &mut *(array as *mut Option<Vec<MaybeUninit<T>>>);
let vec = match vec {
Some(v) => v,
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 8ddd18d..8f41cc1 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -26,7 +26,6 @@
filegroup {
name: "inputconstants_aidl",
srcs: [
- "android/hardware/input/InputDeviceCountryCode.aidl",
"android/os/IInputConstants.aidl",
"android/os/InputEventInjectionResult.aidl",
"android/os/InputEventInjectionSync.aidl",
diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp
index fb6c590..87333f2 100644
--- a/libs/input/InputDevice.cpp
+++ b/libs/input/InputDevice.cpp
@@ -26,7 +26,6 @@
#include <input/InputEventLabels.h>
using android::base::StringPrintf;
-using android::hardware::input::InputDeviceCountryCode;
namespace android {
@@ -178,7 +177,6 @@
mAlias(other.mAlias),
mIsExternal(other.mIsExternal),
mHasMic(other.mHasMic),
- mCountryCode(other.mCountryCode),
mKeyboardLayoutInfo(other.mKeyboardLayoutInfo),
mSources(other.mSources),
mKeyboardType(other.mKeyboardType),
@@ -197,7 +195,7 @@
void InputDeviceInfo::initialize(int32_t id, int32_t generation, int32_t controllerNumber,
const InputDeviceIdentifier& identifier, const std::string& alias,
- bool isExternal, bool hasMic, InputDeviceCountryCode countryCode) {
+ bool isExternal, bool hasMic) {
mId = id;
mGeneration = generation;
mControllerNumber = controllerNumber;
@@ -205,7 +203,6 @@
mAlias = alias;
mIsExternal = isExternal;
mHasMic = hasMic;
- mCountryCode = countryCode;
mSources = 0;
mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE;
mHasVibrator = false;
diff --git a/libs/input/android/hardware/input/InputDeviceCountryCode.aidl b/libs/input/android/hardware/input/InputDeviceCountryCode.aidl
deleted file mode 100644
index 6bb1a60..0000000
--- a/libs/input/android/hardware/input/InputDeviceCountryCode.aidl
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.input;
-
-/**
- * Constant for HID country code declared by a HID device. These constants are declared as AIDL to
- * be used by java and native input code.
- *
- * @hide
- */
-@Backing(type="int")
-enum InputDeviceCountryCode {
- /**
- * Used as default value where country code is not set in the device HID descriptor
- */
- INVALID = -1,
-
- /**
- * Used as default value when country code is not supported by the HID device. The HID
- * descriptor sets "00" as the country code in this case.
- */
- NOT_SUPPORTED = 0,
-
- /**
- * Arabic
- */
- ARABIC = 1,
-
- /**
- * Belgian
- */
- BELGIAN = 2,
-
- /**
- * Canadian (Bilingual)
- */
- CANADIAN_BILINGUAL = 3,
-
- /**
- * Canadian (French)
- */
- CANADIAN_FRENCH = 4,
-
- /**
- * Czech Republic
- */
- CZECH_REPUBLIC = 5,
-
- /**
- * Danish
- */
- DANISH = 6,
-
- /**
- * Finnish
- */
- FINNISH = 7,
-
- /**
- * French
- */
- FRENCH = 8,
-
- /**
- * German
- */
- GERMAN = 9,
-
- /**
- * Greek
- */
- GREEK = 10,
-
- /**
- * Hebrew
- */
- HEBREW = 11,
-
- /**
- * Hungary
- */
- HUNGARY = 12,
-
- /**
- * International (ISO)
- */
- INTERNATIONAL = 13,
-
- /**
- * Italian
- */
- ITALIAN = 14,
-
- /**
- * Japan (Katakana)
- */
- JAPAN = 15,
-
- /**
- * Korean
- */
- KOREAN = 16,
-
- /**
- * Latin American
- */
- LATIN_AMERICAN = 17,
-
- /**
- * Netherlands (Dutch)
- */
- DUTCH = 18,
-
- /**
- * Norwegian
- */
- NORWEGIAN = 19,
-
- /**
- * Persian
- */
- PERSIAN = 20,
-
- /**
- * Poland
- */
- POLAND = 21,
-
- /**
- * Portuguese
- */
- PORTUGUESE = 22,
-
- /**
- * Russia
- */
- RUSSIA = 23,
-
- /**
- * Slovakia
- */
- SLOVAKIA = 24,
-
- /**
- * Spanish
- */
- SPANISH = 25,
-
- /**
- * Swedish
- */
- SWEDISH = 26,
-
- /**
- * Swiss (French)
- */
- SWISS_FRENCH = 27,
-
- /**
- * Swiss (German)
- */
- SWISS_GERMAN = 28,
-
- /**
- * Switzerland
- */
- SWITZERLAND = 29,
-
- /**
- * Taiwan
- */
- TAIWAN = 30,
-
- /**
- * Turkish_Q
- */
- TURKISH_Q = 31,
-
- /**
- * UK
- */
- UK = 32,
-
- /**
- * US
- */
- US = 33,
-
- /**
- * Yugoslavia
- */
- YUGOSLAVIA = 34,
-
- /**
- * Turkish_F
- */
- TURKISH_F = 35,
-}
\ No newline at end of file
diff --git a/libs/jpegrecoverymap/recoverymap.cpp b/libs/jpegrecoverymap/recoverymap.cpp
index 53fa8ce..1b69743 100644
--- a/libs/jpegrecoverymap/recoverymap.cpp
+++ b/libs/jpegrecoverymap/recoverymap.cpp
@@ -192,6 +192,31 @@
return NO_ERROR;
}
+/*
+ * Helper function copies the JPEG image from without EXIF.
+ *
+ * @param dest destination of the data to be written.
+ * @param source source of data being written.
+ * @param exif_pos position of the EXIF package, which is aligned with jpegdecoder.getEXIFPos().
+ * (4 bypes offset to FF sign, the byte after FF E1 XX XX <this byte>).
+ * @param exif_size exif size without the initial 4 bytes, aligned with jpegdecoder.getEXIFSize().
+ */
+void copyJpegWithoutExif(jr_compressed_ptr dest,
+ jr_compressed_ptr source,
+ size_t exif_pos,
+ size_t exif_size) {
+ memcpy(dest, source, sizeof(jpegr_compressed_struct));
+
+ const size_t exif_offset = 4; //exif_pos has 4 bypes offset to the FF sign
+ dest->length = source->length - exif_size - exif_offset;
+ dest->data = malloc(dest->length);
+
+ memcpy(dest->data, source->data, exif_pos - exif_offset);
+ memcpy((uint8_t*)dest->data + exif_pos - exif_offset,
+ (uint8_t*)source->data + exif_pos + exif_size,
+ source->length - exif_pos - exif_size);
+}
+
/* Encode API-0 */
status_t RecoveryMap::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image,
jpegr_transfer_function hdr_tf,
@@ -367,17 +392,18 @@
return ERROR_JPEGR_DECODE_ERROR;
}
+ // Update exif.
jpegr_exif_struct exif;
exif.data = nullptr;
exif.length = 0;
- // Delete EXIF package if it appears, and update exif.
+ jpegr_compressed_struct new_jpeg_image;
+ new_jpeg_image.data = nullptr;
+ new_jpeg_image.length = 0;
if (jpeg_decoder.getEXIFPos() != 0) {
- int new_length = compressed_jpeg_image->length - jpeg_decoder.getEXIFSize() - 4;
- memcpy((uint8_t*)compressed_jpeg_image->data + jpeg_decoder.getEXIFPos() - 4,
- (uint8_t*)compressed_jpeg_image->data + jpeg_decoder.getEXIFPos()
- + jpeg_decoder.getEXIFSize(),
- compressed_jpeg_image->length - jpeg_decoder.getEXIFPos() - jpeg_decoder.getEXIFSize());
- compressed_jpeg_image->length = new_length;
+ copyJpegWithoutExif(&new_jpeg_image,
+ compressed_jpeg_image,
+ jpeg_decoder.getEXIFPos(),
+ jpeg_decoder.getEXIFSize());
exif.data = jpeg_decoder.getEXIFPtr();
exif.length = jpeg_decoder.getEXIFSize();
}
@@ -395,7 +421,12 @@
JPEGR_CHECK(updateExif(&exif, &new_exif));
JPEGR_CHECK(appendRecoveryMap(
- compressed_jpeg_image, &compressed_map, &new_exif, &metadata, dest));
+ new_jpeg_image.data == nullptr ? compressed_jpeg_image : &new_jpeg_image,
+ &compressed_map, &new_exif, &metadata, dest));
+
+ if (new_jpeg_image.data != nullptr) {
+ free(new_jpeg_image.data);
+ }
return NO_ERROR;
}
@@ -421,17 +452,18 @@
uncompressed_yuv_420_image.height = jpeg_decoder.getDecompressedImageHeight();
uncompressed_yuv_420_image.colorGamut = compressed_jpeg_image->colorGamut;
+ // Update exif.
jpegr_exif_struct exif;
exif.data = nullptr;
exif.length = 0;
- // Delete EXIF package if it appears, and update exif.
+ jpegr_compressed_struct new_jpeg_image;
+ new_jpeg_image.data = nullptr;
+ new_jpeg_image.length = 0;
if (jpeg_decoder.getEXIFPos() != 0) {
- int new_length = compressed_jpeg_image->length - jpeg_decoder.getEXIFSize() - 4;
- memcpy((uint8_t*)compressed_jpeg_image->data + jpeg_decoder.getEXIFPos() - 4,
- (uint8_t*)compressed_jpeg_image->data + jpeg_decoder.getEXIFPos()
- + jpeg_decoder.getEXIFSize(),
- compressed_jpeg_image->length - jpeg_decoder.getEXIFPos() - jpeg_decoder.getEXIFSize());
- compressed_jpeg_image->length = new_length;
+ copyJpegWithoutExif(&new_jpeg_image,
+ compressed_jpeg_image,
+ jpeg_decoder.getEXIFPos(),
+ jpeg_decoder.getEXIFSize());
exif.data = jpeg_decoder.getEXIFPtr();
exif.length = jpeg_decoder.getEXIFSize();
}
@@ -472,7 +504,12 @@
JPEGR_CHECK(compressRecoveryMap(&map, &compressed_map));
JPEGR_CHECK(appendRecoveryMap(
- compressed_jpeg_image, &compressed_map, &new_exif, &metadata, dest));
+ new_jpeg_image.data == nullptr ? compressed_jpeg_image : &new_jpeg_image,
+ &compressed_map, &new_exif, &metadata, dest));
+
+ if (new_jpeg_image.data != nullptr) {
+ free(new_jpeg_image.data);
+ }
return NO_ERROR;
}
@@ -864,7 +901,7 @@
// 2 bytes: representing the length of the package
// 29 bytes: length of name space "http://ns.adobe.com/xap/1.0/\0",
// x bytes: length of xmp packet
- const int length = 3 + nameSpaceLength + xmp.size();
+ const int length = 2 + nameSpaceLength + xmp.size();
const uint8_t lengthH = ((length >> 8) & 0xff);
const uint8_t lengthL = (length & 0xff);
JPEGR_CHECK(Write(dest, &photos_editing_formats::image_io::JpegMarker::kStart, 1, pos));
diff --git a/libs/renderengine/include/renderengine/mock/FakeExternalTexture.h b/libs/renderengine/include/renderengine/mock/FakeExternalTexture.h
index 974e0fd..b95f011 100644
--- a/libs/renderengine/include/renderengine/mock/FakeExternalTexture.h
+++ b/libs/renderengine/include/renderengine/mock/FakeExternalTexture.h
@@ -23,7 +23,9 @@
namespace mock {
class FakeExternalTexture : public renderengine::ExternalTexture {
- const sp<GraphicBuffer> mNullBuffer = nullptr;
+ const sp<GraphicBuffer> mEmptyBuffer =
+ sp<GraphicBuffer>::make(1u, 1u, PIXEL_FORMAT_RGBA_8888,
+ GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_OFTEN);
uint32_t mWidth;
uint32_t mHeight;
uint64_t mId;
@@ -34,7 +36,7 @@
FakeExternalTexture(uint32_t width, uint32_t height, uint64_t id, PixelFormat pixelFormat,
uint64_t usage)
: mWidth(width), mHeight(height), mId(id), mPixelFormat(pixelFormat), mUsage(usage) {}
- const sp<GraphicBuffer>& getBuffer() const { return mNullBuffer; }
+ const sp<GraphicBuffer>& getBuffer() const { return mEmptyBuffer; }
bool hasSameBuffer(const renderengine::ExternalTexture& other) const override {
return getId() == other.getId();
}
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index e9fa599..b214750 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -62,7 +62,6 @@
#define INDENT3 " "
using android::base::StringPrintf;
-using android::hardware::input::InputDeviceCountryCode;
namespace android {
@@ -135,6 +134,46 @@
{"green", LightColor::GREEN},
{"blue", LightColor::BLUE}};
+// Mapping for country code to Layout info.
+// See bCountryCode in 6.2.1 of https://usb.org/sites/default/files/hid1_11.pdf.
+const std::unordered_map<std::int32_t, RawLayoutInfo> LAYOUT_INFOS =
+ {{0, RawLayoutInfo{.languageTag = "", .layoutType = ""}}, // NOT_SUPPORTED
+ {1, RawLayoutInfo{.languageTag = "ar-Arab", .layoutType = ""}}, // ARABIC
+ {2, RawLayoutInfo{.languageTag = "fr-BE", .layoutType = ""}}, // BELGIAN
+ {3, RawLayoutInfo{.languageTag = "fr-CA", .layoutType = ""}}, // CANADIAN_BILINGUAL
+ {4, RawLayoutInfo{.languageTag = "fr-CA", .layoutType = ""}}, // CANADIAN_FRENCH
+ {5, RawLayoutInfo{.languageTag = "cs", .layoutType = ""}}, // CZECH_REPUBLIC
+ {6, RawLayoutInfo{.languageTag = "da", .layoutType = ""}}, // DANISH
+ {7, RawLayoutInfo{.languageTag = "fi", .layoutType = ""}}, // FINNISH
+ {8, RawLayoutInfo{.languageTag = "fr-FR", .layoutType = ""}}, // FRENCH
+ {9, RawLayoutInfo{.languageTag = "de", .layoutType = ""}}, // GERMAN
+ {10, RawLayoutInfo{.languageTag = "el", .layoutType = ""}}, // GREEK
+ {11, RawLayoutInfo{.languageTag = "iw", .layoutType = ""}}, // HEBREW
+ {12, RawLayoutInfo{.languageTag = "hu", .layoutType = ""}}, // HUNGARY
+ {13, RawLayoutInfo{.languageTag = "en", .layoutType = "extended"}}, // INTERNATIONAL (ISO)
+ {14, RawLayoutInfo{.languageTag = "it", .layoutType = ""}}, // ITALIAN
+ {15, RawLayoutInfo{.languageTag = "ja", .layoutType = ""}}, // JAPAN
+ {16, RawLayoutInfo{.languageTag = "ko", .layoutType = ""}}, // KOREAN
+ {17, RawLayoutInfo{.languageTag = "es-419", .layoutType = ""}}, // LATIN_AMERICA
+ {18, RawLayoutInfo{.languageTag = "nl", .layoutType = ""}}, // DUTCH
+ {19, RawLayoutInfo{.languageTag = "nb", .layoutType = ""}}, // NORWEGIAN
+ {20, RawLayoutInfo{.languageTag = "fa", .layoutType = ""}}, // PERSIAN
+ {21, RawLayoutInfo{.languageTag = "pl", .layoutType = ""}}, // POLAND
+ {22, RawLayoutInfo{.languageTag = "pt", .layoutType = ""}}, // PORTUGUESE
+ {23, RawLayoutInfo{.languageTag = "ru", .layoutType = ""}}, // RUSSIA
+ {24, RawLayoutInfo{.languageTag = "sk", .layoutType = ""}}, // SLOVAKIA
+ {25, RawLayoutInfo{.languageTag = "es-ES", .layoutType = ""}}, // SPANISH
+ {26, RawLayoutInfo{.languageTag = "sv", .layoutType = ""}}, // SWEDISH
+ {27, RawLayoutInfo{.languageTag = "fr-CH", .layoutType = ""}}, // SWISS_FRENCH
+ {28, RawLayoutInfo{.languageTag = "de-CH", .layoutType = ""}}, // SWISS_GERMAN
+ {29, RawLayoutInfo{.languageTag = "de-CH", .layoutType = ""}}, // SWITZERLAND
+ {30, RawLayoutInfo{.languageTag = "zh-TW", .layoutType = ""}}, // TAIWAN
+ {31, RawLayoutInfo{.languageTag = "tr", .layoutType = "turkish_q"}}, // TURKISH_Q
+ {32, RawLayoutInfo{.languageTag = "en-GB", .layoutType = ""}}, // UK
+ {33, RawLayoutInfo{.languageTag = "en-US", .layoutType = ""}}, // US
+ {34, RawLayoutInfo{.languageTag = "", .layoutType = ""}}, // YUGOSLAVIA
+ {35, RawLayoutInfo{.languageTag = "tr", .layoutType = "turkish_f"}}}; // TURKISH_F
+
static std::string sha1(const std::string& in) {
SHA_CTX ctx;
SHA1_Init(&ctx);
@@ -311,22 +350,27 @@
}
/**
- * Read country code information exposed through the sysfs path.
+ * Read country code information exposed through the sysfs path and convert it to Layout info.
*/
-static InputDeviceCountryCode readCountryCodeLocked(const std::filesystem::path& sysfsRootPath) {
+static std::optional<RawLayoutInfo> readLayoutConfiguration(
+ const std::filesystem::path& sysfsRootPath) {
// Check the sysfs root path
- int hidCountryCode = static_cast<int>(InputDeviceCountryCode::INVALID);
+ int32_t hidCountryCode = -1;
std::string str;
if (base::ReadFileToString(sysfsRootPath / "country", &str)) {
hidCountryCode = std::stoi(str, nullptr, 16);
+ // Update this condition if new supported country codes are added to HID spec.
if (hidCountryCode > 35 || hidCountryCode < 0) {
ALOGE("HID country code should be in range [0, 35], but for sysfs path %s it was %d",
sysfsRootPath.c_str(), hidCountryCode);
- return InputDeviceCountryCode::INVALID;
}
}
+ const auto it = LAYOUT_INFOS.find(hidCountryCode);
+ if (it != LAYOUT_INFOS.end()) {
+ return it->second;
+ }
- return static_cast<InputDeviceCountryCode>(hidCountryCode);
+ return std::nullopt;
}
/**
@@ -1299,13 +1343,13 @@
}
}
-InputDeviceCountryCode EventHub::getCountryCode(int32_t deviceId) const {
+std::optional<RawLayoutInfo> EventHub::getRawLayoutInfo(int32_t deviceId) const {
std::scoped_lock _l(mLock);
Device* device = getDeviceLocked(deviceId);
if (device == nullptr || !device->associatedDevice) {
- return InputDeviceCountryCode::INVALID;
+ return std::nullopt;
}
- return device->associatedDevice->countryCode;
+ return device->associatedDevice->layoutInfo;
}
void EventHub::setExcludedDevices(const std::vector<std::string>& devices) {
@@ -1449,9 +1493,9 @@
std::shared_ptr<const AssociatedDevice> associatedDevice = std::make_shared<AssociatedDevice>(
AssociatedDevice{.sysfsRootPath = path,
- .countryCode = readCountryCodeLocked(path),
.batteryInfos = readBatteryConfiguration(path),
- .lightInfos = readLightsConfiguration(path)});
+ .lightInfos = readLightsConfiguration(path),
+ .layoutInfo = readLayoutConfiguration(path)});
bool associatedDeviceChanged = false;
for (const auto& [id, dev] : mDevices) {
@@ -2686,9 +2730,12 @@
device->keyMap.keyLayoutFile.c_str());
dump += StringPrintf(INDENT3 "KeyCharacterMapFile: %s\n",
device->keyMap.keyCharacterMapFile.c_str());
- dump += StringPrintf(INDENT3 "CountryCode: %d\n",
- device->associatedDevice ? device->associatedDevice->countryCode
- : InputDeviceCountryCode::INVALID);
+ if (device->associatedDevice && device->associatedDevice->layoutInfo) {
+ dump += StringPrintf(INDENT3 "LanguageTag: %s\n",
+ device->associatedDevice->layoutInfo->languageTag.c_str());
+ dump += StringPrintf(INDENT3 "LayoutType: %s\n",
+ device->associatedDevice->layoutInfo->layoutType.c_str());
+ }
dump += StringPrintf(INDENT3 "ConfigurationFile: %s\n",
device->configurationFile.c_str());
dump += StringPrintf(INDENT3 "VideoDevice: %s\n",
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index 13f40ee..6e78e82 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -37,8 +37,6 @@
#include "TouchpadInputMapper.h"
#include "VibratorInputMapper.h"
-using android::hardware::input::InputDeviceCountryCode;
-
namespace android {
InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
@@ -256,7 +254,6 @@
mSources = 0;
mClasses = ftl::Flags<InputDeviceClass>(0);
mControllerNumber = 0;
- mCountryCode = InputDeviceCountryCode::INVALID;
for_each_subdevice([this](InputDeviceContext& context) {
mClasses |= context.getDeviceClasses();
@@ -268,16 +265,6 @@
}
mControllerNumber = controllerNumber;
}
-
- InputDeviceCountryCode countryCode = context.getCountryCode();
- if (countryCode != InputDeviceCountryCode::INVALID) {
- if (mCountryCode != InputDeviceCountryCode::INVALID && mCountryCode != countryCode) {
- ALOGW("InputDevice::configure(): %s device contains multiple unique country "
- "codes",
- getName().c_str());
- }
- mCountryCode = countryCode;
- }
});
mIsExternal = mClasses.test(InputDeviceClass::EXTERNAL);
@@ -465,7 +452,7 @@
InputDeviceInfo InputDevice::getDeviceInfo() {
InputDeviceInfo outDeviceInfo;
outDeviceInfo.initialize(mId, mGeneration, mControllerNumber, mIdentifier, mAlias, mIsExternal,
- mHasMic, mCountryCode);
+ mHasMic);
for_each_mapper(
[&outDeviceInfo](InputMapper& mapper) { mapper.populateDeviceInfo(&outDeviceInfo); });
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index 8a844b2..a3ecf41 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -42,7 +42,6 @@
#include "TouchVideoDevice.h"
#include "VibrationElement.h"
-#include "android/hardware/input/InputDeviceCountryCode.h"
struct inotify_event;
@@ -207,6 +206,15 @@
bool operator!=(const RawBatteryInfo&) const = default;
};
+/* Layout information associated with the device */
+struct RawLayoutInfo {
+ std::string languageTag;
+ std::string layoutType;
+
+ bool operator==(const RawLayoutInfo&) const = default;
+ bool operator!=(const RawLayoutInfo&) const = default;
+};
+
/*
* Gets the class that owns an axis, in cases where multiple classes might claim
* the same axis for different purposes.
@@ -308,8 +316,8 @@
int32_t deviceId, int32_t lightId) const = 0;
virtual void setLightIntensities(int32_t deviceId, int32_t lightId,
std::unordered_map<LightColor, int32_t> intensities) = 0;
- /* Query Country code associated with the input device. */
- virtual hardware::input::InputDeviceCountryCode getCountryCode(int32_t deviceId) const = 0;
+ /* Query Layout info associated with the input device. */
+ virtual std::optional<RawLayoutInfo> getRawLayoutInfo(int32_t deviceId) const = 0;
/* Query current input state. */
virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const = 0;
virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const = 0;
@@ -493,7 +501,7 @@
void setLightIntensities(int32_t deviceId, int32_t lightId,
std::unordered_map<LightColor, int32_t> intensities) override final;
- hardware::input::InputDeviceCountryCode getCountryCode(int32_t deviceId) const override final;
+ std::optional<RawLayoutInfo> getRawLayoutInfo(int32_t deviceId) const override final;
void setExcludedDevices(const std::vector<std::string>& devices) override final;
@@ -556,9 +564,9 @@
struct AssociatedDevice {
// The sysfs root path of the misc device.
std::filesystem::path sysfsRootPath;
- hardware::input::InputDeviceCountryCode countryCode;
std::unordered_map<int32_t /*batteryId*/, RawBatteryInfo> batteryInfos;
std::unordered_map<int32_t /*lightId*/, RawLightInfo> lightInfos;
+ std::optional<RawLayoutInfo> layoutInfo;
bool operator==(const AssociatedDevice&) const = default;
bool operator!=(const AssociatedDevice&) const = default;
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index b173618..7867029 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -167,7 +167,6 @@
int32_t mId;
int32_t mGeneration;
int32_t mControllerNumber;
- hardware::input::InputDeviceCountryCode mCountryCode;
InputDeviceIdentifier mIdentifier;
std::string mAlias;
ftl::Flags<InputDeviceClass> mClasses;
@@ -326,9 +325,6 @@
}
inline std::vector<TouchVideoFrame> getVideoFrames() { return mEventHub->getVideoFrames(mId); }
- inline hardware::input::InputDeviceCountryCode getCountryCode() const {
- return mEventHub->getCountryCode(mId);
- }
inline int32_t getScanCodeState(int32_t scanCode) const {
return mEventHub->getScanCodeState(mId, scanCode);
}
@@ -361,6 +357,9 @@
inline bool setKeyboardLayoutOverlay(std::shared_ptr<KeyCharacterMap> map) {
return mEventHub->setKeyboardLayoutOverlay(mId, map);
}
+ inline const std::optional<RawLayoutInfo> getRawLayoutInfo() {
+ return mEventHub->getRawLayoutInfo(mId);
+ }
inline void vibrate(const VibrationElement& element) {
return mEventHub->vibrate(mId, element);
}
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
index 6f01449..d147d60 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
@@ -123,6 +123,12 @@
if (mKeyboardLayoutInfo) {
info->setKeyboardLayoutInfo(*mKeyboardLayoutInfo);
+ } else {
+ std::optional<RawLayoutInfo> layoutInfo = getDeviceContext().getRawLayoutInfo();
+ if (layoutInfo) {
+ info->setKeyboardLayoutInfo(
+ KeyboardLayoutInfo(layoutInfo->languageTag, layoutInfo->layoutType));
+ }
}
}
diff --git a/services/inputflinger/tests/FakeEventHub.cpp b/services/inputflinger/tests/FakeEventHub.cpp
index 289a780..6ac0bfb 100644
--- a/services/inputflinger/tests/FakeEventHub.cpp
+++ b/services/inputflinger/tests/FakeEventHub.cpp
@@ -120,8 +120,8 @@
getDevice(deviceId)->keyCodeStates.replaceValueFor(keyCode, state);
}
-void FakeEventHub::setCountryCode(int32_t deviceId, InputDeviceCountryCode countryCode) {
- getDevice(deviceId)->countryCode = countryCode;
+void FakeEventHub::setRawLayoutInfo(int32_t deviceId, RawLayoutInfo info) {
+ getDevice(deviceId)->layoutInfo = info;
}
void FakeEventHub::setScanCodeState(int32_t deviceId, int32_t scanCode, int32_t state) {
@@ -389,9 +389,9 @@
return AKEY_STATE_UNKNOWN;
}
-InputDeviceCountryCode FakeEventHub::getCountryCode(int32_t deviceId) const {
+std::optional<RawLayoutInfo> FakeEventHub::getRawLayoutInfo(int32_t deviceId) const {
Device* device = getDevice(deviceId);
- return device ? device->countryCode : InputDeviceCountryCode::INVALID;
+ return device ? device->layoutInfo : std::nullopt;
}
int32_t FakeEventHub::getKeyCodeState(int32_t deviceId, int32_t keyCode) const {
diff --git a/services/inputflinger/tests/FakeEventHub.h b/services/inputflinger/tests/FakeEventHub.h
index fb3c859..72f8ac0 100644
--- a/services/inputflinger/tests/FakeEventHub.h
+++ b/services/inputflinger/tests/FakeEventHub.h
@@ -30,10 +30,6 @@
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
-#include "android/hardware/input/InputDeviceCountryCode.h"
-
-using android::hardware::input::InputDeviceCountryCode;
-
namespace android {
class FakeEventHub : public EventHubInterface {
@@ -67,7 +63,7 @@
BitArray<MSC_MAX> mscBitmask;
std::vector<VirtualKeyDefinition> virtualKeys;
bool enabled;
- InputDeviceCountryCode countryCode;
+ std::optional<RawLayoutInfo> layoutInfo;
status_t enable() {
enabled = true;
@@ -124,7 +120,7 @@
void addRelativeAxis(int32_t deviceId, int32_t axis);
void setAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t value);
- void setCountryCode(int32_t deviceId, InputDeviceCountryCode countryCode);
+ void setRawLayoutInfo(int32_t deviceId, RawLayoutInfo info);
void setKeyCodeState(int32_t deviceId, int32_t keyCode, int32_t state);
void setScanCodeState(int32_t deviceId, int32_t scanCode, int32_t state);
@@ -180,7 +176,7 @@
std::vector<RawEvent> getEvents(int) override;
std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) override;
int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const override;
- InputDeviceCountryCode getCountryCode(int32_t deviceId) const override;
+ std::optional<RawLayoutInfo> getRawLayoutInfo(int32_t deviceId) const override;
int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const override;
int32_t getSwitchState(int32_t deviceId, int32_t sw) const override;
status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t* outValue) const override;
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 96d27b8..a464639 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -48,12 +48,9 @@
#include "InputMapperTest.h"
#include "InstrumentedInputReader.h"
#include "TestConstants.h"
-#include "android/hardware/input/InputDeviceCountryCode.h"
#include "input/DisplayViewport.h"
#include "input/Input.h"
-using android::hardware::input::InputDeviceCountryCode;
-
namespace android {
using namespace ftl::flag_operators;
@@ -2240,17 +2237,6 @@
ASSERT_EQ(ftl::Flags<InputDeviceClass>(0), mDevice->getClasses());
}
-TEST_F(InputDeviceTest, CountryCodeCorrectlyMapped) {
- mFakeEventHub->setCountryCode(EVENTHUB_ID, InputDeviceCountryCode::INTERNATIONAL);
-
- // Configuration
- mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD);
- InputReaderConfiguration config;
- std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, &config, 0);
-
- ASSERT_EQ(InputDeviceCountryCode::INTERNATIONAL, mDevice->getDeviceInfo().getCountryCode());
-}
-
TEST_F(InputDeviceTest, WhenDeviceCreated_EnabledIsFalse) {
ASSERT_EQ(mDevice->isEnabled(), false);
}
@@ -3600,6 +3586,20 @@
deviceInfo.getKeyboardLayoutInfo()->layoutType);
}
+TEST_F(KeyboardInputMapperTest, LayoutInfoCorrectlyMapped) {
+ mFakeEventHub->setRawLayoutInfo(EVENTHUB_ID,
+ RawLayoutInfo{.languageTag = "en", .layoutType = "extended"});
+
+ // Configuration
+ addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
+ AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+ InputReaderConfiguration config;
+ std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, &config, 0);
+
+ ASSERT_EQ("en", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->languageTag);
+ ASSERT_EQ("extended", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->layoutType);
+}
+
// --- KeyboardInputMapperTest_ExternalDevice ---
class KeyboardInputMapperTest_ExternalDevice : public InputMapperTest {
diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h
index a0910ea..7c9be5c 100644
--- a/services/inputflinger/tests/fuzzers/MapperHelpers.h
+++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h
@@ -19,9 +19,6 @@
#include <InputMapper.h>
#include <InputReader.h>
#include <ThreadSafeFuzzedDataProvider.h>
-#include "android/hardware/input/InputDeviceCountryCode.h"
-
-using android::hardware::input::InputDeviceCountryCode;
constexpr size_t kValidTypes[] = {EV_SW,
EV_SYN,
@@ -65,46 +62,6 @@
BTN_TASK,
};
-constexpr InputDeviceCountryCode kCountryCodes[] = {
- InputDeviceCountryCode::INVALID,
- InputDeviceCountryCode::NOT_SUPPORTED,
- InputDeviceCountryCode::ARABIC,
- InputDeviceCountryCode::BELGIAN,
- InputDeviceCountryCode::CANADIAN_BILINGUAL,
- InputDeviceCountryCode::CANADIAN_FRENCH,
- InputDeviceCountryCode::CZECH_REPUBLIC,
- InputDeviceCountryCode::DANISH,
- InputDeviceCountryCode::FINNISH,
- InputDeviceCountryCode::FRENCH,
- InputDeviceCountryCode::GERMAN,
- InputDeviceCountryCode::GREEK,
- InputDeviceCountryCode::HEBREW,
- InputDeviceCountryCode::HUNGARY,
- InputDeviceCountryCode::INTERNATIONAL,
- InputDeviceCountryCode::ITALIAN,
- InputDeviceCountryCode::JAPAN,
- InputDeviceCountryCode::KOREAN,
- InputDeviceCountryCode::LATIN_AMERICAN,
- InputDeviceCountryCode::DUTCH,
- InputDeviceCountryCode::NORWEGIAN,
- InputDeviceCountryCode::PERSIAN,
- InputDeviceCountryCode::POLAND,
- InputDeviceCountryCode::PORTUGUESE,
- InputDeviceCountryCode::RUSSIA,
- InputDeviceCountryCode::SLOVAKIA,
- InputDeviceCountryCode::SPANISH,
- InputDeviceCountryCode::SWEDISH,
- InputDeviceCountryCode::SWISS_FRENCH,
- InputDeviceCountryCode::SWISS_GERMAN,
- InputDeviceCountryCode::SWITZERLAND,
- InputDeviceCountryCode::TAIWAN,
- InputDeviceCountryCode::TURKISH_Q,
- InputDeviceCountryCode::UK,
- InputDeviceCountryCode::US,
- InputDeviceCountryCode::YUGOSLAVIA,
- InputDeviceCountryCode::TURKISH_F,
-};
-
constexpr size_t kMaxSize = 256;
namespace android {
@@ -197,8 +154,8 @@
void setLightIntensities(int32_t deviceId, int32_t lightId,
std::unordered_map<LightColor, int32_t> intensities) override{};
- InputDeviceCountryCode getCountryCode(int32_t deviceId) const override {
- return mFdp->PickValueInArray<InputDeviceCountryCode>(kCountryCodes);
+ std::optional<RawLayoutInfo> getRawLayoutInfo(int32_t deviceId) const override {
+ return std::nullopt;
};
int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const override {
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
index 2a5bfae..b86782f 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
@@ -137,6 +137,7 @@
HwcBufferCache hwcBufferCache;
// The previously-active buffer for this layer.
+ uint64_t activeBufferId;
uint32_t activeBufferSlot;
// Set to true when overridden info has been sent to HW composer
diff --git a/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp b/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp
index 34ed214..f0105b2 100644
--- a/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp
@@ -28,11 +28,6 @@
}
HwcSlotAndBuffer HwcBufferCache::getHwcSlotAndBuffer(const sp<GraphicBuffer>& buffer) {
- // TODO(b/261930578): This is for unit tests which don't mock GraphicBuffers but instead send
- // in nullptrs.
- if (buffer == nullptr) {
- return {0, nullptr};
- }
if (auto i = mCacheByBufferId.find(buffer->getId()); i != mCacheByBufferId.end()) {
Cache& cache = i->second;
// mark this cache slot as more recently used so it won't get evicted anytime soon
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index 766d7ea..60a2c83 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -617,13 +617,24 @@
return;
}
+ // Uncache the active buffer last so that it's the first buffer to be purged from the cache
+ // next time a buffer is sent to this layer.
+ bool uncacheActiveBuffer = false;
+
std::vector<uint32_t> slotsToClear;
for (uint64_t bufferId : bufferIdsToUncache) {
- uint32_t slot = state.hwc->hwcBufferCache.uncache(bufferId);
- if (slot != UINT32_MAX) {
- slotsToClear.push_back(slot);
+ if (bufferId == state.hwc->activeBufferId) {
+ uncacheActiveBuffer = true;
+ } else {
+ uint32_t slot = state.hwc->hwcBufferCache.uncache(bufferId);
+ if (slot != UINT32_MAX) {
+ slotsToClear.push_back(slot);
+ }
}
}
+ if (uncacheActiveBuffer) {
+ slotsToClear.push_back(state.hwc->hwcBufferCache.uncache(state.hwc->activeBufferId));
+ }
hal::Error error =
state.hwc->hwcLayer->setBufferSlotsToClear(slotsToClear, state.hwc->activeBufferSlot);
@@ -655,17 +666,20 @@
hwcSlotAndBuffer = state.hwc->hwcBufferCache.getOverrideHwcSlotAndBuffer(
state.overrideInfo.buffer->getBuffer());
hwcFence = state.overrideInfo.acquireFence;
+ // Keep track of the active buffer ID so when it's discarded we uncache it last so its
+ // slot will be used first, allowing the memory to be freed as soon as possible.
+ state.hwc->activeBufferId = state.overrideInfo.buffer->getBuffer()->getId();
} else {
hwcSlotAndBuffer =
state.hwc->hwcBufferCache.getHwcSlotAndBuffer(outputIndependentState.buffer);
hwcFence = outputIndependentState.acquireFence;
+ // Keep track of the active buffer ID so when it's discarded we uncache it last so its
+ // slot will be used first, allowing the memory to be freed as soon as possible.
+ state.hwc->activeBufferId = outputIndependentState.buffer->getId();
}
-
// Keep track of the active buffer slot, so we can restore it after clearing other buffer
// slots.
- if (hwcSlotAndBuffer.buffer) {
- state.hwc->activeBufferSlot = hwcSlotAndBuffer.slot;
- }
+ state.hwc->activeBufferSlot = hwcSlotAndBuffer.slot;
}
if (auto error = hwcLayer->setBuffer(hwcSlotAndBuffer.slot, hwcSlotAndBuffer.buffer, hwcFence);
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index 0edc226..9ad2edb 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -1318,6 +1318,7 @@
struct OutputLayerUncacheBufferTest : public OutputLayerTest {
static const sp<GraphicBuffer> kBuffer1;
static const sp<GraphicBuffer> kBuffer2;
+ static const sp<GraphicBuffer> kBuffer3;
static const sp<Fence> kFence;
OutputLayerUncacheBufferTest() {
@@ -1343,6 +1344,10 @@
sp<GraphicBuffer>::make(2, 3, PIXEL_FORMAT_RGBA_8888,
AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN);
+const sp<GraphicBuffer> OutputLayerUncacheBufferTest::kBuffer3 =
+ sp<GraphicBuffer>::make(4, 5, PIXEL_FORMAT_RGBA_8888,
+ AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
+ AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN);
const sp<Fence> OutputLayerUncacheBufferTest::kFence = sp<Fence>::make();
TEST_F(OutputLayerUncacheBufferTest, canUncacheAndReuseSlot) {
@@ -1360,26 +1365,38 @@
/*zIsOverridden*/ false, /*isPeekingThrough*/ false);
Mock::VerifyAndClearExpectations(&mHwcLayer);
- // buffer slots are cleared in HWC
- std::vector<uint32_t> slotsToClear = {0, 1};
- EXPECT_CALL(mHwcLayer,
- setBufferSlotsToClear(/*slotsToClear*/ slotsToClear, /*activeBufferSlot*/ 1));
- mOutputLayer.uncacheBuffers({kBuffer1->getId(), kBuffer2->getId()});
+ // Buffer3 is stored in slot 2
+ mLayerFEState.buffer = kBuffer3;
+ EXPECT_CALL(mHwcLayer, setBuffer(/*slot*/ 2, kBuffer3, kFence));
+ mOutputLayer.writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, 0,
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
Mock::VerifyAndClearExpectations(&mHwcLayer);
- // rather than allocating a new slot, the active buffer slot (slot 1) is reused first to free
- // the memory as soon as possible
+ // Buffer2 becomes the active buffer again (with a nullptr) and reuses slot 1
+ mLayerFEState.buffer = kBuffer2;
+ sp<GraphicBuffer> nullBuffer = nullptr;
+ EXPECT_CALL(mHwcLayer, setBuffer(/*slot*/ 1, nullBuffer, kFence));
+ mOutputLayer.writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, 0,
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ Mock::VerifyAndClearExpectations(&mHwcLayer);
+
+ // Buffer slots are cleared
+ std::vector<uint32_t> slotsToClear = {0, 2, 1}; // order doesn't matter
+ EXPECT_CALL(mHwcLayer, setBufferSlotsToClear(slotsToClear, /*activeBufferSlot*/ 1));
+ // Uncache the active buffer in between other buffers to exercise correct algorithmic behavior.
+ mOutputLayer.uncacheBuffers({kBuffer1->getId(), kBuffer2->getId(), kBuffer3->getId()});
+ Mock::VerifyAndClearExpectations(&mHwcLayer);
+
+ // Buffer1 becomes active again, and rather than allocating a new slot, or re-using slot 0,
+ // the active buffer slot (slot 1 for Buffer2) is reused first, which allows HWC to free the
+ // memory for the active buffer. Note: slot 1 is different from the first and last buffer slot
+ // requested to be cleared in slotsToClear (slot 1), above, indicating that the algorithm
+ // correctly identifies the active buffer as the buffer in slot 1, despite ping-ponging.
mLayerFEState.buffer = kBuffer1;
EXPECT_CALL(mHwcLayer, setBuffer(/*slot*/ 1, kBuffer1, kFence));
mOutputLayer.writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, 0,
/*zIsOverridden*/ false, /*isPeekingThrough*/ false);
Mock::VerifyAndClearExpectations(&mHwcLayer);
-
- // rather than allocating a new slot, slot 0 is reused
- mLayerFEState.buffer = kBuffer2;
- EXPECT_CALL(mHwcLayer, setBuffer(/*slot*/ 0, kBuffer2, kFence));
- mOutputLayer.writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
}
/*
diff --git a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
index f1a6c0e..ab98dbf 100644
--- a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
+++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
@@ -27,7 +27,6 @@
#include <log/log.h>
#include <mock/MockEventThread.h>
#include <renderengine/ExternalTexture.h>
-#include <renderengine/mock/FakeExternalTexture.h>
#include <renderengine/mock/RenderEngine.h>
#include <utils/String16.h>
#include <string>
@@ -95,6 +94,30 @@
}
};
+class FakeExternalTexture : public renderengine::ExternalTexture {
+ const sp<GraphicBuffer> mNullBuffer = nullptr;
+ uint32_t mWidth;
+ uint32_t mHeight;
+ uint64_t mId;
+ PixelFormat mPixelFormat;
+ uint64_t mUsage;
+
+public:
+ FakeExternalTexture(uint32_t width, uint32_t height, uint64_t id, PixelFormat pixelFormat,
+ uint64_t usage)
+ : mWidth(width), mHeight(height), mId(id), mPixelFormat(pixelFormat), mUsage(usage) {}
+ const sp<GraphicBuffer>& getBuffer() const { return mNullBuffer; }
+ bool hasSameBuffer(const renderengine::ExternalTexture& other) const override {
+ return getId() == other.getId();
+ }
+ uint32_t getWidth() const override { return mWidth; }
+ uint32_t getHeight() const override { return mHeight; }
+ uint64_t getId() const override { return mId; }
+ PixelFormat getPixelFormat() const override { return mPixelFormat; }
+ uint64_t getUsage() const override { return mUsage; }
+ ~FakeExternalTexture() = default;
+};
+
class MockSurfaceFlinger : public SurfaceFlinger {
public:
MockSurfaceFlinger(Factory& factory)
@@ -102,12 +125,10 @@
std::shared_ptr<renderengine::ExternalTexture> getExternalTextureFromBufferData(
BufferData& bufferData, const char* /* layerName */,
uint64_t /* transactionId */) override {
- return std::make_shared<renderengine::mock::FakeExternalTexture>(bufferData.getWidth(),
- bufferData.getHeight(),
- bufferData.getId(),
- bufferData
- .getPixelFormat(),
- bufferData.getUsage());
+ return std::make_shared<FakeExternalTexture>(bufferData.getWidth(), bufferData.getHeight(),
+ bufferData.getId(),
+ bufferData.getPixelFormat(),
+ bufferData.getUsage());
};
// b/220017192 migrate from transact codes to ISurfaceComposer apis
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 06b9caa..ba77600 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -182,7 +182,9 @@
sp<mock::NativeWindow> mNativeWindow = sp<mock::NativeWindow>::make();
std::vector<sp<Layer>> mAuxiliaryLayers;
- sp<GraphicBuffer> mBuffer = sp<GraphicBuffer>::make();
+ sp<GraphicBuffer> mBuffer =
+ sp<GraphicBuffer>::make(1u, 1u, PIXEL_FORMAT_RGBA_8888,
+ GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_OFTEN);
ANativeWindowBuffer* mNativeWindowBuffer = mBuffer->getNativeBuffer();
Hwc2::mock::Composer* mComposer = nullptr;
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
index d58e644..223f4db 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
@@ -115,7 +115,9 @@
TestableSurfaceFlinger mFlinger;
sp<mock::NativeWindow> mNativeWindow = sp<mock::NativeWindow>::make();
- sp<GraphicBuffer> mBuffer = sp<GraphicBuffer>::make();
+ sp<GraphicBuffer> mBuffer =
+ sp<GraphicBuffer>::make(1u, 1u, PIXEL_FORMAT_RGBA_8888,
+ GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_OFTEN);
Hwc2::mock::PowerAdvisor mPowerAdvisor;
FakeDisplayInjector mFakeDisplayInjector{mFlinger, mPowerAdvisor, mNativeWindow};
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
index c9fefe3..a78f42c 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
@@ -2508,10 +2508,6 @@
// b/190578904
TEST_P(RefreshRateSelectorTest,
getBestFrameRateMode_withCloseRefreshRates_LayerVoteType_Heuristic) {
- if (g_noSlowTests) {
- GTEST_SKIP();
- }
-
const int kMinRefreshRate = RefreshRateSelector::kMinSupportedFrameRate.getIntValue();
constexpr int kMaxRefreshRate = 240;
@@ -2540,10 +2536,6 @@
}
TEST_P(RefreshRateSelectorTest,
getBestFrameRateMode_withCloseRefreshRates_LayerVoteType_ExplicitDefault) {
- if (g_noSlowTests) {
- GTEST_SKIP();
- }
-
const int kMinRefreshRate = RefreshRateSelector::kMinSupportedFrameRate.getIntValue();
constexpr int kMaxRefreshRate = 240;
@@ -2572,10 +2564,6 @@
}
TEST_P(RefreshRateSelectorTest,
getBestFrameRateMode_withCloseRefreshRates_LayerVoteType_ExplicitExactOrMultiple) {
- if (g_noSlowTests) {
- GTEST_SKIP();
- }
-
const int kMinRefreshRate = RefreshRateSelector::kMinSupportedFrameRate.getIntValue();
constexpr int kMaxRefreshRate = 240;
@@ -2604,10 +2592,6 @@
}
TEST_P(RefreshRateSelectorTest,
getBestFrameRateMode_withCloseRefreshRates_LayerVoteType_ExplicitExact) {
- if (g_noSlowTests) {
- GTEST_SKIP();
- }
-
const int kMinRefreshRate = RefreshRateSelector::kMinSupportedFrameRate.getIntValue();
constexpr int kMaxRefreshRate = 240;