diff options
36 files changed, 571 insertions, 371 deletions
diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp index a135796179..738d16ac66 100644 --- a/libs/binder/rust/Android.bp +++ b/libs/binder/rust/Android.bp @@ -88,6 +88,7 @@ rust_library { min_sdk_version: "Tiramisu", lints: "none", clippy_lints: "none", + visibility: [":__subpackages__"], } rust_bindgen { diff --git a/libs/vibrator/ExternalVibration.cpp b/libs/vibrator/ExternalVibration.cpp index ec906458a3..80e911c65d 100644 --- a/libs/vibrator/ExternalVibration.cpp +++ b/libs/vibrator/ExternalVibration.cpp @@ -22,15 +22,6 @@ #include <log/log.h> #include <utils/Errors.h> - -// To guarantee if HapticScale enum has the same value as IExternalVibratorService -static_assert(static_cast<int>(android::os::HapticScale::MUTE) == static_cast<int>(android::os::IExternalVibratorService::SCALE_MUTE)); -static_assert(static_cast<int>(android::os::HapticScale::VERY_LOW) == static_cast<int>(android::os::IExternalVibratorService::SCALE_VERY_LOW)); -static_assert(static_cast<int>(android::os::HapticScale::LOW) == static_cast<int>(android::os::IExternalVibratorService::SCALE_LOW)); -static_assert(static_cast<int>(android::os::HapticScale::NONE) == static_cast<int>(android::os::IExternalVibratorService::SCALE_NONE)); -static_assert(static_cast<int>(android::os::HapticScale::HIGH) == static_cast<int>(android::os::IExternalVibratorService::SCALE_HIGH)); -static_assert(static_cast<int>(android::os::HapticScale::VERY_HIGH) == static_cast<int>(android::os::IExternalVibratorService::SCALE_VERY_HIGH)); - void writeAudioAttributes(const audio_attributes_t& attrs, android::Parcel* out) { out->writeInt32(attrs.usage); out->writeInt32(attrs.content_type); @@ -74,5 +65,25 @@ inline bool ExternalVibration::operator==(const ExternalVibration& rhs) const { return mToken == rhs.mToken; } +os::HapticScale ExternalVibration::externalVibrationScaleToHapticScale(int externalVibrationScale) { + switch (externalVibrationScale) { + case IExternalVibratorService::SCALE_MUTE: + return os::HapticScale::MUTE; + case IExternalVibratorService::SCALE_VERY_LOW: + return os::HapticScale::VERY_LOW; + case IExternalVibratorService::SCALE_LOW: + return os::HapticScale::LOW; + case IExternalVibratorService::SCALE_NONE: + return os::HapticScale::NONE; + case IExternalVibratorService::SCALE_HIGH: + return os::HapticScale::HIGH; + case IExternalVibratorService::SCALE_VERY_HIGH: + return os::HapticScale::VERY_HIGH; + default: + ALOGE("Unknown ExternalVibrationScale %d, not applying scaling", externalVibrationScale); + return os::HapticScale::NONE; + } +} + } // namespace os } // namespace android diff --git a/libs/vibrator/include/vibrator/ExternalVibration.h b/libs/vibrator/include/vibrator/ExternalVibration.h index 760dbce149..00cd3cd256 100644 --- a/libs/vibrator/include/vibrator/ExternalVibration.h +++ b/libs/vibrator/include/vibrator/ExternalVibration.h @@ -23,6 +23,7 @@ #include <binder/Parcelable.h> #include <system/audio.h> #include <utils/RefBase.h> +#include <vibrator/ExternalVibrationUtils.h> namespace android { namespace os { @@ -44,6 +45,10 @@ public : audio_attributes_t getAudioAttributes() const { return mAttrs; } sp<IExternalVibrationController> getController() { return mController; } + /* Converts the scale from non-public ExternalVibrationService into the HapticScale + * used by the utils. + */ + static os::HapticScale externalVibrationScaleToHapticScale(int externalVibrationScale); private: int32_t mUid; @@ -53,7 +58,7 @@ private: sp<IBinder> mToken = new BBinder(); }; -} // namespace android } // namespace os +} // namespace android #endif // ANDROID_EXTERNAL_VIBRATION_H diff --git a/libs/vibrator/include/vibrator/ExternalVibrationUtils.h b/libs/vibrator/include/vibrator/ExternalVibrationUtils.h index c588bfdedd..ca219d3cbf 100644 --- a/libs/vibrator/include/vibrator/ExternalVibrationUtils.h +++ b/libs/vibrator/include/vibrator/ExternalVibrationUtils.h @@ -19,8 +19,6 @@ namespace android::os { -// Copied from frameworks/base/core/java/android/os/IExternalVibratorService.aidl -// The values are checked in ExternalVibration.cpp enum class HapticScale { MUTE = -100, VERY_LOW = -2, diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp index c5e1f0ca94..a53fcd763d 100644 --- a/services/inputflinger/reader/Android.bp +++ b/services/inputflinger/reader/Android.bp @@ -54,6 +54,7 @@ filegroup { "mapper/VibratorInputMapper.cpp", "mapper/accumulator/CursorButtonAccumulator.cpp", "mapper/accumulator/CursorScrollAccumulator.cpp", + "mapper/accumulator/HidUsageAccumulator.cpp", "mapper/accumulator/SingleTouchMotionAccumulator.cpp", "mapper/accumulator/TouchButtonAccumulator.cpp", ], diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp index 18d03f8bab..0aaef53c0d 100644 --- a/services/inputflinger/reader/EventHub.cpp +++ b/services/inputflinger/reader/EventHub.cpp @@ -149,6 +149,14 @@ static std::string sha1(const std::string& in) { return out; } +/* The set of all Android key codes that correspond to buttons (bit-switches) on a stylus. */ +static constexpr std::array<int32_t, 4> STYLUS_BUTTON_KEYCODES = { + AKEYCODE_STYLUS_BUTTON_PRIMARY, + AKEYCODE_STYLUS_BUTTON_SECONDARY, + AKEYCODE_STYLUS_BUTTON_TERTIARY, + AKEYCODE_STYLUS_BUTTON_TAIL, +}; + /** * Return true if name matches "v4l-touch*" */ @@ -2171,13 +2179,15 @@ void EventHub::openDeviceLocked(const std::string& devicePath) { device->readDeviceBitMask(EVIOCGBIT(EV_MSC, 0), device->mscBitmask); device->readDeviceBitMask(EVIOCGPROP(0), device->propBitmask); - // See if this is a keyboard. Ignore everything in the button range except for - // joystick and gamepad buttons which are handled like keyboards for the most part. + // See if this is a device with keys. This could be full keyboard, or other devices like + // gamepads, joysticks, and styluses with buttons that should generate key presses. bool haveKeyboardKeys = device->keyBitmask.any(0, BTN_MISC) || device->keyBitmask.any(BTN_WHEEL, KEY_MAX + 1); bool haveGamepadButtons = device->keyBitmask.any(BTN_MISC, BTN_MOUSE) || device->keyBitmask.any(BTN_JOYSTICK, BTN_DIGI); - if (haveKeyboardKeys || haveGamepadButtons) { + bool haveStylusButtons = device->keyBitmask.test(BTN_STYLUS) || + device->keyBitmask.test(BTN_STYLUS2) || device->keyBitmask.test(BTN_STYLUS3); + if (haveKeyboardKeys || haveGamepadButtons || haveStylusButtons) { device->classes |= InputDeviceClass::KEYBOARD; } @@ -2187,11 +2197,13 @@ void EventHub::openDeviceLocked(const std::string& devicePath) { device->classes |= InputDeviceClass::CURSOR; } - // See if this is a rotary encoder type device. + // See if the device is specially configured to be of a certain type. std::string deviceType; if (device->configuration && device->configuration->tryGetProperty("device.type", deviceType)) { if (deviceType == "rotaryEncoder") { device->classes |= InputDeviceClass::ROTARY_ENCODER; + } else if (deviceType == "externalStylus") { + device->classes |= InputDeviceClass::EXTERNAL_STYLUS; } } @@ -2208,14 +2220,10 @@ void EventHub::openDeviceLocked(const std::string& devicePath) { } else if (device->keyBitmask.test(BTN_TOUCH) && device->absBitmask.test(ABS_X) && device->absBitmask.test(ABS_Y)) { device->classes |= InputDeviceClass::TOUCH; - // Is this a BT stylus? + // Is this a stylus that reports contact/pressure independently of touch coordinates? } else if ((device->absBitmask.test(ABS_PRESSURE) || device->keyBitmask.test(BTN_TOUCH)) && !device->absBitmask.test(ABS_X) && !device->absBitmask.test(ABS_Y)) { device->classes |= InputDeviceClass::EXTERNAL_STYLUS; - // Keyboard will try to claim some of the buttons but we really want to reserve those so we - // can fuse it with the touch screen data, so just take them back. Note this means an - // external stylus cannot also be a keyboard device. - device->classes &= ~InputDeviceClass::KEYBOARD; } // See if this device is a joystick. @@ -2300,6 +2308,16 @@ void EventHub::openDeviceLocked(const std::string& devicePath) { break; } } + + // See if this device has any stylus buttons that we would want to fuse with touch data. + if (!device->classes.any(InputDeviceClass::TOUCH | InputDeviceClass::TOUCH_MT)) { + for (int32_t keycode : STYLUS_BUTTON_KEYCODES) { + if (device->hasKeycodeLocked(keycode)) { + device->classes |= InputDeviceClass::EXTERNAL_STYLUS; + break; + } + } + } } // If the device isn't recognized as something we handle, don't monitor it. diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h index b9a2b4ce92..439123bf1d 100644 --- a/services/inputflinger/reader/include/InputDevice.h +++ b/services/inputflinger/reader/include/InputDevice.h @@ -378,8 +378,11 @@ public: mEventHub->getAbsoluteAxisInfo(mId, code, &info); return info.valid; } - inline bool isKeyPressed(int32_t code) const { - return mEventHub->getScanCodeState(mId, code) == AKEY_STATE_DOWN; + inline bool isKeyPressed(int32_t scanCode) const { + return mEventHub->getScanCodeState(mId, scanCode) == AKEY_STATE_DOWN; + } + inline bool isKeyCodePressed(int32_t keyCode) const { + return mEventHub->getKeyCodeState(mId, keyCode) == AKEY_STATE_DOWN; } inline int32_t getAbsoluteAxisValue(int32_t code) const { int32_t value; diff --git a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp index 0404c9acc1..56fc5fa99a 100644 --- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp +++ b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp @@ -24,7 +24,7 @@ namespace android { ExternalStylusInputMapper::ExternalStylusInputMapper(InputDeviceContext& deviceContext) - : InputMapper(deviceContext) {} + : InputMapper(deviceContext), mTouchButtonAccumulator(deviceContext) {} uint32_t ExternalStylusInputMapper::getSources() const { return AINPUT_SOURCE_STYLUS; @@ -48,13 +48,13 @@ std::list<NotifyArgs> ExternalStylusInputMapper::configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) { getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPressureAxis); - mTouchButtonAccumulator.configure(getDeviceContext()); + mTouchButtonAccumulator.configure(); return {}; } std::list<NotifyArgs> ExternalStylusInputMapper::reset(nsecs_t when) { mSingleTouchMotionAccumulator.reset(getDeviceContext()); - mTouchButtonAccumulator.reset(getDeviceContext()); + mTouchButtonAccumulator.reset(); return InputMapper::reset(when); } diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp index 8704d1b211..da9413e4ca 100644 --- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp +++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp @@ -24,67 +24,70 @@ namespace android { // --- Static Definitions --- -static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation, - const int32_t map[][4], size_t mapSize) { +static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) { + static constexpr int32_t KEYCODE_ROTATION_MAP[][4] = { + // key codes enumerated counter-clockwise with the original (unrotated) key first + // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation + {AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT}, + {AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN}, + {AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT}, + {AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP}, + {AKEYCODE_SYSTEM_NAVIGATION_DOWN, AKEYCODE_SYSTEM_NAVIGATION_RIGHT, + AKEYCODE_SYSTEM_NAVIGATION_UP, AKEYCODE_SYSTEM_NAVIGATION_LEFT}, + {AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP, + AKEYCODE_SYSTEM_NAVIGATION_LEFT, AKEYCODE_SYSTEM_NAVIGATION_DOWN}, + {AKEYCODE_SYSTEM_NAVIGATION_UP, AKEYCODE_SYSTEM_NAVIGATION_LEFT, + AKEYCODE_SYSTEM_NAVIGATION_DOWN, AKEYCODE_SYSTEM_NAVIGATION_RIGHT}, + {AKEYCODE_SYSTEM_NAVIGATION_LEFT, AKEYCODE_SYSTEM_NAVIGATION_DOWN, + AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP}, + }; + + LOG_ALWAYS_FATAL_IF(orientation < 0 || orientation > 3, "Invalid orientation: %d", orientation); if (orientation != DISPLAY_ORIENTATION_0) { - for (size_t i = 0; i < mapSize; i++) { - if (value == map[i][0]) { - return map[i][orientation]; + for (const auto& rotation : KEYCODE_ROTATION_MAP) { + if (rotation[DISPLAY_ORIENTATION_0] == keyCode) { + return rotation[orientation]; } } } - return value; + return keyCode; } -static const int32_t keyCodeRotationMap[][4] = { - // key codes enumerated counter-clockwise with the original (unrotated) key first - // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation - {AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT}, - {AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN}, - {AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT}, - {AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP}, - {AKEYCODE_SYSTEM_NAVIGATION_DOWN, AKEYCODE_SYSTEM_NAVIGATION_RIGHT, - AKEYCODE_SYSTEM_NAVIGATION_UP, AKEYCODE_SYSTEM_NAVIGATION_LEFT}, - {AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP, - AKEYCODE_SYSTEM_NAVIGATION_LEFT, AKEYCODE_SYSTEM_NAVIGATION_DOWN}, - {AKEYCODE_SYSTEM_NAVIGATION_UP, AKEYCODE_SYSTEM_NAVIGATION_LEFT, - AKEYCODE_SYSTEM_NAVIGATION_DOWN, AKEYCODE_SYSTEM_NAVIGATION_RIGHT}, - {AKEYCODE_SYSTEM_NAVIGATION_LEFT, AKEYCODE_SYSTEM_NAVIGATION_DOWN, - AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP}, -}; - -static const size_t keyCodeRotationMapSize = - sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]); - -static int32_t rotateStemKey(int32_t value, int32_t orientation, const int32_t map[][2], - size_t mapSize) { - if (orientation == DISPLAY_ORIENTATION_180) { - for (size_t i = 0; i < mapSize; i++) { - if (value == map[i][0]) { - return map[i][1]; - } - } - } - return value; +static bool isSupportedScanCode(int32_t scanCode) { + // KeyboardInputMapper handles keys from keyboards, gamepads, and styluses. + return scanCode < BTN_MOUSE || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI) || + scanCode == BTN_STYLUS || scanCode == BTN_STYLUS2 || scanCode == BTN_STYLUS3 || + scanCode >= BTN_WHEEL; } -// The mapping can be defined using input device configuration properties keyboard.rotated.stem_X -static int32_t stemKeyRotationMap[][2] = { - // key codes enumerated with the original (unrotated) key first - // no rotation, 180 degree rotation - {AKEYCODE_STEM_PRIMARY, AKEYCODE_STEM_PRIMARY}, - {AKEYCODE_STEM_1, AKEYCODE_STEM_1}, - {AKEYCODE_STEM_2, AKEYCODE_STEM_2}, - {AKEYCODE_STEM_3, AKEYCODE_STEM_3}, -}; - -static const size_t stemKeyRotationMapSize = - sizeof(stemKeyRotationMap) / sizeof(stemKeyRotationMap[0]); - -static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) { - keyCode = rotateStemKey(keyCode, orientation, stemKeyRotationMap, stemKeyRotationMapSize); - return rotateValueUsingRotationMap(keyCode, orientation, keyCodeRotationMap, - keyCodeRotationMapSize); +static bool isMediaKey(int32_t keyCode) { + switch (keyCode) { + case AKEYCODE_MEDIA_PLAY: + case AKEYCODE_MEDIA_PAUSE: + case AKEYCODE_MEDIA_PLAY_PAUSE: + case AKEYCODE_MUTE: + case AKEYCODE_HEADSETHOOK: + case AKEYCODE_MEDIA_STOP: + case AKEYCODE_MEDIA_NEXT: + case AKEYCODE_MEDIA_PREVIOUS: + case AKEYCODE_MEDIA_REWIND: + case AKEYCODE_MEDIA_RECORD: + case AKEYCODE_MEDIA_FAST_FORWARD: + case AKEYCODE_MEDIA_SKIP_FORWARD: + case AKEYCODE_MEDIA_SKIP_BACKWARD: + case AKEYCODE_MEDIA_STEP_FORWARD: + case AKEYCODE_MEDIA_STEP_BACKWARD: + case AKEYCODE_MEDIA_AUDIO_TRACK: + case AKEYCODE_VOLUME_UP: + case AKEYCODE_VOLUME_DOWN: + case AKEYCODE_VOLUME_MUTE: + case AKEYCODE_TV_AUDIO_DESCRIPTION: + case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP: + case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN: + return true; + default: + return false; + } } // --- KeyboardInputMapper --- @@ -93,8 +96,6 @@ KeyboardInputMapper::KeyboardInputMapper(InputDeviceContext& deviceContext, uint int32_t keyboardType) : InputMapper(deviceContext), mSource(source), mKeyboardType(keyboardType) {} -KeyboardInputMapper::~KeyboardInputMapper() {} - uint32_t KeyboardInputMapper::getSources() const { return mSource; } @@ -130,7 +131,7 @@ void KeyboardInputMapper::dump(std::string& dump) { } std::optional<DisplayViewport> KeyboardInputMapper::findViewport( - nsecs_t when, const InputReaderConfiguration* config) { + const InputReaderConfiguration* config) { if (getDeviceContext().getAssociatedViewport()) { return getDeviceContext().getAssociatedViewport(); } @@ -154,35 +155,16 @@ std::list<NotifyArgs> KeyboardInputMapper::configure(nsecs_t when, } if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) { - mViewport = findViewport(when, config); + mViewport = findViewport(config); } return out; } -static void mapStemKey(int32_t keyCode, const PropertyMap& config, char const* property) { - int32_t mapped = 0; - if (config.tryGetProperty(property, mapped) && mapped > 0) { - for (size_t i = 0; i < stemKeyRotationMapSize; i++) { - if (stemKeyRotationMap[i][0] == keyCode) { - stemKeyRotationMap[i][1] = mapped; - return; - } - } - } -} - void KeyboardInputMapper::configureParameters() { mParameters.orientationAware = false; const PropertyMap& config = getDeviceContext().getConfiguration(); config.tryGetProperty("keyboard.orientationAware", mParameters.orientationAware); - if (mParameters.orientationAware) { - mapStemKey(AKEYCODE_STEM_PRIMARY, config, "keyboard.rotated.stem_primary"); - mapStemKey(AKEYCODE_STEM_1, config, "keyboard.rotated.stem_1"); - mapStemKey(AKEYCODE_STEM_2, config, "keyboard.rotated.stem_2"); - mapStemKey(AKEYCODE_STEM_3, config, "keyboard.rotated.stem_3"); - } - mParameters.handlesKeyRepeat = false; config.tryGetProperty("keyboard.handlesKeyRepeat", mParameters.handlesKeyRepeat); @@ -190,7 +172,7 @@ void KeyboardInputMapper::configureParameters() { config.tryGetProperty("keyboard.doNotWakeByDefault", mParameters.doNotWakeByDefault); } -void KeyboardInputMapper::dumpParameters(std::string& dump) { +void KeyboardInputMapper::dumpParameters(std::string& dump) const { dump += INDENT3 "Parameters:\n"; dump += StringPrintf(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware)); dump += StringPrintf(INDENT4 "HandlesKeyRepeat: %s\n", toString(mParameters.handlesKeyRepeat)); @@ -198,7 +180,7 @@ void KeyboardInputMapper::dumpParameters(std::string& dump) { std::list<NotifyArgs> KeyboardInputMapper::reset(nsecs_t when) { std::list<NotifyArgs> out = cancelAllDownKeys(when); - mCurrentHidUsage = 0; + mHidUsageAccumulator.reset(); resetLedState(); @@ -208,68 +190,21 @@ std::list<NotifyArgs> KeyboardInputMapper::reset(nsecs_t when) { std::list<NotifyArgs> KeyboardInputMapper::process(const RawEvent* rawEvent) { std::list<NotifyArgs> out; + mHidUsageAccumulator.process(*rawEvent); switch (rawEvent->type) { case EV_KEY: { int32_t scanCode = rawEvent->code; - int32_t usageCode = mCurrentHidUsage; - mCurrentHidUsage = 0; - if (isKeyboardOrGamepadKey(scanCode)) { + if (isSupportedScanCode(scanCode)) { out += processKey(rawEvent->when, rawEvent->readTime, rawEvent->value != 0, - scanCode, usageCode); - } - break; - } - case EV_MSC: { - if (rawEvent->code == MSC_SCAN) { - mCurrentHidUsage = rawEvent->value; + scanCode, mHidUsageAccumulator.consumeCurrentHidUsage()); } break; } - case EV_SYN: { - if (rawEvent->code == SYN_REPORT) { - mCurrentHidUsage = 0; - } - } } return out; } -bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) { - return scanCode < BTN_MOUSE || scanCode >= BTN_WHEEL || - (scanCode >= BTN_MISC && scanCode < BTN_MOUSE) || - (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI); -} - -bool KeyboardInputMapper::isMediaKey(int32_t keyCode) { - switch (keyCode) { - case AKEYCODE_MEDIA_PLAY: - case AKEYCODE_MEDIA_PAUSE: - case AKEYCODE_MEDIA_PLAY_PAUSE: - case AKEYCODE_MUTE: - case AKEYCODE_HEADSETHOOK: - case AKEYCODE_MEDIA_STOP: - case AKEYCODE_MEDIA_NEXT: - case AKEYCODE_MEDIA_PREVIOUS: - case AKEYCODE_MEDIA_REWIND: - case AKEYCODE_MEDIA_RECORD: - case AKEYCODE_MEDIA_FAST_FORWARD: - case AKEYCODE_MEDIA_SKIP_FORWARD: - case AKEYCODE_MEDIA_SKIP_BACKWARD: - case AKEYCODE_MEDIA_STEP_FORWARD: - case AKEYCODE_MEDIA_STEP_BACKWARD: - case AKEYCODE_MEDIA_AUDIO_TRACK: - case AKEYCODE_VOLUME_UP: - case AKEYCODE_VOLUME_DOWN: - case AKEYCODE_VOLUME_MUTE: - case AKEYCODE_TV_AUDIO_DESCRIPTION: - case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP: - case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN: - return true; - } - return false; -} - std::list<NotifyArgs> KeyboardInputMapper::processKey(nsecs_t when, nsecs_t readTime, bool down, int32_t scanCode, int32_t usageCode) { std::list<NotifyArgs> out; @@ -285,6 +220,7 @@ std::list<NotifyArgs> KeyboardInputMapper::processKey(nsecs_t when, nsecs_t read } nsecs_t downTime = when; + std::optional<size_t> keyDownIndex = findKeyDownIndex(scanCode); if (down) { // Rotate key codes according to orientation if needed. if (mParameters.orientationAware) { @@ -292,11 +228,10 @@ std::list<NotifyArgs> KeyboardInputMapper::processKey(nsecs_t when, nsecs_t read } // Add key down. - ssize_t keyDownIndex = findKeyDown(scanCode); - if (keyDownIndex >= 0) { + if (keyDownIndex) { // key repeat, be sure to use same keycode as before in case of rotation - keyCode = mKeyDowns[keyDownIndex].keyCode; - downTime = mKeyDowns[keyDownIndex].downTime; + keyCode = mKeyDowns[*keyDownIndex].keyCode; + downTime = mKeyDowns[*keyDownIndex].downTime; } else { // key down if ((policyFlags & POLICY_FLAG_VIRTUAL) && @@ -315,12 +250,11 @@ std::list<NotifyArgs> KeyboardInputMapper::processKey(nsecs_t when, nsecs_t read } } else { // Remove key down. - ssize_t keyDownIndex = findKeyDown(scanCode); - if (keyDownIndex >= 0) { + if (keyDownIndex) { // key up, be sure to use same keycode as before in case of rotation - keyCode = mKeyDowns[keyDownIndex].keyCode; - downTime = mKeyDowns[keyDownIndex].downTime; - mKeyDowns.erase(mKeyDowns.begin() + (size_t)keyDownIndex); + keyCode = mKeyDowns[*keyDownIndex].keyCode; + downTime = mKeyDowns[*keyDownIndex].downTime; + mKeyDowns.erase(mKeyDowns.begin() + *keyDownIndex); } else { // key was not actually down ALOGI("Dropping key up from device %s because the key was not down. " @@ -353,22 +287,22 @@ std::list<NotifyArgs> KeyboardInputMapper::processKey(nsecs_t when, nsecs_t read policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT; } - out.push_back(NotifyKeyArgs(getContext()->getNextId(), when, readTime, getDeviceId(), mSource, - getDisplayId(), policyFlags, - down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, - AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, - downTime)); + out.emplace_back(NotifyKeyArgs(getContext()->getNextId(), when, readTime, getDeviceId(), + mSource, getDisplayId(), policyFlags, + down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, + AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, + downTime)); return out; } -ssize_t KeyboardInputMapper::findKeyDown(int32_t scanCode) { +std::optional<size_t> KeyboardInputMapper::findKeyDownIndex(int32_t scanCode) { size_t n = mKeyDowns.size(); for (size_t i = 0; i < n; i++) { if (mKeyDowns[i].scanCode == scanCode) { return i; } } - return -1; + return {}; } int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) { @@ -481,12 +415,12 @@ std::list<NotifyArgs> KeyboardInputMapper::cancelAllDownKeys(nsecs_t when) { std::list<NotifyArgs> out; size_t n = mKeyDowns.size(); for (size_t i = 0; i < n; i++) { - out.push_back(NotifyKeyArgs(getContext()->getNextId(), when, - systemTime(SYSTEM_TIME_MONOTONIC), getDeviceId(), mSource, - getDisplayId(), 0 /*policyFlags*/, AKEY_EVENT_ACTION_UP, - AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_CANCELED, - mKeyDowns[i].keyCode, mKeyDowns[i].scanCode, AMETA_NONE, - mKeyDowns[i].downTime)); + out.emplace_back(NotifyKeyArgs(getContext()->getNextId(), when, + systemTime(SYSTEM_TIME_MONOTONIC), getDeviceId(), mSource, + getDisplayId(), 0 /*policyFlags*/, AKEY_EVENT_ACTION_UP, + AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_CANCELED, + mKeyDowns[i].keyCode, mKeyDowns[i].scanCode, AMETA_NONE, + mKeyDowns[i].downTime)); } mKeyDowns.clear(); mMetaState = AMETA_NONE; diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.h b/services/inputflinger/reader/mapper/KeyboardInputMapper.h index 8d72ee9629..11d5ad26e8 100644 --- a/services/inputflinger/reader/mapper/KeyboardInputMapper.h +++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.h @@ -16,6 +16,7 @@ #pragma once +#include "HidUsageAccumulator.h" #include "InputMapper.h" namespace android { @@ -23,7 +24,7 @@ namespace android { class KeyboardInputMapper : public InputMapper { public: KeyboardInputMapper(InputDeviceContext& deviceContext, uint32_t source, int32_t keyboardType); - virtual ~KeyboardInputMapper(); + ~KeyboardInputMapper() override = default; uint32_t getSources() const override; void populateDeviceInfo(InputDeviceInfo* deviceInfo) override; @@ -47,58 +48,54 @@ public: private: // The current viewport. - std::optional<DisplayViewport> mViewport; + std::optional<DisplayViewport> mViewport{}; struct KeyDown { - nsecs_t downTime; - int32_t keyCode; - int32_t scanCode; + nsecs_t downTime{}; + int32_t keyCode{}; + int32_t scanCode{}; }; - uint32_t mSource; - int32_t mKeyboardType; + uint32_t mSource{}; + int32_t mKeyboardType{}; - std::vector<KeyDown> mKeyDowns; // keys that are down - int32_t mMetaState; + std::vector<KeyDown> mKeyDowns{}; // keys that are down + int32_t mMetaState{}; - int32_t mCurrentHidUsage; // most recent HID usage seen this packet, or 0 if none + HidUsageAccumulator mHidUsageAccumulator; struct LedState { - bool avail; // led is available - bool on; // we think the led is currently on + bool avail{}; // led is available + bool on{}; // we think the led is currently on }; - LedState mCapsLockLedState; - LedState mNumLockLedState; - LedState mScrollLockLedState; + LedState mCapsLockLedState{}; + LedState mNumLockLedState{}; + LedState mScrollLockLedState{}; // Immutable configuration parameters. struct Parameters { - bool orientationAware; - bool handlesKeyRepeat; - bool doNotWakeByDefault; - } mParameters; + bool orientationAware{}; + bool handlesKeyRepeat{}; + bool doNotWakeByDefault{}; + } mParameters{}; void configureParameters(); - void dumpParameters(std::string& dump); + void dumpParameters(std::string& dump) const; int32_t getOrientation(); int32_t getDisplayId(); - bool isKeyboardOrGamepadKey(int32_t scanCode); - bool isMediaKey(int32_t keyCode); - [[nodiscard]] std::list<NotifyArgs> processKey(nsecs_t when, nsecs_t readTime, bool down, int32_t scanCode, int32_t usageCode); bool updateMetaStateIfNeeded(int32_t keyCode, bool down); - ssize_t findKeyDown(int32_t scanCode); + std::optional<size_t> findKeyDownIndex(int32_t scanCode); void resetLedState(); void initializeLedState(LedState& ledState, int32_t led); void updateLedStateForModifier(LedState& ledState, int32_t led, int32_t modifier, bool reset); - std::optional<DisplayViewport> findViewport(nsecs_t when, - const InputReaderConfiguration* config); + std::optional<DisplayViewport> findViewport(const InputReaderConfiguration* config); [[nodiscard]] std::list<NotifyArgs> cancelAllDownKeys(nsecs_t when); }; diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp index 615889ebe3..d17cdf5559 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp @@ -170,6 +170,7 @@ void CookedPointerData::copyFrom(const CookedPointerData& other) { TouchInputMapper::TouchInputMapper(InputDeviceContext& deviceContext) : InputMapper(deviceContext), + mTouchButtonAccumulator(deviceContext), mSource(0), mDeviceMode(DeviceMode::DISABLED), mDisplayWidth(-1), @@ -360,7 +361,7 @@ std::list<NotifyArgs> TouchInputMapper::configure(nsecs_t when, // Configure common accumulators. mCursorScrollAccumulator.configure(getDeviceContext()); - mTouchButtonAccumulator.configure(getDeviceContext()); + mTouchButtonAccumulator.configure(); // Configure absolute axis information. configureRawPointerAxes(); @@ -1449,7 +1450,7 @@ std::list<NotifyArgs> TouchInputMapper::reset(nsecs_t when) { mCursorButtonAccumulator.reset(getDeviceContext()); mCursorScrollAccumulator.reset(getDeviceContext()); - mTouchButtonAccumulator.reset(getDeviceContext()); + mTouchButtonAccumulator.reset(); mPointerVelocityControl.reset(); mWheelXVelocityControl.reset(); diff --git a/services/inputflinger/reader/mapper/accumulator/HidUsageAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/HidUsageAccumulator.cpp new file mode 100644 index 0000000000..2da1d814fa --- /dev/null +++ b/services/inputflinger/reader/mapper/accumulator/HidUsageAccumulator.cpp @@ -0,0 +1,39 @@ +/* + * 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. + */ + +#include "HidUsageAccumulator.h" + +namespace android { + +void HidUsageAccumulator::process(const RawEvent& rawEvent) { + if (rawEvent.type == EV_MSC && rawEvent.code == MSC_SCAN) { + mCurrentHidUsage = rawEvent.value; + return; + } + + if (rawEvent.type == EV_SYN && rawEvent.code == SYN_REPORT) { + reset(); + return; + } +} + +int32_t HidUsageAccumulator::consumeCurrentHidUsage() { + const int32_t currentHidUsage = mCurrentHidUsage; + reset(); + return currentHidUsage; +} + +} // namespace android diff --git a/services/inputflinger/reader/mapper/accumulator/HidUsageAccumulator.h b/services/inputflinger/reader/mapper/accumulator/HidUsageAccumulator.h new file mode 100644 index 0000000000..740a710483 --- /dev/null +++ b/services/inputflinger/reader/mapper/accumulator/HidUsageAccumulator.h @@ -0,0 +1,40 @@ +/* + * 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. + */ + +#pragma once + +#include "EventHub.h" + +#include <cstdint> + +namespace android { + +/* Keeps track of the state of currently reported HID usage code. */ +class HidUsageAccumulator { +public: + explicit HidUsageAccumulator() = default; + inline void reset() { *this = HidUsageAccumulator(); } + + void process(const RawEvent& rawEvent); + + /* This must be called when processing the `EV_KEY` event. Returns 0 if invalid. */ + int32_t consumeCurrentHidUsage(); + +private: + int32_t mCurrentHidUsage{}; +}; + +} // namespace android diff --git a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp index 86153d3f5e..5d5bee7feb 100644 --- a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp +++ b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp @@ -21,55 +21,39 @@ namespace android { -TouchButtonAccumulator::TouchButtonAccumulator() : mHaveBtnTouch(false), mHaveStylus(false) { - clearButtons(); +void TouchButtonAccumulator::configure() { + mHaveBtnTouch = mDeviceContext.hasScanCode(BTN_TOUCH); + mHaveStylus = mDeviceContext.hasScanCode(BTN_TOOL_PEN) || + mDeviceContext.hasScanCode(BTN_TOOL_RUBBER) || + mDeviceContext.hasScanCode(BTN_TOOL_BRUSH) || + mDeviceContext.hasScanCode(BTN_TOOL_PENCIL) || + mDeviceContext.hasScanCode(BTN_TOOL_AIRBRUSH); } -void TouchButtonAccumulator::configure(InputDeviceContext& deviceContext) { - mHaveBtnTouch = deviceContext.hasScanCode(BTN_TOUCH); - mHaveStylus = deviceContext.hasScanCode(BTN_TOOL_PEN) || - deviceContext.hasScanCode(BTN_TOOL_RUBBER) || - deviceContext.hasScanCode(BTN_TOOL_BRUSH) || - deviceContext.hasScanCode(BTN_TOOL_PENCIL) || - deviceContext.hasScanCode(BTN_TOOL_AIRBRUSH); -} - -void TouchButtonAccumulator::reset(InputDeviceContext& deviceContext) { - mBtnTouch = deviceContext.isKeyPressed(BTN_TOUCH); - mBtnStylus = deviceContext.isKeyPressed(BTN_STYLUS); +void TouchButtonAccumulator::reset() { + mBtnTouch = mDeviceContext.isKeyPressed(BTN_TOUCH); + mBtnStylus = mDeviceContext.isKeyPressed(BTN_STYLUS) || + mDeviceContext.isKeyCodePressed(AKEYCODE_STYLUS_BUTTON_PRIMARY); // BTN_0 is what gets mapped for the HID usage Digitizers.SecondaryBarrelSwitch - mBtnStylus2 = deviceContext.isKeyPressed(BTN_STYLUS2) || deviceContext.isKeyPressed(BTN_0); - mBtnToolFinger = deviceContext.isKeyPressed(BTN_TOOL_FINGER); - mBtnToolPen = deviceContext.isKeyPressed(BTN_TOOL_PEN); - mBtnToolRubber = deviceContext.isKeyPressed(BTN_TOOL_RUBBER); - mBtnToolBrush = deviceContext.isKeyPressed(BTN_TOOL_BRUSH); - mBtnToolPencil = deviceContext.isKeyPressed(BTN_TOOL_PENCIL); - mBtnToolAirbrush = deviceContext.isKeyPressed(BTN_TOOL_AIRBRUSH); - mBtnToolMouse = deviceContext.isKeyPressed(BTN_TOOL_MOUSE); - mBtnToolLens = deviceContext.isKeyPressed(BTN_TOOL_LENS); - mBtnToolDoubleTap = deviceContext.isKeyPressed(BTN_TOOL_DOUBLETAP); - mBtnToolTripleTap = deviceContext.isKeyPressed(BTN_TOOL_TRIPLETAP); - mBtnToolQuadTap = deviceContext.isKeyPressed(BTN_TOOL_QUADTAP); -} - -void TouchButtonAccumulator::clearButtons() { - mBtnTouch = 0; - mBtnStylus = 0; - mBtnStylus2 = 0; - mBtnToolFinger = 0; - mBtnToolPen = 0; - mBtnToolRubber = 0; - mBtnToolBrush = 0; - mBtnToolPencil = 0; - mBtnToolAirbrush = 0; - mBtnToolMouse = 0; - mBtnToolLens = 0; - mBtnToolDoubleTap = 0; - mBtnToolTripleTap = 0; - mBtnToolQuadTap = 0; + mBtnStylus2 = mDeviceContext.isKeyPressed(BTN_STYLUS2) || mDeviceContext.isKeyPressed(BTN_0) || + mDeviceContext.isKeyCodePressed(AKEYCODE_STYLUS_BUTTON_SECONDARY); + mBtnToolFinger = mDeviceContext.isKeyPressed(BTN_TOOL_FINGER); + mBtnToolPen = mDeviceContext.isKeyPressed(BTN_TOOL_PEN); + mBtnToolRubber = mDeviceContext.isKeyPressed(BTN_TOOL_RUBBER); + mBtnToolBrush = mDeviceContext.isKeyPressed(BTN_TOOL_BRUSH); + mBtnToolPencil = mDeviceContext.isKeyPressed(BTN_TOOL_PENCIL); + mBtnToolAirbrush = mDeviceContext.isKeyPressed(BTN_TOOL_AIRBRUSH); + mBtnToolMouse = mDeviceContext.isKeyPressed(BTN_TOOL_MOUSE); + mBtnToolLens = mDeviceContext.isKeyPressed(BTN_TOOL_LENS); + mBtnToolDoubleTap = mDeviceContext.isKeyPressed(BTN_TOOL_DOUBLETAP); + mBtnToolTripleTap = mDeviceContext.isKeyPressed(BTN_TOOL_TRIPLETAP); + mBtnToolQuadTap = mDeviceContext.isKeyPressed(BTN_TOOL_QUADTAP); + mHidUsageAccumulator.reset(); } void TouchButtonAccumulator::process(const RawEvent* rawEvent) { + mHidUsageAccumulator.process(*rawEvent); + if (rawEvent->type == EV_KEY) { switch (rawEvent->code) { case BTN_TOUCH: @@ -116,7 +100,29 @@ void TouchButtonAccumulator::process(const RawEvent* rawEvent) { case BTN_TOOL_QUADTAP: mBtnToolQuadTap = rawEvent->value; break; + default: + processMappedKey(rawEvent->code, rawEvent->value); } + return; + } +} + +void TouchButtonAccumulator::processMappedKey(int32_t scanCode, bool down) { + int32_t outKeyCode, outMetaState; + uint32_t outFlags; + if (mDeviceContext.mapKey(scanCode, mHidUsageAccumulator.consumeCurrentHidUsage(), + 0 /*metaState*/, &outKeyCode, &outMetaState, &outFlags) != OK) { + return; + } + switch (outKeyCode) { + case AKEYCODE_STYLUS_BUTTON_PRIMARY: + mBtnStylus = down; + break; + case AKEYCODE_STYLUS_BUTTON_SECONDARY: + mBtnStylus2 = down; + break; + default: + break; } } diff --git a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h index 7b889be238..65b0a62747 100644 --- a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h +++ b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h @@ -16,7 +16,8 @@ #pragma once -#include <stdint.h> +#include <cstdint> +#include "HidUsageAccumulator.h" namespace android { @@ -26,9 +27,11 @@ struct RawEvent; /* Keeps track of the state of touch, stylus and tool buttons. */ class TouchButtonAccumulator { public: - TouchButtonAccumulator(); - void configure(InputDeviceContext& deviceContext); - void reset(InputDeviceContext& deviceContext); + explicit TouchButtonAccumulator(InputDeviceContext& deviceContext) + : mDeviceContext(deviceContext){}; + + void configure(); + void reset(); void process(const RawEvent* rawEvent); @@ -39,25 +42,29 @@ public: bool hasStylus() const; private: - bool mHaveBtnTouch; - bool mHaveStylus; - - bool mBtnTouch; - bool mBtnStylus; - bool mBtnStylus2; - bool mBtnToolFinger; - bool mBtnToolPen; - bool mBtnToolRubber; - bool mBtnToolBrush; - bool mBtnToolPencil; - bool mBtnToolAirbrush; - bool mBtnToolMouse; - bool mBtnToolLens; - bool mBtnToolDoubleTap; - bool mBtnToolTripleTap; - bool mBtnToolQuadTap; - - void clearButtons(); + bool mHaveBtnTouch{}; + bool mHaveStylus{}; + + bool mBtnTouch{}; + bool mBtnStylus{}; + bool mBtnStylus2{}; + bool mBtnToolFinger{}; + bool mBtnToolPen{}; + bool mBtnToolRubber{}; + bool mBtnToolBrush{}; + bool mBtnToolPencil{}; + bool mBtnToolAirbrush{}; + bool mBtnToolMouse{}; + bool mBtnToolLens{}; + bool mBtnToolDoubleTap{}; + bool mBtnToolTripleTap{}; + bool mBtnToolQuadTap{}; + + HidUsageAccumulator mHidUsageAccumulator{}; + + InputDeviceContext& mDeviceContext; + + void processMappedKey(int32_t scanCode, bool down); }; } // namespace android diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index f333306f26..2142070a09 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -2391,18 +2391,11 @@ TEST_F(InputReaderIntegrationTest, AddNewDevice) { ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled()); ASSERT_EQ(initialNumDevices + 1, mFakePolicy->getInputDevices().size()); - // Find the test device by its name. - const std::vector<InputDeviceInfo> inputDevices = mFakePolicy->getInputDevices(); - const auto& it = - std::find_if(inputDevices.begin(), inputDevices.end(), - [&keyboard](const InputDeviceInfo& info) { - return info.getIdentifier().name == keyboard->getName(); - }); - - ASSERT_NE(it, inputDevices.end()); - ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, it->getKeyboardType()); - ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, it->getSources()); - ASSERT_EQ(0U, it->getMotionRanges().size()); + const auto device = findDeviceByName(keyboard->getName()); + ASSERT_TRUE(device.has_value()); + ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, device->getKeyboardType()); + ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources()); + ASSERT_EQ(0U, device->getMotionRanges().size()); keyboard.reset(); ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged()); @@ -2437,6 +2430,41 @@ TEST_F(InputReaderIntegrationTest, SendsEventsToInputListener) { ASSERT_LE(keyArgs.eventTime, keyArgs.readTime); } +TEST_F(InputReaderIntegrationTest, ExternalStylusesButtons) { + std::unique_ptr<UinputExternalStylus> stylus = createUinputDevice<UinputExternalStylus>(); + ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged()); + + const auto device = findDeviceByName(stylus->getName()); + ASSERT_TRUE(device.has_value()); + + // An external stylus with buttons should also be recognized as a keyboard. + ASSERT_EQ(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_STYLUS, device->getSources()) + << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str(); + ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, device->getKeyboardType()); + + const auto DOWN = + AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD)); + const auto UP = AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD)); + + stylus->pressAndReleaseKey(BTN_STYLUS); + ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled( + AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY)))); + ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled( + AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY)))); + + stylus->pressAndReleaseKey(BTN_STYLUS2); + ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled( + AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_SECONDARY)))); + ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled( + AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_SECONDARY)))); + + stylus->pressAndReleaseKey(BTN_STYLUS3); + ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled( + AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_TERTIARY)))); + ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled( + AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_TERTIARY)))); +} + /** * The Steam controller sends BTN_GEAR_DOWN and BTN_GEAR_UP for the two "paddle" buttons * on the back. In this test, we make sure that BTN_GEAR_DOWN / BTN_WHEEL and BTN_GEAR_UP @@ -2772,6 +2800,20 @@ TEST_F(TouchIntegrationTest, NotifiesPolicyWhenStylusGestureStarted) { ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotified(mDeviceInfo.getId())); } +TEST_F(TouchIntegrationTest, StylusButtonsGenerateKeyEvents) { + mDevice->sendKey(BTN_STYLUS, 1); + mDevice->sendSync(); + ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled( + AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD), + WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY)))); + + mDevice->sendKey(BTN_STYLUS, 0); + mDevice->sendSync(); + ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled( + AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD), + WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY)))); +} + // --- InputDeviceTest --- class InputDeviceTest : public testing::Test { protected: @@ -7296,6 +7338,7 @@ protected: void processSlot(MultiTouchInputMapper& mapper, int32_t slot); void processToolType(MultiTouchInputMapper& mapper, int32_t toolType); void processKey(MultiTouchInputMapper& mapper, int32_t code, int32_t value); + void processHidUsage(MultiTouchInputMapper& mapper, int32_t usageCode, int32_t value); void processMTSync(MultiTouchInputMapper& mapper); void processSync(MultiTouchInputMapper& mapper); }; @@ -7400,6 +7443,12 @@ void MultiTouchInputMapperTest::processKey(MultiTouchInputMapper& mapper, int32_ process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, code, value); } +void MultiTouchInputMapperTest::processHidUsage(MultiTouchInputMapper& mapper, int32_t usageCode, + int32_t value) { + process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, usageCode); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UNKNOWN, value); +} + void MultiTouchInputMapperTest::processMTSync(MultiTouchInputMapper& mapper) { process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_MT_REPORT, 0); } @@ -8515,6 +8564,63 @@ TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllButtons) { ASSERT_EQ(0, motionArgs.buttonState); } +TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleMappedStylusButtons) { + addConfigurationProperty("touch.deviceType", "touchScreen"); + prepareDisplay(DISPLAY_ORIENTATION_0); + prepareAxes(POSITION | ID | SLOT); + MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); + + mFakeEventHub->addKey(EVENTHUB_ID, BTN_A, 0, AKEYCODE_STYLUS_BUTTON_PRIMARY, 0); + mFakeEventHub->addKey(EVENTHUB_ID, 0, 0xabcd, AKEYCODE_STYLUS_BUTTON_SECONDARY, 0); + + // Touch down. + processId(mapper, 1); + processPosition(mapper, 100, 200); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled( + AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithButtonState(0)))); + + // Press and release button mapped to the primary stylus button. + processKey(mapper, BTN_A, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled( + AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), + WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)))); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled( + AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS), + WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)))); + + processKey(mapper, BTN_A, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled( + AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE), WithButtonState(0)))); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled( + AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0)))); + + // Press and release the HID usage mapped to the secondary stylus button. + processHidUsage(mapper, 0xabcd, 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled( + AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), + WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY)))); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled( + AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS), + WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY)))); + + processHidUsage(mapper, 0xabcd, 0); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled( + AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE), WithButtonState(0)))); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled( + AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0)))); + + // Release touch. + processId(mapper, -1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled( + AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0)))); +} + TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllToolTypes) { addConfigurationProperty("touch.deviceType", "touchScreen"); prepareDisplay(DISPLAY_ORIENTATION_0); diff --git a/services/inputflinger/tests/TestInputListener.cpp b/services/inputflinger/tests/TestInputListener.cpp index 29093efc67..5e47b8019b 100644 --- a/services/inputflinger/tests/TestInputListener.cpp +++ b/services/inputflinger/tests/TestInputListener.cpp @@ -59,6 +59,12 @@ void TestInputListener::assertNotifyKeyWasCalled(NotifyKeyArgs* outEventArgs) { assertCalled<NotifyKeyArgs>(outEventArgs, "Expected notifyKey() to have been called.")); } +void TestInputListener::assertNotifyKeyWasCalled(const ::testing::Matcher<NotifyKeyArgs>& matcher) { + NotifyKeyArgs outEventArgs; + ASSERT_NO_FATAL_FAILURE(assertNotifyKeyWasCalled(&outEventArgs)); + ASSERT_THAT(outEventArgs, matcher); +} + void TestInputListener::assertNotifyKeyWasNotCalled() { ASSERT_NO_FATAL_FAILURE(assertNotCalled<NotifyKeyArgs>("notifyKey() should not be called.")); } diff --git a/services/inputflinger/tests/TestInputListener.h b/services/inputflinger/tests/TestInputListener.h index 4ad1c4264d..87752e1487 100644 --- a/services/inputflinger/tests/TestInputListener.h +++ b/services/inputflinger/tests/TestInputListener.h @@ -44,6 +44,8 @@ public: void assertNotifyKeyWasCalled(NotifyKeyArgs* outEventArgs = nullptr); + void assertNotifyKeyWasCalled(const ::testing::Matcher<NotifyKeyArgs>& matcher); + void assertNotifyKeyWasNotCalled(); void assertNotifyMotionWasCalled(NotifyMotionArgs* outEventArgs = nullptr); diff --git a/services/inputflinger/tests/TestInputListenerMatchers.h b/services/inputflinger/tests/TestInputListenerMatchers.h index e48f1d9082..5107af7e27 100644 --- a/services/inputflinger/tests/TestInputListenerMatchers.h +++ b/services/inputflinger/tests/TestInputListenerMatchers.h @@ -23,7 +23,7 @@ namespace android { -MATCHER_P(WithMotionAction, action, "InputEvent with specified action") { +MATCHER_P(WithMotionAction, action, "MotionEvent with specified action") { bool matches = action == arg.action; if (!matches) { *result_listener << "expected action " << MotionEvent::actionToString(action) @@ -39,6 +39,12 @@ MATCHER_P(WithMotionAction, action, "InputEvent with specified action") { return matches; } +MATCHER_P(WithKeyAction, action, "KeyEvent with specified action") { + *result_listener << "expected action " << KeyEvent::actionToString(action) << ", but got " + << KeyEvent::actionToString(arg.action); + return arg.action == action; +} + MATCHER_P(WithSource, source, "InputEvent with specified source") { *result_listener << "expected source " << source << ", but got " << arg.source; return arg.source == source; @@ -49,6 +55,11 @@ MATCHER_P(WithDisplayId, displayId, "InputEvent with specified displayId") { return arg.displayId == displayId; } +MATCHER_P(WithKeyCode, keyCode, "KeyEvent with specified key code") { + *result_listener << "expected key code " << keyCode << ", but got " << arg.keyCode; + return arg.keyCode == keyCode; +} + MATCHER_P2(WithCoords, x, y, "InputEvent with specified coords") { const auto argX = arg.pointerCoords[0].getX(); const auto argY = arg.pointerCoords[0].getY(); @@ -75,4 +86,9 @@ MATCHER_P(WithFlags, flags, "InputEvent with specified flags") { return arg.flags == flags; } +MATCHER_P(WithButtonState, buttons, "InputEvent with specified button state") { + *result_listener << "expected button state " << buttons << ", but got " << arg.buttonState; + return arg.buttonState == buttons; +} + } // namespace android diff --git a/services/inputflinger/tests/UinputDevice.cpp b/services/inputflinger/tests/UinputDevice.cpp index 626ad67c71..c4830dc815 100644 --- a/services/inputflinger/tests/UinputDevice.cpp +++ b/services/inputflinger/tests/UinputDevice.cpp @@ -76,8 +76,8 @@ void UinputDevice::injectEvent(uint16_t type, uint16_t code, int32_t value) { // --- UinputKeyboard --- -UinputKeyboard::UinputKeyboard(std::initializer_list<int> keys) - : UinputDevice(UinputKeyboard::KEYBOARD_NAME), mKeys(keys.begin(), keys.end()) {} +UinputKeyboard::UinputKeyboard(const char* name, std::initializer_list<int> keys) + : UinputDevice(name), mKeys(keys.begin(), keys.end()) {} void UinputKeyboard::configureDevice(int fd, uinput_user_dev* device) { // enable key press/release event @@ -121,14 +121,19 @@ void UinputKeyboard::pressAndReleaseKey(int key) { // --- UinputHomeKey --- -UinputHomeKey::UinputHomeKey() : UinputKeyboard({KEY_HOME}) {} +UinputHomeKey::UinputHomeKey() : UinputKeyboard("Test Uinput Home Key", {KEY_HOME}) {} void UinputHomeKey::pressAndReleaseHomeKey() { pressAndReleaseKey(KEY_HOME); } // --- UinputSteamController -UinputSteamController::UinputSteamController() : UinputKeyboard({BTN_GEAR_DOWN, BTN_GEAR_UP}) {} +UinputSteamController::UinputSteamController() + : UinputKeyboard("Test Uinput Steam Controller", {BTN_GEAR_DOWN, BTN_GEAR_UP}) {} + +// --- UinputExternalStylus +UinputExternalStylus::UinputExternalStylus() + : UinputKeyboard("Test Uinput External Stylus", {BTN_STYLUS, BTN_STYLUS2, BTN_STYLUS3}) {} // --- UinputTouchScreen --- UinputTouchScreen::UinputTouchScreen(const Rect* size) @@ -147,6 +152,9 @@ void UinputTouchScreen::configureDevice(int fd, uinput_user_dev* device) { ioctl(fd, UI_SET_ABSBIT, ABS_MT_TOOL_TYPE); ioctl(fd, UI_SET_PROPBIT, INPUT_PROP_DIRECT); ioctl(fd, UI_SET_KEYBIT, BTN_TOUCH); + ioctl(fd, UI_SET_KEYBIT, BTN_STYLUS); + ioctl(fd, UI_SET_KEYBIT, BTN_STYLUS2); + ioctl(fd, UI_SET_KEYBIT, BTN_STYLUS3); device->absmin[ABS_MT_SLOT] = RAW_SLOT_MIN; device->absmax[ABS_MT_SLOT] = RAW_SLOT_MAX; @@ -198,6 +206,10 @@ void UinputTouchScreen::sendSync() { injectEvent(EV_SYN, SYN_REPORT, 0); } +void UinputTouchScreen::sendKey(int32_t scanCode, int32_t value) { + injectEvent(EV_KEY, scanCode, value); +} + // Get the center x, y base on the range definition. const Point UinputTouchScreen::getCenterPoint() { return Point(mSize.left + mSize.width() / 2, mSize.top + mSize.height() / 2); diff --git a/services/inputflinger/tests/UinputDevice.h b/services/inputflinger/tests/UinputDevice.h index e0ff8c3d4c..53dcfd0a68 100644 --- a/services/inputflinger/tests/UinputDevice.h +++ b/services/inputflinger/tests/UinputDevice.h @@ -84,7 +84,7 @@ public: friend std::unique_ptr<D> createUinputDevice(Ts... args); protected: - UinputKeyboard(std::initializer_list<int> keys = {}); + UinputKeyboard(const char* name, std::initializer_list<int> keys = {}); private: void configureDevice(int fd, uinput_user_dev* device) override; @@ -117,6 +117,16 @@ private: UinputSteamController(); }; +// A stylus that reports button presses. +class UinputExternalStylus : public UinputKeyboard { +public: + template <class D, class... Ts> + friend std::unique_ptr<D> createUinputDevice(Ts... args); + +private: + UinputExternalStylus(); +}; + // --- UinputTouchScreen --- // A touch screen device with specific size. class UinputTouchScreen : public UinputDevice { @@ -142,6 +152,7 @@ public: void sendUp(); void sendToolType(int32_t toolType); void sendSync(); + void sendKey(int32_t scanCode, int32_t value); const Point getCenterPoint(); diff --git a/services/stats/StatsAidl.cpp b/services/stats/StatsAidl.cpp index 3de51a437d..9e13849485 100644 --- a/services/stats/StatsAidl.cpp +++ b/services/stats/StatsAidl.cpp @@ -69,6 +69,10 @@ ndk::ScopedAStatus StatsHal::reportVendorAtom(const VendorAtom& vendorAtom) { case VendorAtomValue::repeatedIntValue: { const std::optional<std::vector<int>>& repeatedIntValue = atomValue.get<VendorAtomValue::repeatedIntValue>(); + if (!repeatedIntValue) { + AStatsEvent_writeInt32Array(event, {}, 0); + break; + } AStatsEvent_writeInt32Array(event, repeatedIntValue->data(), repeatedIntValue->size()); break; @@ -76,6 +80,10 @@ ndk::ScopedAStatus StatsHal::reportVendorAtom(const VendorAtom& vendorAtom) { case VendorAtomValue::repeatedLongValue: { const std::optional<std::vector<int64_t>>& repeatedLongValue = atomValue.get<VendorAtomValue::repeatedLongValue>(); + if (!repeatedLongValue) { + AStatsEvent_writeInt64Array(event, {}, 0); + break; + } AStatsEvent_writeInt64Array(event, repeatedLongValue->data(), repeatedLongValue->size()); break; @@ -83,6 +91,10 @@ ndk::ScopedAStatus StatsHal::reportVendorAtom(const VendorAtom& vendorAtom) { case VendorAtomValue::repeatedFloatValue: { const std::optional<std::vector<float>>& repeatedFloatValue = atomValue.get<VendorAtomValue::repeatedFloatValue>(); + if (!repeatedFloatValue) { + AStatsEvent_writeFloatArray(event, {}, 0); + break; + } AStatsEvent_writeFloatArray(event, repeatedFloatValue->data(), repeatedFloatValue->size()); break; @@ -90,12 +102,18 @@ ndk::ScopedAStatus StatsHal::reportVendorAtom(const VendorAtom& vendorAtom) { case VendorAtomValue::repeatedStringValue: { const std::optional<std::vector<std::optional<std::string>>>& repeatedStringValue = atomValue.get<VendorAtomValue::repeatedStringValue>(); + if (!repeatedStringValue) { + AStatsEvent_writeStringArray(event, {}, 0); + break; + } const std::vector<std::optional<std::string>>& repeatedStringVector = *repeatedStringValue; const char* cStringArray[repeatedStringVector.size()]; for (int i = 0; i < repeatedStringVector.size(); ++i) { - cStringArray[i] = repeatedStringVector[i]->c_str(); + cStringArray[i] = repeatedStringVector[i].has_value() + ? repeatedStringVector[i]->c_str() + : ""; } AStatsEvent_writeStringArray(event, cStringArray, repeatedStringVector.size()); @@ -104,6 +122,10 @@ ndk::ScopedAStatus StatsHal::reportVendorAtom(const VendorAtom& vendorAtom) { case VendorAtomValue::repeatedBoolValue: { const std::optional<std::vector<bool>>& repeatedBoolValue = atomValue.get<VendorAtomValue::repeatedBoolValue>(); + if (!repeatedBoolValue) { + AStatsEvent_writeBoolArray(event, {}, 0); + break; + } const std::vector<bool>& repeatedBoolVector = *repeatedBoolValue; bool boolArray[repeatedBoolValue->size()]; @@ -117,7 +139,10 @@ ndk::ScopedAStatus StatsHal::reportVendorAtom(const VendorAtom& vendorAtom) { case VendorAtomValue::byteArrayValue: { const std::optional<std::vector<uint8_t>>& byteArrayValue = atomValue.get<VendorAtomValue::byteArrayValue>(); - + if (!byteArrayValue) { + AStatsEvent_writeByteArray(event, {}, 0); + break; + } AStatsEvent_writeByteArray(event, byteArrayValue->data(), byteArrayValue->size()); break; } diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index 7202bef606..bdbc79b8e1 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -25,6 +25,7 @@ #include "Client.h" #include "FrontEnd/LayerCreationArgs.h" +#include "FrontEnd/LayerHandle.h" #include "Layer.h" #include "SurfaceFlinger.h" @@ -47,36 +48,6 @@ status_t Client::initCheck() const { return NO_ERROR; } -void Client::attachLayer(const sp<IBinder>& handle, const sp<Layer>& layer) -{ - Mutex::Autolock _l(mLock); - mLayers.add(handle, layer); -} - -void Client::detachLayer(const Layer* layer) -{ - Mutex::Autolock _l(mLock); - // we do a linear search here, because this doesn't happen often - const size_t count = mLayers.size(); - for (size_t i=0 ; i<count ; i++) { - if (mLayers.valueAt(i) == layer) { - mLayers.removeItemsAt(i, 1); - break; - } - } -} -sp<Layer> Client::getLayerUser(const sp<IBinder>& handle) const -{ - Mutex::Autolock _l(mLock); - sp<Layer> lbc; - wp<Layer> layer(mLayers.valueFor(handle)); - if (layer != 0) { - lbc = layer.promote(); - ALOGE_IF(lbc==0, "getLayerUser(name=%p) is dead", handle.get()); - } - return lbc; -} - binder::Status Client::createSurface(const std::string& name, int32_t flags, const sp<IBinder>& parent, const gui::LayerMetadata& metadata, gui::CreateSurfaceResult* outResult) { @@ -91,7 +62,7 @@ binder::Status Client::createSurface(const std::string& name, int32_t flags, binder::Status Client::clearLayerFrameStats(const sp<IBinder>& handle) { status_t status; - sp<Layer> layer = getLayerUser(handle); + sp<Layer> layer = LayerHandle::getLayer(handle); if (layer == nullptr) { status = NAME_NOT_FOUND; } else { @@ -103,7 +74,7 @@ binder::Status Client::clearLayerFrameStats(const sp<IBinder>& handle) { binder::Status Client::getLayerFrameStats(const sp<IBinder>& handle, gui::FrameStats* outStats) { status_t status; - sp<Layer> layer = getLayerUser(handle); + sp<Layer> layer = LayerHandle::getLayer(handle); if (layer == nullptr) { status = NAME_NOT_FOUND; } else { diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h index 02079a3b3f..af410ea19c 100644 --- a/services/surfaceflinger/Client.h +++ b/services/surfaceflinger/Client.h @@ -38,12 +38,6 @@ public: status_t initCheck() const; - // protected by SurfaceFlinger::mStateLock - void attachLayer(const sp<IBinder>& handle, const sp<Layer>& layer); - void detachLayer(const Layer* layer); - - sp<Layer> getLayerUser(const sp<IBinder>& handle) const; - private: // ISurfaceComposerClient interface @@ -64,9 +58,6 @@ private: // constant sp<SurfaceFlinger> mFlinger; - // protected by mLock - DefaultKeyedVector< wp<IBinder>, wp<Layer> > mLayers; - // thread-safe mutable Mutex mLock; }; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h index 6832ae12df..8661063e12 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h @@ -56,7 +56,7 @@ public: virtual void setHwComposer(std::unique_ptr<HWComposer>) = 0; virtual renderengine::RenderEngine& getRenderEngine() const = 0; - virtual void setRenderEngine(std::unique_ptr<renderengine::RenderEngine>) = 0; + virtual void setRenderEngine(renderengine::RenderEngine*) = 0; virtual TimeStats& getTimeStats() const = 0; virtual void setTimeStats(const std::shared_ptr<TimeStats>&) = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h index dd4dbe9318..2af6c80f1e 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h @@ -34,7 +34,7 @@ public: void setHwComposer(std::unique_ptr<HWComposer>) override; renderengine::RenderEngine& getRenderEngine() const override; - void setRenderEngine(std::unique_ptr<renderengine::RenderEngine>) override; + void setRenderEngine(renderengine::RenderEngine*) override; TimeStats& getTimeStats() const override; void setTimeStats(const std::shared_ptr<TimeStats>&) override; @@ -58,7 +58,7 @@ public: private: std::unique_ptr<HWComposer> mHwComposer; - std::unique_ptr<renderengine::RenderEngine> mRenderEngine; + renderengine::RenderEngine* mRenderEngine; std::shared_ptr<TimeStats> mTimeStats; bool mNeedsAnotherUpdate = false; nsecs_t mRefreshStartTime = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h index a48cc6f975..fc71649949 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h @@ -40,7 +40,7 @@ public: MOCK_METHOD1(setHwComposer, void(std::unique_ptr<HWComposer>)); MOCK_CONST_METHOD0(getRenderEngine, renderengine::RenderEngine&()); - MOCK_METHOD1(setRenderEngine, void(std::unique_ptr<renderengine::RenderEngine>)); + MOCK_METHOD1(setRenderEngine, void(renderengine::RenderEngine*)); MOCK_CONST_METHOD0(getTimeStats, TimeStats&()); MOCK_METHOD1(setTimeStats, void(const std::shared_ptr<TimeStats>&)); diff --git a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp index a4e1fff2ad..e42f11a9b9 100644 --- a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp +++ b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp @@ -65,11 +65,11 @@ void CompositionEngine::setHwComposer(std::unique_ptr<HWComposer> hwComposer) { } renderengine::RenderEngine& CompositionEngine::getRenderEngine() const { - return *mRenderEngine.get(); + return *mRenderEngine; } -void CompositionEngine::setRenderEngine(std::unique_ptr<renderengine::RenderEngine> renderEngine) { - mRenderEngine = std::move(renderEngine); +void CompositionEngine::setRenderEngine(renderengine::RenderEngine* renderEngine) { + mRenderEngine = renderEngine; } TimeStats& CompositionEngine::getTimeStats() const { diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp index 0b69d44ac4..1c5cbedd88 100644 --- a/services/surfaceflinger/CompositionEngine/src/Display.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp @@ -248,12 +248,17 @@ bool Display::chooseCompositionStrategy( return false; } - const TimePoint startTime = TimePoint::now(); - // Get any composition changes requested by the HWC device, and apply them. std::optional<android::HWComposer::DeviceRequestedChanges> changes; auto& hwc = getCompositionEngine().getHwComposer(); const bool requiresClientComposition = anyLayersRequireClientComposition(); + + if (isPowerHintSessionEnabled()) { + mPowerAdvisor->setRequiresClientComposition(mId, requiresClientComposition); + } + + const TimePoint hwcValidateStartTime = TimePoint::now(); + if (status_t result = hwc.getDeviceCompositionChanges(*halDisplayId, requiresClientComposition, getState().earliestPresentTime, @@ -266,8 +271,10 @@ bool Display::chooseCompositionStrategy( } if (isPowerHintSessionEnabled()) { - mPowerAdvisor->setHwcValidateTiming(mId, startTime, TimePoint::now()); - mPowerAdvisor->setRequiresClientComposition(mId, requiresClientComposition); + mPowerAdvisor->setHwcValidateTiming(mId, hwcValidateStartTime, TimePoint::now()); + if (auto halDisplayId = HalDisplayId::tryCast(mId)) { + mPowerAdvisor->setSkippedValidate(mId, hwc.getValidateSkipped(*halDisplayId)); + } } return true; @@ -432,13 +439,6 @@ void Display::finishFrame(const compositionengine::CompositionRefreshArgs& refre } impl::Output::finishFrame(refreshArgs, std::move(result)); - - if (isPowerHintSessionEnabled()) { - auto& hwc = getCompositionEngine().getHwComposer(); - if (auto halDisplayId = HalDisplayId::tryCast(mId)) { - mPowerAdvisor->setSkippedValidate(mId, hwc.getValidateSkipped(*halDisplayId)); - } - } } } // namespace android::compositionengine::impl diff --git a/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp index b570979f1f..8d99f894a6 100644 --- a/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp @@ -62,11 +62,10 @@ TEST_F(CompositionEngineTest, canSetHWComposer) { } TEST_F(CompositionEngineTest, canSetRenderEngine) { - renderengine::mock::RenderEngine* renderEngine = - new StrictMock<renderengine::mock::RenderEngine>(); - mEngine.setRenderEngine(std::unique_ptr<renderengine::RenderEngine>(renderEngine)); + auto renderEngine = std::make_unique<StrictMock<renderengine::mock::RenderEngine>>(); + mEngine.setRenderEngine(renderEngine.get()); - EXPECT_EQ(renderEngine, &mEngine.getRenderEngine()); + EXPECT_EQ(renderEngine.get(), &mEngine.getRenderEngine()); } TEST_F(CompositionEngineTest, canSetTimeStats) { diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 977709286b..97e47e8e68 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -240,11 +240,6 @@ Layer::~Layer() { mFlinger->mTimeStats->onDestroy(layerId); mFlinger->mFrameTracer->onDestroy(layerId); - sp<Client> c(mClientRef.promote()); - if (c != 0) { - c->detachLayer(this); - } - mFrameTracker.logAndResetStats(mName); mFlinger->onLayerDestroyed(this); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 8fefcb1a62..23843ab11d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -602,7 +602,7 @@ HWComposer& SurfaceFlinger::getHwComposer() const { } renderengine::RenderEngine& SurfaceFlinger::getRenderEngine() const { - return mCompositionEngine->getRenderEngine(); + return *mRenderEngine; } compositionengine::CompositionEngine& SurfaceFlinger::getCompositionEngine() const { @@ -763,7 +763,8 @@ void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) { if (auto type = chooseRenderEngineTypeViaSysProp()) { builder.setRenderEngineType(type.value()); } - mCompositionEngine->setRenderEngine(renderengine::RenderEngine::create(builder.build())); + mRenderEngine = renderengine::RenderEngine::create(builder.build()); + mCompositionEngine->setRenderEngine(mRenderEngine.get()); mMaxRenderTargetSize = std::min(getRenderEngine().getMaxTextureSize(), getRenderEngine().getMaxViewportDims()); @@ -3641,11 +3642,6 @@ status_t SurfaceFlinger::addClientLayer(const LayerCreationArgs& args, const sp< mCreatedLayers.emplace_back(layer, parent, args.addToRoot); } - // attach this layer to the client - if (args.client != nullptr) { - args.client->attachLayer(handle, layer); - } - setTransactionFlags(eTransactionNeeded); return NO_ERROR; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 85c194bbb5..1009402d8d 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -1248,6 +1248,7 @@ private: ui::Dataspace mColorSpaceAgnosticDataspace; float mDimmingRatio = -1.f; + std::unique_ptr<renderengine::RenderEngine> mRenderEngine; std::unique_ptr<compositionengine::CompositionEngine> mCompositionEngine; // mMaxRenderTargetSize is only set once in init() so it doesn't need to be protected by // any mutex. diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp index 14384a7028..ce4d18fbe1 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp +++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp @@ -245,6 +245,7 @@ void SurfaceFlingerFuzzer::process(const uint8_t *data, size_t size) { setDisplayStateLocked(); setTransactionState(); + mTestableFlinger.flushTransactionQueues(); onTransact(data, size); } diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h index e55586774f..985fd17440 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h +++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h @@ -633,7 +633,8 @@ public: } void setupRenderEngine(std::unique_ptr<renderengine::RenderEngine> renderEngine) { - mFlinger->mCompositionEngine->setRenderEngine(std::move(renderEngine)); + mFlinger->mRenderEngine = std::move(renderEngine); + mFlinger->mCompositionEngine->setRenderEngine(mFlinger->mRenderEngine.get()); } void setupComposer(std::unique_ptr<Hwc2::Composer> composer) { @@ -748,6 +749,11 @@ public: listenerCallbacks, transactionId); } + auto flushTransactionQueues() { + ftl::FakeGuard guard(kMainThreadContext); + return mFlinger->flushTransactionQueues(VsyncId{0}); + } + auto onTransact(uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { return mFlinger->onTransact(code, data, reply, flags); } @@ -775,8 +781,8 @@ public: mutableDrawingState().displays.clear(); mFlinger->mScheduler.reset(); mFlinger->mCompositionEngine->setHwComposer(std::unique_ptr<HWComposer>()); - mFlinger->mCompositionEngine->setRenderEngine( - std::unique_ptr<renderengine::RenderEngine>()); + mFlinger->mRenderEngine = std::unique_ptr<renderengine::RenderEngine>(); + mFlinger->mCompositionEngine->setRenderEngine(mFlinger->mRenderEngine.get()); } private: diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 7f471bc8b8..31df4c675e 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -168,7 +168,8 @@ public: // functions. void setupRenderEngine(std::unique_ptr<renderengine::RenderEngine> renderEngine) { - mFlinger->mCompositionEngine->setRenderEngine(std::move(renderEngine)); + mFlinger->mRenderEngine = std::move(renderEngine); + mFlinger->mCompositionEngine->setRenderEngine(mFlinger->mRenderEngine.get()); } void setupComposer(std::unique_ptr<Hwc2::Composer> composer) { @@ -543,8 +544,8 @@ public: mutableDrawingState().displays.clear(); mFlinger->mScheduler.reset(); mFlinger->mCompositionEngine->setHwComposer(std::unique_ptr<HWComposer>()); - mFlinger->mCompositionEngine->setRenderEngine( - std::unique_ptr<renderengine::RenderEngine>()); + mFlinger->mRenderEngine = std::unique_ptr<renderengine::RenderEngine>(); + mFlinger->mCompositionEngine->setRenderEngine(mFlinger->mRenderEngine.get()); } /* ------------------------------------------------------------------------ |