Merge "Add a feature to signal fitness quality heart rate monitors" into cw-f-dev
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index c2f8891..e3cc9da 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -1,6 +1,6 @@
## Permissions to allow system-wide tracing to the kernel trace buffer.
##
-on boot
+on fs
# Allow writing to the kernel trace log.
chmod 0222 /sys/kernel/debug/tracing/trace_marker
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 45db71c..6c1dd48 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -821,12 +821,12 @@
static void dump_iptables() {
run_command("IPTABLES", 10, "iptables", "-L", "-nvx", NULL);
run_command("IP6TABLES", 10, "ip6tables", "-L", "-nvx", NULL);
- run_command("IPTABLE NAT", 10, "iptables", "-t", "nat", "-L", "-nvx", NULL);
+ run_command("IPTABLES NAT", 10, "iptables", "-t", "nat", "-L", "-nvx", NULL);
/* no ip6 nat */
- run_command("IPTABLE MANGLE", 10, "iptables", "-t", "mangle", "-L", "-nvx", NULL);
- run_command("IP6TABLE MANGLE", 10, "ip6tables", "-t", "mangle", "-L", "-nvx", NULL);
- run_command("IPTABLE RAW", 10, "iptables", "-t", "raw", "-L", "-nvx", NULL);
- run_command("IP6TABLE RAW", 10, "ip6tables", "-t", "raw", "-L", "-nvx", NULL);
+ run_command("IPTABLES MANGLE", 10, "iptables", "-t", "mangle", "-L", "-nvx", NULL);
+ run_command("IP6TABLES MANGLE", 10, "ip6tables", "-t", "mangle", "-L", "-nvx", NULL);
+ run_command("IPTABLES RAW", 10, "iptables", "-t", "raw", "-L", "-nvx", NULL);
+ run_command("IP6TABLES RAW", 10, "ip6tables", "-t", "raw", "-L", "-nvx", NULL);
}
static void dumpstate(const std::string& screenshot_path, const std::string& version) {
@@ -1533,6 +1533,9 @@
add_mountinfo();
dump_iptables();
+ // Capture any IPSec policies in play. No keys are exposed here.
+ run_command("IP XFRM POLICY", 10, "ip", "xfrm", "policy", nullptr);
+
// Run ss as root so we can see socket marks.
run_command("DETAILED SOCKET STATE", 10, "ss", "-eionptu", NULL);
diff --git a/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h
index cc5c536..1226feb 100644
--- a/include/gui/BufferQueueCore.h
+++ b/include/gui/BufferQueueCore.h
@@ -185,8 +185,12 @@
// PID of the process which last successfully called connect(...)
pid_t mConnectedPid;
- // mConnectedProducerToken is used to set a binder death notification on
+ // mLinkedToDeath is used to set a binder death notification on
// the producer.
+ sp<IProducerListener> mLinkedToDeath;
+
+ // mConnectedProducerListener is used to handle the onBufferReleased
+ // notification.
sp<IProducerListener> mConnectedProducerListener;
// mSlots is an array of buffer slots that must be mirrored on the producer
diff --git a/include/gui/IProducerListener.h b/include/gui/IProducerListener.h
index 3848a6c..b7826c6 100644
--- a/include/gui/IProducerListener.h
+++ b/include/gui/IProducerListener.h
@@ -41,6 +41,7 @@
// This is called without any lock held and can be called concurrently by
// multiple threads.
virtual void onBufferReleased() = 0; // Asynchronous
+ virtual bool needsReleaseNotify() = 0;
};
class IProducerListener : public ProducerListener, public IInterface
@@ -54,12 +55,14 @@
public:
virtual status_t onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags = 0);
+ virtual bool needsReleaseNotify();
};
class DummyProducerListener : public BnProducerListener
{
public:
virtual void onBufferReleased() {}
+ virtual bool needsReleaseNotify() { return false; }
};
} // namespace android
diff --git a/include/ui/Fence.h b/include/ui/Fence.h
index b431bd5..fa4b9bc 100644
--- a/include/ui/Fence.h
+++ b/include/ui/Fence.h
@@ -79,6 +79,9 @@
// becomes signaled when both f1 and f2 are signaled (even if f1 or f2 is
// destroyed before it becomes signaled). The name argument specifies the
// human-readable name to associated with the new Fence object.
+ static sp<Fence> merge(const char* name, const sp<Fence>& f1,
+ const sp<Fence>& f2);
+
static sp<Fence> merge(const String8& name, const sp<Fence>& f1,
const sp<Fence>& f2);
@@ -93,6 +96,17 @@
// occurs then -1 is returned.
nsecs_t getSignalTime() const;
+ // hasSignaled returns whether the fence has signaled yet. Prefer this to
+ // getSignalTime() or wait() if all you care about is whether the fence has
+ // signaled.
+ inline bool hasSignaled() {
+ // The sync_wait call underlying wait() has been measured to be
+ // significantly faster than the sync_fence_info call underlying
+ // getSignalTime(), which might otherwise appear to be the more obvious
+ // way to check whether a fence has signaled.
+ return wait(0) == NO_ERROR;
+ }
+
// Flattenable interface
size_t getFlattenedSize() const;
size_t getFdCount() const;
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index 9cb9c62..fd85c43 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -59,6 +59,7 @@
mConsumerListener(),
mConsumerUsageBits(0),
mConnectedApi(NO_CONNECTED_API),
+ mLinkedToDeath(),
mConnectedProducerListener(),
mSlots(),
mQueue(),
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 48b1db8..7020214 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -1113,18 +1113,22 @@
static_cast<uint32_t>(mCore->mQueue.size()),
mCore->mFrameCounter + 1);
- // Set up a death notification so that we can disconnect
- // automatically if the remote producer dies
- if (listener != NULL &&
- IInterface::asBinder(listener)->remoteBinder() != NULL) {
- status = IInterface::asBinder(listener)->linkToDeath(
- static_cast<IBinder::DeathRecipient*>(this));
- if (status != NO_ERROR) {
- BQ_LOGE("connect: linkToDeath failed: %s (%d)",
- strerror(-status), status);
+ if (listener != NULL) {
+ // Set up a death notification so that we can disconnect
+ // automatically if the remote producer dies
+ if (IInterface::asBinder(listener)->remoteBinder() != NULL) {
+ status = IInterface::asBinder(listener)->linkToDeath(
+ static_cast<IBinder::DeathRecipient*>(this));
+ if (status != NO_ERROR) {
+ BQ_LOGE("connect: linkToDeath failed: %s (%d)",
+ strerror(-status), status);
+ }
+ mCore->mLinkedToDeath = listener;
+ }
+ if (listener->needsReleaseNotify()) {
+ mCore->mConnectedProducerListener = listener;
}
}
- mCore->mConnectedProducerListener = listener;
break;
default:
BQ_LOGE("connect: unknown API %d", api);
@@ -1186,9 +1190,9 @@
mCore->freeAllBuffersLocked();
// Remove our death notification callback if we have one
- if (mCore->mConnectedProducerListener != NULL) {
+ if (mCore->mLinkedToDeath != NULL) {
sp<IBinder> token =
- IInterface::asBinder(mCore->mConnectedProducerListener);
+ IInterface::asBinder(mCore->mLinkedToDeath);
// This can fail if we're here because of the death
// notification, but we just ignore it
token->unlinkToDeath(
@@ -1196,6 +1200,7 @@
}
mCore->mSharedBufferSlot =
BufferQueueCore::INVALID_BUFFER_SLOT;
+ mCore->mLinkedToDeath = NULL;
mCore->mConnectedProducerListener = NULL;
mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
mCore->mConnectedPid = -1;
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index a1bdf4a..e7bc7dc 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -315,9 +315,10 @@
if (!mSlots[slot].mFence.get()) {
mSlots[slot].mFence = fence;
} else {
+ char fenceName[32] = {};
+ snprintf(fenceName, 32, "%.28s:%d", mName.string(), slot);
sp<Fence> mergedFence = Fence::merge(
- String8::format("%.28s:%d", mName.string(), slot),
- mSlots[slot].mFence, fence);
+ fenceName, mSlots[slot].mFence, fence);
if (!mergedFence.get()) {
CB_LOGE("failed to merge release fences");
// synchronization is broken, the best we can do is hope fences
diff --git a/libs/gui/IProducerListener.cpp b/libs/gui/IProducerListener.cpp
index 81adc95..da54ce1 100644
--- a/libs/gui/IProducerListener.cpp
+++ b/libs/gui/IProducerListener.cpp
@@ -22,6 +22,7 @@
enum {
ON_BUFFER_RELEASED = IBinder::FIRST_CALL_TRANSACTION,
+ NEEDS_RELEASE_NOTIFY,
};
class BpProducerListener : public BpInterface<IProducerListener>
@@ -37,6 +38,23 @@
data.writeInterfaceToken(IProducerListener::getInterfaceDescriptor());
remote()->transact(ON_BUFFER_RELEASED, data, &reply, IBinder::FLAG_ONEWAY);
}
+
+ virtual bool needsReleaseNotify() {
+ bool result;
+ Parcel data, reply;
+ data.writeInterfaceToken(IProducerListener::getInterfaceDescriptor());
+ status_t err = remote()->transact(NEEDS_RELEASE_NOTIFY, data, &reply);
+ if (err != NO_ERROR) {
+ ALOGE("IProducerListener: binder call \'needsReleaseNotify\' failed");
+ return true;
+ }
+ err = reply.readBool(&result);
+ if (err != NO_ERROR) {
+ ALOGE("IProducerListener: malformed binder reply");
+ return true;
+ }
+ return result;
+ }
};
// Out-of-line virtual method definition to trigger vtable emission in this
@@ -52,8 +70,16 @@
CHECK_INTERFACE(IProducerListener, data, reply);
onBufferReleased();
return NO_ERROR;
+ case NEEDS_RELEASE_NOTIFY:
+ CHECK_INTERFACE(IProducerListener, data, reply);
+ reply->writeBool(needsReleaseNotify());
+ return NO_ERROR;
}
return BBinder::onTransact(code, data, reply, flags);
}
+bool BnProducerListener::needsReleaseNotify() {
+ return true;
+}
+
} // namespace android
diff --git a/libs/ui/Fence.cpp b/libs/ui/Fence.cpp
index bf24ffb..7cf8233 100644
--- a/libs/ui/Fence.cpp
+++ b/libs/ui/Fence.cpp
@@ -72,7 +72,7 @@
return err < 0 ? -errno : status_t(NO_ERROR);
}
-sp<Fence> Fence::merge(const String8& name, const sp<Fence>& f1,
+sp<Fence> Fence::merge(const char* name, const sp<Fence>& f1,
const sp<Fence>& f2) {
ATRACE_CALL();
int result;
@@ -80,24 +80,29 @@
// valid fence (e.g. NO_FENCE) we merge the one valid fence with itself so
// that a new fence with the given name is created.
if (f1->isValid() && f2->isValid()) {
- result = sync_merge(name.string(), f1->mFenceFd, f2->mFenceFd);
+ result = sync_merge(name, f1->mFenceFd, f2->mFenceFd);
} else if (f1->isValid()) {
- result = sync_merge(name.string(), f1->mFenceFd, f1->mFenceFd);
+ result = sync_merge(name, f1->mFenceFd, f1->mFenceFd);
} else if (f2->isValid()) {
- result = sync_merge(name.string(), f2->mFenceFd, f2->mFenceFd);
+ result = sync_merge(name, f2->mFenceFd, f2->mFenceFd);
} else {
return NO_FENCE;
}
if (result == -1) {
status_t err = -errno;
ALOGE("merge: sync_merge(\"%s\", %d, %d) returned an error: %s (%d)",
- name.string(), f1->mFenceFd, f2->mFenceFd,
+ name, f1->mFenceFd, f2->mFenceFd,
strerror(-err), err);
return NO_FENCE;
}
return sp<Fence>(new Fence(result));
}
+sp<Fence> Fence::merge(const String8& name, const sp<Fence>& f1,
+ const sp<Fence>& f2) {
+ return merge(name.string(), f1, f2);
+}
+
int Fence::dup() const {
return ::dup(mFenceFd);
}