Merge "Allow touch if some pointers are MT_TOOL_PALM"
diff --git a/cmds/idlcli/vibrator/CommandCompose.cpp b/cmds/idlcli/vibrator/CommandCompose.cpp
index 97c057f..eb9008b 100644
--- a/cmds/idlcli/vibrator/CommandCompose.cpp
+++ b/cmds/idlcli/vibrator/CommandCompose.cpp
@@ -37,7 +37,7 @@
{"-b", {"Block for duration of vibration."}},
{"<delay>", {"In milliseconds"}},
{"<primitive>", {"Primitive ID."}},
- {"<scale>", {"0.0 (exclusive) - 1.0 (inclusive)."}},
+ {"<scale>", {"0.0 (inclusive) - 1.0 (inclusive)."}},
{"...", {"May repeat multiple times."}},
};
return details;
@@ -72,7 +72,7 @@
return USAGE;
}
if (auto scale = args.pop<decltype(effect.scale)>();
- scale && *scale > 0.0 && scale <= 1.0) {
+ scale && *scale >= 0.0 && scale <= 1.0) {
effect.scale = *scale;
std::cout << "Scale: " << effect.scale << std::endl;
} else {
diff --git a/include/android/choreographer.h b/include/android/choreographer.h
index bdf11e4..e9f559c 100644
--- a/include/android/choreographer.h
+++ b/include/android/choreographer.h
@@ -130,6 +130,13 @@
* This api is thread-safe. Any thread is allowed to register a new refresh
* rate callback for the choreographer instance.
*
+ * Note that in API level 30, this api is not guaranteed to be atomic with
+ * DisplayManager. That is, calling Display#getRefreshRate very soon after
+ * a refresh rate callback is invoked may return a stale refresh rate. If any
+ * Display properties would be required by this callback, then it is recommended
+ * to listen directly to DisplayManager.DisplayListener#onDisplayChanged events
+ * instead.
+ *
* Available since API level 30.
*/
void AChoreographer_registerRefreshRateCallback(AChoreographer* choreographer,
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index e0fb543..6ca3b16 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -24,6 +24,7 @@
#include <binder/IShellCallback.h>
#include <binder/Parcel.h>
+#include <linux/sched.h>
#include <stdio.h>
namespace android {
@@ -133,6 +134,8 @@
// unlocked objects
bool mRequestingSid = false;
sp<IBinder> mExtension;
+ int mPolicy = SCHED_NORMAL;
+ int mPriority = 0;
// for below objects
Mutex mLock;
@@ -279,6 +282,47 @@
return e->mExtension;
}
+void BBinder::setMinSchedulerPolicy(int policy, int priority) {
+ switch (policy) {
+ case SCHED_NORMAL:
+ LOG_ALWAYS_FATAL_IF(priority < -20 || priority > 19, "Invalid priority for SCHED_NORMAL: %d", priority);
+ break;
+ case SCHED_RR:
+ case SCHED_FIFO:
+ LOG_ALWAYS_FATAL_IF(priority < 1 || priority > 99, "Invalid priority for sched %d: %d", policy, priority);
+ break;
+ default:
+ LOG_ALWAYS_FATAL("Unrecognized scheduling policy: %d", policy);
+ }
+
+ Extras* e = mExtras.load(std::memory_order_acquire);
+
+ if (e == nullptr) {
+ // Avoid allocations if called with default.
+ if (policy == SCHED_NORMAL && priority == 0) {
+ return;
+ }
+
+ e = getOrCreateExtras();
+ if (!e) return; // out of memory
+ }
+
+ e->mPolicy = policy;
+ e->mPriority = priority;
+}
+
+int BBinder::getMinSchedulerPolicy() {
+ Extras* e = mExtras.load(std::memory_order_acquire);
+ if (e == nullptr) return SCHED_NORMAL;
+ return e->mPolicy;
+}
+
+int BBinder::getMinSchedulerPriority() {
+ Extras* e = mExtras.load(std::memory_order_acquire);
+ if (e == nullptr) return 0;
+ return e->mPriority;
+}
+
pid_t BBinder::getDebugPid() {
return getpid();
}
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 5ea56de..8fd59ba 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -20,6 +20,7 @@
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
+#include <linux/sched.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
@@ -188,16 +189,18 @@
return OK;
}
+static constexpr inline int schedPolicyMask(int policy, int priority) {
+ return (priority & FLAT_BINDER_FLAG_PRIORITY_MASK) | ((policy & 3) << FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT);
+}
+
status_t Parcel::flattenBinder(const sp<IBinder>& binder)
{
flat_binder_object obj;
+ obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
- if (IPCThreadState::self()->backgroundSchedulingDisabled()) {
- /* minimum priority for all nodes is nice 0 */
- obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
- } else {
- /* minimum priority for all nodes is MAX_NICE(19) */
- obj.flags = 0x13 | FLAT_BINDER_FLAG_ACCEPTS_FDS;
+ int schedBits = 0;
+ if (!IPCThreadState::self()->backgroundSchedulingDisabled()) {
+ schedBits = schedPolicyMask(SCHED_NORMAL, 19);
}
if (binder != nullptr) {
@@ -213,6 +216,13 @@
obj.handle = handle;
obj.cookie = 0;
} else {
+ int policy = local->getMinSchedulerPolicy();
+ int priority = local->getMinSchedulerPriority();
+
+ if (policy != 0 || priority != 0) {
+ // override value, since it is set explicitly
+ schedBits = schedPolicyMask(policy, priority);
+ }
if (local->isRequestingSid()) {
obj.flags |= FLAT_BINDER_FLAG_TXN_SECURITY_CTX;
}
@@ -226,6 +236,8 @@
obj.cookie = 0;
}
+ obj.flags |= schedBits;
+
return finishFlattenBinder(binder, obj);
}
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index 74e52db..f3fea16 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -72,6 +72,22 @@
// This must be called before the object is sent to another process. Not thread safe.
void setExtension(const sp<IBinder>& extension);
+ // This must be called before the object is sent to another process. Not thread safe.
+ //
+ // This function will abort if improper parameters are set. This is like
+ // sched_setscheduler. However, it sets the minimum scheduling policy
+ // only for the duration that this specific binder object is handling the
+ // call in a threadpool. By default, this API is set to SCHED_NORMAL/0. In
+ // this case, the scheduling priority will not actually be modified from
+ // binder defaults. See also IPCThreadState::disableBackgroundScheduling.
+ //
+ // Appropriate values are:
+ // SCHED_NORMAL: -20 <= priority <= 19
+ // SCHED_RR/SCHED_FIFO: 1 <= priority <= 99
+ void setMinSchedulerPolicy(int policy, int priority);
+ int getMinSchedulerPolicy();
+ int getMinSchedulerPriority();
+
pid_t getDebugPid();
protected:
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 40de2db..917751e 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -50,6 +50,9 @@
static char *binderserversuffix;
static char binderserverarg[] = "--binderserver";
+static constexpr int kSchedPolicy = SCHED_RR;
+static constexpr int kSchedPriority = 7;
+
static String16 binderLibTestServiceName = String16("test.binderLib");
enum BinderLibTestTranscationCode {
@@ -75,6 +78,7 @@
BINDER_LIB_TEST_GET_PTR_SIZE_TRANSACTION,
BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION,
BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION,
+ BINDER_LIB_TEST_GET_SCHEDULING_POLICY,
BINDER_LIB_TEST_ECHO_VECTOR,
BINDER_LIB_TEST_REJECT_BUF,
};
@@ -1015,6 +1019,22 @@
EXPECT_EQ(NO_ERROR, ret2);
}
+TEST_F(BinderLibTest, SchedPolicySet) {
+ sp<IBinder> server = addServer();
+ ASSERT_TRUE(server != nullptr);
+
+ Parcel data, reply;
+ status_t ret = server->transact(BINDER_LIB_TEST_GET_SCHEDULING_POLICY, data, &reply);
+ EXPECT_EQ(NO_ERROR, ret);
+
+ int policy = reply.readInt32();
+ int priority = reply.readInt32();
+
+ EXPECT_EQ(kSchedPolicy, policy & (~SCHED_RESET_ON_FORK));
+ EXPECT_EQ(kSchedPriority, priority);
+}
+
+
TEST_F(BinderLibTest, VectorSent) {
Parcel data, reply;
sp<IBinder> server = addServer();
@@ -1332,6 +1352,16 @@
reply->writeInt32(IPCThreadState::self()->getCallingWorkSourceUid());
return NO_ERROR;
}
+ case BINDER_LIB_TEST_GET_SCHEDULING_POLICY: {
+ int policy = 0;
+ sched_param param;
+ if (0 != pthread_getschedparam(pthread_self(), &policy, ¶m)) {
+ return UNKNOWN_ERROR;
+ }
+ reply->writeInt32(policy);
+ reply->writeInt32(param.sched_priority);
+ return NO_ERROR;
+ }
case BINDER_LIB_TEST_ECHO_VECTOR: {
std::vector<uint64_t> vector;
auto err = data.readUint64Vector(&vector);
@@ -1368,6 +1398,8 @@
{
sp<BinderLibTestService> testService = new BinderLibTestService(index);
+ testService->setMinSchedulerPolicy(kSchedPolicy, kSchedPriority);
+
/*
* Normally would also contain functionality as well, but we are only
* testing the extension mechanism.
diff --git a/libs/input/android/os/IInputFlinger.aidl b/libs/input/android/os/IInputFlinger.aidl
index 8ff9dae..8b7c4fc 100644
--- a/libs/input/android/os/IInputFlinger.aidl
+++ b/libs/input/android/os/IInputFlinger.aidl
@@ -23,7 +23,11 @@
/** @hide */
interface IInputFlinger
{
- void setInputWindows(in InputWindowInfo[] inputHandles,
+ // SurfaceFlinger is the caller of this method, it uses the listener callback to ensure the
+ // ordering when needed.
+ // SurfaceFlinger calls this only every VSync, so overflow of binder's oneway buffer
+ // shouldn't be a concern.
+ oneway void setInputWindows(in InputWindowInfo[] inputHandles,
in @nullable ISetInputWindowsListener setInputWindowsListener);
void registerInputChannel(in InputChannelInfo info);
void unregisterInputChannel(in InputChannelInfo info);
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index 5e590d0..fe428f1 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -43,22 +43,11 @@
#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/Timers.h>
-#include <utils/threads.h>
#include <filesystem>
#include "EventHub.h"
-/* this macro is used to tell if "bit" is set in "array"
- * it selects a byte from the array, and does a boolean AND
- * operation with a byte that only has the relevant bit set.
- * eg. to check for the 12th bit, we do (array[1] & 1<<4)
- */
-#define test_bit(bit, array) ((array)[(bit) / 8] & (1 << ((bit) % 8)))
-
-/* this macro computes the number of bytes needed to represent a bit array of the specified size */
-#define sizeof_bit_array(bits) (((bits) + 7) / 8)
-
#define INDENT " "
#define INDENT2 " "
#define INDENT3 " "
@@ -193,15 +182,7 @@
ffEffectId(-1),
controllerNumber(0),
enabled(true),
- isVirtual(fd < 0) {
- memset(keyBitmask, 0, sizeof(keyBitmask));
- memset(absBitmask, 0, sizeof(absBitmask));
- memset(relBitmask, 0, sizeof(relBitmask));
- memset(swBitmask, 0, sizeof(swBitmask));
- memset(ledBitmask, 0, sizeof(ledBitmask));
- memset(ffBitmask, 0, sizeof(ffBitmask));
- memset(propBitmask, 0, sizeof(propBitmask));
-}
+ isVirtual(fd < 0) {}
EventHub::Device::~Device() {
close();
@@ -391,7 +372,7 @@
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device && device->hasValidFd() && test_bit(axis, device->absBitmask)) {
+ if (device != nullptr && device->hasValidFd() && device->absBitmask.test(axis)) {
struct input_absinfo info;
if (ioctl(device->fd, EVIOCGABS(axis), &info)) {
ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d", axis,
@@ -418,9 +399,7 @@
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device) {
- return test_bit(axis, device->relBitmask);
- }
+ return device != nullptr ? device->relBitmask.test(axis) : false;
}
return false;
}
@@ -430,9 +409,7 @@
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device) {
- return test_bit(property, device->propBitmask);
- }
+ return device != nullptr ? device->propBitmask.test(property) : false;
}
return false;
}
@@ -442,11 +419,9 @@
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device && device->hasValidFd() && test_bit(scanCode, device->keyBitmask)) {
- uint8_t keyState[sizeof_bit_array(KEY_MAX + 1)];
- memset(keyState, 0, sizeof(keyState));
- if (ioctl(device->fd, EVIOCGKEY(sizeof(keyState)), keyState) >= 0) {
- return test_bit(scanCode, keyState) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
+ if (device != nullptr && device->hasValidFd() && device->keyBitmask.test(scanCode)) {
+ if (device->readDeviceBitMask(EVIOCGKEY(0), device->keyState) >= 0) {
+ return device->keyState.test(scanCode) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
}
}
}
@@ -457,16 +432,14 @@
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device && device->hasValidFd() && device->keyMap.haveKeyLayout()) {
+ if (device != nullptr && device->hasValidFd() && device->keyMap.haveKeyLayout()) {
std::vector<int32_t> scanCodes;
device->keyMap.keyLayoutMap->findScanCodesForKey(keyCode, &scanCodes);
if (scanCodes.size() != 0) {
- uint8_t keyState[sizeof_bit_array(KEY_MAX + 1)];
- memset(keyState, 0, sizeof(keyState));
- if (ioctl(device->fd, EVIOCGKEY(sizeof(keyState)), keyState) >= 0) {
+ if (device->readDeviceBitMask(EVIOCGKEY(0), device->keyState) >= 0) {
for (size_t i = 0; i < scanCodes.size(); i++) {
int32_t sc = scanCodes[i];
- if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, keyState)) {
+ if (sc >= 0 && sc <= KEY_MAX && device->keyState.test(sc)) {
return AKEY_STATE_DOWN;
}
}
@@ -482,11 +455,9 @@
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device && device->hasValidFd() && test_bit(sw, device->swBitmask)) {
- uint8_t swState[sizeof_bit_array(SW_MAX + 1)];
- memset(swState, 0, sizeof(swState));
- if (ioctl(device->fd, EVIOCGSW(sizeof(swState)), swState) >= 0) {
- return test_bit(sw, swState) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
+ if (device != nullptr && device->hasValidFd() && device->swBitmask.test(sw)) {
+ if (device->readDeviceBitMask(EVIOCGSW(0), device->swState) >= 0) {
+ return device->swState.test(sw) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
}
}
}
@@ -500,7 +471,7 @@
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device && device->hasValidFd() && test_bit(axis, device->absBitmask)) {
+ if (device != nullptr && device->hasValidFd() && device->absBitmask.test(axis)) {
struct input_absinfo info;
if (ioctl(device->fd, EVIOCGABS(axis), &info)) {
ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d", axis,
@@ -520,7 +491,7 @@
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device && device->keyMap.haveKeyLayout()) {
+ if (device != nullptr && device->keyMap.haveKeyLayout()) {
std::vector<int32_t> scanCodes;
for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) {
scanCodes.clear();
@@ -531,7 +502,7 @@
// check the possible scan codes identified by the layout map against the
// map of codes actually emitted by the driver
for (size_t sc = 0; sc < scanCodes.size(); sc++) {
- if (test_bit(scanCodes[sc], device->keyBitmask)) {
+ if (device->keyBitmask.test(scanCodes[sc])) {
outFlags[codeIndex] = 1;
break;
}
@@ -549,7 +520,7 @@
Device* device = getDeviceLocked(deviceId);
status_t status = NAME_NOT_FOUND;
- if (device) {
+ if (device != nullptr) {
// Check the key character map first.
sp<KeyCharacterMap> kcm = device->getKeyCharacterMap();
if (kcm != nullptr) {
@@ -588,7 +559,7 @@
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device && device->keyMap.haveKeyLayout()) {
+ if (device != nullptr && device->keyMap.haveKeyLayout()) {
status_t err = device->keyMap.keyLayoutMap->mapAxis(scanCode, outAxisInfo);
if (err == NO_ERROR) {
return NO_ERROR;
@@ -607,10 +578,8 @@
bool EventHub::hasScanCode(int32_t deviceId, int32_t scanCode) const {
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device && scanCode >= 0 && scanCode <= KEY_MAX) {
- if (test_bit(scanCode, device->keyBitmask)) {
- return true;
- }
+ if (device != nullptr && scanCode >= 0 && scanCode <= KEY_MAX) {
+ return device->keyBitmask.test(scanCode);
}
return false;
}
@@ -619,10 +588,8 @@
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
int32_t sc;
- if (device && mapLed(device, led, &sc) == NO_ERROR) {
- if (test_bit(sc, device->ledBitmask)) {
- return true;
- }
+ if (device != nullptr && mapLed(device, led, &sc) == NO_ERROR) {
+ return device->ledBitmask.test(sc);
}
return false;
}
@@ -635,7 +602,7 @@
void EventHub::setLedStateLocked(Device* device, int32_t led, bool on) {
int32_t sc;
- if (device && device->hasValidFd() && mapLed(device, led, &sc) != NAME_NOT_FOUND) {
+ if (device != nullptr && device->hasValidFd() && mapLed(device, led, &sc) != NAME_NOT_FOUND) {
struct input_event ev;
ev.time.tv_sec = 0;
ev.time.tv_usec = 0;
@@ -656,7 +623,7 @@
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device && device->virtualKeyMap) {
+ if (device != nullptr && device->virtualKeyMap) {
const std::vector<VirtualKeyDefinition> virtualKeys =
device->virtualKeyMap->getVirtualKeys();
outVirtualKeys.insert(outVirtualKeys.end(), virtualKeys.begin(), virtualKeys.end());
@@ -666,7 +633,7 @@
sp<KeyCharacterMap> EventHub::getKeyCharacterMap(int32_t deviceId) const {
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device) {
+ if (device != nullptr) {
return device->getKeyCharacterMap();
}
return nullptr;
@@ -675,7 +642,7 @@
bool EventHub::setKeyboardLayoutOverlay(int32_t deviceId, const sp<KeyCharacterMap>& map) {
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device) {
+ if (device != nullptr) {
if (map != device->overlayKeyMap) {
device->overlayKeyMap = map;
device->combinedKeyMap = KeyCharacterMap::combine(device->keyMap.keyCharacterMap, map);
@@ -738,7 +705,7 @@
void EventHub::vibrate(int32_t deviceId, nsecs_t duration) {
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device && device->hasValidFd()) {
+ if (device != nullptr && device->hasValidFd()) {
ff_effect effect;
memset(&effect, 0, sizeof(effect));
effect.type = FF_RUMBLE;
@@ -772,7 +739,7 @@
void EventHub::cancelVibrate(int32_t deviceId) {
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device && device->hasValidFd()) {
+ if (device != nullptr && device->hasValidFd()) {
if (device->ffEffectPlaying) {
device->ffEffectPlaying = false;
@@ -1089,7 +1056,7 @@
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (!device || !device->videoDevice) {
+ if (device == nullptr || !device->videoDevice) {
return {};
}
return device->videoDevice->consumeFrames();
@@ -1126,17 +1093,6 @@
// ----------------------------------------------------------------------------
-static bool containsNonZeroByte(const uint8_t* array, uint32_t startIndex, uint32_t endIndex) {
- const uint8_t* end = array + endIndex;
- array += startIndex;
- while (array != end) {
- if (*(array++) != 0) {
- return true;
- }
- }
- return false;
-}
-
static const int32_t GAMEPAD_KEYCODES[] = {
AKEYCODE_BUTTON_A, AKEYCODE_BUTTON_B, AKEYCODE_BUTTON_C, //
AKEYCODE_BUTTON_X, AKEYCODE_BUTTON_Y, AKEYCODE_BUTTON_Z, //
@@ -1306,31 +1262,27 @@
loadConfigurationLocked(device);
// Figure out the kinds of events the device reports.
- ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(device->keyBitmask)), device->keyBitmask);
- ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(device->absBitmask)), device->absBitmask);
- ioctl(fd, EVIOCGBIT(EV_REL, sizeof(device->relBitmask)), device->relBitmask);
- ioctl(fd, EVIOCGBIT(EV_SW, sizeof(device->swBitmask)), device->swBitmask);
- ioctl(fd, EVIOCGBIT(EV_LED, sizeof(device->ledBitmask)), device->ledBitmask);
- ioctl(fd, EVIOCGBIT(EV_FF, sizeof(device->ffBitmask)), device->ffBitmask);
- ioctl(fd, EVIOCGPROP(sizeof(device->propBitmask)), device->propBitmask);
+ device->readDeviceBitMask(EVIOCGBIT(EV_KEY, 0), device->keyBitmask);
+ device->readDeviceBitMask(EVIOCGBIT(EV_ABS, 0), device->absBitmask);
+ device->readDeviceBitMask(EVIOCGBIT(EV_REL, 0), device->relBitmask);
+ device->readDeviceBitMask(EVIOCGBIT(EV_SW, 0), device->swBitmask);
+ device->readDeviceBitMask(EVIOCGBIT(EV_LED, 0), device->ledBitmask);
+ device->readDeviceBitMask(EVIOCGBIT(EV_FF, 0), device->ffBitmask);
+ 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.
bool haveKeyboardKeys =
- containsNonZeroByte(device->keyBitmask, 0, sizeof_bit_array(BTN_MISC)) ||
- containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_WHEEL),
- sizeof_bit_array(KEY_MAX + 1));
- bool haveGamepadButtons = containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_MISC),
- sizeof_bit_array(BTN_MOUSE)) ||
- containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_JOYSTICK),
- sizeof_bit_array(BTN_DIGI));
+ 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) {
device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
}
// See if this is a cursor device such as a trackball or mouse.
- if (test_bit(BTN_MOUSE, device->keyBitmask) && test_bit(REL_X, device->relBitmask) &&
- test_bit(REL_Y, device->relBitmask)) {
+ if (device->keyBitmask.test(BTN_MOUSE) && device->relBitmask.test(REL_X) &&
+ device->relBitmask.test(REL_Y)) {
device->classes |= INPUT_DEVICE_CLASS_CURSOR;
}
@@ -1345,22 +1297,20 @@
// See if this is a touch pad.
// Is this a new modern multi-touch driver?
- if (test_bit(ABS_MT_POSITION_X, device->absBitmask) &&
- test_bit(ABS_MT_POSITION_Y, device->absBitmask)) {
+ if (device->absBitmask.test(ABS_MT_POSITION_X) && device->absBitmask.test(ABS_MT_POSITION_Y)) {
// Some joysticks such as the PS3 controller report axes that conflict
// with the ABS_MT range. Try to confirm that the device really is
// a touch screen.
- if (test_bit(BTN_TOUCH, device->keyBitmask) || !haveGamepadButtons) {
+ if (device->keyBitmask.test(BTN_TOUCH) || !haveGamepadButtons) {
device->classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
}
// Is this an old style single-touch driver?
- } else if (test_bit(BTN_TOUCH, device->keyBitmask) && test_bit(ABS_X, device->absBitmask) &&
- test_bit(ABS_Y, device->absBitmask)) {
+ } else if (device->keyBitmask.test(BTN_TOUCH) && device->absBitmask.test(ABS_X) &&
+ device->absBitmask.test(ABS_Y)) {
device->classes |= INPUT_DEVICE_CLASS_TOUCH;
// Is this a BT stylus?
- } else if ((test_bit(ABS_PRESSURE, device->absBitmask) ||
- test_bit(BTN_TOUCH, device->keyBitmask)) &&
- !test_bit(ABS_X, device->absBitmask) && !test_bit(ABS_Y, device->absBitmask)) {
+ } else if ((device->absBitmask.test(ABS_PRESSURE) || device->keyBitmask.test(BTN_TOUCH)) &&
+ !device->absBitmask.test(ABS_X) && !device->absBitmask.test(ABS_Y)) {
device->classes |= INPUT_DEVICE_CLASS_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
@@ -1374,7 +1324,7 @@
if (haveGamepadButtons) {
uint32_t assumedClasses = device->classes | INPUT_DEVICE_CLASS_JOYSTICK;
for (int i = 0; i <= ABS_MAX; i++) {
- if (test_bit(i, device->absBitmask) &&
+ if (device->absBitmask.test(i) &&
(getAbsAxisUsage(i, assumedClasses) & INPUT_DEVICE_CLASS_JOYSTICK)) {
device->classes = assumedClasses;
break;
@@ -1384,14 +1334,14 @@
// Check whether this device has switches.
for (int i = 0; i <= SW_MAX; i++) {
- if (test_bit(i, device->swBitmask)) {
+ if (device->swBitmask.test(i)) {
device->classes |= INPUT_DEVICE_CLASS_SWITCH;
break;
}
}
// Check whether this device supports the vibrator.
- if (test_bit(FF_RUMBLE, device->ffBitmask)) {
+ if (device->ffBitmask.test(FF_RUMBLE)) {
device->classes |= INPUT_DEVICE_CLASS_VIBRATOR;
}
@@ -1703,7 +1653,7 @@
const size_t N = scanCodes.size();
for (size_t i = 0; i < N && i <= KEY_MAX; i++) {
int32_t sc = scanCodes[i];
- if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, device->keyBitmask)) {
+ if (sc >= 0 && sc <= KEY_MAX && device->keyBitmask.test(sc)) {
return true;
}
}
@@ -1718,7 +1668,7 @@
int32_t scanCode;
if (device->keyMap.keyLayoutMap->findScanCodeForLed(led, &scanCode) != NAME_NOT_FOUND) {
- if (scanCode >= 0 && scanCode <= LED_MAX && test_bit(scanCode, device->ledBitmask)) {
+ if (scanCode >= 0 && scanCode <= LED_MAX && device->ledBitmask.test(scanCode)) {
*outScanCode = scanCode;
return NO_ERROR;
}
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index ee62c9a..baff6e3 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -17,6 +17,8 @@
#ifndef _RUNTIME_EVENT_HUB_H
#define _RUNTIME_EVENT_HUB_H
+#include <bitset>
+#include <climits>
#include <vector>
#include <input/Input.h>
@@ -38,11 +40,6 @@
#include "TouchVideoDevice.h"
-/* Convenience constants. */
-
-#define BTN_FIRST 0x100 // first button code
-#define BTN_LAST 0x15f // last button code
-
namespace android {
/*
@@ -256,6 +253,76 @@
virtual status_t disableDevice(int32_t deviceId) = 0;
};
+template <std::size_t BITS>
+class BitArray {
+ /* Array element type and vector of element type. */
+ using Element = std::uint32_t;
+ /* Number of bits in each BitArray element. */
+ static constexpr size_t WIDTH = sizeof(Element) * CHAR_BIT;
+ /* Number of elements to represent a bit array of the specified size of bits. */
+ static constexpr size_t COUNT = (BITS + WIDTH - 1) / WIDTH;
+
+public:
+ /* BUFFER type declaration for BitArray */
+ using Buffer = std::array<Element, COUNT>;
+ /* To tell if a bit is set in array, it selects an element from the array, and test
+ * if the relevant bit set.
+ * Note the parameter "bit" is an index to the bit, 0 <= bit < BITS.
+ */
+ inline bool test(size_t bit) const {
+ return (bit < BITS) ? mData[bit / WIDTH].test(bit % WIDTH) : false;
+ }
+ /* Returns total number of bytes needed for the array */
+ inline size_t bytes() { return (BITS + CHAR_BIT - 1) / CHAR_BIT; }
+ /* Returns true if array contains any non-zero bit from the range defined by start and end
+ * bit index [startIndex, endIndex).
+ */
+ bool any(size_t startIndex, size_t endIndex) {
+ if (startIndex >= endIndex || startIndex > BITS || endIndex > BITS + 1) {
+ ALOGE("Invalid start/end index. start = %zu, end = %zu, total bits = %zu", startIndex,
+ endIndex, BITS);
+ return false;
+ }
+ size_t se = startIndex / WIDTH; // Start of element
+ size_t ee = endIndex / WIDTH; // End of element
+ size_t si = startIndex % WIDTH; // Start index in start element
+ size_t ei = endIndex % WIDTH; // End index in end element
+ // Need to check first unaligned bitset for any non zero bit
+ if (si > 0) {
+ size_t nBits = se == ee ? ei - si : WIDTH - si;
+ // Generate the mask of interested bit range
+ Element mask = ((1 << nBits) - 1) << si;
+ if (mData[se++].to_ulong() & mask) {
+ return true;
+ }
+ }
+ // Check whole bitset for any bit set
+ for (; se < ee; se++) {
+ if (mData[se].any()) {
+ return true;
+ }
+ }
+ // Need to check last unaligned bitset for any non zero bit
+ if (ei > 0 && se <= ee) {
+ // Generate the mask of interested bit range
+ Element mask = (1 << ei) - 1;
+ if (mData[se].to_ulong() & mask) {
+ return true;
+ }
+ }
+ return false;
+ }
+ /* Load bit array values from buffer */
+ void loadFromBuffer(const Buffer& buffer) {
+ for (size_t i = 0; i < COUNT; i++) {
+ mData[i] = std::bitset<WIDTH>(buffer[i]);
+ }
+ }
+
+private:
+ std::array<std::bitset<WIDTH>, COUNT> mData;
+};
+
class EventHub : public EventHubInterface {
public:
EventHub();
@@ -332,13 +399,15 @@
uint32_t classes;
- uint8_t keyBitmask[(KEY_MAX + 1) / 8];
- uint8_t absBitmask[(ABS_MAX + 1) / 8];
- uint8_t relBitmask[(REL_MAX + 1) / 8];
- uint8_t swBitmask[(SW_MAX + 1) / 8];
- uint8_t ledBitmask[(LED_MAX + 1) / 8];
- uint8_t ffBitmask[(FF_MAX + 1) / 8];
- uint8_t propBitmask[(INPUT_PROP_MAX + 1) / 8];
+ BitArray<KEY_MAX> keyBitmask;
+ BitArray<KEY_MAX> keyState;
+ BitArray<ABS_MAX> absBitmask;
+ BitArray<REL_MAX> relBitmask;
+ BitArray<SW_MAX> swBitmask;
+ BitArray<SW_MAX> swState;
+ BitArray<LED_MAX> ledBitmask;
+ BitArray<FF_MAX> ffBitmask;
+ BitArray<INPUT_PROP_MAX> propBitmask;
std::string configurationFile;
PropertyMap* configuration;
@@ -371,6 +440,21 @@
}
return keyMap.keyCharacterMap;
}
+
+ template <std::size_t N>
+ status_t readDeviceBitMask(unsigned long ioctlCode, BitArray<N>& bitArray) {
+ if (!hasValidFd()) {
+ return BAD_VALUE;
+ }
+ if ((_IOC_SIZE(ioctlCode) == 0)) {
+ ioctlCode |= _IOC(0, 0, 0, bitArray.bytes());
+ }
+
+ typename BitArray<N>::Buffer buffer;
+ status_t ret = ioctl(fd, ioctlCode, buffer.data());
+ bitArray.loadFromBuffer(buffer);
+ return ret;
+ }
};
status_t openDeviceLocked(const std::string& devicePath);
diff --git a/services/inputflinger/tests/EventHub_test.cpp b/services/inputflinger/tests/EventHub_test.cpp
index 71731b0..ef68a84 100644
--- a/services/inputflinger/tests/EventHub_test.cpp
+++ b/services/inputflinger/tests/EventHub_test.cpp
@@ -199,3 +199,76 @@
lastEventTime = event.when; // Ensure all returned events are monotonic
}
}
+
+// --- BitArrayTest ---
+class BitArrayTest : public testing::Test {
+protected:
+ static constexpr size_t SINGLE_ELE_BITS = 32UL;
+ static constexpr size_t MULTI_ELE_BITS = 256UL;
+
+ virtual void SetUp() override {
+ mBitmaskSingle.loadFromBuffer(mBufferSingle);
+ mBitmaskMulti.loadFromBuffer(mBufferMulti);
+ }
+
+ android::BitArray<SINGLE_ELE_BITS> mBitmaskSingle;
+ android::BitArray<MULTI_ELE_BITS> mBitmaskMulti;
+
+private:
+ const typename android::BitArray<SINGLE_ELE_BITS>::Buffer mBufferSingle = {
+ 0x800F0F0FUL // bit 0 - 31
+ };
+ const typename android::BitArray<MULTI_ELE_BITS>::Buffer mBufferMulti = {
+ 0xFFFFFFFFUL, // bit 0 - 31
+ 0x01000001UL, // bit 32 - 63
+ 0x00000000UL, // bit 64 - 95
+ 0x80000000UL, // bit 96 - 127
+ 0x00000000UL, // bit 128 - 159
+ 0x00000000UL, // bit 160 - 191
+ 0x80000008UL, // bit 192 - 223
+ 0x00000000UL, // bit 224 - 255
+ };
+};
+
+TEST_F(BitArrayTest, SetBit) {
+ ASSERT_TRUE(mBitmaskSingle.test(0));
+ ASSERT_TRUE(mBitmaskSingle.test(31));
+ ASSERT_FALSE(mBitmaskSingle.test(7));
+
+ ASSERT_TRUE(mBitmaskMulti.test(32));
+ ASSERT_TRUE(mBitmaskMulti.test(56));
+ ASSERT_FALSE(mBitmaskMulti.test(192));
+ ASSERT_TRUE(mBitmaskMulti.test(223));
+ ASSERT_FALSE(mBitmaskMulti.test(255));
+}
+
+TEST_F(BitArrayTest, AnyBit) {
+ ASSERT_TRUE(mBitmaskSingle.any(31, 32));
+ ASSERT_FALSE(mBitmaskSingle.any(12, 16));
+
+ ASSERT_TRUE(mBitmaskMulti.any(31, 32));
+ ASSERT_FALSE(mBitmaskMulti.any(33, 33));
+ ASSERT_TRUE(mBitmaskMulti.any(32, 55));
+ ASSERT_TRUE(mBitmaskMulti.any(33, 57));
+ ASSERT_FALSE(mBitmaskMulti.any(33, 55));
+ ASSERT_FALSE(mBitmaskMulti.any(130, 190));
+
+ ASSERT_FALSE(mBitmaskMulti.any(128, 195));
+ ASSERT_TRUE(mBitmaskMulti.any(128, 196));
+ ASSERT_TRUE(mBitmaskMulti.any(128, 224));
+ ASSERT_FALSE(mBitmaskMulti.any(255, 256));
+}
+
+TEST_F(BitArrayTest, SetBit_InvalidBitIndex) {
+ ASSERT_FALSE(mBitmaskSingle.test(32));
+ ASSERT_FALSE(mBitmaskMulti.test(256));
+}
+
+TEST_F(BitArrayTest, AnyBit_InvalidBitIndex) {
+ ASSERT_FALSE(mBitmaskSingle.any(32, 32));
+ ASSERT_FALSE(mBitmaskSingle.any(33, 34));
+
+ ASSERT_FALSE(mBitmaskMulti.any(256, 256));
+ ASSERT_FALSE(mBitmaskMulti.any(257, 258));
+ ASSERT_FALSE(mBitmaskMulti.any(0, 0));
+}
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 8dd4b0a..b53e2dc 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -61,36 +61,46 @@
} while (false)
namespace android {
+
namespace {
-std::unique_ptr<DispSync> createDispSync(bool supportKernelTimer) {
- // TODO (140302863) remove this and use the vsync_reactor system.
- if (property_get_bool("debug.sf.vsync_reactor", true)) {
+std::unique_ptr<scheduler::VSyncTracker> createVSyncTracker() {
+ // TODO (144707443) tune Predictor tunables.
+ static constexpr int default_rate = 60;
+ static constexpr auto initial_period =
+ std::chrono::duration<nsecs_t, std::ratio<1, default_rate>>(1);
+ static constexpr size_t vsyncTimestampHistorySize = 20;
+ static constexpr size_t minimumSamplesForPrediction = 6;
+ static constexpr uint32_t discardOutlierPercent = 20;
+ return std::make_unique<
+ scheduler::VSyncPredictor>(std::chrono::duration_cast<std::chrono::nanoseconds>(
+ initial_period)
+ .count(),
+ vsyncTimestampHistorySize, minimumSamplesForPrediction,
+ discardOutlierPercent);
+}
+
+std::unique_ptr<scheduler::VSyncDispatch> createVSyncDispatch(
+ const std::unique_ptr<scheduler::VSyncTracker>& vSyncTracker) {
+ if (!vSyncTracker) return {};
+
+ // TODO (144707443) tune Predictor tunables.
+ static constexpr auto vsyncMoveThreshold =
+ std::chrono::duration_cast<std::chrono::nanoseconds>(3ms);
+ static constexpr auto timerSlack = std::chrono::duration_cast<std::chrono::nanoseconds>(500us);
+ return std::make_unique<
+ scheduler::VSyncDispatchTimerQueue>(std::make_unique<scheduler::Timer>(), *vSyncTracker,
+ timerSlack.count(), vsyncMoveThreshold.count());
+}
+
+std::unique_ptr<DispSync> createDispSync(
+ const std::unique_ptr<scheduler::VSyncTracker>& vSyncTracker,
+ const std::unique_ptr<scheduler::VSyncDispatch>& vSyncDispatch, bool supportKernelTimer) {
+ if (vSyncTracker && vSyncDispatch) {
// TODO (144707443) tune Predictor tunables.
- static constexpr int defaultRate = 60;
- static constexpr auto initialPeriod =
- std::chrono::duration<nsecs_t, std::ratio<1, defaultRate>>(1);
- static constexpr size_t vsyncTimestampHistorySize = 20;
- static constexpr size_t minimumSamplesForPrediction = 6;
- static constexpr uint32_t discardOutlierPercent = 20;
- auto tracker = std::make_unique<
- scheduler::VSyncPredictor>(std::chrono::duration_cast<std::chrono::nanoseconds>(
- initialPeriod)
- .count(),
- vsyncTimestampHistorySize, minimumSamplesForPrediction,
- discardOutlierPercent);
-
- static constexpr auto vsyncMoveThreshold =
- std::chrono::duration_cast<std::chrono::nanoseconds>(3ms);
- static constexpr auto timerSlack =
- std::chrono::duration_cast<std::chrono::nanoseconds>(500us);
- auto dispatch = std::make_unique<
- scheduler::VSyncDispatchTimerQueue>(std::make_unique<scheduler::Timer>(), *tracker,
- timerSlack.count(), vsyncMoveThreshold.count());
-
static constexpr size_t pendingFenceLimit = 20;
return std::make_unique<scheduler::VSyncReactor>(std::make_unique<scheduler::SystemClock>(),
- std::move(dispatch), std::move(tracker),
+ *vSyncDispatch, *vSyncTracker,
pendingFenceLimit, supportKernelTimer);
} else {
return std::make_unique<impl::DispSync>("SchedulerDispSync",
@@ -110,7 +120,11 @@
ISchedulerCallback& schedulerCallback, bool useContentDetectionV2,
bool useContentDetection)
: mSupportKernelTimer(sysprop::support_kernel_idle_timer(false)),
- mPrimaryDispSync(createDispSync(mSupportKernelTimer)),
+ // TODO (140302863) remove this and use the vsync_reactor system.
+ mUseVsyncPredictor(property_get_bool("debug.sf.vsync_reactor", true)),
+ mVSyncTracker(mUseVsyncPredictor ? createVSyncTracker() : nullptr),
+ mVSyncDispatch(createVSyncDispatch(mVSyncTracker)),
+ mPrimaryDispSync(createDispSync(mVSyncTracker, mVSyncDispatch, mSupportKernelTimer)),
mEventControlThread(new impl::EventControlThread(std::move(function))),
mLayerHistory(createLayerHistory(refreshRateConfigs, useContentDetectionV2)),
mSchedulerCallback(schedulerCallback),
@@ -156,6 +170,7 @@
std::unique_ptr<LayerHistory> layerHistory, bool useContentDetectionV2,
bool useContentDetection)
: mSupportKernelTimer(false),
+ mUseVsyncPredictor(true),
mPrimaryDispSync(std::move(primaryDispSync)),
mEventControlThread(std::move(eventControlThread)),
mLayerHistory(std::move(layerHistory)),
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 5fee4b4..2fe5629 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -44,7 +44,11 @@
class DispSync;
class FenceTime;
class InjectVSyncSource;
-struct DisplayStateInfo;
+
+namespace scheduler {
+class VSyncDispatch;
+class VSyncTracker;
+} // namespace scheduler
class ISchedulerCallback {
public:
@@ -230,6 +234,9 @@
// Whether to use idle timer callbacks that support the kernel timer.
const bool mSupportKernelTimer;
+ const bool mUseVsyncPredictor;
+ const std::unique_ptr<scheduler::VSyncTracker> mVSyncTracker;
+ const std::unique_ptr<scheduler::VSyncDispatch> mVSyncDispatch;
std::unique_ptr<DispSync> mPrimaryDispSync;
std::unique_ptr<EventControlThread> mEventControlThread;
diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.cpp b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
index efa8bab..a2b279b 100644
--- a/services/surfaceflinger/Scheduler/VSyncReactor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
@@ -55,15 +55,15 @@
}
};
-VSyncReactor::VSyncReactor(std::unique_ptr<Clock> clock, std::unique_ptr<VSyncDispatch> dispatch,
- std::unique_ptr<VSyncTracker> tracker, size_t pendingFenceLimit,
+VSyncReactor::VSyncReactor(std::unique_ptr<Clock> clock, VSyncDispatch& dispatch,
+ VSyncTracker& tracker, size_t pendingFenceLimit,
bool supportKernelIdleTimer)
: mClock(std::move(clock)),
- mTracker(std::move(tracker)),
- mDispatch(std::move(dispatch)),
+ mTracker(tracker),
+ mDispatch(dispatch),
mPendingLimit(pendingFenceLimit),
mPredictedVsyncTracer(property_get_bool("debug.sf.show_predicted_vsync", false)
- ? std::make_unique<PredictedVsyncTracer>(*mDispatch)
+ ? std::make_unique<PredictedVsyncTracer>(mDispatch)
: nullptr),
mSupportKernelIdleTimer(supportKernelIdleTimer) {}
@@ -182,7 +182,7 @@
} else if (time == Fence::SIGNAL_TIME_INVALID) {
it = mUnfiredFences.erase(it);
} else {
- timestampAccepted &= mTracker->addVsyncTimestamp(time);
+ timestampAccepted &= mTracker.addVsyncTimestamp(time);
it = mUnfiredFences.erase(it);
}
@@ -194,7 +194,7 @@
}
mUnfiredFences.push_back(fence);
} else {
- timestampAccepted &= mTracker->addVsyncTimestamp(signalTime);
+ timestampAccepted &= mTracker.addVsyncTimestamp(signalTime);
}
if (!timestampAccepted) {
@@ -224,12 +224,12 @@
}
nsecs_t VSyncReactor::computeNextRefresh(int periodOffset, nsecs_t now) const {
- auto const currentPeriod = periodOffset ? mTracker->currentPeriod() : 0;
- return mTracker->nextAnticipatedVSyncTimeFrom(now + periodOffset * currentPeriod);
+ auto const currentPeriod = periodOffset ? mTracker.currentPeriod() : 0;
+ return mTracker.nextAnticipatedVSyncTimeFrom(now + periodOffset * currentPeriod);
}
nsecs_t VSyncReactor::expectedPresentTime(nsecs_t now) {
- return mTracker->nextAnticipatedVSyncTimeFrom(now);
+ return mTracker.nextAnticipatedVSyncTimeFrom(now);
}
void VSyncReactor::startPeriodTransition(nsecs_t newPeriod) {
@@ -262,11 +262,11 @@
}
nsecs_t VSyncReactor::getPeriod() {
- return mTracker->currentPeriod();
+ return mTracker.currentPeriod();
}
void VSyncReactor::beginResync() {
- mTracker->resetModel();
+ mTracker.resetModel();
}
void VSyncReactor::endResync() {}
@@ -307,7 +307,7 @@
if (periodConfirmed(timestamp, hwcVsyncPeriod)) {
ATRACE_NAME("VSR: period confirmed");
if (mPeriodTransitioningTo) {
- mTracker->setPeriod(*mPeriodTransitioningTo);
+ mTracker.setPeriod(*mPeriodTransitioningTo);
for (auto& entry : mCallbacks) {
entry.second->setPeriod(*mPeriodTransitioningTo);
}
@@ -315,12 +315,12 @@
}
if (mLastHwVsync) {
- mTracker->addVsyncTimestamp(*mLastHwVsync);
+ mTracker.addVsyncTimestamp(*mLastHwVsync);
}
- mTracker->addVsyncTimestamp(timestamp);
+ mTracker.addVsyncTimestamp(timestamp);
endPeriodTransition();
- mMoreSamplesNeeded = mTracker->needsMoreSamples();
+ mMoreSamplesNeeded = mTracker.needsMoreSamples();
} else if (mPeriodConfirmationInProgress) {
ATRACE_NAME("VSR: still confirming period");
mLastHwVsync = timestamp;
@@ -329,8 +329,8 @@
} else {
ATRACE_NAME("VSR: adding sample");
*periodFlushed = false;
- mTracker->addVsyncTimestamp(timestamp);
- mMoreSamplesNeeded = mTracker->needsMoreSamples();
+ mTracker.addVsyncTimestamp(timestamp);
+ mMoreSamplesNeeded = mTracker.needsMoreSamples();
}
if (!mMoreSamplesNeeded) {
@@ -353,9 +353,9 @@
return NO_MEMORY;
}
- auto const period = mTracker->currentPeriod();
- auto repeater = std::make_unique<CallbackRepeater>(*mDispatch, callback, name, period,
- phase, mClock->now());
+ auto const period = mTracker.currentPeriod();
+ auto repeater = std::make_unique<CallbackRepeater>(mDispatch, callback, name, period, phase,
+ mClock->now());
it = mCallbacks.emplace(std::pair(callback, std::move(repeater))).first;
}
@@ -409,9 +409,9 @@
}
StringAppendF(&result, "VSyncTracker:\n");
- mTracker->dump(result);
+ mTracker.dump(result);
StringAppendF(&result, "VSyncDispatch:\n");
- mDispatch->dump(result);
+ mDispatch.dump(result);
}
void VSyncReactor::reset() {}
diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.h b/services/surfaceflinger/Scheduler/VSyncReactor.h
index 265d89c..22ceb39 100644
--- a/services/surfaceflinger/Scheduler/VSyncReactor.h
+++ b/services/surfaceflinger/Scheduler/VSyncReactor.h
@@ -35,9 +35,8 @@
// TODO (b/145217110): consider renaming.
class VSyncReactor : public android::DispSync {
public:
- VSyncReactor(std::unique_ptr<Clock> clock, std::unique_ptr<VSyncDispatch> dispatch,
- std::unique_ptr<VSyncTracker> tracker, size_t pendingFenceLimit,
- bool supportKernelIdleTimer);
+ VSyncReactor(std::unique_ptr<Clock> clock, VSyncDispatch& dispatch, VSyncTracker& tracker,
+ size_t pendingFenceLimit, bool supportKernelIdleTimer);
~VSyncReactor();
bool addPresentFence(const std::shared_ptr<FenceTime>& fence) final;
@@ -72,8 +71,8 @@
REQUIRES(mMutex);
std::unique_ptr<Clock> const mClock;
- std::unique_ptr<VSyncTracker> const mTracker;
- std::unique_ptr<VSyncDispatch> const mDispatch;
+ VSyncTracker& mTracker;
+ VSyncDispatch& mDispatch;
size_t const mPendingLimit;
mutable std::mutex mMutex;
diff --git a/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp
index 6856612..c5cddf3 100644
--- a/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp
@@ -45,26 +45,6 @@
MOCK_CONST_METHOD1(dump, void(std::string&));
};
-class VSyncTrackerWrapper : public VSyncTracker {
-public:
- VSyncTrackerWrapper(std::shared_ptr<VSyncTracker> const& tracker) : mTracker(tracker) {}
-
- bool addVsyncTimestamp(nsecs_t timestamp) final {
- return mTracker->addVsyncTimestamp(timestamp);
- }
- nsecs_t nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const final {
- return mTracker->nextAnticipatedVSyncTimeFrom(timePoint);
- }
- nsecs_t currentPeriod() const final { return mTracker->currentPeriod(); }
- void setPeriod(nsecs_t period) final { mTracker->setPeriod(period); }
- void resetModel() final { mTracker->resetModel(); }
- bool needsMoreSamples() const final { return mTracker->needsMoreSamples(); }
- void dump(std::string& result) const final { mTracker->dump(result); }
-
-private:
- std::shared_ptr<VSyncTracker> const mTracker;
-};
-
class MockClock : public Clock {
public:
MOCK_CONST_METHOD0(now, nsecs_t());
@@ -90,29 +70,6 @@
MOCK_CONST_METHOD1(dump, void(std::string&));
};
-class VSyncDispatchWrapper : public VSyncDispatch {
-public:
- VSyncDispatchWrapper(std::shared_ptr<VSyncDispatch> const& dispatch) : mDispatch(dispatch) {}
- CallbackToken registerCallback(std::function<void(nsecs_t, nsecs_t)> const& callbackFn,
- std::string callbackName) final {
- return mDispatch->registerCallback(callbackFn, callbackName);
- }
-
- void unregisterCallback(CallbackToken token) final { mDispatch->unregisterCallback(token); }
-
- ScheduleResult schedule(CallbackToken token, nsecs_t workDuration,
- nsecs_t earliestVsync) final {
- return mDispatch->schedule(token, workDuration, earliestVsync);
- }
-
- CancelResult cancel(CallbackToken token) final { return mDispatch->cancel(token); }
-
- void dump(std::string& result) const final { return mDispatch->dump(result); }
-
-private:
- std::shared_ptr<VSyncDispatch> const mDispatch;
-};
-
std::shared_ptr<FenceTime> generateInvalidFence() {
sp<Fence> fence = new Fence();
return std::make_shared<FenceTime>(fence);
@@ -157,10 +114,8 @@
: mMockDispatch(std::make_shared<NiceMock<MockVSyncDispatch>>()),
mMockTracker(std::make_shared<NiceMock<MockVSyncTracker>>()),
mMockClock(std::make_shared<NiceMock<MockClock>>()),
- mReactor(std::make_unique<ClockWrapper>(mMockClock),
- std::make_unique<VSyncDispatchWrapper>(mMockDispatch),
- std::make_unique<VSyncTrackerWrapper>(mMockTracker), kPendingLimit,
- false /* supportKernelIdleTimer */) {
+ mReactor(std::make_unique<ClockWrapper>(mMockClock), *mMockDispatch, *mMockTracker,
+ kPendingLimit, false /* supportKernelIdleTimer */) {
ON_CALL(*mMockClock, now()).WillByDefault(Return(mFakeNow));
ON_CALL(*mMockTracker, currentPeriod()).WillByDefault(Return(period));
}
@@ -745,10 +700,9 @@
TEST_F(VSyncReactorTest, periodIsMeasuredIfIgnoringComposer) {
// Create a reactor which supports the kernel idle timer
- auto idleReactor = VSyncReactor(std::make_unique<ClockWrapper>(mMockClock),
- std::make_unique<VSyncDispatchWrapper>(mMockDispatch),
- std::make_unique<VSyncTrackerWrapper>(mMockTracker),
- kPendingLimit, true /* supportKernelIdleTimer */);
+ auto idleReactor =
+ VSyncReactor(std::make_unique<ClockWrapper>(mMockClock), *mMockDispatch, *mMockTracker,
+ kPendingLimit, true /* supportKernelIdleTimer */);
bool periodFlushed = true;
EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(4);