Merge "Fix layer Z dump"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 9e77e8f..b3d628c 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -144,10 +144,12 @@
* Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
* The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime|
* is set, the vector only contains files that were written in the last 30 minutes.
+ * If |limit_by_count| is set, the vector only contains the ten latest files.
*/
static std::vector<DumpData>* GetDumpFds(const std::string& dir_path,
const std::string& file_prefix,
- bool limit_by_mtime) {
+ bool limit_by_mtime,
+ bool limit_by_count = true) {
const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
std::unique_ptr<std::vector<DumpData>> dump_data(new std::vector<DumpData>());
@@ -190,6 +192,10 @@
std::sort(dump_data->begin(), dump_data->end());
+ if (limit_by_count && dump_data->size() > 10) {
+ dump_data->erase(dump_data->begin() + 10, dump_data->end());
+ }
+
return dump_data.release();
}
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index 73c7f18..3227749 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -16,6 +16,7 @@
#include <algorithm>
#include <chrono>
+#include <iomanip>
#include <thread>
#include <android-base/file.h>
@@ -282,7 +283,14 @@
std::chrono::duration<double> elapsed_seconds =
std::chrono::steady_clock::now() - start;
aout << StringPrintf("--------- %.3fs ", elapsed_seconds.count()).c_str()
- << "was the duration of dumpsys " << service_name << endl;
+ << "was the duration of dumpsys " << service_name;
+
+ using std::chrono::system_clock;
+ const auto finish = system_clock::to_time_t(system_clock::now());
+ std::tm finish_tm;
+ localtime_r(&finish, &finish_tm);
+ aout << ", ending at: " << std::put_time(&finish_tm, "%Y-%m-%d %H:%M:%S")
+ << endl;
}
} else {
aerr << "Can't find service: " << service_name << endl;
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index efa1ffb..0dd15b1 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -370,14 +370,14 @@
int32_t idToIndex[MAX_POINTER_ID + 1];
PointerCoords pointers[MAX_POINTERS];
- void initializeFrom(const InputMessage* msg) {
- eventTime = msg->body.motion.eventTime;
+ void initializeFrom(const InputMessage& msg) {
+ eventTime = msg.body.motion.eventTime;
idBits.clear();
- for (uint32_t i = 0; i < msg->body.motion.pointerCount; i++) {
- uint32_t id = msg->body.motion.pointers[i].properties.id;
+ for (uint32_t i = 0; i < msg.body.motion.pointerCount; i++) {
+ uint32_t id = msg.body.motion.pointers[i].properties.id;
idBits.markBit(id);
idToIndex[id] = i;
- pointers[i].copyFrom(msg->body.motion.pointers[i].coords);
+ pointers[i].copyFrom(msg.body.motion.pointers[i].coords);
}
}
@@ -402,7 +402,7 @@
lastResample.idBits.clear();
}
- void addHistory(const InputMessage* msg) {
+ void addHistory(const InputMessage& msg) {
historyCurrent ^= 1;
if (historySize < 2) {
historySize += 1;
@@ -413,6 +413,21 @@
const History* getHistory(size_t index) const {
return &history[(historyCurrent + index) & 1];
}
+
+ bool recentCoordinatesAreIdentical(uint32_t id) const {
+ // Return true if the two most recently received "raw" coordinates are identical
+ if (historySize < 2) {
+ return false;
+ }
+ float currentX = getHistory(0)->getPointerById(id).getX();
+ float currentY = getHistory(0)->getPointerById(id).getY();
+ float previousX = getHistory(1)->getPointerById(id).getX();
+ float previousY = getHistory(1)->getPointerById(id).getY();
+ if (currentX == previousX && currentY == previousY) {
+ return true;
+ }
+ return false;
+ }
};
Vector<TouchState> mTouchStates;
@@ -432,8 +447,8 @@
Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent,
int32_t* displayId);
- void updateTouchState(InputMessage* msg);
- void rewriteMessage(const TouchState& state, InputMessage* msg);
+ void updateTouchState(InputMessage& msg);
+ bool rewriteMessage(const TouchState& state, InputMessage& msg);
void resampleTouchState(nsecs_t frameTime, MotionEvent* event,
const InputMessage *next);
diff --git a/libs/binder/Value.cpp b/libs/binder/Value.cpp
index fd1dfd5..85cd739 100644
--- a/libs/binder/Value.cpp
+++ b/libs/binder/Value.cpp
@@ -182,10 +182,12 @@
Value& Value::operator=(const Value& rhs)
{
- delete mContent;
- mContent = rhs.mContent
- ? rhs.mContent->clone()
- : NULL;
+ if (this != &rhs) {
+ delete mContent;
+ mContent = rhs.mContent
+ ? rhs.mContent->clone()
+ : NULL;
+ }
return *this;
}
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index 3d36376..7aa7872 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -335,16 +335,25 @@
return OK;
}
- auto status = mSlots[slot].mFence->getStatus();
-
- if (status == Fence::Status::Invalid) {
- CB_LOGE("fence has invalid state");
+ // Check status of fences first because merging is expensive.
+ // Merging an invalid fence with any other fence results in an
+ // invalid fence.
+ auto currentStatus = mSlots[slot].mFence->getStatus();
+ if (currentStatus == Fence::Status::Invalid) {
+ CB_LOGE("Existing fence has invalid state");
return BAD_VALUE;
}
- if (status == Fence::Status::Signaled) {
+ auto incomingStatus = fence->getStatus();
+ if (incomingStatus == Fence::Status::Invalid) {
+ CB_LOGE("New fence has invalid state");
mSlots[slot].mFence = fence;
- } else { // status == Fence::Status::Unsignaled
+ return BAD_VALUE;
+ }
+
+ // If both fences are signaled or both are unsignaled, we need to merge
+ // them to get an accurate timestamp.
+ if (currentStatus == incomingStatus) {
char fenceName[32] = {};
snprintf(fenceName, 32, "%.28s:%d", mName.string(), slot);
sp<Fence> mergedFence = Fence::merge(
@@ -357,7 +366,17 @@
return BAD_VALUE;
}
mSlots[slot].mFence = mergedFence;
+ } else if (incomingStatus == Fence::Status::Unsignaled) {
+ // If one fence has signaled and the other hasn't, the unsignaled
+ // fence will approximately correspond with the correct timestamp.
+ // There's a small race if both fences signal at about the same time
+ // and their statuses are retrieved with unfortunate timing. However,
+ // by this point, they will have both signaled and only the timestamp
+ // will be slightly off; any dependencies after this point will
+ // already have been met.
+ mSlots[slot].mFence = fence;
}
+ // else if (currentStatus == Fence::Status::Unsignaled) is a no-op.
return OK;
}
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 63e98bb..9abd04c 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -496,7 +496,7 @@
MotionEvent* motionEvent = factory->createMotionEvent();
if (! motionEvent) return NO_MEMORY;
- updateTouchState(&mMsg);
+ updateTouchState(mMsg);
initializeMotionEvent(motionEvent, &mMsg);
*outSeq = mMsg.body.motion.seq;
*outEvent = motionEvent;
@@ -564,7 +564,7 @@
uint32_t chain = 0;
for (size_t i = 0; i < count; i++) {
InputMessage& msg = batch.samples.editItemAt(i);
- updateTouchState(&msg);
+ updateTouchState(msg);
if (i) {
SeqChain seqChain;
seqChain.seq = msg.body.motion.seq;
@@ -584,20 +584,19 @@
return OK;
}
-void InputConsumer::updateTouchState(InputMessage* msg) {
+void InputConsumer::updateTouchState(InputMessage& msg) {
if (!mResampleTouch ||
- !(msg->body.motion.source & AINPUT_SOURCE_CLASS_POINTER)) {
+ !(msg.body.motion.source & AINPUT_SOURCE_CLASS_POINTER)) {
return;
}
- int32_t deviceId = msg->body.motion.deviceId;
- int32_t source = msg->body.motion.source;
- nsecs_t eventTime = msg->body.motion.eventTime;
+ int32_t deviceId = msg.body.motion.deviceId;
+ int32_t source = msg.body.motion.source;
// Update the touch state history to incorporate the new input message.
// If the message is in the past relative to the most recently produced resampled
// touch, then use the resampled time and coordinates instead.
- switch (msg->body.motion.action & AMOTION_EVENT_ACTION_MASK) {
+ switch (msg.body.motion.action & AMOTION_EVENT_ACTION_MASK) {
case AMOTION_EVENT_ACTION_DOWN: {
ssize_t index = findTouchState(deviceId, source);
if (index < 0) {
@@ -615,9 +614,8 @@
if (index >= 0) {
TouchState& touchState = mTouchStates.editItemAt(index);
touchState.addHistory(msg);
- if (eventTime < touchState.lastResample.eventTime) {
- rewriteMessage(touchState, msg);
- } else {
+ bool messageRewritten = rewriteMessage(touchState, msg);
+ if (!messageRewritten) {
touchState.lastResample.idBits.clear();
}
}
@@ -628,7 +626,7 @@
ssize_t index = findTouchState(deviceId, source);
if (index >= 0) {
TouchState& touchState = mTouchStates.editItemAt(index);
- touchState.lastResample.idBits.clearBit(msg->body.motion.getActionId());
+ touchState.lastResample.idBits.clearBit(msg.body.motion.getActionId());
rewriteMessage(touchState, msg);
}
break;
@@ -639,7 +637,7 @@
if (index >= 0) {
TouchState& touchState = mTouchStates.editItemAt(index);
rewriteMessage(touchState, msg);
- touchState.lastResample.idBits.clearBit(msg->body.motion.getActionId());
+ touchState.lastResample.idBits.clearBit(msg.body.motion.getActionId());
}
break;
}
@@ -666,23 +664,28 @@
}
}
-void InputConsumer::rewriteMessage(const TouchState& state, InputMessage* msg) {
- for (uint32_t i = 0; i < msg->body.motion.pointerCount; i++) {
- uint32_t id = msg->body.motion.pointers[i].properties.id;
+bool InputConsumer::rewriteMessage(const TouchState& state, InputMessage& msg) {
+ bool messageRewritten = false;
+ nsecs_t eventTime = msg.body.motion.eventTime;
+ for (uint32_t i = 0; i < msg.body.motion.pointerCount; i++) {
+ uint32_t id = msg.body.motion.pointers[i].properties.id;
if (state.lastResample.idBits.hasBit(id)) {
- PointerCoords& msgCoords = msg->body.motion.pointers[i].coords;
+ PointerCoords& msgCoords = msg.body.motion.pointers[i].coords;
const PointerCoords& resampleCoords = state.lastResample.getPointerById(id);
+ if (eventTime < state.lastResample.eventTime ||
+ state.recentCoordinatesAreIdentical(id)) {
+ msgCoords.setAxisValue(AMOTION_EVENT_AXIS_X, resampleCoords.getX());
+ msgCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, resampleCoords.getY());
#if DEBUG_RESAMPLING
- ALOGD("[%d] - rewrite (%0.3f, %0.3f), old (%0.3f, %0.3f)", id,
- resampleCoords.getAxisValue(AMOTION_EVENT_AXIS_X),
- resampleCoords.getAxisValue(AMOTION_EVENT_AXIS_Y),
- msgCoords.getAxisValue(AMOTION_EVENT_AXIS_X),
- msgCoords.getAxisValue(AMOTION_EVENT_AXIS_Y));
+ ALOGD("[%d] - rewrite (%0.3f, %0.3f), old (%0.3f, %0.3f)", id,
+ resampleCoords.getX(), resampleCoords.getY(),
+ msgCoords.getX(), msgCoords.getY());
#endif
- msgCoords.setAxisValue(AMOTION_EVENT_AXIS_X, resampleCoords.getX());
- msgCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, resampleCoords.getY());
+ messageRewritten = true;
+ }
}
}
+ return messageRewritten;
}
void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event,
@@ -710,6 +713,7 @@
}
// Ensure that the current sample has all of the pointers that need to be reported.
+ // Also ensure that the past two "real" touch events do not contain duplicate coordinates
const History* current = touchState.getHistory(0);
size_t pointerCount = event->getPointerCount();
for (size_t i = 0; i < pointerCount; i++) {
@@ -720,6 +724,12 @@
#endif
return;
}
+ if (touchState.recentCoordinatesAreIdentical(id)) {
+#if DEBUG_RESAMPLING
+ ALOGD("Not resampled, past two historical events have duplicate coordinates");
+#endif
+ return;
+ }
}
// Find the data to use for resampling.
@@ -729,12 +739,12 @@
if (next) {
// Interpolate between current sample and future sample.
// So current->eventTime <= sampleTime <= future.eventTime.
- future.initializeFrom(next);
+ future.initializeFrom(*next);
other = &future;
nsecs_t delta = future.eventTime - current->eventTime;
if (delta < RESAMPLE_MIN_DELTA) {
#if DEBUG_RESAMPLING
- ALOGD("Not resampled, delta time is too small: %lld ns.", delta);
+ ALOGD("Not resampled, delta time is too small: %" PRId64 " ns.", delta);
#endif
return;
}
@@ -746,12 +756,12 @@
nsecs_t delta = current->eventTime - other->eventTime;
if (delta < RESAMPLE_MIN_DELTA) {
#if DEBUG_RESAMPLING
- ALOGD("Not resampled, delta time is too small: %lld ns.", delta);
+ ALOGD("Not resampled, delta time is too small: %" PRId64 " ns.", delta);
#endif
return;
} else if (delta > RESAMPLE_MAX_DELTA) {
#if DEBUG_RESAMPLING
- ALOGD("Not resampled, delta time is too large: %lld ns.", delta);
+ ALOGD("Not resampled, delta time is too large: %" PRId64 " ns.", delta);
#endif
return;
}
@@ -759,7 +769,7 @@
if (sampleTime > maxPredict) {
#if DEBUG_RESAMPLING
ALOGD("Sample time is too far in the future, adjusting prediction "
- "from %lld to %lld ns.",
+ "from %" PRId64 " to %" PRId64 " ns.",
sampleTime - current->eventTime, maxPredict - current->eventTime);
#endif
sampleTime = maxPredict;
diff --git a/libs/vr/libpdx_default_transport/Android.bp b/libs/vr/libpdx_default_transport/Android.bp
index 8cfa86f..0f6511b 100644
--- a/libs/vr/libpdx_default_transport/Android.bp
+++ b/libs/vr/libpdx_default_transport/Android.bp
@@ -36,10 +36,10 @@
}
cc_binary {
- name: "servicetool",
+ name: "pdx_tool",
defaults: ["pdx_default_transport_compiler_defaults"],
srcs: [
- "servicetool.cpp",
+ "pdx_tool.cpp",
],
shared_libs: [
"liblog",
diff --git a/libs/vr/libpdx_default_transport/servicetool.cpp b/libs/vr/libpdx_default_transport/pdx_tool.cpp
similarity index 100%
rename from libs/vr/libpdx_default_transport/servicetool.cpp
rename to libs/vr/libpdx_default_transport/pdx_tool.cpp
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index f350762..af18e21 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -243,18 +243,16 @@
surface_status.GetErrorMessage().c_str());
return ErrorStatus(surface_status.error());
}
+ auto surface = surface_status.take();
+ message.SetChannel(surface);
- SurfaceType surface_type = surface_status.get()->surface_type();
- display::SurfaceUpdateFlags update_flags =
- surface_status.get()->update_flags();
- display::SurfaceInfo surface_info{surface_status.get()->surface_id(),
- surface_status.get()->visible(),
- surface_status.get()->z_order()};
+ // Update the surface with the attributes supplied with the create call. For
+ // application surfaces this has the side effect of notifying the display
+ // manager of the new surface. For direct surfaces, this may trigger a mode
+ // change, depending on the value of the visible attribute.
+ surface->OnSetAttributes(message, attributes);
- message.SetChannel(surface_status.take());
-
- SurfaceUpdated(surface_type, update_flags);
- return {surface_info};
+ return {{surface->surface_id(), surface->visible(), surface->z_order()}};
}
void DisplayService::SurfaceUpdated(SurfaceType surface_type,
diff --git a/libs/vr/libvrflinger/display_surface.cpp b/libs/vr/libvrflinger/display_surface.cpp
index 4852fab..6853781 100644
--- a/libs/vr/libvrflinger/display_surface.cpp
+++ b/libs/vr/libvrflinger/display_surface.cpp
@@ -26,14 +26,12 @@
DisplaySurface::DisplaySurface(DisplayService* service,
SurfaceType surface_type, int surface_id,
- int process_id, int user_id,
- const display::SurfaceAttributes& attributes)
+ int process_id, int user_id)
: service_(service),
surface_type_(surface_type),
surface_id_(surface_id),
process_id_(process_id),
user_id_(user_id),
- attributes_(attributes),
update_flags_(display::SurfaceUpdateFlags::NewSurface) {}
DisplaySurface::~DisplaySurface() {
@@ -471,8 +469,8 @@
if (direct) {
const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
if (trusted) {
- return {std::shared_ptr<DisplaySurface>{new DirectDisplaySurface(
- service, surface_id, process_id, user_id, attributes)}};
+ return {std::shared_ptr<DisplaySurface>{
+ new DirectDisplaySurface(service, surface_id, process_id, user_id)}};
} else {
ALOGE(
"DisplaySurface::Create: Direct surfaces may only be created by "
@@ -482,7 +480,7 @@
}
} else {
return {std::shared_ptr<DisplaySurface>{new ApplicationDisplaySurface(
- service, surface_id, process_id, user_id, attributes)}};
+ service, surface_id, process_id, user_id)}};
}
}
diff --git a/libs/vr/libvrflinger/display_surface.h b/libs/vr/libvrflinger/display_surface.h
index 7a0fb18..c8b1a07 100644
--- a/libs/vr/libvrflinger/display_surface.h
+++ b/libs/vr/libvrflinger/display_surface.h
@@ -53,8 +53,7 @@
protected:
DisplaySurface(DisplayService* service, SurfaceType surface_type,
- int surface_id, int process_id, int user_id,
- const display::SurfaceAttributes& attributes);
+ int surface_id, int process_id, int user_id);
// Utility to retrieve a shared pointer to this channel as the desired derived
// type.
@@ -119,10 +118,9 @@
class ApplicationDisplaySurface : public DisplaySurface {
public:
ApplicationDisplaySurface(DisplayService* service, int surface_id,
- int process_id, int user_id,
- const display::SurfaceAttributes& attributes)
+ int process_id, int user_id)
: DisplaySurface(service, SurfaceType::Application, surface_id,
- process_id, user_id, attributes) {}
+ process_id, user_id) {}
std::shared_ptr<ConsumerQueue> GetQueue(int32_t queue_id);
std::vector<int32_t> GetQueueIds() const override;
@@ -140,12 +138,11 @@
class DirectDisplaySurface : public DisplaySurface {
public:
DirectDisplaySurface(DisplayService* service, int surface_id, int process_id,
- int user_id,
- const display::SurfaceAttributes& attributes)
+ int user_id)
: DisplaySurface(service, SurfaceType::Direct, surface_id, process_id,
- user_id, attributes),
+ user_id),
acquired_buffers_(kMaxPostedBuffers),
- metadata_(nullptr){}
+ metadata_(nullptr) {}
std::vector<int32_t> GetQueueIds() const override;
bool IsBufferAvailable();
bool IsBufferPosted();