Merge "GPU Memory: remove an infeasible TODO"
diff --git a/include/input/Input.h b/include/input/Input.h
index 194db1c..40d655f 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -342,6 +342,8 @@
void scale(float globalScale, float windowXScale, float windowYScale);
void applyOffset(float xOffset, float yOffset);
+ void transform(const ui::Transform& transform);
+
inline float getX() const {
return getAxisValue(AMOTION_EVENT_AXIS_X);
}
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 0219cf7..09cebef 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -41,7 +41,6 @@
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/Timers.h>
-#include <utils/Vector.h>
#include <android-base/unique_fd.h>
@@ -71,10 +70,7 @@
struct Header {
Type type; // 4 bytes
- // We don't need this field in order to align the body below but we
- // leave it here because InputMessage::size() and other functions
- // compute the size of this structure as sizeof(Header) + sizeof(Body).
- uint32_t padding;
+ uint32_t seq;
} header;
// Body *must* be 8 byte aligned.
@@ -83,8 +79,8 @@
static_assert(sizeof(std::array<uint8_t, 32>) == 32);
union Body {
struct Key {
- uint32_t seq;
int32_t eventId;
+ uint32_t empty1;
nsecs_t eventTime __attribute__((aligned(8)));
int32_t deviceId;
int32_t source;
@@ -103,8 +99,8 @@
} key;
struct Motion {
- uint32_t seq;
int32_t eventId;
+ uint32_t empty1;
nsecs_t eventTime __attribute__((aligned(8)));
int32_t deviceId;
int32_t source;
@@ -153,16 +149,14 @@
} motion;
struct Finished {
- uint32_t seq;
+ uint32_t empty1;
uint32_t handled; // actually a bool, but we must maintain 8-byte alignment
inline size_t size() const { return sizeof(Finished); }
} finished;
struct Focus {
- uint32_t seq;
int32_t eventId;
- uint32_t empty1;
// The following two fields take up 4 bytes total
uint16_t hasFocus; // actually a bool
uint16_t inTouchMode; // actually a bool, but we must maintain 8-byte alignment
@@ -174,6 +168,19 @@
bool isValid(size_t actualSize) const;
size_t size() const;
void getSanitizedCopy(InputMessage* msg) const;
+
+ static const char* typeToString(Type type) {
+ switch (type) {
+ case Type::KEY:
+ return "KEY";
+ case Type::MOTION:
+ return "MOTION";
+ case Type::FINISHED:
+ return "FINISHED";
+ case Type::FOCUS:
+ return "FOCUS";
+ }
+ }
};
struct InputChannelInfo : public Parcelable {
@@ -438,6 +445,8 @@
*/
int32_t getPendingBatchSource() const;
+ std::string dump() const;
+
private:
// True if touch resampling is enabled.
const bool mResampleTouch;
@@ -454,9 +463,9 @@
// Batched motion events per device and source.
struct Batch {
- Vector<InputMessage> samples;
+ std::vector<InputMessage> samples;
};
- Vector<Batch> mBatches;
+ std::vector<Batch> mBatches;
// Touch state per device and source, only for sources of class pointer.
struct History {
@@ -543,7 +552,7 @@
return false;
}
};
- Vector<TouchState> mTouchStates;
+ std::vector<TouchState> mTouchStates;
// Chain of batched sequence numbers. When multiple input messages are combined into
// a batch, we append a record here that associates the last sequence number in the
@@ -553,7 +562,7 @@
uint32_t seq; // sequence number of batched input message
uint32_t chain; // sequence number of previous batched input message
};
- Vector<SeqChain> mSeqChains;
+ std::vector<SeqChain> mSeqChains;
status_t consumeBatch(InputEventFactoryInterface* factory,
nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent);
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 05f43e3..25c0b19 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -326,6 +326,11 @@
while(true) {
{
+ // It would be really nice if we could read binder commands on this
+ // thread instead of needing a threadpool to be started, but for
+ // instance, if we call getAndExecuteCommand, it might be the case
+ // that another thread serves the callback, and we never get a
+ // command, so we hang indefinitely.
std::unique_lock<std::mutex> lock(waiter->mMutex);
using std::literals::chrono_literals::operator""s;
waiter->mCv.wait_for(lock, 1s, [&] {
@@ -334,6 +339,8 @@
if (waiter->mBinder != nullptr) return waiter->mBinder;
}
+ ALOGW("Waited one second for %s (is service started? are binder threads started and available?)", name.c_str());
+
// Handle race condition for lazy services. Here is what can happen:
// - the service dies (not processed by init yet).
// - sm processes death notification.
@@ -347,8 +354,6 @@
return nullptr;
}
if (out != nullptr) return out;
-
- ALOGW("Waited one second for %s", name.c_str());
}
}
diff --git a/libs/binder/include/binder/TextOutput.h b/libs/binder/include/binder/TextOutput.h
index f66406f..c7e1e14 100644
--- a/libs/binder/include/binder/TextOutput.h
+++ b/libs/binder/include/binder/TextOutput.h
@@ -50,12 +50,18 @@
// ---------------------------------------------------------------------------
+// DO NOT USE: prefer libutils/libbase logs, which don't require static data to
+// be allocated.
// Text output stream for printing to the log (via utils/Log.h).
extern TextOutput& alog;
+// DO NOT USE: prefer libutils/libbase logs, which don't require static data to
+// be allocated.
// Text output stream for printing to stdout.
extern TextOutput& aout;
+// DO NOT USE: prefer libutils/libbase logs, which don't require static data to
+// be allocated.
// Text output stream for printing to stderr.
extern TextOutput& aerr;
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 7540cae..d287290 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -698,3 +698,14 @@
const char* AIBinder_getCallingSid() {
return ::android::IPCThreadState::self()->getCallingSid();
}
+
+android::sp<android::IBinder> AIBinder_toPlatformBinder(AIBinder* binder) {
+ if (binder == nullptr) return nullptr;
+ return binder->getBinder();
+}
+
+AIBinder* AIBinder_fromPlatformBinder(const android::sp<android::IBinder>& binder) {
+ sp<AIBinder> ndkBinder = ABpBinder::lookupOrCreateFromBinder(binder);
+ AIBinder_incStrong(ndkBinder.get());
+ return ndkBinder.get();
+}
diff --git a/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h b/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
index 1f5a237..d4feaba 100644
--- a/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
+++ b/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
@@ -18,6 +18,10 @@
#include <android/binder_ibinder.h>
+#if !defined(__ANDROID_APEX__) && !defined(__ANDROID_VNDK__)
+#include <binder/IBinder.h>
+#endif
+
__BEGIN_DECLS
/**
@@ -44,3 +48,33 @@
__attribute__((warn_unused_result)) const char* AIBinder_getCallingSid() __INTRODUCED_IN(31);
__END_DECLS
+
+#if !defined(__ANDROID_APEX__) && !defined(__ANDROID_VNDK__)
+
+/**
+ * Get libbinder version of binder from AIBinder.
+ *
+ * WARNING: function calls to a local object on the other side of this function
+ * will parcel. When converting between binders, keep in mind it is not as
+ * efficient as a direct function call.
+ *
+ * \param binder binder with ownership retained by the client
+ * \return platform binder object
+ */
+android::sp<android::IBinder> AIBinder_toPlatformBinder(AIBinder* binder);
+
+/**
+ * Get libbinder_ndk version of binder from platform binder.
+ *
+ * WARNING: function calls to a local object on the other side of this function
+ * will parcel. When converting between binders, keep in mind it is not as
+ * efficient as a direct function call.
+ *
+ * \param binder platform binder which may be from anywhere (doesn't have to be
+ * created with libbinder_ndK)
+ * \return binder with one reference count of ownership given to the client. See
+ * AIBinder_decStrong
+ */
+AIBinder* AIBinder_fromPlatformBinder(const android::sp<android::IBinder>& binder);
+
+#endif
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index d58b75c..9b5fa26 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -95,8 +95,6 @@
AServiceManager_addService; # apex llndk
AServiceManager_checkService; # apex llndk
AServiceManager_getService; # apex llndk
- local:
- *;
};
LIBBINDER_NDK30 { # introduced=30
@@ -111,19 +109,21 @@
AIBinder_markVendorStability; # llndk
AIBinder_markVintfStability; # apex llndk
AIBinder_Class_setHandleShellCommand; # apex llndk
- local:
- *;
};
LIBBINDER_NDK31 { # introduced=31
global:
AIBinder_getCallingSid; # apex
AIBinder_setRequestingSid; # apex
- local:
- *;
};
LIBBINDER_NDK_PLATFORM {
global:
AParcel_getAllowFds;
+ extern "C++" {
+ AIBinder_fromPlatformBinder*;
+ AIBinder_toPlatformBinder*;
+ };
+ local:
+ *;
};
diff --git a/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl b/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl
index 4bba9e4..dc77467d 100644
--- a/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl
+++ b/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl
@@ -22,6 +22,8 @@
import IEmpty;
interface IBinderNdkUnitTest {
+ int repeatInt(int a);
+
void takeInterface(IEmpty test);
void forceFlushCommands();
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index 6869220..e3fdb4b 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -44,6 +44,10 @@
constexpr char kBinderNdkUnitTestService[] = "BinderNdkUnitTest";
class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest {
+ ndk::ScopedAStatus repeatInt(int32_t in, int32_t* out) {
+ *out = in;
+ return ndk::ScopedAStatus::ok();
+ }
ndk::ScopedAStatus takeInterface(const std::shared_ptr<aidl::IEmpty>& empty) {
(void)empty;
return ndk::ScopedAStatus::ok();
@@ -329,6 +333,30 @@
EXPECT_TRUE(destroyed);
}
+TEST(NdkBinder, ConvertToPlatformBinder) {
+ for (const ndk::SpAIBinder& binder :
+ {// remote
+ ndk::SpAIBinder(AServiceManager_getService(kBinderNdkUnitTestService)),
+ // local
+ ndk::SharedRefBase::make<MyBinderNdkUnitTest>()->asBinder()}) {
+ // convert to platform binder
+ EXPECT_NE(binder.get(), nullptr);
+ sp<IBinder> platformBinder = AIBinder_toPlatformBinder(binder.get());
+ EXPECT_NE(platformBinder.get(), nullptr);
+ auto proxy = interface_cast<IBinderNdkUnitTest>(platformBinder);
+ EXPECT_NE(proxy, nullptr);
+
+ // use platform binder
+ int out;
+ EXPECT_TRUE(proxy->repeatInt(4, &out).isOk());
+ EXPECT_EQ(out, 4);
+
+ // convert back
+ ndk::SpAIBinder backBinder = ndk::SpAIBinder(AIBinder_fromPlatformBinder(platformBinder));
+ EXPECT_EQ(backBinder.get(), binder.get());
+ }
+}
+
class MyResultReceiver : public BnResultReceiver {
public:
Mutex mMutex;
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 31aa685..2ac079e 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -301,6 +301,11 @@
}
}
+void PointerCoords::transform(const ui::Transform& transform) {
+ vec2 newCoords = transform.transform(getX(), getY());
+ setAxisValue(AMOTION_EVENT_AXIS_X, newCoords.x);
+ setAxisValue(AMOTION_EVENT_AXIS_Y, newCoords.y);
+}
// --- PointerProperties ---
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index c6043ac..60ad578 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -133,12 +133,11 @@
// Write the header
msg->header.type = header.type;
+ msg->header.seq = header.seq;
// Write the body
switch(header.type) {
case InputMessage::Type::KEY: {
- // uint32_t seq
- msg->body.key.seq = body.key.seq;
// int32_t eventId
msg->body.key.eventId = body.key.eventId;
// nsecs_t eventTime
@@ -168,8 +167,6 @@
break;
}
case InputMessage::Type::MOTION: {
- // uint32_t seq
- msg->body.motion.seq = body.motion.seq;
// int32_t eventId
msg->body.motion.eventId = body.motion.eventId;
// nsecs_t eventTime
@@ -232,12 +229,10 @@
break;
}
case InputMessage::Type::FINISHED: {
- msg->body.finished.seq = body.finished.seq;
msg->body.finished.handled = body.finished.handled;
break;
}
case InputMessage::Type::FOCUS: {
- msg->body.focus.seq = body.focus.seq;
msg->body.focus.eventId = body.focus.eventId;
msg->body.focus.hasFocus = body.focus.hasFocus;
msg->body.focus.inTouchMode = body.focus.inTouchMode;
@@ -468,7 +463,7 @@
InputMessage msg;
msg.header.type = InputMessage::Type::KEY;
- msg.body.key.seq = seq;
+ msg.header.seq = seq;
msg.body.key.eventId = eventId;
msg.body.key.deviceId = deviceId;
msg.body.key.source = source;
@@ -526,7 +521,7 @@
InputMessage msg;
msg.header.type = InputMessage::Type::MOTION;
- msg.body.motion.seq = seq;
+ msg.header.seq = seq;
msg.body.motion.eventId = eventId;
msg.body.motion.deviceId = deviceId;
msg.body.motion.source = source;
@@ -570,7 +565,7 @@
InputMessage msg;
msg.header.type = InputMessage::Type::FOCUS;
- msg.body.focus.seq = seq;
+ msg.header.seq = seq;
msg.body.focus.eventId = eventId;
msg.body.focus.hasFocus = hasFocus ? 1 : 0;
msg.body.focus.inTouchMode = inTouchMode ? 1 : 0;
@@ -594,7 +589,7 @@
mChannel->getName().c_str(), msg.header.type);
return UNKNOWN_ERROR;
}
- *outSeq = msg.body.finished.seq;
+ *outSeq = msg.header.seq;
*outHandled = msg.body.finished.handled == 1;
return OK;
}
@@ -655,7 +650,7 @@
if (!keyEvent) return NO_MEMORY;
initializeKeyEvent(keyEvent, &mMsg);
- *outSeq = mMsg.body.key.seq;
+ *outSeq = mMsg.header.seq;
*outEvent = keyEvent;
if (DEBUG_TRANSPORT_ACTIONS) {
ALOGD("channel '%s' consumer ~ consumed key event, seq=%u",
@@ -667,9 +662,9 @@
case InputMessage::Type::MOTION: {
ssize_t batchIndex = findBatch(mMsg.body.motion.deviceId, mMsg.body.motion.source);
if (batchIndex >= 0) {
- Batch& batch = mBatches.editItemAt(batchIndex);
+ Batch& batch = mBatches[batchIndex];
if (canAddSample(batch, &mMsg)) {
- batch.samples.push(mMsg);
+ batch.samples.push_back(mMsg);
if (DEBUG_TRANSPORT_ACTIONS) {
ALOGD("channel '%s' consumer ~ appended to batch event",
mChannel->getName().c_str());
@@ -680,18 +675,18 @@
// No need to process events that we are going to cancel anyways
const size_t count = batch.samples.size();
for (size_t i = 0; i < count; i++) {
- const InputMessage& msg = batch.samples.itemAt(i);
- sendFinishedSignal(msg.body.motion.seq, false);
+ const InputMessage& msg = batch.samples[i];
+ sendFinishedSignal(msg.header.seq, false);
}
- batch.samples.removeItemsAt(0, count);
- mBatches.removeAt(batchIndex);
+ batch.samples.erase(batch.samples.begin(), batch.samples.begin() + count);
+ mBatches.erase(mBatches.begin() + batchIndex);
} else {
// We cannot append to the batch in progress, so we need to consume
// the previous batch right now and defer the new message until later.
mMsgDeferred = true;
status_t result = consumeSamples(factory, batch, batch.samples.size(),
outSeq, outEvent);
- mBatches.removeAt(batchIndex);
+ mBatches.erase(mBatches.begin() + batchIndex);
if (result) {
return result;
}
@@ -707,9 +702,9 @@
// Start a new batch if needed.
if (mMsg.body.motion.action == AMOTION_EVENT_ACTION_MOVE ||
mMsg.body.motion.action == AMOTION_EVENT_ACTION_HOVER_MOVE) {
- mBatches.push();
- Batch& batch = mBatches.editTop();
- batch.samples.push(mMsg);
+ Batch batch;
+ batch.samples.push_back(mMsg);
+ mBatches.push_back(batch);
if (DEBUG_TRANSPORT_ACTIONS) {
ALOGD("channel '%s' consumer ~ started batch event",
mChannel->getName().c_str());
@@ -722,7 +717,7 @@
updateTouchState(mMsg);
initializeMotionEvent(motionEvent, &mMsg);
- *outSeq = mMsg.body.motion.seq;
+ *outSeq = mMsg.header.seq;
*outEvent = motionEvent;
if (DEBUG_TRANSPORT_ACTIONS) {
@@ -743,7 +738,7 @@
if (!focusEvent) return NO_MEMORY;
initializeFocusEvent(focusEvent, &mMsg);
- *outSeq = mMsg.body.focus.seq;
+ *outSeq = mMsg.header.seq;
*outEvent = focusEvent;
break;
}
@@ -757,10 +752,10 @@
status_t result;
for (size_t i = mBatches.size(); i > 0; ) {
i--;
- Batch& batch = mBatches.editItemAt(i);
+ Batch& batch = mBatches[i];
if (frameTime < 0) {
result = consumeSamples(factory, batch, batch.samples.size(), outSeq, outEvent);
- mBatches.removeAt(i);
+ mBatches.erase(mBatches.begin() + i);
return result;
}
@@ -775,11 +770,11 @@
result = consumeSamples(factory, batch, split + 1, outSeq, outEvent);
const InputMessage* next;
- if (batch.samples.isEmpty()) {
- mBatches.removeAt(i);
+ if (batch.samples.empty()) {
+ mBatches.erase(mBatches.begin() + i);
next = nullptr;
} else {
- next = &batch.samples.itemAt(0);
+ next = &batch.samples[0];
}
if (!result && mResampleTouch) {
resampleTouchState(sampleTime, static_cast<MotionEvent*>(*outEvent), next);
@@ -797,20 +792,20 @@
uint32_t chain = 0;
for (size_t i = 0; i < count; i++) {
- InputMessage& msg = batch.samples.editItemAt(i);
+ InputMessage& msg = batch.samples[i];
updateTouchState(msg);
if (i) {
SeqChain seqChain;
- seqChain.seq = msg.body.motion.seq;
+ seqChain.seq = msg.header.seq;
seqChain.chain = chain;
- mSeqChains.push(seqChain);
+ mSeqChains.push_back(seqChain);
addSample(motionEvent, &msg);
} else {
initializeMotionEvent(motionEvent, &msg);
}
- chain = msg.body.motion.seq;
+ chain = msg.header.seq;
}
- batch.samples.removeItemsAt(0, count);
+ batch.samples.erase(batch.samples.begin(), batch.samples.begin() + count);
*outSeq = chain;
*outEvent = motionEvent;
@@ -832,10 +827,10 @@
case AMOTION_EVENT_ACTION_DOWN: {
ssize_t index = findTouchState(deviceId, source);
if (index < 0) {
- mTouchStates.push();
+ mTouchStates.push_back({});
index = mTouchStates.size() - 1;
}
- TouchState& touchState = mTouchStates.editItemAt(index);
+ TouchState& touchState = mTouchStates[index];
touchState.initialize(deviceId, source);
touchState.addHistory(msg);
break;
@@ -844,7 +839,7 @@
case AMOTION_EVENT_ACTION_MOVE: {
ssize_t index = findTouchState(deviceId, source);
if (index >= 0) {
- TouchState& touchState = mTouchStates.editItemAt(index);
+ TouchState& touchState = mTouchStates[index];
touchState.addHistory(msg);
rewriteMessage(touchState, msg);
}
@@ -854,7 +849,7 @@
case AMOTION_EVENT_ACTION_POINTER_DOWN: {
ssize_t index = findTouchState(deviceId, source);
if (index >= 0) {
- TouchState& touchState = mTouchStates.editItemAt(index);
+ TouchState& touchState = mTouchStates[index];
touchState.lastResample.idBits.clearBit(msg.body.motion.getActionId());
rewriteMessage(touchState, msg);
}
@@ -864,7 +859,7 @@
case AMOTION_EVENT_ACTION_POINTER_UP: {
ssize_t index = findTouchState(deviceId, source);
if (index >= 0) {
- TouchState& touchState = mTouchStates.editItemAt(index);
+ TouchState& touchState = mTouchStates[index];
rewriteMessage(touchState, msg);
touchState.lastResample.idBits.clearBit(msg.body.motion.getActionId());
}
@@ -874,7 +869,7 @@
case AMOTION_EVENT_ACTION_SCROLL: {
ssize_t index = findTouchState(deviceId, source);
if (index >= 0) {
- TouchState& touchState = mTouchStates.editItemAt(index);
+ TouchState& touchState = mTouchStates[index];
rewriteMessage(touchState, msg);
}
break;
@@ -884,9 +879,9 @@
case AMOTION_EVENT_ACTION_CANCEL: {
ssize_t index = findTouchState(deviceId, source);
if (index >= 0) {
- TouchState& touchState = mTouchStates.editItemAt(index);
+ TouchState& touchState = mTouchStates[index];
rewriteMessage(touchState, msg);
- mTouchStates.removeAt(index);
+ mTouchStates.erase(mTouchStates.begin() + index);
}
break;
}
@@ -943,7 +938,7 @@
return;
}
- TouchState& touchState = mTouchStates.editItemAt(index);
+ TouchState& touchState = mTouchStates[index];
if (touchState.historySize < 1) {
#if DEBUG_RESAMPLING
ALOGD("Not resampled, no history for device.");
@@ -1089,11 +1084,11 @@
size_t chainIndex = 0;
for (size_t i = seqChainCount; i > 0; ) {
i--;
- const SeqChain& seqChain = mSeqChains.itemAt(i);
+ const SeqChain& seqChain = mSeqChains[i];
if (seqChain.seq == currentSeq) {
currentSeq = seqChain.chain;
chainSeqs[chainIndex++] = currentSeq;
- mSeqChains.removeAt(i);
+ mSeqChains.erase(mSeqChains.begin() + i);
}
}
status_t status = OK;
@@ -1107,7 +1102,7 @@
SeqChain seqChain;
seqChain.seq = chainIndex != 0 ? chainSeqs[chainIndex - 1] : seq;
seqChain.chain = chainSeqs[chainIndex];
- mSeqChains.push(seqChain);
+ mSeqChains.push_back(seqChain);
if (!chainIndex) break;
chainIndex--;
}
@@ -1122,7 +1117,7 @@
status_t InputConsumer::sendUnchainedFinishedSignal(uint32_t seq, bool handled) {
InputMessage msg;
msg.header.type = InputMessage::Type::FINISHED;
- msg.body.finished.seq = seq;
+ msg.header.seq = seq;
msg.body.finished.handled = handled ? 1 : 0;
return mChannel->sendMessage(&msg);
}
@@ -1132,23 +1127,23 @@
}
bool InputConsumer::hasPendingBatch() const {
- return !mBatches.isEmpty();
+ return !mBatches.empty();
}
int32_t InputConsumer::getPendingBatchSource() const {
- if (mBatches.isEmpty()) {
+ if (mBatches.empty()) {
return AINPUT_SOURCE_CLASS_NONE;
}
- const Batch& batch = mBatches.itemAt(0);
- const InputMessage& head = batch.samples.itemAt(0);
+ const Batch& batch = mBatches[0];
+ const InputMessage& head = batch.samples[0];
return head.body.motion.source;
}
ssize_t InputConsumer::findBatch(int32_t deviceId, int32_t source) const {
for (size_t i = 0; i < mBatches.size(); i++) {
- const Batch& batch = mBatches.itemAt(i);
- const InputMessage& head = batch.samples.itemAt(0);
+ const Batch& batch = mBatches[i];
+ const InputMessage& head = batch.samples[0];
if (head.body.motion.deviceId == deviceId && head.body.motion.source == source) {
return i;
}
@@ -1158,7 +1153,7 @@
ssize_t InputConsumer::findTouchState(int32_t deviceId, int32_t source) const {
for (size_t i = 0; i < mTouchStates.size(); i++) {
- const TouchState& touchState = mTouchStates.itemAt(i);
+ const TouchState& touchState = mTouchStates[i];
if (touchState.deviceId == deviceId && touchState.source == source) {
return i;
}
@@ -1212,7 +1207,7 @@
}
bool InputConsumer::canAddSample(const Batch& batch, const InputMessage *msg) {
- const InputMessage& head = batch.samples.itemAt(0);
+ const InputMessage& head = batch.samples[0];
uint32_t pointerCount = msg->body.motion.pointerCount;
if (head.body.motion.pointerCount != pointerCount
|| head.body.motion.action != msg->body.motion.action) {
@@ -1230,11 +1225,72 @@
ssize_t InputConsumer::findSampleNoLaterThan(const Batch& batch, nsecs_t time) {
size_t numSamples = batch.samples.size();
size_t index = 0;
- while (index < numSamples
- && batch.samples.itemAt(index).body.motion.eventTime <= time) {
+ while (index < numSamples && batch.samples[index].body.motion.eventTime <= time) {
index += 1;
}
return ssize_t(index) - 1;
}
+std::string InputConsumer::dump() const {
+ std::string out;
+ out = out + "mResampleTouch = " + toString(mResampleTouch) + "\n";
+ out = out + "mChannel = " + mChannel->getName() + "\n";
+ out = out + "mMsgDeferred: " + toString(mMsgDeferred) + "\n";
+ if (mMsgDeferred) {
+ out = out + "mMsg : " + InputMessage::typeToString(mMsg.header.type) + "\n";
+ }
+ out += "Batches:\n";
+ for (const Batch& batch : mBatches) {
+ out += " Batch:\n";
+ for (const InputMessage& msg : batch.samples) {
+ out += android::base::StringPrintf(" Message %" PRIu32 ": %s ", msg.header.seq,
+ InputMessage::typeToString(msg.header.type));
+ switch (msg.header.type) {
+ case InputMessage::Type::KEY: {
+ out += android::base::StringPrintf("action=%s keycode=%" PRId32,
+ KeyEvent::actionToString(
+ msg.body.key.action),
+ msg.body.key.keyCode);
+ break;
+ }
+ case InputMessage::Type::MOTION: {
+ out = out + "action=" + MotionEvent::actionToString(msg.body.motion.action);
+ for (uint32_t i = 0; i < msg.body.motion.pointerCount; i++) {
+ const float x = msg.body.motion.pointers[i].coords.getX();
+ const float y = msg.body.motion.pointers[i].coords.getY();
+ out += android::base::StringPrintf("\n Pointer %" PRIu32
+ " : x=%.1f y=%.1f",
+ i, x, y);
+ }
+ break;
+ }
+ case InputMessage::Type::FINISHED: {
+ out += android::base::StringPrintf("handled=%s",
+ toString(msg.body.finished.handled));
+ break;
+ }
+ case InputMessage::Type::FOCUS: {
+ out += android::base::StringPrintf("hasFocus=%s inTouchMode=%s",
+ toString(msg.body.focus.hasFocus),
+ toString(msg.body.focus.inTouchMode));
+ break;
+ }
+ }
+ out += "\n";
+ }
+ }
+ if (mBatches.empty()) {
+ out += " <empty>\n";
+ }
+ out += "mSeqChains:\n";
+ for (const SeqChain& chain : mSeqChains) {
+ out += android::base::StringPrintf(" chain: seq = %" PRIu32 " chain=%" PRIu32, chain.seq,
+ chain.chain);
+ }
+ if (mSeqChains.empty()) {
+ out += " <empty>\n";
+ }
+ return out;
+}
+
} // namespace android
diff --git a/libs/input/tests/InputChannel_test.cpp b/libs/input/tests/InputChannel_test.cpp
index 7f4bd6e..4187ca9 100644
--- a/libs/input/tests/InputChannel_test.cpp
+++ b/libs/input/tests/InputChannel_test.cpp
@@ -103,7 +103,7 @@
InputMessage clientReply;
memset(&clientReply, 0, sizeof(InputMessage));
clientReply.header.type = InputMessage::Type::FINISHED;
- clientReply.body.finished.seq = 0x11223344;
+ clientReply.header.seq = 0x11223344;
clientReply.body.finished.handled = true;
EXPECT_EQ(OK, clientChannel->sendMessage(&clientReply))
<< "client channel should be able to send message to server channel";
@@ -113,7 +113,7 @@
<< "server channel should be able to receive message from client channel";
EXPECT_EQ(clientReply.header.type, serverReply.header.type)
<< "server channel should receive the correct message from client channel";
- EXPECT_EQ(clientReply.body.finished.seq, serverReply.body.finished.seq)
+ EXPECT_EQ(clientReply.header.seq, serverReply.header.seq)
<< "server channel should receive the correct message from client channel";
EXPECT_EQ(clientReply.body.finished.handled, serverReply.body.finished.handled)
<< "server channel should receive the correct message from client channel";
@@ -181,7 +181,7 @@
InputMessage serverMsg = {}, clientMsg;
serverMsg.header.type = InputMessage::Type::MOTION;
- serverMsg.body.motion.seq = 1;
+ serverMsg.header.seq = 1;
serverMsg.body.motion.pointerCount = 1;
for (MotionClassification classification : classifications) {
diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp
index 1fe7bb9..50be9ad 100644
--- a/libs/input/tests/StructLayout_test.cpp
+++ b/libs/input/tests/StructLayout_test.cpp
@@ -34,8 +34,7 @@
void TestInputMessageAlignment() {
CHECK_OFFSET(InputMessage, body, 8);
- CHECK_OFFSET(InputMessage::Body::Key, seq, 0);
- CHECK_OFFSET(InputMessage::Body::Key, eventId, 4);
+ CHECK_OFFSET(InputMessage::Body::Key, eventId, 0);
CHECK_OFFSET(InputMessage::Body::Key, eventTime, 8);
CHECK_OFFSET(InputMessage::Body::Key, deviceId, 16);
CHECK_OFFSET(InputMessage::Body::Key, source, 20);
@@ -49,8 +48,7 @@
CHECK_OFFSET(InputMessage::Body::Key, repeatCount, 80);
CHECK_OFFSET(InputMessage::Body::Key, downTime, 88);
- CHECK_OFFSET(InputMessage::Body::Motion, seq, 0);
- CHECK_OFFSET(InputMessage::Body::Motion, eventId, 4);
+ CHECK_OFFSET(InputMessage::Body::Motion, eventId, 0);
CHECK_OFFSET(InputMessage::Body::Motion, eventTime, 8);
CHECK_OFFSET(InputMessage::Body::Motion, deviceId, 16);
CHECK_OFFSET(InputMessage::Body::Motion, source, 20);
@@ -75,16 +73,16 @@
CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 128);
CHECK_OFFSET(InputMessage::Body::Motion, pointers, 136);
- CHECK_OFFSET(InputMessage::Body::Focus, seq, 0);
- CHECK_OFFSET(InputMessage::Body::Focus, eventId, 4);
- CHECK_OFFSET(InputMessage::Body::Focus, hasFocus, 12);
- CHECK_OFFSET(InputMessage::Body::Focus, inTouchMode, 14);
+ CHECK_OFFSET(InputMessage::Body::Focus, eventId, 0);
+ CHECK_OFFSET(InputMessage::Body::Focus, hasFocus, 4);
+ CHECK_OFFSET(InputMessage::Body::Focus, inTouchMode, 6);
- CHECK_OFFSET(InputMessage::Body::Finished, seq, 0);
CHECK_OFFSET(InputMessage::Body::Finished, handled, 4);
}
void TestHeaderSize() {
+ CHECK_OFFSET(InputMessage::Header, type, 0);
+ CHECK_OFFSET(InputMessage::Header, seq, 4);
static_assert(sizeof(InputMessage::Header) == 8);
}
@@ -98,7 +96,7 @@
offsetof(InputMessage::Body::Motion, pointers) +
sizeof(InputMessage::Body::Motion::Pointer) * MAX_POINTERS);
static_assert(sizeof(InputMessage::Body::Finished) == 8);
- static_assert(sizeof(InputMessage::Body::Focus) == 16);
+ static_assert(sizeof(InputMessage::Body::Focus) == 8);
}
// --- VerifiedInputEvent ---
diff --git a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
index e2d036b..f371667 100644
--- a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
+++ b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
@@ -79,6 +79,8 @@
/**
* ASurfaceTexture_dequeueBuffer returns the next available AHardwareBuffer.
+ * The caller gets ownership of the buffer and need to release it with
+ * AHardwareBuffer_release.
*/
AHardwareBuffer* ASurfaceTexture_dequeueBuffer(ASurfaceTexture* st, int* outSlotid,
android_dataspace* outDataspace,
diff --git a/libs/nativedisplay/surfacetexture/surface_texture.cpp b/libs/nativedisplay/surfacetexture/surface_texture.cpp
index d1bcd8d..ebe4484 100644
--- a/libs/nativedisplay/surfacetexture/surface_texture.cpp
+++ b/libs/nativedisplay/surfacetexture/surface_texture.cpp
@@ -208,7 +208,15 @@
*outNewContent = true;
}
} while (buffer.get() && (!queueEmpty));
- return reinterpret_cast<AHardwareBuffer*>(buffer.get());
+ AHardwareBuffer* result = nullptr;
+ if (buffer.get()) {
+ result = buffer->toAHardwareBuffer();
+ // add a reference to keep the hardware buffer alive, even if
+ // BufferQueueProducer is disconnected. This is needed, because
+ // sp reference is destroyed at the end of this function.
+ AHardwareBuffer_acquire(result);
+ }
+ return result;
}
} // namespace android
diff --git a/libs/ui/Transform.cpp b/libs/ui/Transform.cpp
index 06b6bfe..3bf3903 100644
--- a/libs/ui/Transform.cpp
+++ b/libs/ui/Transform.cpp
@@ -55,7 +55,6 @@
mMatrix[1][1] == other.mMatrix[1][1] && mMatrix[1][2] == other.mMatrix[1][2] &&
mMatrix[2][0] == other.mMatrix[2][0] && mMatrix[2][1] == other.mMatrix[2][1] &&
mMatrix[2][2] == other.mMatrix[2][2];
- ;
}
Transform Transform::operator * (const Transform& rhs) const
@@ -87,6 +86,19 @@
return r;
}
+Transform Transform::operator * (float value) const {
+ Transform r(*this);
+ const mat33& M(mMatrix);
+ mat33& R(r.mMatrix);
+ for (size_t i = 0; i < 3; i++) {
+ for (size_t j = 0; j < 2; j++) {
+ R[i][j] = M[i][j] * value;
+ }
+ }
+ r.type();
+ return r;
+}
+
Transform& Transform::operator=(const Transform& other) {
mMatrix = other.mMatrix;
mType = other.mType;
@@ -105,11 +117,19 @@
return mMatrix[2][1];
}
-float Transform::sx() const {
+float Transform::dsdx() const {
return mMatrix[0][0];
}
-float Transform::sy() const {
+float Transform::dtdx() const {
+ return mMatrix[1][0];
+}
+
+float Transform::dtdy() const {
+ return mMatrix[0][1];
+}
+
+float Transform::dsdy() const {
return mMatrix[1][1];
}
@@ -187,6 +207,15 @@
return NO_ERROR;
}
+void Transform::set(const std::array<float, 9>& matrix) {
+ mat33& M(mMatrix);
+ M[0][0] = matrix[0]; M[1][0] = matrix[1]; M[2][0] = matrix[2];
+ M[0][1] = matrix[3]; M[1][1] = matrix[4]; M[2][1] = matrix[5];
+ M[0][2] = matrix[6]; M[1][2] = matrix[7]; M[2][2] = matrix[8];
+ mType = UNKNOWN_TYPE;
+ type();
+}
+
vec2 Transform::transform(const vec2& v) const {
vec2 r;
const mat33& M(mMatrix);
@@ -204,9 +233,8 @@
return r;
}
-vec2 Transform::transform(int x, int y) const
-{
- return transform(vec2(x,y));
+vec2 Transform::transform(float x, float y) const {
+ return transform(vec2(x, y));
}
Rect Transform::makeBounds(int w, int h) const
diff --git a/libs/ui/include/ui/Transform.h b/libs/ui/include/ui/Transform.h
index 3e8caf4..cf59467 100644
--- a/libs/ui/include/ui/Transform.h
+++ b/libs/ui/include/ui/Transform.h
@@ -18,6 +18,7 @@
#include <stdint.h>
#include <sys/types.h>
+#include <array>
#include <ostream>
#include <string>
@@ -68,24 +69,28 @@
const vec3& operator [] (size_t i) const; // returns column i
float tx() const;
float ty() const;
- float sx() const;
- float sy() const;
+ float dsdx() const;
+ float dtdx() const;
+ float dtdy() const;
+ float dsdy() const;
// modify the transform
void reset();
void set(float tx, float ty);
void set(float a, float b, float c, float d);
status_t set(uint32_t flags, float w, float h);
+ void set(const std::array<float, 9>& matrix);
// transform data
Rect makeBounds(int w, int h) const;
- vec2 transform(int x, int y) const;
+ vec2 transform(float x, float y) const;
Region transform(const Region& reg) const;
Rect transform(const Rect& bounds,
bool roundOutwards = false) const;
FloatRect transform(const FloatRect& bounds) const;
Transform& operator = (const Transform& other);
Transform operator * (const Transform& rhs) const;
+ Transform operator * (float value) const;
// assumes the last row is < 0 , 0 , 1 >
vec2 transform(const vec2& v) const;
vec3 transform(const vec3& v) const;
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 9deea63..5df4aec 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -4269,10 +4269,10 @@
dump += INDENT4;
entry->eventEntry->appendDescription(dump);
dump += StringPrintf(", targetFlags=0x%08x, resolvedAction=%d, "
- "age=%" PRId64 "ms, wait=%" PRId64 "ms\n",
+ "age=%" PRId64 "ms, wait=%" PRId64 "ms seq=%" PRIu32 "\n",
entry->targetFlags, entry->resolvedAction,
ns2ms(currentTime - entry->eventEntry->eventTime),
- ns2ms(currentTime - entry->deliveryTime));
+ ns2ms(currentTime - entry->deliveryTime), entry->seq);
}
} else {
dump += INDENT3 "WaitQueue: <empty>\n";
diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp
index 83a610f..0ccada9 100644
--- a/services/inputflinger/reader/Android.bp
+++ b/services/inputflinger/reader/Android.bp
@@ -81,4 +81,7 @@
export_header_lib_headers: [
"libinputreader_headers",
],
+ static_libs: [
+ "libc++fs"
+ ],
}
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index 5f1d475..5e590d0 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -34,20 +34,20 @@
#define LOG_TAG "EventHub"
// #define LOG_NDEBUG 0
-
-#include "EventHub.h"
-
#include <android-base/stringprintf.h>
#include <cutils/properties.h>
+#include <input/KeyCharacterMap.h>
+#include <input/KeyLayoutMap.h>
+#include <input/VirtualKeyMap.h>
#include <openssl/sha.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/Timers.h>
#include <utils/threads.h>
-#include <input/KeyCharacterMap.h>
-#include <input/KeyLayoutMap.h>
-#include <input/VirtualKeyMap.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
@@ -94,8 +94,8 @@
/**
* Return true if name matches "v4l-touch*"
*/
-static bool isV4lTouchNode(const char* name) {
- return strstr(name, "v4l-touch") == name;
+static bool isV4lTouchNode(std::string name) {
+ return name.find("v4l-touch") != std::string::npos;
}
/**
@@ -810,7 +810,7 @@
return index >= 0 ? mDevices.valueAt(index) : NULL;
}
-EventHub::Device* EventHub::getDeviceByPathLocked(const char* devicePath) const {
+EventHub::Device* EventHub::getDeviceByPathLocked(const std::string& devicePath) const {
for (size_t i = 0; i < mDevices.size(); i++) {
Device* device = mDevices.valueAt(i);
if (device->path == devicePath) {
@@ -1215,14 +1215,14 @@
}
}
-status_t EventHub::openDeviceLocked(const char* devicePath) {
+status_t EventHub::openDeviceLocked(const std::string& devicePath) {
char buffer[80];
- ALOGV("Opening device: %s", devicePath);
+ ALOGV("Opening device: %s", devicePath.c_str());
- int fd = open(devicePath, O_RDWR | O_CLOEXEC | O_NONBLOCK);
+ int fd = open(devicePath.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);
if (fd < 0) {
- ALOGE("could not open %s, %s\n", devicePath, strerror(errno));
+ ALOGE("could not open %s, %s\n", devicePath.c_str(), strerror(errno));
return -1;
}
@@ -1230,7 +1230,7 @@
// Get device name.
if (ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
- ALOGE("Could not get device name for %s: %s", devicePath, strerror(errno));
+ ALOGE("Could not get device name for %s: %s", devicePath.c_str(), strerror(errno));
} else {
buffer[sizeof(buffer) - 1] = '\0';
identifier.name = buffer;
@@ -1240,7 +1240,7 @@
for (size_t i = 0; i < mExcludedDevices.size(); i++) {
const std::string& item = mExcludedDevices[i];
if (identifier.name == item) {
- ALOGI("ignoring event id %s driver %s\n", devicePath, item.c_str());
+ ALOGI("ignoring event id %s driver %s\n", devicePath.c_str(), item.c_str());
close(fd);
return -1;
}
@@ -1249,7 +1249,7 @@
// Get device driver version.
int driverVersion;
if (ioctl(fd, EVIOCGVERSION, &driverVersion)) {
- ALOGE("could not get driver version for %s, %s\n", devicePath, strerror(errno));
+ ALOGE("could not get driver version for %s, %s\n", devicePath.c_str(), strerror(errno));
close(fd);
return -1;
}
@@ -1257,7 +1257,7 @@
// Get device identifier.
struct input_id inputId;
if (ioctl(fd, EVIOCGID, &inputId)) {
- ALOGE("could not get device input id for %s, %s\n", devicePath, strerror(errno));
+ ALOGE("could not get device input id for %s, %s\n", devicePath.c_str(), strerror(errno));
close(fd);
return -1;
}
@@ -1289,7 +1289,7 @@
int32_t deviceId = mNextDeviceId++;
Device* device = new Device(fd, deviceId, devicePath, identifier);
- ALOGV("add device %d: %s\n", deviceId, devicePath);
+ ALOGV("add device %d: %s\n", deviceId, devicePath.c_str());
ALOGV(" bus: %04x\n"
" vendor %04x\n"
" product %04x\n"
@@ -1446,7 +1446,7 @@
// If the device isn't recognized as something we handle, don't monitor it.
if (device->classes == 0) {
- ALOGV("Dropping device: id=%d, path='%s', name='%s'", deviceId, devicePath,
+ ALOGV("Dropping device: id=%d, path='%s', name='%s'", deviceId, devicePath.c_str(),
device->identifier.name.c_str());
delete device;
return -1;
@@ -1492,7 +1492,7 @@
ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
"configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, ",
- deviceId, fd, devicePath, device->identifier.name.c_str(), device->classes,
+ deviceId, fd, devicePath.c_str(), device->identifier.name.c_str(), device->classes,
device->configurationFile.c_str(), device->keyMap.keyLayoutFile.c_str(),
device->keyMap.keyCharacterMapFile.c_str(), toString(mBuiltInKeyboardId == deviceId));
@@ -1726,13 +1726,13 @@
return NAME_NOT_FOUND;
}
-void EventHub::closeDeviceByPathLocked(const char* devicePath) {
+void EventHub::closeDeviceByPathLocked(const std::string& devicePath) {
Device* device = getDeviceByPathLocked(devicePath);
if (device) {
closeDeviceLocked(device);
return;
}
- ALOGV("Remove device: %s not found, device may already have been removed.", devicePath);
+ ALOGV("Remove device: %s not found, device may already have been removed.", devicePath.c_str());
}
/**
@@ -1837,16 +1837,16 @@
event = (struct inotify_event*)(event_buf + event_pos);
if (event->len) {
if (event->wd == mInputWd) {
- std::string filename = StringPrintf("%s/%s", DEVICE_PATH, event->name);
+ std::string filename = std::string(DEVICE_PATH) + "/" + event->name;
if (event->mask & IN_CREATE) {
- openDeviceLocked(filename.c_str());
+ openDeviceLocked(filename);
} else {
ALOGI("Removing device '%s' due to inotify event\n", filename.c_str());
- closeDeviceByPathLocked(filename.c_str());
+ closeDeviceByPathLocked(filename);
}
} else if (event->wd == mVideoWd) {
if (isV4lTouchNode(event->name)) {
- std::string filename = StringPrintf("%s/%s", VIDEO_DEVICE_PATH, event->name);
+ std::string filename = std::string(VIDEO_DEVICE_PATH) + "/" + event->name;
if (event->mask & IN_CREATE) {
openVideoDeviceLocked(filename);
} else {
@@ -1865,24 +1865,10 @@
return 0;
}
-status_t EventHub::scanDirLocked(const char* dirname) {
- char devname[PATH_MAX];
- char* filename;
- DIR* dir;
- struct dirent* de;
- dir = opendir(dirname);
- if (dir == nullptr) return -1;
- strcpy(devname, dirname);
- filename = devname + strlen(devname);
- *filename++ = '/';
- while ((de = readdir(dir))) {
- if (de->d_name[0] == '.' &&
- (de->d_name[1] == '\0' || (de->d_name[1] == '.' && de->d_name[2] == '\0')))
- continue;
- strcpy(filename, de->d_name);
- openDeviceLocked(devname);
+status_t EventHub::scanDirLocked(const std::string& dirname) {
+ for (const auto& entry : std::filesystem::directory_iterator(dirname)) {
+ openDeviceLocked(entry.path());
}
- closedir(dir);
return 0;
}
@@ -1890,22 +1876,12 @@
* Look for all dirname/v4l-touch* devices, and open them.
*/
status_t EventHub::scanVideoDirLocked(const std::string& dirname) {
- DIR* dir;
- struct dirent* de;
- dir = opendir(dirname.c_str());
- if (!dir) {
- ALOGE("Could not open video directory %s", dirname.c_str());
- return BAD_VALUE;
- }
-
- while ((de = readdir(dir))) {
- const char* name = de->d_name;
- if (isV4lTouchNode(name)) {
- ALOGI("Found touch video device %s", name);
- openVideoDeviceLocked(dirname + "/" + name);
+ for (const auto& entry : std::filesystem::directory_iterator(dirname)) {
+ if (isV4lTouchNode(entry.path())) {
+ ALOGI("Found touch video device %s", entry.path().c_str());
+ openVideoDeviceLocked(entry.path());
}
}
- closedir(dir);
return OK;
}
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index c17f3a1..ee62c9a 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -373,13 +373,13 @@
}
};
- status_t openDeviceLocked(const char* devicePath);
+ status_t openDeviceLocked(const std::string& devicePath);
void openVideoDeviceLocked(const std::string& devicePath);
void createVirtualKeyboardLocked();
void addDeviceLocked(Device* device);
void assignDescriptorLocked(InputDeviceIdentifier& identifier);
- void closeDeviceByPathLocked(const char* devicePath);
+ void closeDeviceByPathLocked(const std::string& devicePath);
void closeVideoDeviceByPathLocked(const std::string& devicePath);
void closeDeviceLocked(Device* device);
void closeAllDevicesLocked();
@@ -396,14 +396,14 @@
status_t unregisterDeviceFromEpollLocked(Device* device);
void unregisterVideoDeviceFromEpollLocked(const TouchVideoDevice& videoDevice);
- status_t scanDirLocked(const char* dirname);
+ status_t scanDirLocked(const std::string& dirname);
status_t scanVideoDirLocked(const std::string& dirname);
void scanDevicesLocked();
status_t readNotifyLocked();
Device* getDeviceByDescriptorLocked(const std::string& descriptor) const;
Device* getDeviceLocked(int32_t deviceId) const;
- Device* getDeviceByPathLocked(const char* devicePath) const;
+ Device* getDeviceByPathLocked(const std::string& devicePath) const;
/**
* Look through all available fd's (both for input devices and for video devices),
* and return the device pointer.
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index eae0963..eb9ac68 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -44,5 +44,8 @@
"frameworks/native/libs/input",
],
},
+ static_libs: [
+ "libc++fs"
+ ],
require_root: true,
}
diff --git a/services/inputflinger/tests/InputFlingerService_test.cpp b/services/inputflinger/tests/InputFlingerService_test.cpp
index fd3f562..6d50519 100644
--- a/services/inputflinger/tests/InputFlingerService_test.cpp
+++ b/services/inputflinger/tests/InputFlingerService_test.cpp
@@ -402,7 +402,9 @@
} else {
android::ProcessState::self()->startThreadPool();
::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
+ int result = RUN_ALL_TESTS();
+ kill(forkPid, SIGKILL);
+ return result;
}
return 0;
}
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 1156f55..89284f2 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -324,9 +324,6 @@
}
uint64_t bufferID = mQueueItems[0].mGraphicBuffer->getId();
- mFlinger->mFrameTracer->traceFence(layerId, bufferID, currentFrameNumber,
- mQueueItems[0].mFenceTime,
- FrameTracer::FrameEvent::ACQUIRE_FENCE);
mFlinger->mTimeStats->setLatchTime(layerId, currentFrameNumber, latchTime);
mFlinger->mFrameTracer->traceTimestamp(layerId, bufferID, currentFrameNumber, latchTime,
FrameTracer::FrameEvent::LATCH);
@@ -393,8 +390,12 @@
void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
const int32_t layerId = getSequence();
- mFlinger->mFrameTracer->traceTimestamp(layerId, item.mGraphicBuffer->getId(), item.mFrameNumber,
- systemTime(), FrameTracer::FrameEvent::QUEUE);
+ const uint64_t bufferId = item.mGraphicBuffer->getId();
+ mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, item.mFrameNumber, systemTime(),
+ FrameTracer::FrameEvent::QUEUE);
+ mFlinger->mFrameTracer->traceFence(layerId, bufferId, item.mFrameNumber,
+ std::make_shared<FenceTime>(item.mFence),
+ FrameTracer::FrameEvent::ACQUIRE_FENCE);
ATRACE_CALL();
// Add this buffer from our internal queue tracker
@@ -460,8 +461,12 @@
}
const int32_t layerId = getSequence();
- mFlinger->mFrameTracer->traceTimestamp(layerId, item.mGraphicBuffer->getId(), item.mFrameNumber,
- systemTime(), FrameTracer::FrameEvent::QUEUE);
+ const uint64_t bufferId = item.mGraphicBuffer->getId();
+ mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, item.mFrameNumber, systemTime(),
+ FrameTracer::FrameEvent::QUEUE);
+ mFlinger->mFrameTracer->traceFence(layerId, bufferId, item.mFrameNumber,
+ std::make_shared<FenceTime>(item.mFence),
+ FrameTracer::FrameEvent::ACQUIRE_FENCE);
mConsumer->onBufferAvailable(item);
}
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 8cfb908..67becab 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2385,8 +2385,8 @@
}
ui::Transform t = getTransform();
- const float xScale = t.sx();
- const float yScale = t.sy();
+ const float xScale = t.dsdx();
+ const float yScale = t.dsdy();
int32_t xSurfaceInset = info.surfaceInset;
int32_t ySurfaceInset = info.surfaceInset;
if (xScale != 1.0f || yScale != 1.0f) {
diff --git a/services/vibratorservice/VibratorHalController.cpp b/services/vibratorservice/VibratorHalController.cpp
index 896c162..03e51ae 100644
--- a/services/vibratorservice/VibratorHalController.cpp
+++ b/services/vibratorservice/VibratorHalController.cpp
@@ -47,105 +47,77 @@
static constexpr int MAX_RETRIES = 1;
-template <typename T>
-using hal_connect_fn = std::function<sp<T>()>;
-
-template <typename T>
-sp<T> connectToHal(bool* halExists, const hal_connect_fn<T>& connectFn, const char* halName) {
- if (!*halExists) {
+std::shared_ptr<HalWrapper> HalConnector::connect(std::shared_ptr<CallbackScheduler> scheduler) {
+ static bool gHalExists = true;
+ if (!gHalExists) {
+ // We already tried to connect to all of the vibrator HAL versions and none was available.
return nullptr;
}
- sp<T> hal = connectFn();
- if (hal) {
- ALOGV("Successfully connected to Vibrator HAL %s service.", halName);
- } else {
- ALOGV("Vibrator HAL %s service not available.", halName);
- *halExists = false;
- }
- return hal;
-}
-sp<Aidl::IVibrator> connectToAidl() {
- static bool gHalExists = true;
- static hal_connect_fn<Aidl::IVibrator> connectFn = []() {
- return waitForVintfService<Aidl::IVibrator>();
- };
- return connectToHal(&gHalExists, connectFn, "AIDL");
-}
-
-sp<V1_0::IVibrator> connectToHidl() {
- static bool gHalExists = true;
- static hal_connect_fn<V1_0::IVibrator> connectFn = []() {
- return V1_0::IVibrator::getService();
- };
- return connectToHal(&gHalExists, connectFn, "v1.0");
-}
-
-// -------------------------------------------------------------------------------------------------
-
-std::shared_ptr<HalWrapper> HalConnector::connect(std::shared_ptr<CallbackScheduler> scheduler) {
- sp<Aidl::IVibrator> aidlHal = connectToAidl();
+ sp<Aidl::IVibrator> aidlHal = waitForVintfService<Aidl::IVibrator>();
if (aidlHal) {
+ ALOGV("Successfully connected to Vibrator HAL AIDL service.");
return std::make_shared<AidlHalWrapper>(std::move(scheduler), aidlHal);
}
- sp<V1_0::IVibrator> halV1_0 = connectToHidl();
+
+ sp<V1_0::IVibrator> halV1_0 = V1_0::IVibrator::getService();
if (halV1_0 == nullptr) {
- // No Vibrator HAL service available.
+ ALOGV("Vibrator HAL service not available.");
+ gHalExists = false;
return nullptr;
}
+
sp<V1_3::IVibrator> halV1_3 = V1_3::IVibrator::castFrom(halV1_0);
if (halV1_3) {
- ALOGV("Successfully converted to Vibrator HAL v1.3 service.");
+ ALOGV("Successfully connected to Vibrator HAL v1.3 service.");
return std::make_shared<HidlHalWrapperV1_3>(std::move(scheduler), halV1_3);
}
sp<V1_2::IVibrator> halV1_2 = V1_2::IVibrator::castFrom(halV1_0);
if (halV1_2) {
- ALOGV("Successfully converted to Vibrator HAL v1.2 service.");
+ ALOGV("Successfully connected to Vibrator HAL v1.2 service.");
return std::make_shared<HidlHalWrapperV1_2>(std::move(scheduler), halV1_2);
}
sp<V1_1::IVibrator> halV1_1 = V1_1::IVibrator::castFrom(halV1_0);
if (halV1_1) {
- ALOGV("Successfully converted to Vibrator HAL v1.1 service.");
+ ALOGV("Successfully connected to Vibrator HAL v1.1 service.");
return std::make_shared<HidlHalWrapperV1_1>(std::move(scheduler), halV1_1);
}
+ ALOGV("Successfully connected to Vibrator HAL v1.0 service.");
return std::make_shared<HidlHalWrapperV1_0>(std::move(scheduler), halV1_0);
}
// -------------------------------------------------------------------------------------------------
-std::shared_ptr<HalWrapper> HalController::initHal() {
- std::lock_guard<std::mutex> lock(mConnectedHalMutex);
- if (mConnectedHal == nullptr) {
- mConnectedHal = mHalConnector->connect(mCallbackScheduler);
- }
- return mConnectedHal;
-}
-
template <typename T>
HalResult<T> HalController::processHalResult(HalResult<T> result, const char* functionName) {
if (result.isFailed()) {
ALOGE("%s failed: Vibrator HAL not available", functionName);
std::lock_guard<std::mutex> lock(mConnectedHalMutex);
- // Drop HAL handle. This will force future api calls to reconnect.
- mConnectedHal = nullptr;
+ mConnectedHal->tryReconnect();
}
return result;
}
template <typename T>
HalResult<T> HalController::apply(HalController::hal_fn<T>& halFn, const char* functionName) {
- std::shared_ptr<HalWrapper> hal = initHal();
- if (hal == nullptr) {
- ALOGV("Skipped %s because Vibrator HAL is not available", functionName);
- return HalResult<T>::unsupported();
+ std::shared_ptr<HalWrapper> hal = nullptr;
+ {
+ std::lock_guard<std::mutex> lock(mConnectedHalMutex);
+ if (mConnectedHal == nullptr) {
+ // Init was never called, so connect to HAL for the first time during this call.
+ mConnectedHal = mHalConnector->connect(mCallbackScheduler);
+
+ if (mConnectedHal == nullptr) {
+ ALOGV("Skipped %s because Vibrator HAL is not available", functionName);
+ return HalResult<T>::unsupported();
+ }
+ }
+ hal = mConnectedHal;
}
HalResult<T> ret = processHalResult(halFn(hal), functionName);
for (int i = 0; i < MAX_RETRIES && ret.isFailed(); i++) {
- hal = initHal();
- if (hal) {
- ret = processHalResult(halFn(hal), functionName);
- }
+ ret = processHalResult(halFn(hal), functionName);
}
return ret;
@@ -153,11 +125,27 @@
// -------------------------------------------------------------------------------------------------
+void HalController::init() {
+ std::lock_guard<std::mutex> lock(mConnectedHalMutex);
+ if (mConnectedHal == nullptr) {
+ mConnectedHal = mHalConnector->connect(mCallbackScheduler);
+ }
+}
+
HalResult<void> HalController::ping() {
hal_fn<void> pingFn = [](std::shared_ptr<HalWrapper> hal) { return hal->ping(); };
return apply(pingFn, "ping");
}
+void HalController::tryReconnect() {
+ std::lock_guard<std::mutex> lock(mConnectedHalMutex);
+ if (mConnectedHal == nullptr) {
+ mConnectedHal = mHalConnector->connect(mCallbackScheduler);
+ } else {
+ mConnectedHal->tryReconnect();
+ }
+}
+
HalResult<void> HalController::on(milliseconds timeout,
const std::function<void()>& completionCallback) {
hal_fn<void> onFn = [&](std::shared_ptr<HalWrapper> hal) {
diff --git a/services/vibratorservice/VibratorHalWrapper.cpp b/services/vibratorservice/VibratorHalWrapper.cpp
index 94db538..9d219ff 100644
--- a/services/vibratorservice/VibratorHalWrapper.cpp
+++ b/services/vibratorservice/VibratorHalWrapper.cpp
@@ -149,8 +149,16 @@
// -------------------------------------------------------------------------------------------------
HalResult<void> AidlHalWrapper::ping() {
- return IInterface::asBinder(mHandle)->pingBinder() ? HalResult<void>::ok()
- : HalResult<void>::failed();
+ return IInterface::asBinder(getHal())->pingBinder() ? HalResult<void>::ok()
+ : HalResult<void>::failed();
+}
+
+void AidlHalWrapper::tryReconnect() {
+ sp<Aidl::IVibrator> newHandle = checkVintfService<Aidl::IVibrator>();
+ if (newHandle) {
+ std::lock_guard<std::mutex> lock(mHandleMutex);
+ mHandle = std::move(newHandle);
+ }
}
HalResult<void> AidlHalWrapper::on(milliseconds timeout,
@@ -160,7 +168,7 @@
static_cast<int32_t>(capabilities.value() & Capabilities::ON_CALLBACK);
auto cb = supportsCallback ? new HalCallbackWrapper(completionCallback) : nullptr;
- auto ret = HalResult<void>::fromStatus(mHandle->on(timeout.count(), cb));
+ auto ret = HalResult<void>::fromStatus(getHal()->on(timeout.count(), cb));
if (!supportsCallback && ret.isOk()) {
mCallbackScheduler->schedule(completionCallback, timeout);
}
@@ -169,24 +177,24 @@
}
HalResult<void> AidlHalWrapper::off() {
- return HalResult<void>::fromStatus(mHandle->off());
+ return HalResult<void>::fromStatus(getHal()->off());
}
HalResult<void> AidlHalWrapper::setAmplitude(int32_t amplitude) {
float convertedAmplitude = static_cast<float>(amplitude) / std::numeric_limits<uint8_t>::max();
- return HalResult<void>::fromStatus(mHandle->setAmplitude(convertedAmplitude));
+ return HalResult<void>::fromStatus(getHal()->setAmplitude(convertedAmplitude));
}
HalResult<void> AidlHalWrapper::setExternalControl(bool enabled) {
- return HalResult<void>::fromStatus(mHandle->setExternalControl(enabled));
+ return HalResult<void>::fromStatus(getHal()->setExternalControl(enabled));
}
HalResult<void> AidlHalWrapper::alwaysOnEnable(int32_t id, Effect effect, EffectStrength strength) {
- return HalResult<void>::fromStatus(mHandle->alwaysOnEnable(id, effect, strength));
+ return HalResult<void>::fromStatus(getHal()->alwaysOnEnable(id, effect, strength));
}
HalResult<void> AidlHalWrapper::alwaysOnDisable(int32_t id) {
- return HalResult<void>::fromStatus(mHandle->alwaysOnDisable(id));
+ return HalResult<void>::fromStatus(getHal()->alwaysOnDisable(id));
}
HalResult<Capabilities> AidlHalWrapper::getCapabilities() {
@@ -210,7 +218,7 @@
auto cb = supportsCallback ? new HalCallbackWrapper(completionCallback) : nullptr;
int32_t lengthMs;
- auto result = mHandle->perform(effect, strength, cb, &lengthMs);
+ auto result = getHal()->perform(effect, strength, cb, &lengthMs);
milliseconds length = milliseconds(lengthMs);
auto ret = HalResult<milliseconds>::fromStatus(result, length);
@@ -226,31 +234,47 @@
const std::function<void()>& completionCallback) {
// This method should always support callbacks, so no need to double check.
auto cb = new HalCallbackWrapper(completionCallback);
- return HalResult<void>::fromStatus(mHandle->compose(primitiveEffects, cb));
+ return HalResult<void>::fromStatus(getHal()->compose(primitiveEffects, cb));
}
HalResult<Capabilities> AidlHalWrapper::getCapabilitiesInternal() {
int32_t capabilities = 0;
- auto result = mHandle->getCapabilities(&capabilities);
+ auto result = getHal()->getCapabilities(&capabilities);
return HalResult<Capabilities>::fromStatus(result, static_cast<Capabilities>(capabilities));
}
HalResult<std::vector<Effect>> AidlHalWrapper::getSupportedEffectsInternal() {
std::vector<Effect> supportedEffects;
- auto result = mHandle->getSupportedEffects(&supportedEffects);
+ auto result = getHal()->getSupportedEffects(&supportedEffects);
return HalResult<std::vector<Effect>>::fromStatus(result, supportedEffects);
}
+sp<Aidl::IVibrator> AidlHalWrapper::getHal() {
+ std::lock_guard<std::mutex> lock(mHandleMutex);
+ return mHandle;
+}
+
// -------------------------------------------------------------------------------------------------
-HalResult<void> HidlHalWrapperV1_0::ping() {
- auto result = mHandleV1_0->ping();
+template <typename I>
+HalResult<void> HidlHalWrapper<I>::ping() {
+ auto result = getHal()->ping();
return HalResult<void>::fromReturn(result);
}
-HalResult<void> HidlHalWrapperV1_0::on(milliseconds timeout,
- const std::function<void()>& completionCallback) {
- auto result = mHandleV1_0->on(timeout.count());
+template <typename I>
+void HidlHalWrapper<I>::tryReconnect() {
+ sp<I> newHandle = I::tryGetService();
+ if (newHandle) {
+ std::lock_guard<std::mutex> lock(mHandleMutex);
+ mHandle = std::move(newHandle);
+ }
+}
+
+template <typename I>
+HalResult<void> HidlHalWrapper<I>::on(milliseconds timeout,
+ const std::function<void()>& completionCallback) {
+ auto result = getHal()->on(timeout.count());
auto ret = HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
if (ret.isOk()) {
mCallbackScheduler->schedule(completionCallback, timeout);
@@ -258,69 +282,68 @@
return ret;
}
-HalResult<void> HidlHalWrapperV1_0::off() {
- auto result = mHandleV1_0->off();
+template <typename I>
+HalResult<void> HidlHalWrapper<I>::off() {
+ auto result = getHal()->off();
return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
}
-HalResult<void> HidlHalWrapperV1_0::setAmplitude(int32_t amplitude) {
- auto result = mHandleV1_0->setAmplitude(static_cast<uint8_t>(amplitude));
+template <typename I>
+HalResult<void> HidlHalWrapper<I>::setAmplitude(int32_t amplitude) {
+ auto result = getHal()->setAmplitude(static_cast<uint8_t>(amplitude));
return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
}
-HalResult<void> HidlHalWrapperV1_0::setExternalControl(bool) {
+template <typename I>
+HalResult<void> HidlHalWrapper<I>::setExternalControl(bool) {
ALOGV("Skipped setExternalControl because Vibrator HAL does not support it");
return HalResult<void>::unsupported();
}
-HalResult<void> HidlHalWrapperV1_0::alwaysOnEnable(int32_t, Effect, EffectStrength) {
+template <typename I>
+HalResult<void> HidlHalWrapper<I>::alwaysOnEnable(int32_t, Effect, EffectStrength) {
ALOGV("Skipped alwaysOnEnable because Vibrator HAL AIDL is not available");
return HalResult<void>::unsupported();
}
-HalResult<void> HidlHalWrapperV1_0::alwaysOnDisable(int32_t) {
+template <typename I>
+HalResult<void> HidlHalWrapper<I>::alwaysOnDisable(int32_t) {
ALOGV("Skipped alwaysOnDisable because Vibrator HAL AIDL is not available");
return HalResult<void>::unsupported();
}
-HalResult<Capabilities> HidlHalWrapperV1_0::getCapabilities() {
+template <typename I>
+HalResult<Capabilities> HidlHalWrapper<I>::getCapabilities() {
std::lock_guard<std::mutex> lock(mCapabilitiesMutex);
- return loadCached<Capabilities>(std::bind(&HidlHalWrapperV1_0::getCapabilitiesInternal, this),
+ return loadCached<Capabilities>(std::bind(&HidlHalWrapper<I>::getCapabilitiesInternal, this),
mCapabilities);
}
-HalResult<std::vector<Effect>> HidlHalWrapperV1_0::getSupportedEffects() {
+template <typename I>
+HalResult<std::vector<Effect>> HidlHalWrapper<I>::getSupportedEffects() {
ALOGV("Skipped getSupportedEffects because Vibrator HAL AIDL is not available");
return HalResult<std::vector<Effect>>::unsupported();
}
-HalResult<milliseconds> HidlHalWrapperV1_0::performEffect(
- Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
- if (isStaticCastValid<V1_0::Effect>(effect)) {
- return performInternalV1_0(effect, strength, completionCallback);
- }
-
- ALOGV("Skipped performEffect because Vibrator HAL does not support effect %s",
- Aidl::toString(effect).c_str());
- return HalResult<milliseconds>::unsupported();
-}
-
-HalResult<void> HidlHalWrapperV1_0::performComposedEffect(const std::vector<CompositeEffect>&,
- const std::function<void()>&) {
+template <typename I>
+HalResult<void> HidlHalWrapper<I>::performComposedEffect(const std::vector<CompositeEffect>&,
+ const std::function<void()>&) {
ALOGV("Skipped composed effect because Vibrator HAL AIDL is not available");
return HalResult<void>::unsupported();
}
-HalResult<Capabilities> HidlHalWrapperV1_0::getCapabilitiesInternal() {
- hardware::Return<bool> result = mHandleV1_0->supportsAmplitudeControl();
+template <typename I>
+HalResult<Capabilities> HidlHalWrapper<I>::getCapabilitiesInternal() {
+ hardware::Return<bool> result = getHal()->supportsAmplitudeControl();
Capabilities capabilities =
result.withDefault(false) ? Capabilities::AMPLITUDE_CONTROL : Capabilities::NONE;
return HalResult<Capabilities>::fromReturn(result, capabilities);
}
-template <class I, class T>
-HalResult<milliseconds> HidlHalWrapperV1_0::performInternal(
- perform_fn<I, T> performFn, sp<I> handle, T effect, EffectStrength strength,
+template <typename I>
+template <typename T>
+HalResult<milliseconds> HidlHalWrapper<I>::performInternal(
+ perform_fn<T> performFn, sp<I> handle, T effect, EffectStrength strength,
const std::function<void()>& completionCallback) {
V1_0::Status status;
int32_t lengthMs;
@@ -341,10 +364,24 @@
return ret;
}
-HalResult<milliseconds> HidlHalWrapperV1_0::performInternalV1_0(
+template <typename I>
+sp<I> HidlHalWrapper<I>::getHal() {
+ std::lock_guard<std::mutex> lock(mHandleMutex);
+ return mHandle;
+}
+
+// -------------------------------------------------------------------------------------------------
+
+HalResult<milliseconds> HidlHalWrapperV1_0::performEffect(
Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
- V1_0::Effect e = static_cast<V1_0::Effect>(effect);
- return performInternal(&V1_0::IVibrator::perform, mHandleV1_0, e, strength, completionCallback);
+ if (isStaticCastValid<V1_0::Effect>(effect)) {
+ return performInternal(&V1_0::IVibrator::perform, getHal(),
+ static_cast<V1_0::Effect>(effect), strength, completionCallback);
+ }
+
+ ALOGV("Skipped performEffect because Vibrator HAL does not support effect %s",
+ Aidl::toString(effect).c_str());
+ return HalResult<milliseconds>::unsupported();
}
// -------------------------------------------------------------------------------------------------
@@ -352,10 +389,12 @@
HalResult<milliseconds> HidlHalWrapperV1_1::performEffect(
Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
if (isStaticCastValid<V1_0::Effect>(effect)) {
- return performInternalV1_0(effect, strength, completionCallback);
+ return performInternal(&V1_1::IVibrator::perform, getHal(),
+ static_cast<V1_0::Effect>(effect), strength, completionCallback);
}
if (isStaticCastValid<V1_1::Effect_1_1>(effect)) {
- return performInternalV1_1(effect, strength, completionCallback);
+ return performInternal(&V1_1::IVibrator::perform_1_1, getHal(),
+ static_cast<V1_1::Effect_1_1>(effect), strength, completionCallback);
}
ALOGV("Skipped performEffect because Vibrator HAL does not support effect %s",
@@ -363,25 +402,21 @@
return HalResult<milliseconds>::unsupported();
}
-HalResult<milliseconds> HidlHalWrapperV1_1::performInternalV1_1(
- Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
- V1_1::Effect_1_1 e = static_cast<V1_1::Effect_1_1>(effect);
- return performInternal(&V1_1::IVibrator::perform_1_1, mHandleV1_1, e, strength,
- completionCallback);
-}
-
// -------------------------------------------------------------------------------------------------
HalResult<milliseconds> HidlHalWrapperV1_2::performEffect(
Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
if (isStaticCastValid<V1_0::Effect>(effect)) {
- return performInternalV1_0(effect, strength, completionCallback);
+ return performInternal(&V1_2::IVibrator::perform, getHal(),
+ static_cast<V1_0::Effect>(effect), strength, completionCallback);
}
if (isStaticCastValid<V1_1::Effect_1_1>(effect)) {
- return performInternalV1_1(effect, strength, completionCallback);
+ return performInternal(&V1_2::IVibrator::perform_1_1, getHal(),
+ static_cast<V1_1::Effect_1_1>(effect), strength, completionCallback);
}
if (isStaticCastValid<V1_2::Effect>(effect)) {
- return performInternalV1_2(effect, strength, completionCallback);
+ return performInternal(&V1_2::IVibrator::perform_1_2, getHal(),
+ static_cast<V1_2::Effect>(effect), strength, completionCallback);
}
ALOGV("Skipped performEffect because Vibrator HAL does not support effect %s",
@@ -389,33 +424,30 @@
return HalResult<milliseconds>::unsupported();
}
-HalResult<milliseconds> HidlHalWrapperV1_2::performInternalV1_2(
- Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
- V1_2::Effect e = static_cast<V1_2::Effect>(effect);
- return performInternal(&V1_2::IVibrator::perform_1_2, mHandleV1_2, e, strength,
- completionCallback);
-}
-
// -------------------------------------------------------------------------------------------------
HalResult<void> HidlHalWrapperV1_3::setExternalControl(bool enabled) {
- auto result = mHandleV1_3->setExternalControl(static_cast<uint32_t>(enabled));
+ auto result = getHal()->setExternalControl(static_cast<uint32_t>(enabled));
return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
}
HalResult<milliseconds> HidlHalWrapperV1_3::performEffect(
Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
if (isStaticCastValid<V1_0::Effect>(effect)) {
- return performInternalV1_0(effect, strength, completionCallback);
+ return performInternal(&V1_3::IVibrator::perform, getHal(),
+ static_cast<V1_0::Effect>(effect), strength, completionCallback);
}
if (isStaticCastValid<V1_1::Effect_1_1>(effect)) {
- return performInternalV1_1(effect, strength, completionCallback);
+ return performInternal(&V1_3::IVibrator::perform_1_1, getHal(),
+ static_cast<V1_1::Effect_1_1>(effect), strength, completionCallback);
}
if (isStaticCastValid<V1_2::Effect>(effect)) {
- return performInternalV1_2(effect, strength, completionCallback);
+ return performInternal(&V1_3::IVibrator::perform_1_2, getHal(),
+ static_cast<V1_2::Effect>(effect), strength, completionCallback);
}
if (isStaticCastValid<V1_3::Effect>(effect)) {
- return performInternalV1_3(effect, strength, completionCallback);
+ return performInternal(&V1_3::IVibrator::perform_1_3, getHal(),
+ static_cast<V1_3::Effect>(effect), strength, completionCallback);
}
ALOGV("Skipped performEffect because Vibrator HAL does not support effect %s",
@@ -424,23 +456,23 @@
}
HalResult<Capabilities> HidlHalWrapperV1_3::getCapabilitiesInternal() {
- HalResult<Capabilities> parentResult = HidlHalWrapperV1_2::getCapabilitiesInternal();
- if (!parentResult.isOk()) {
- // Loading for previous HAL versions already failed, so propagate failure.
- return parentResult;
+ sp<V1_3::IVibrator> hal = getHal();
+ auto amplitudeResult = hal->supportsAmplitudeControl();
+ if (!amplitudeResult.isOk()) {
+ return HalResult<Capabilities>::failed();
}
- Capabilities capabilities = parentResult.value();
- auto result = mHandleV1_3->supportsExternalControl();
- capabilities |= result.withDefault(false) ? Capabilities::EXTERNAL_CONTROL : Capabilities::NONE;
- return HalResult<Capabilities>::fromReturn(result, capabilities);
-}
+ auto externalControlResult = hal->supportsExternalControl();
+ Capabilities capabilities = Capabilities::NONE;
-HalResult<milliseconds> HidlHalWrapperV1_3::performInternalV1_3(
- Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
- V1_3::Effect e = static_cast<V1_3::Effect>(effect);
- return performInternal(&V1_3::IVibrator::perform_1_3, mHandleV1_3, e, strength,
- completionCallback);
+ if (amplitudeResult.withDefault(false)) {
+ capabilities |= Capabilities::AMPLITUDE_CONTROL;
+ }
+ if (externalControlResult.withDefault(false)) {
+ capabilities |= Capabilities::EXTERNAL_CONTROL;
+ }
+
+ return HalResult<Capabilities>::fromReturn(externalControlResult, capabilities);
}
// -------------------------------------------------------------------------------------------------
diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalController.h b/services/vibratorservice/include/vibratorservice/VibratorHalController.h
index 1fb7d05..daf2c8c 100644
--- a/services/vibratorservice/include/vibratorservice/VibratorHalController.h
+++ b/services/vibratorservice/include/vibratorservice/VibratorHalController.h
@@ -51,7 +51,10 @@
mConnectedHal(nullptr) {}
virtual ~HalController() = default;
+ void init();
+
HalResult<void> ping() final override;
+ void tryReconnect() final override;
HalResult<void> on(std::chrono::milliseconds timeout,
const std::function<void()>& completionCallback) final override;
@@ -81,8 +84,6 @@
// Shared pointer to allow local copies to be used by different threads.
std::shared_ptr<HalWrapper> mConnectedHal GUARDED_BY(mConnectedHalMutex);
- std::shared_ptr<HalWrapper> initHal();
-
template <typename T>
HalResult<T> processHalResult(HalResult<T> result, const char* functionName);
diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
index 5e3c275..a4fa869 100644
--- a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
+++ b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
@@ -20,6 +20,7 @@
#include <android-base/thread_annotations.h>
#include <android/hardware/vibrator/1.3/IVibrator.h>
#include <android/hardware/vibrator/IVibrator.h>
+#include <binder/IServiceManager.h>
#include <vibratorservice/VibratorCallbackScheduler.h>
@@ -131,6 +132,7 @@
virtual ~HalWrapper() = default;
virtual HalResult<void> ping() = 0;
+ virtual void tryReconnect() = 0;
virtual HalResult<void> on(std::chrono::milliseconds timeout,
const std::function<void()>& completionCallback) = 0;
@@ -167,34 +169,36 @@
: HalWrapper(std::move(scheduler)), mHandle(std::move(handle)) {}
virtual ~AidlHalWrapper() = default;
- virtual HalResult<void> ping() override;
+ HalResult<void> ping() override final;
+ void tryReconnect() override final;
- virtual HalResult<void> on(std::chrono::milliseconds timeout,
- const std::function<void()>& completionCallback) override;
- virtual HalResult<void> off() override;
+ HalResult<void> on(std::chrono::milliseconds timeout,
+ const std::function<void()>& completionCallback) override final;
+ HalResult<void> off() override final;
- virtual HalResult<void> setAmplitude(int32_t amplitude) override;
- virtual HalResult<void> setExternalControl(bool enabled) override;
+ HalResult<void> setAmplitude(int32_t amplitude) override final;
+ HalResult<void> setExternalControl(bool enabled) override final;
- virtual HalResult<void> alwaysOnEnable(int32_t id, hardware::vibrator::Effect effect,
- hardware::vibrator::EffectStrength strength) override;
- virtual HalResult<void> alwaysOnDisable(int32_t id) override;
+ HalResult<void> alwaysOnEnable(int32_t id, hardware::vibrator::Effect effect,
+ hardware::vibrator::EffectStrength strength) override final;
+ HalResult<void> alwaysOnDisable(int32_t id) override final;
- virtual HalResult<Capabilities> getCapabilities() override;
- virtual HalResult<std::vector<hardware::vibrator::Effect>> getSupportedEffects() override;
+ HalResult<Capabilities> getCapabilities() override final;
+ HalResult<std::vector<hardware::vibrator::Effect>> getSupportedEffects() override final;
- virtual HalResult<std::chrono::milliseconds> performEffect(
+ HalResult<std::chrono::milliseconds> performEffect(
hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
- const std::function<void()>& completionCallback) override;
+ const std::function<void()>& completionCallback) override final;
- virtual HalResult<void> performComposedEffect(
+ HalResult<void> performComposedEffect(
const std::vector<hardware::vibrator::CompositeEffect>& primitiveEffects,
- const std::function<void()>& completionCallback) override;
+ const std::function<void()>& completionCallback) override final;
private:
- const sp<hardware::vibrator::IVibrator> mHandle;
+ std::mutex mHandleMutex;
std::mutex mCapabilitiesMutex;
std::mutex mSupportedEffectsMutex;
+ sp<hardware::vibrator::IVibrator> mHandle GUARDED_BY(mHandleMutex);
std::optional<Capabilities> mCapabilities GUARDED_BY(mCapabilitiesMutex);
std::optional<std::vector<hardware::vibrator::Effect>> mSupportedEffects
GUARDED_BY(mSupportedEffectsMutex);
@@ -202,125 +206,120 @@
// Loads directly from IVibrator handle, skipping caches.
HalResult<Capabilities> getCapabilitiesInternal();
HalResult<std::vector<hardware::vibrator::Effect>> getSupportedEffectsInternal();
+ sp<hardware::vibrator::IVibrator> getHal();
};
-// Wrapper for the HDIL Vibrator HAL v1.0.
-class HidlHalWrapperV1_0 : public HalWrapper {
+// Wrapper for the HDIL Vibrator HALs.
+template <typename I>
+class HidlHalWrapper : public HalWrapper {
public:
- HidlHalWrapperV1_0(std::shared_ptr<CallbackScheduler> scheduler,
- sp<hardware::vibrator::V1_0::IVibrator> handle)
- : HalWrapper(std::move(scheduler)), mHandleV1_0(std::move(handle)) {}
- virtual ~HidlHalWrapperV1_0() = default;
+ HidlHalWrapper(std::shared_ptr<CallbackScheduler> scheduler, sp<I> handle)
+ : HalWrapper(std::move(scheduler)), mHandle(std::move(handle)) {}
+ virtual ~HidlHalWrapper() = default;
- virtual HalResult<void> ping() override;
+ HalResult<void> ping() override final;
+ void tryReconnect() override final;
- virtual HalResult<void> on(std::chrono::milliseconds timeout,
- const std::function<void()>& completionCallback) override;
- virtual HalResult<void> off() override;
+ HalResult<void> on(std::chrono::milliseconds timeout,
+ const std::function<void()>& completionCallback) override final;
+ HalResult<void> off() override final;
- virtual HalResult<void> setAmplitude(int32_t amplitude) override;
+ HalResult<void> setAmplitude(int32_t amplitude) override final;
virtual HalResult<void> setExternalControl(bool enabled) override;
- virtual HalResult<void> alwaysOnEnable(int32_t id, hardware::vibrator::Effect effect,
- hardware::vibrator::EffectStrength strength) override;
- virtual HalResult<void> alwaysOnDisable(int32_t id) override;
+ HalResult<void> alwaysOnEnable(int32_t id, hardware::vibrator::Effect effect,
+ hardware::vibrator::EffectStrength strength) override final;
+ HalResult<void> alwaysOnDisable(int32_t id) override final;
- virtual HalResult<Capabilities> getCapabilities() override;
- virtual HalResult<std::vector<hardware::vibrator::Effect>> getSupportedEffects() override;
+ HalResult<Capabilities> getCapabilities() override final;
+ HalResult<std::vector<hardware::vibrator::Effect>> getSupportedEffects() override final;
- virtual HalResult<std::chrono::milliseconds> performEffect(
- hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
- const std::function<void()>& completionCallback) override;
-
- virtual HalResult<void> performComposedEffect(
+ HalResult<void> performComposedEffect(
const std::vector<hardware::vibrator::CompositeEffect>& primitiveEffects,
- const std::function<void()>& completionCallback) override;
+ const std::function<void()>& completionCallback) override final;
protected:
- const sp<hardware::vibrator::V1_0::IVibrator> mHandleV1_0;
+ std::mutex mHandleMutex;
std::mutex mCapabilitiesMutex;
+ sp<I> mHandle GUARDED_BY(mHandleMutex);
std::optional<Capabilities> mCapabilities GUARDED_BY(mCapabilitiesMutex);
// Loads directly from IVibrator handle, skipping the mCapabilities cache.
virtual HalResult<Capabilities> getCapabilitiesInternal();
- template <class I, class T>
+ template <class T>
using perform_fn =
hardware::Return<void> (I::*)(T, hardware::vibrator::V1_0::EffectStrength,
hardware::vibrator::V1_0::IVibrator::perform_cb);
- template <class I, class T>
+ template <class T>
HalResult<std::chrono::milliseconds> performInternal(
- perform_fn<I, T> performFn, sp<I> handle, T effect,
+ perform_fn<T> performFn, sp<I> handle, T effect,
hardware::vibrator::EffectStrength strength,
const std::function<void()>& completionCallback);
- HalResult<std::chrono::milliseconds> performInternalV1_0(
+ sp<I> getHal();
+};
+
+// Wrapper for the HDIL Vibrator HAL v1.0.
+class HidlHalWrapperV1_0 : public HidlHalWrapper<hardware::vibrator::V1_0::IVibrator> {
+public:
+ HidlHalWrapperV1_0(std::shared_ptr<CallbackScheduler> scheduler,
+ sp<hardware::vibrator::V1_0::IVibrator> handle)
+ : HidlHalWrapper<hardware::vibrator::V1_0::IVibrator>(std::move(scheduler),
+ std::move(handle)) {}
+ virtual ~HidlHalWrapperV1_0() = default;
+
+ HalResult<std::chrono::milliseconds> performEffect(
hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
- const std::function<void()>& completionCallback);
+ const std::function<void()>& completionCallback) override final;
};
// Wrapper for the HDIL Vibrator HAL v1.1.
-class HidlHalWrapperV1_1 : public HidlHalWrapperV1_0 {
+class HidlHalWrapperV1_1 : public HidlHalWrapper<hardware::vibrator::V1_1::IVibrator> {
public:
HidlHalWrapperV1_1(std::shared_ptr<CallbackScheduler> scheduler,
sp<hardware::vibrator::V1_1::IVibrator> handle)
- : HidlHalWrapperV1_0(std::move(scheduler), handle), mHandleV1_1(handle) {}
+ : HidlHalWrapper<hardware::vibrator::V1_1::IVibrator>(std::move(scheduler),
+ std::move(handle)) {}
virtual ~HidlHalWrapperV1_1() = default;
- virtual HalResult<std::chrono::milliseconds> performEffect(
+ HalResult<std::chrono::milliseconds> performEffect(
hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
- const std::function<void()>& completionCallback) override;
-
-protected:
- const sp<hardware::vibrator::V1_1::IVibrator> mHandleV1_1;
-
- HalResult<std::chrono::milliseconds> performInternalV1_1(
- hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
- const std::function<void()>& completionCallback);
+ const std::function<void()>& completionCallback) override final;
};
// Wrapper for the HDIL Vibrator HAL v1.2.
-class HidlHalWrapperV1_2 : public HidlHalWrapperV1_1 {
+class HidlHalWrapperV1_2 : public HidlHalWrapper<hardware::vibrator::V1_2::IVibrator> {
public:
HidlHalWrapperV1_2(std::shared_ptr<CallbackScheduler> scheduler,
sp<hardware::vibrator::V1_2::IVibrator> handle)
- : HidlHalWrapperV1_1(std::move(scheduler), handle), mHandleV1_2(handle) {}
+ : HidlHalWrapper<hardware::vibrator::V1_2::IVibrator>(std::move(scheduler),
+ std::move(handle)) {}
virtual ~HidlHalWrapperV1_2() = default;
- virtual HalResult<std::chrono::milliseconds> performEffect(
+ HalResult<std::chrono::milliseconds> performEffect(
hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
- const std::function<void()>& completionCallback) override;
-
-protected:
- const sp<hardware::vibrator::V1_2::IVibrator> mHandleV1_2;
-
- HalResult<std::chrono::milliseconds> performInternalV1_2(
- hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
- const std::function<void()>& completionCallback);
+ const std::function<void()>& completionCallback) override final;
};
// Wrapper for the HDIL Vibrator HAL v1.3.
-class HidlHalWrapperV1_3 : public HidlHalWrapperV1_2 {
+class HidlHalWrapperV1_3 : public HidlHalWrapper<hardware::vibrator::V1_3::IVibrator> {
public:
HidlHalWrapperV1_3(std::shared_ptr<CallbackScheduler> scheduler,
sp<hardware::vibrator::V1_3::IVibrator> handle)
- : HidlHalWrapperV1_2(std::move(scheduler), handle), mHandleV1_3(handle) {}
+ : HidlHalWrapper<hardware::vibrator::V1_3::IVibrator>(std::move(scheduler),
+ std::move(handle)) {}
virtual ~HidlHalWrapperV1_3() = default;
- virtual HalResult<void> setExternalControl(bool enabled) override;
+ HalResult<void> setExternalControl(bool enabled) override final;
- virtual HalResult<std::chrono::milliseconds> performEffect(
+ HalResult<std::chrono::milliseconds> performEffect(
hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
- const std::function<void()>& completionCallback) override;
+ const std::function<void()>& completionCallback) override final;
protected:
- const sp<hardware::vibrator::V1_3::IVibrator> mHandleV1_3;
-
- virtual HalResult<Capabilities> getCapabilitiesInternal() override;
- HalResult<std::chrono::milliseconds> performInternalV1_3(
- hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
- const std::function<void()>& completionCallback);
+ HalResult<Capabilities> getCapabilitiesInternal() override final;
};
// -------------------------------------------------------------------------------------------------
diff --git a/services/vibratorservice/test/VibratorHalControllerTest.cpp b/services/vibratorservice/test/VibratorHalControllerTest.cpp
index 24e6a1e..2d55549 100644
--- a/services/vibratorservice/test/VibratorHalControllerTest.cpp
+++ b/services/vibratorservice/test/VibratorHalControllerTest.cpp
@@ -53,6 +53,7 @@
virtual ~MockHalWrapper() = default;
MOCK_METHOD(vibrator::HalResult<void>, ping, (), (override));
+ MOCK_METHOD(void, tryReconnect, (), (override));
MOCK_METHOD(vibrator::HalResult<void>, on,
(milliseconds timeout, const std::function<void()>& completionCallback),
(override));
@@ -132,7 +133,6 @@
vibrator::HalResult<vibrator::Capabilities> capabilitiesResult,
vibrator::HalResult<std::vector<Effect>> effectsResult,
vibrator::HalResult<milliseconds> durationResult) {
- InSequence seq;
EXPECT_CALL(*mMockHal.get(), ping())
.Times(Exactly(cardinality))
.WillRepeatedly(Return(voidResult));
@@ -167,11 +167,25 @@
EXPECT_CALL(*mMockHal.get(), performComposedEffect(Eq(compositeEffects), _))
.Times(Exactly(cardinality))
.WillRepeatedly(Return(voidResult));
+
+ if (cardinality > 1) {
+ // One reconnection call after each failure.
+ EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(11 * cardinality));
+ }
}
};
// -------------------------------------------------------------------------------------------------
+TEST_F(VibratorHalControllerTest, TestInit) {
+ mController->init();
+ ASSERT_EQ(1, mConnectCounter);
+
+ // Noop when wrapper was already initialized.
+ mController->init();
+ ASSERT_EQ(1, mConnectCounter);
+}
+
TEST_F(VibratorHalControllerTest, TestApiCallsAreForwardedToHal) {
std::vector<Effect> supportedEffects;
supportedEffects.push_back(Effect::CLICK);
@@ -211,7 +225,6 @@
ASSERT_TRUE(mController->performComposedEffect(compositeEffects, []() {}).isOk());
- // No reconnection attempt was made after the first one.
ASSERT_EQ(1, mConnectCounter);
}
@@ -239,7 +252,6 @@
ASSERT_TRUE(mController->performComposedEffect(std::vector<CompositeEffect>(), []() {})
.isUnsupported());
- // No reconnection attempt was made after the first one.
ASSERT_EQ(1, mConnectCounter);
}
@@ -266,23 +278,24 @@
ASSERT_TRUE(
mController->performComposedEffect(std::vector<CompositeEffect>(), []() {}).isFailed());
- // One reconnection attempt + retry attempts per api call.
- ASSERT_EQ(11 * MAX_ATTEMPTS, mConnectCounter);
+ ASSERT_EQ(1, mConnectCounter);
}
TEST_F(VibratorHalControllerTest, TestFailedApiResultReturnsSuccessAfterRetries) {
{
InSequence seq;
EXPECT_CALL(*mMockHal.get(), ping())
- .Times(Exactly(2))
- .WillOnce(Return(vibrator::HalResult<void>::failed()))
+ .Times(Exactly(1))
+ .WillRepeatedly(Return(vibrator::HalResult<void>::failed()));
+ EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(1));
+ EXPECT_CALL(*mMockHal.get(), ping())
+ .Times(Exactly(1))
.WillRepeatedly(Return(vibrator::HalResult<void>::ok()));
}
ASSERT_EQ(0, mConnectCounter);
ASSERT_TRUE(mController->ping().isOk());
- // One connect + one retry.
- ASSERT_EQ(2, mConnectCounter);
+ ASSERT_EQ(1, mConnectCounter);
}
TEST_F(VibratorHalControllerTest, TestMultiThreadConnectsOnlyOnce) {
@@ -323,7 +336,7 @@
ASSERT_TRUE(mController->performComposedEffect(std::vector<CompositeEffect>(), []() {})
.isUnsupported());
- // One reconnection attempt per api call, no retry.
+ // One connection attempt per api call.
ASSERT_EQ(11, mConnectCounter);
}
@@ -337,19 +350,24 @@
return vibrator::HalResult<void>::ok();
});
EXPECT_CALL(*mMockHal.get(), ping())
- .Times(Exactly(MAX_ATTEMPTS))
+ .Times(Exactly(1))
.WillRepeatedly(Return(vibrator::HalResult<void>::failed()));
+ EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(1));
+ EXPECT_CALL(*mMockHal.get(), ping())
+ .Times(Exactly(1))
+ .WillRepeatedly(Return(vibrator::HalResult<void>::failed()));
+ EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(1));
}
std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>();
auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get());
ASSERT_TRUE(mController->on(10ms, callback).isOk());
- ASSERT_TRUE(mController->ping().isFailed()); // Delete connected HAL pointer from controller.
- mMockHal.reset(); // Delete mock HAL pointer from test class.
+ ASSERT_TRUE(mController->ping().isFailed());
+ mMockHal.reset();
ASSERT_EQ(0, *callbackCounter.get());
- // Callback triggered even after HalWrapper was completely destroyed.
+ // Callback triggered even after HalWrapper was reconnected.
std::this_thread::sleep_for(15ms);
ASSERT_EQ(1, *callbackCounter.get());
}