Merge "vkjson: report VkPhysicalDeviceDriverPropertiesKHR"
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 73098f8..28c7658 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -361,12 +361,11 @@
}
std::string preopted_boot_art_path = StringPrintf("/system/framework/%s/boot.art", isa);
- if (access(preopted_boot_art_path.c_str(), F_OK) == 0) {
- return PatchoatBootImage(isa_path, isa);
- } else {
+ if (access(preopted_boot_art_path.c_str(), F_OK) != 0) {
// No preopted boot image. Try to compile.
return Dex2oatBootImage(boot_classpath_, art_path, oat_path, isa);
}
+ return true;
}
static bool CreatePath(const std::string& path) {
@@ -431,29 +430,6 @@
CHECK_EQ(0, closedir(c_dir)) << "Unable to close directory.";
}
- bool PatchoatBootImage(const std::string& output_dir, const char* isa) const {
- // This needs to be kept in sync with ART, see art/runtime/gc/space/image_space.cc.
-
- std::vector<std::string> cmd;
- cmd.push_back("/system/bin/patchoat");
-
- cmd.push_back("--input-image-location=/system/framework/boot.art");
- cmd.push_back(StringPrintf("--output-image-directory=%s", output_dir.c_str()));
-
- cmd.push_back(StringPrintf("--instruction-set=%s", isa));
-
- int32_t base_offset = ChooseRelocationOffsetDelta(art::GetImageMinBaseAddressDelta(),
- art::GetImageMaxBaseAddressDelta());
- cmd.push_back(StringPrintf("--base-offset-delta=%d", base_offset));
-
- std::string error_msg;
- bool result = Exec(cmd, &error_msg);
- if (!result) {
- LOG(ERROR) << "Could not generate boot image: " << error_msg;
- }
- return result;
- }
-
bool Dex2oatBootImage(const std::string& boot_cp,
const std::string& art_path,
const std::string& oat_path,
diff --git a/services/inputflinger/InputApplication.h b/include/input/InputApplication.h
similarity index 100%
rename from services/inputflinger/InputApplication.h
rename to include/input/InputApplication.h
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 5fd86b4..4782c9b 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -37,6 +37,7 @@
#include <utils/BitSet.h>
namespace android {
+class Parcel;
/*
* Intermediate representation used to send input events and related signals.
@@ -143,6 +144,7 @@
virtual ~InputChannel();
public:
+ InputChannel() = default;
InputChannel(const std::string& name, int fd);
/* Creates a pair of input channels.
@@ -183,9 +185,14 @@
/* Returns a new object that has a duplicate of this channel's fd. */
sp<InputChannel> dup() const;
+ status_t write(Parcel& out) const;
+ status_t read(const Parcel& from);
+
private:
+ void setFd(int fd);
+
std::string mName;
- int mFd;
+ int mFd = -1;
};
/*
diff --git a/services/inputflinger/InputWindow.h b/include/input/InputWindow.h
similarity index 97%
rename from services/inputflinger/InputWindow.h
rename to include/input/InputWindow.h
index c481853..7c284dd 100644
--- a/services/inputflinger/InputWindow.h
+++ b/include/input/InputWindow.h
@@ -27,7 +27,7 @@
#include "InputApplication.h"
namespace android {
-
+class Parcel;
/*
* Describes the properties of a window that can receive input.
@@ -151,6 +151,9 @@
bool supportsSplitTouch() const;
bool overlaps(const InputWindowInfo* other) const;
+
+ status_t write(Parcel& output) const;
+ static InputWindowInfo read(const Parcel& from);
};
@@ -168,9 +171,7 @@
return mInfo;
}
- inline sp<InputChannel> getInputChannel() const {
- return mInfo ? mInfo->inputChannel : nullptr;
- }
+ sp<InputChannel> getInputChannel() const;
inline std::string getName() const {
return mInfo ? mInfo->name : "<invalid>";
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index 02064c6..7ecadf8 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -44,6 +44,7 @@
"libgui",
"libhidlbase",
"libhidltransport",
+ "libinput",
"libui",
"libutils",
"libnativewindow"
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index a2d6a8a..72558a6 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -47,11 +47,14 @@
"InputTransport.cpp",
"VelocityControl.cpp",
"VelocityTracker.cpp",
+ "InputApplication.cpp",
+ "InputWindow.cpp"
],
shared_libs: [
"libutils",
"libbinder",
+ "libui"
],
sanitize: {
diff --git a/services/inputflinger/InputApplication.cpp b/libs/input/InputApplication.cpp
similarity index 96%
rename from services/inputflinger/InputApplication.cpp
rename to libs/input/InputApplication.cpp
index c56dfe6..a0d1668 100644
--- a/services/inputflinger/InputApplication.cpp
+++ b/libs/input/InputApplication.cpp
@@ -16,7 +16,7 @@
#define LOG_TAG "InputApplication"
-#include "InputApplication.h"
+#include <input/InputApplication.h>
#include <android/log.h>
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 770d483..32444f9 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -30,6 +30,7 @@
#include <cutils/properties.h>
#include <log/log.h>
+#include <binder/Parcel.h>
#include <input/InputTransport.h>
namespace android {
@@ -100,15 +101,13 @@
// --- InputChannel ---
InputChannel::InputChannel(const std::string& name, int fd) :
- mName(name), mFd(fd) {
+ mName(name) {
#if DEBUG_CHANNEL_LIFECYCLE
ALOGD("Input channel constructed: name='%s', fd=%d",
mName.c_str(), fd);
#endif
- int result = fcntl(mFd, F_SETFL, O_NONBLOCK);
- LOG_ALWAYS_FATAL_IF(result != 0, "channel '%s' ~ Could not make socket "
- "non-blocking. errno=%d", mName.c_str(), errno);
+ setFd(fd);
}
InputChannel::~InputChannel() {
@@ -120,6 +119,18 @@
::close(mFd);
}
+void InputChannel::setFd(int fd) {
+ if (mFd > 0) {
+ ::close(mFd);
+ }
+ mFd = fd;
+ if (mFd > 0) {
+ int result = fcntl(mFd, F_SETFL, O_NONBLOCK);
+ LOG_ALWAYS_FATAL_IF(result != 0, "channel '%s' ~ Could not make socket "
+ "non-blocking. errno=%d", mName.c_str(), errno);
+ }
+}
+
status_t InputChannel::openInputChannelPair(const std::string& name,
sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
int sockets[2];
@@ -230,6 +241,31 @@
}
+status_t InputChannel::write(Parcel& out) const {
+ status_t s = out.writeString8(String8(getName().c_str()));
+
+ if (s != OK) {
+ return s;
+ }
+
+ s = out.writeDupFileDescriptor(getFd());
+
+ return s;
+}
+
+status_t InputChannel::read(const Parcel& from) {
+ mName = from.readString8();
+
+ int rawFd = from.readFileDescriptor();
+ setFd(::dup(rawFd));
+
+ if (mFd < 0) {
+ return BAD_VALUE;
+ }
+
+ return OK;
+}
+
// --- InputPublisher ---
InputPublisher::InputPublisher(const sp<InputChannel>& channel) :
diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp
new file mode 100644
index 0000000..f94faba
--- /dev/null
+++ b/libs/input/InputWindow.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "InputWindow"
+#define LOG_NDEBUG 0
+
+#include <binder/Parcel.h>
+#include <input/InputWindow.h>
+#include <input/InputTransport.h>
+
+#include <log/log.h>
+
+#include <ui/Rect.h>
+#include <ui/Region.h>
+
+namespace android {
+
+// --- InputWindowInfo ---
+void InputWindowInfo::addTouchableRegion(const Rect& region) {
+ touchableRegion.orSelf(region);
+}
+
+bool InputWindowInfo::touchableRegionContainsPoint(int32_t x, int32_t y) const {
+ return touchableRegion.contains(x,y);
+}
+
+bool InputWindowInfo::frameContainsPoint(int32_t x, int32_t y) const {
+ return x >= frameLeft && x < frameRight
+ && y >= frameTop && y < frameBottom;
+}
+
+bool InputWindowInfo::isTrustedOverlay() const {
+ return layoutParamsType == TYPE_INPUT_METHOD
+ || layoutParamsType == TYPE_INPUT_METHOD_DIALOG
+ || layoutParamsType == TYPE_MAGNIFICATION_OVERLAY
+ || layoutParamsType == TYPE_STATUS_BAR
+ || layoutParamsType == TYPE_NAVIGATION_BAR
+ || layoutParamsType == TYPE_NAVIGATION_BAR_PANEL
+ || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY
+ || layoutParamsType == TYPE_DOCK_DIVIDER
+ || layoutParamsType == TYPE_ACCESSIBILITY_OVERLAY
+ || layoutParamsType == TYPE_INPUT_CONSUMER;
+}
+
+bool InputWindowInfo::supportsSplitTouch() const {
+ return layoutParamsFlags & FLAG_SPLIT_TOUCH;
+}
+
+bool InputWindowInfo::overlaps(const InputWindowInfo* other) const {
+ return frameLeft < other->frameRight && frameRight > other->frameLeft
+ && frameTop < other->frameBottom && frameBottom > other->frameTop;
+}
+
+status_t InputWindowInfo::write(Parcel& output) const {
+ if (inputChannel == nullptr) {
+ output.writeInt32(0);
+ return OK;
+ }
+ output.writeInt32(1);
+ status_t s = inputChannel->write(output);
+ if (s != OK) return s;
+
+ output.writeString8(String8(name.c_str()));
+ output.writeInt32(layoutParamsFlags);
+ output.writeInt32(layoutParamsType);
+ output.writeInt64(dispatchingTimeout);
+ output.writeInt32(frameLeft);
+ output.writeInt32(frameTop);
+ output.writeInt32(frameRight);
+ output.writeInt32(frameBottom);
+ output.writeFloat(scaleFactor);
+ output.writeBool(visible);
+ output.writeBool(canReceiveKeys);
+ output.writeBool(hasFocus);
+ output.writeBool(hasWallpaper);
+ output.writeBool(paused);
+ output.writeInt32(layer);
+ output.writeInt32(ownerPid);
+ output.writeInt32(ownerUid);
+ output.writeInt32(inputFeatures);
+ output.writeInt32(displayId);
+ output.write(touchableRegion);
+
+ return OK;
+}
+
+InputWindowInfo InputWindowInfo::read(const Parcel& from) {
+ InputWindowInfo ret;
+
+ if (from.readInt32() == 0) {
+ return ret;
+
+ }
+ sp<InputChannel> inputChannel = new InputChannel();
+ status_t s = inputChannel->read(from);
+ if (s != OK) {
+ return ret;
+ }
+
+ ret.inputChannel = inputChannel;
+ ret.name = from.readString8().c_str();
+ ret.layoutParamsFlags = from.readInt32();
+ ret.layoutParamsType = from.readInt32();
+ ret.dispatchingTimeout = from.readInt64();
+ ret.frameLeft = from.readInt32();
+ ret.frameTop = from.readInt32();
+ ret.frameRight = from.readInt32();
+ ret.frameBottom = from.readInt32();
+ ret.scaleFactor = from.readFloat();
+ ret.visible = from.readBool();
+ ret.canReceiveKeys = from.readBool();
+ ret.hasFocus = from.readBool();
+ ret.hasWallpaper = from.readBool();
+ ret.paused = from.readBool();
+ ret.layer = from.readInt32();
+ ret.ownerPid = from.readInt32();
+ ret.ownerUid = from.readInt32();
+ ret.inputFeatures = from.readInt32();
+ ret.displayId = from.readInt32();
+ from.read(ret.touchableRegion);
+
+ return ret;
+}
+
+// --- InputWindowHandle ---
+
+InputWindowHandle::InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle) :
+ inputApplicationHandle(inputApplicationHandle), mInfo(nullptr) {
+}
+
+InputWindowHandle::~InputWindowHandle() {
+ delete mInfo;
+}
+
+void InputWindowHandle::releaseInfo() {
+ if (mInfo) {
+ delete mInfo;
+ mInfo = nullptr;
+ }
+}
+
+sp<InputChannel> InputWindowHandle::getInputChannel() const {
+ return mInfo ? mInfo->inputChannel : nullptr;
+}
+
+} // namespace android
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index f06119f..fdd945e 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -6,6 +6,7 @@
"InputEvent_test.cpp",
"InputPublisherAndConsumer_test.cpp",
"VelocityTracker_test.cpp",
+ "InputWindow_test.cpp"
],
cflags: [
"-Wall",
@@ -34,4 +35,12 @@
"-Wall",
"-Werror",
],
+ shared_libs: [
+ "libinput",
+ "libcutils",
+ "libutils",
+ "libbinder",
+ "libui",
+ "libbase",
+ ]
}
diff --git a/libs/input/tests/InputWindow_test.cpp b/libs/input/tests/InputWindow_test.cpp
new file mode 100644
index 0000000..39ad26e
--- /dev/null
+++ b/libs/input/tests/InputWindow_test.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <binder/Parcel.h>
+
+#include <input/InputWindow.h>
+#include <input/InputTransport.h>
+
+namespace android {
+namespace test {
+
+TEST(InputWindowInfo, ParcellingWithoutChannel) {
+ InputWindowInfo i;
+ i.inputChannel = nullptr;
+
+ Parcel p;
+ ASSERT_EQ(OK, i.write(p));
+ p.setDataPosition(0);
+ InputWindowInfo i2 = InputWindowInfo::read(p);
+ ASSERT_TRUE(i2.inputChannel == nullptr);
+}
+
+TEST(InputWindowInfo, Parcelling) {
+ sp<InputChannel> channel, junkChannel;
+ status_t result = InputChannel::openInputChannelPair("name", channel, junkChannel);
+ ASSERT_EQ(OK, result) << "openInputChannelPair should have returned valid channels";
+
+ InputWindowInfo i;
+ i.inputChannel = channel;
+ i.name = "Foobar";
+ i.layoutParamsFlags = 7;
+ i.layoutParamsType = 39;
+ i.dispatchingTimeout = 12;
+ i.frameLeft = 93;
+ i.frameTop = 34;
+ i.frameRight = 16;
+ i.frameBottom = 19;
+ i.scaleFactor = 0.3;
+ i.visible = false;
+ i.canReceiveKeys = false;
+ i.hasFocus = false;
+ i.hasWallpaper = false;
+ i.paused = false;
+ i.layer = 7;
+ i.ownerPid = 19;
+ i.ownerUid = 24;
+ i.inputFeatures = 29;
+ i.displayId = 34;
+
+ Parcel p;
+ i.write(p);
+
+ p.setDataPosition(0);
+ InputWindowInfo i2 = InputWindowInfo::read(p);
+ ASSERT_EQ(i.inputChannel->getName(), i2.inputChannel->getName());
+ ASSERT_EQ(i.name, i2.name);
+ ASSERT_EQ(i.layoutParamsFlags, i2.layoutParamsFlags);
+ ASSERT_EQ(i.layoutParamsType, i2.layoutParamsType);
+ ASSERT_EQ(i.dispatchingTimeout, i2.dispatchingTimeout);
+ ASSERT_EQ(i.frameLeft, i2.frameLeft);
+ ASSERT_EQ(i.frameTop, i2.frameTop);
+ ASSERT_EQ(i.frameRight, i2.frameRight);
+ ASSERT_EQ(i.frameBottom, i2.frameBottom);
+ ASSERT_EQ(i.scaleFactor, i2.scaleFactor);
+ ASSERT_EQ(i.visible, i2.visible);
+ ASSERT_EQ(i.canReceiveKeys, i2.canReceiveKeys);
+ ASSERT_EQ(i.hasFocus, i2.hasFocus);
+ ASSERT_EQ(i.hasWallpaper, i2.hasWallpaper);
+ ASSERT_EQ(i.paused, i2.paused);
+ ASSERT_EQ(i.layer, i2.layer);
+ ASSERT_EQ(i.ownerPid, i2.ownerPid);
+ ASSERT_EQ(i.ownerUid, i2.ownerUid);
+ ASSERT_EQ(i.inputFeatures, i2.inputFeatures);
+ ASSERT_EQ(i.displayId, i2.displayId);
+}
+
+} // namespace test
+} // namespace android
diff --git a/libs/vr/libbufferhub/consumer_buffer.cpp b/libs/vr/libbufferhub/consumer_buffer.cpp
index 4e8c36b..c9d8554 100644
--- a/libs/vr/libbufferhub/consumer_buffer.cpp
+++ b/libs/vr/libbufferhub/consumer_buffer.cpp
@@ -174,10 +174,5 @@
int ConsumerBuffer::Discard() { return Release(LocalHandle()); }
-int ConsumerBuffer::SetIgnore(bool ignore) {
- return ReturnStatusOrError(
- InvokeRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(ignore));
-}
-
} // namespace dvr
} // namespace android
diff --git a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
index 1483e16..0c7fc90 100644
--- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
+++ b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
@@ -314,7 +314,6 @@
kOpProducerGain,
kOpConsumerAcquire,
kOpConsumerRelease,
- kOpConsumerSetIgnore,
kOpProducerBufferDetach,
kOpConsumerBufferDetach,
kOpDetachedBufferCreate,
@@ -348,7 +347,6 @@
PDX_REMOTE_METHOD(ConsumerAcquire, kOpConsumerAcquire, LocalFence(Void));
PDX_REMOTE_METHOD(ConsumerRelease, kOpConsumerRelease,
void(LocalFence release_fence));
- PDX_REMOTE_METHOD(ConsumerSetIgnore, kOpConsumerSetIgnore, void(bool ignore));
PDX_REMOTE_METHOD(ProducerBufferDetach, kOpProducerBufferDetach,
LocalChannelHandle(Void));
diff --git a/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h b/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h
index 089eff8..2044c53 100644
--- a/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h
@@ -76,13 +76,6 @@
// negative unix error code.
int Discard();
- // When set, this consumer is no longer notified when this buffer is
- // available. The system behaves as if Discard() is immediately called
- // whenever the buffer is posted. If ignore is set to true while a buffer is
- // pending, it will act as if Discard() was also called.
- // This returns zero or a negative unix error code.
- int SetIgnore(bool ignore);
-
private:
friend BASE;
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 1ed9850..d2dc514 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -562,6 +562,15 @@
break;
}
}
+
+ // If the driver doesn't understand it, we should map sRGB-encoded P3 to
+ // sRGB rather than just dropping the colorspace on the floor.
+ // For this format, the driver is expected to apply the sRGB
+ // transfer function during framebuffer operations.
+ if (!copyAttribute && attr[1] == EGL_GL_COLORSPACE_DISPLAY_P3_EXT) {
+ strippedAttribList->push_back(attr[0]);
+ strippedAttribList->push_back(EGL_GL_COLORSPACE_SRGB_KHR);
+ }
}
if (copyAttribute) {
strippedAttribList->push_back(attr[0]);
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 45efb9f..9a65452 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -19,12 +19,10 @@
srcs: [
"EventHub.cpp",
- "InputApplication.cpp",
"InputDispatcher.cpp",
"InputListener.cpp",
"InputManager.cpp",
"InputReader.cpp",
- "InputWindow.cpp",
],
shared_libs: [
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index d609573..38104c4 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -235,6 +235,12 @@
}
}
+template<typename T, typename U>
+static T getValueByKey(std::unordered_map<U, T>& map, U key) {
+ typename std::unordered_map<U, T>::const_iterator it = map.find(key);
+ return it != map.end() ? it->second : T{};
+}
+
// --- InputDispatcher ---
@@ -244,6 +250,7 @@
mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
mNextUnblockedEvent(nullptr),
mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),
+ mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
mLooper = new Looper(false);
@@ -808,8 +815,10 @@
if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
CommandEntry* commandEntry = postCommandLocked(
& InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
- if (mFocusedWindowHandle != nullptr) {
- commandEntry->inputWindowHandle = mFocusedWindowHandle;
+ sp<InputWindowHandle> focusedWindowHandle =
+ getValueByKey(mFocusedWindowHandlesByDisplay, getTargetDisplayId(entry));
+ if (focusedWindowHandle != nullptr) {
+ commandEntry->inputWindowHandle = focusedWindowHandle;
}
commandEntry->keyEntry = entry;
entry->refCount += 1;
@@ -1108,17 +1117,49 @@
mInputTargetWaitApplicationHandle.clear();
}
+/**
+ * Get the display id that the given event should go to. If this event specifies a valid display id,
+ * then it should be dispatched to that display. Otherwise, the event goes to the focused display.
+ * Focused display is the display that the user most recently interacted with.
+ */
+int32_t InputDispatcher::getTargetDisplayId(const EventEntry* entry) {
+ int32_t displayId;
+ switch (entry->type) {
+ case EventEntry::TYPE_KEY: {
+ const KeyEntry* typedEntry = static_cast<const KeyEntry*>(entry);
+ displayId = typedEntry->displayId;
+ break;
+ }
+ case EventEntry::TYPE_MOTION: {
+ const MotionEntry* typedEntry = static_cast<const MotionEntry*>(entry);
+ displayId = typedEntry->displayId;
+ break;
+ }
+ default: {
+ ALOGE("Unsupported event type '%" PRId32 "' for target display.", entry->type);
+ return ADISPLAY_ID_NONE;
+ }
+ }
+ return displayId == ADISPLAY_ID_NONE ? mFocusedDisplayId : displayId;
+}
+
int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
const EventEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime) {
int32_t injectionResult;
std::string reason;
+ int32_t displayId = getTargetDisplayId(entry);
+ sp<InputWindowHandle> focusedWindowHandle =
+ getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
+ sp<InputApplicationHandle> focusedApplicationHandle =
+ getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
+
// If there is no currently focused window and no focused application
// then drop the event.
- if (mFocusedWindowHandle == nullptr) {
- if (mFocusedApplicationHandle != nullptr) {
+ if (focusedWindowHandle == nullptr) {
+ if (focusedApplicationHandle != nullptr) {
injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- mFocusedApplicationHandle, nullptr, nextWakeupTime,
+ focusedApplicationHandle, nullptr, nextWakeupTime,
"Waiting because no window has focus but there is a "
"focused application that may eventually add a window "
"when it finishes starting up.");
@@ -1131,23 +1172,23 @@
}
// Check permissions.
- if (! checkInjectionPermission(mFocusedWindowHandle, entry->injectionState)) {
+ if (!checkInjectionPermission(focusedWindowHandle, entry->injectionState)) {
injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
goto Failed;
}
// Check whether the window is ready for more input.
reason = checkWindowReadyForMoreInputLocked(currentTime,
- mFocusedWindowHandle, entry, "focused");
+ focusedWindowHandle, entry, "focused");
if (!reason.empty()) {
injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime, reason.c_str());
+ focusedApplicationHandle, focusedWindowHandle, nextWakeupTime, reason.c_str());
goto Unresponsive;
}
// Success! Output targets.
injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
- addWindowTargetLocked(mFocusedWindowHandle,
+ addWindowTargetLocked(focusedWindowHandle,
InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS, BitSet32(0),
inputTargets);
@@ -1802,8 +1843,11 @@
}
void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
- if (mFocusedWindowHandle != nullptr) {
- const InputWindowInfo* info = mFocusedWindowHandle->getInfo();
+ int32_t displayId = getTargetDisplayId(eventEntry);
+ sp<InputWindowHandle> focusedWindowHandle =
+ getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
+ if (focusedWindowHandle != nullptr) {
+ const InputWindowInfo* info = focusedWindowHandle->getInfo();
if (info->inputFeatures & InputWindowInfo::INPUT_FEATURE_DISABLE_USER_ACTIVITY) {
#if DEBUG_DISPATCH_CYCLE
ALOGD("Not poking user activity: disabled by window '%s'.", info->name.c_str());
@@ -2978,18 +3022,7 @@
// Copy old handles for release if they are no longer present.
const Vector<sp<InputWindowHandle>> oldWindowHandles = getWindowHandlesLocked(displayId);
- // TODO(b/111361570): multi-display focus, one focus window per display.
- sp<InputWindowHandle> newFocusedWindowHandle = mFocusedWindowHandle;
- // Reset newFocusedWindowHandle to nullptr if current display own the focus window,
- // that will be updated below when going through all window handles in current display.
- // And if list of window handles becomes empty then it will be updated by other display.
- if (mFocusedWindowHandle != nullptr) {
- const InputWindowInfo* info = mFocusedWindowHandle->getInfo();
- if (info == nullptr || info->displayId == displayId) {
- newFocusedWindowHandle = nullptr;
- }
- }
-
+ sp<InputWindowHandle> newFocusedWindowHandle = nullptr;
bool foundHoveredWindow = false;
if (inputWindowHandles.isEmpty()) {
@@ -3026,28 +3059,31 @@
mLastHoverWindowHandle = nullptr;
}
- // TODO(b/111361570): multi-display focus, one focus in all display in current.
- if (mFocusedWindowHandle != newFocusedWindowHandle) {
- if (mFocusedWindowHandle != nullptr) {
+ sp<InputWindowHandle> oldFocusedWindowHandle =
+ getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
+
+ if (oldFocusedWindowHandle != newFocusedWindowHandle) {
+ if (oldFocusedWindowHandle != nullptr) {
#if DEBUG_FOCUS
ALOGD("Focus left window: %s",
- mFocusedWindowHandle->getName().c_str());
+ oldFocusedWindowHandle->getName().c_str());
#endif
- sp<InputChannel> focusedInputChannel = mFocusedWindowHandle->getInputChannel();
+ sp<InputChannel> focusedInputChannel = oldFocusedWindowHandle->getInputChannel();
if (focusedInputChannel != nullptr) {
CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
"focus left window");
synthesizeCancelationEventsForInputChannelLocked(
focusedInputChannel, options);
}
+ mFocusedWindowHandlesByDisplay.erase(displayId);
}
if (newFocusedWindowHandle != nullptr) {
#if DEBUG_FOCUS
ALOGD("Focus entered window: %s",
newFocusedWindowHandle->getName().c_str());
#endif
+ mFocusedWindowHandlesByDisplay[displayId] = newFocusedWindowHandle;
}
- mFocusedWindowHandle = newFocusedWindowHandle;
}
ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(displayId);
@@ -3096,25 +3132,28 @@
}
void InputDispatcher::setFocusedApplication(
- const sp<InputApplicationHandle>& inputApplicationHandle) {
+ int32_t displayId, const sp<InputApplicationHandle>& inputApplicationHandle) {
#if DEBUG_FOCUS
ALOGD("setFocusedApplication");
#endif
{ // acquire lock
AutoMutex _l(mLock);
+ sp<InputApplicationHandle> oldFocusedApplicationHandle =
+ getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
if (inputApplicationHandle != nullptr && inputApplicationHandle->updateInfo()) {
- if (mFocusedApplicationHandle != inputApplicationHandle) {
- if (mFocusedApplicationHandle != nullptr) {
+ if (oldFocusedApplicationHandle != inputApplicationHandle) {
+ if (oldFocusedApplicationHandle != nullptr) {
resetANRTimeoutsLocked();
- mFocusedApplicationHandle->releaseInfo();
+ oldFocusedApplicationHandle->releaseInfo();
}
- mFocusedApplicationHandle = inputApplicationHandle;
+ mFocusedApplicationHandlesByDisplay[displayId] = inputApplicationHandle;
}
- } else if (mFocusedApplicationHandle != nullptr) {
+ } else if (oldFocusedApplicationHandle != nullptr) {
resetANRTimeoutsLocked();
- mFocusedApplicationHandle->releaseInfo();
- mFocusedApplicationHandle.clear();
+ oldFocusedApplicationHandle->releaseInfo();
+ oldFocusedApplicationHandle.clear();
+ mFocusedApplicationHandlesByDisplay.erase(displayId);
}
#if DEBUG_FOCUS
@@ -3126,6 +3165,62 @@
mLooper->wake();
}
+/**
+ * Sets the focused display, which is responsible for receiving focus-dispatched input events where
+ * the display not specified.
+ *
+ * We track any unreleased events for each window. If a window loses the ability to receive the
+ * released event, we will send a cancel event to it. So when the focused display is changed, we
+ * cancel all the unreleased display-unspecified events for the focused window on the old focused
+ * display. The display-specified events won't be affected.
+ */
+void InputDispatcher::setFocusedDisplay(int32_t displayId) {
+#if DEBUG_FOCUS
+ ALOGD("setFocusedDisplay displayId=%" PRId32, displayId);
+#endif
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ if (mFocusedDisplayId != displayId) {
+ sp<InputWindowHandle> oldFocusedWindowHandle =
+ getValueByKey(mFocusedWindowHandlesByDisplay, mFocusedDisplayId);
+ if (oldFocusedWindowHandle != nullptr) {
+ sp<InputChannel> inputChannel = oldFocusedWindowHandle->getInputChannel();
+ if (inputChannel != nullptr) {
+ CancelationOptions options(
+ CancelationOptions::CANCEL_DISPLAY_UNSPECIFIED_EVENTS,
+ "The display which contains this window no longer has focus.");
+ synthesizeCancelationEventsForInputChannelLocked(inputChannel, options);
+ }
+ }
+ mFocusedDisplayId = displayId;
+
+ // Sanity check
+ sp<InputWindowHandle> newFocusedWindowHandle =
+ getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
+ if (newFocusedWindowHandle == nullptr) {
+ ALOGW("Focused display #%" PRId32 " does not have a focused window.", displayId);
+ if (!mFocusedWindowHandlesByDisplay.empty()) {
+ ALOGE("But another display has a focused window:");
+ for (auto& it : mFocusedWindowHandlesByDisplay) {
+ const int32_t displayId = it.first;
+ const sp<InputWindowHandle>& windowHandle = it.second;
+ ALOGE("Display #%" PRId32 " has focused window: '%s'\n",
+ displayId, windowHandle->getName().c_str());
+ }
+ }
+ }
+ }
+
+#if DEBUG_FOCUS
+ logDispatchStateLocked();
+#endif
+ } // release lock
+
+ // Wake up poll loop since it may need to make new input dispatching choices.
+ mLooper->wake();
+}
+
void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
#if DEBUG_FOCUS
ALOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
@@ -3152,7 +3247,7 @@
}
#if DEBUG_FOCUS
- //logDispatchStateLocked();
+ logDispatchStateLocked();
#endif
} // release lock
@@ -3297,17 +3392,35 @@
void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
dump += StringPrintf(INDENT "DispatchEnabled: %d\n", mDispatchEnabled);
dump += StringPrintf(INDENT "DispatchFrozen: %d\n", mDispatchFrozen);
+ dump += StringPrintf(INDENT "FocusedDisplayId: %" PRId32 "\n", mFocusedDisplayId);
- if (mFocusedApplicationHandle != nullptr) {
- dump += StringPrintf(INDENT "FocusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
- mFocusedApplicationHandle->getName().c_str(),
- mFocusedApplicationHandle->getDispatchingTimeout(
- DEFAULT_INPUT_DISPATCHING_TIMEOUT) / 1000000.0);
+ if (!mFocusedApplicationHandlesByDisplay.empty()) {
+ dump += StringPrintf(INDENT "FocusedApplications:\n");
+ for (auto& it : mFocusedApplicationHandlesByDisplay) {
+ const int32_t displayId = it.first;
+ const sp<InputApplicationHandle>& applicationHandle = it.second;
+ dump += StringPrintf(
+ INDENT2 "displayId=%" PRId32 ", name='%s', dispatchingTimeout=%0.3fms\n",
+ displayId,
+ applicationHandle->getName().c_str(),
+ applicationHandle->getDispatchingTimeout(
+ DEFAULT_INPUT_DISPATCHING_TIMEOUT) / 1000000.0);
+ }
} else {
- dump += StringPrintf(INDENT "FocusedApplication: <null>\n");
+ dump += StringPrintf(INDENT "FocusedApplications: <none>\n");
}
- dump += StringPrintf(INDENT "FocusedWindow: name='%s'\n",
- mFocusedWindowHandle != nullptr ? mFocusedWindowHandle->getName().c_str() : "<null>");
+
+ if (!mFocusedWindowHandlesByDisplay.empty()) {
+ dump += StringPrintf(INDENT "FocusedWindows:\n");
+ for (auto& it : mFocusedWindowHandlesByDisplay) {
+ const int32_t displayId = it.first;
+ const sp<InputWindowHandle>& windowHandle = it.second;
+ dump += StringPrintf(INDENT2 "displayId=%" PRId32 ", name='%s'\n",
+ displayId, windowHandle->getName().c_str());
+ }
+ } else {
+ dump += StringPrintf(INDENT "FocusedWindows: <none>\n");
+ }
if (!mTouchStatesByDisplay.isEmpty()) {
dump += StringPrintf(INDENT "TouchStatesByDisplay:\n");
@@ -4527,6 +4640,8 @@
return true;
case CancelationOptions::CANCEL_FALLBACK_EVENTS:
return memento.flags & AKEY_EVENT_FLAG_FALLBACK;
+ case CancelationOptions::CANCEL_DISPLAY_UNSPECIFIED_EVENTS:
+ return memento.displayId == ADISPLAY_ID_NONE;
default:
return false;
}
@@ -4545,6 +4660,8 @@
return memento.source & AINPUT_SOURCE_CLASS_POINTER;
case CancelationOptions::CANCEL_NON_POINTER_EVENTS:
return !(memento.source & AINPUT_SOURCE_CLASS_POINTER);
+ case CancelationOptions::CANCEL_DISPLAY_UNSPECIFIED_EVENTS:
+ return memento.displayId == ADISPLAY_ID_NONE;
default:
return false;
}
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index fdf75f6..aedad2f 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -18,7 +18,9 @@
#define _UI_INPUT_DISPATCHER_H
#include <input/Input.h>
+#include <input/InputApplication.h>
#include <input/InputTransport.h>
+#include <input/InputWindow.h>
#include <utils/KeyedVector.h>
#include <utils/Vector.h>
#include <utils/threads.h>
@@ -33,8 +35,6 @@
#include <limits.h>
#include <unordered_map>
-#include "InputWindow.h"
-#include "InputApplication.h"
#include "InputListener.h"
@@ -311,12 +311,18 @@
virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles,
int32_t displayId) = 0;
- /* Sets the focused application.
+ /* Sets the focused application on the given display.
*
* This method may be called on any thread (usually by the input manager).
*/
virtual void setFocusedApplication(
- const sp<InputApplicationHandle>& inputApplicationHandle) = 0;
+ int32_t displayId, const sp<InputApplicationHandle>& inputApplicationHandle) = 0;
+
+ /* Sets the focused display.
+ *
+ * This method may be called on any thread (usually by the input manager).
+ */
+ virtual void setFocusedDisplay(int32_t displayId) = 0;
/* Sets the input dispatching mode.
*
@@ -391,7 +397,9 @@
virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles,
int32_t displayId);
- virtual void setFocusedApplication(const sp<InputApplicationHandle>& inputApplicationHandle);
+ virtual void setFocusedApplication(int32_t displayId,
+ const sp<InputApplicationHandle>& inputApplicationHandle);
+ virtual void setFocusedDisplay(int32_t displayId);
virtual void setInputDispatchMode(bool enabled, bool frozen);
virtual void setInputFilterEnabled(bool enabled);
@@ -686,6 +694,10 @@
CANCEL_POINTER_EVENTS = 1,
CANCEL_NON_POINTER_EVENTS = 2,
CANCEL_FALLBACK_EVENTS = 3,
+
+ /* Cancel events where the display not specified. These events would go to the focused
+ * display. */
+ CANCEL_DISPLAY_UNSPECIFIED_EVENTS = 4,
};
// The criterion to use to determine which events should be canceled.
@@ -966,7 +978,7 @@
bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const;
// Focus tracking for keys, trackball, etc.
- sp<InputWindowHandle> mFocusedWindowHandle;
+ std::unordered_map<int32_t, sp<InputWindowHandle>> mFocusedWindowHandlesByDisplay;
// Focus tracking for touch.
struct TouchedWindow {
@@ -997,8 +1009,11 @@
KeyedVector<int32_t, TouchState> mTouchStatesByDisplay;
TouchState mTempTouchState;
- // Focused application.
- sp<InputApplicationHandle> mFocusedApplicationHandle;
+ // Focused applications.
+ std::unordered_map<int32_t, sp<InputApplicationHandle>> mFocusedApplicationHandlesByDisplay;
+
+ // Top focused display.
+ int32_t mFocusedDisplayId;
// Dispatcher state at time of last ANR.
std::string mLastANRState;
@@ -1046,6 +1061,7 @@
nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime);
void resetANRTimeoutsLocked();
+ int32_t getTargetDisplayId(const EventEntry* entry);
int32_t findFocusedWindowTargetsLocked(nsecs_t currentTime, const EventEntry* entry,
Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime);
int32_t findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry* entry,
diff --git a/services/inputflinger/InputWindow.cpp b/services/inputflinger/InputWindow.cpp
deleted file mode 100644
index 0d1dfdd..0000000
--- a/services/inputflinger/InputWindow.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "InputWindow"
-#define LOG_NDEBUG 0
-
-#include "InputWindow.h"
-
-#include <log/log.h>
-
-#include <ui/Rect.h>
-#include <ui/Region.h>
-
-namespace android {
-
-// --- InputWindowInfo ---
-void InputWindowInfo::addTouchableRegion(const Rect& region) {
- touchableRegion.orSelf(region);
-}
-
-bool InputWindowInfo::touchableRegionContainsPoint(int32_t x, int32_t y) const {
- return touchableRegion.contains(x,y);
-}
-
-bool InputWindowInfo::frameContainsPoint(int32_t x, int32_t y) const {
- return x >= frameLeft && x < frameRight
- && y >= frameTop && y < frameBottom;
-}
-
-bool InputWindowInfo::isTrustedOverlay() const {
- return layoutParamsType == TYPE_INPUT_METHOD
- || layoutParamsType == TYPE_INPUT_METHOD_DIALOG
- || layoutParamsType == TYPE_MAGNIFICATION_OVERLAY
- || layoutParamsType == TYPE_STATUS_BAR
- || layoutParamsType == TYPE_NAVIGATION_BAR
- || layoutParamsType == TYPE_NAVIGATION_BAR_PANEL
- || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY
- || layoutParamsType == TYPE_DOCK_DIVIDER
- || layoutParamsType == TYPE_ACCESSIBILITY_OVERLAY
- || layoutParamsType == TYPE_INPUT_CONSUMER;
-}
-
-bool InputWindowInfo::supportsSplitTouch() const {
- return layoutParamsFlags & FLAG_SPLIT_TOUCH;
-}
-
-bool InputWindowInfo::overlaps(const InputWindowInfo* other) const {
- return frameLeft < other->frameRight && frameRight > other->frameLeft
- && frameTop < other->frameBottom && frameBottom > other->frameTop;
-}
-
-
-// --- InputWindowHandle ---
-
-InputWindowHandle::InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle) :
- inputApplicationHandle(inputApplicationHandle), mInfo(nullptr) {
-}
-
-InputWindowHandle::~InputWindowHandle() {
- delete mInfo;
-}
-
-void InputWindowHandle::releaseInfo() {
- if (mInfo) {
- delete mInfo;
- mInfo = nullptr;
- }
-}
-
-} // namespace android
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 61dcdd9..2bbfb1b 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -382,12 +382,13 @@
int32_t mDisplayId;
};
-static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher) {
+static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
+ int32_t displayId = ADISPLAY_ID_NONE) {
KeyEvent event;
nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
// Define a valid key down event.
- event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
AKEY_EVENT_ACTION_DOWN, /* flags */ 0,
AKEYCODE_A, KEY_A, AMETA_NONE, /* repeatCount */ 0, currentTime, currentTime);
@@ -466,7 +467,7 @@
sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second");
// Set focus application.
- mDispatcher->setFocusedApplication(application);
+ mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
// Expect one focus window exist in display.
windowSecond->setFocus();
@@ -511,15 +512,21 @@
windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
}
-// TODO(b/111361570): multi-display focus, one focus window per display.
TEST_F(InputDispatcherTest, SetInputWindow_FocusedInMultiDisplay) {
sp<FakeApplicationHandle> application = new FakeApplicationHandle();
sp<FakeWindowHandle> windowInPrimary = new FakeWindowHandle(application, mDispatcher, "D_1");
sp<FakeApplicationHandle> application2 = new FakeApplicationHandle();
sp<FakeWindowHandle> windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2");
+ constexpr int32_t SECOND_DISPLAY_ID = 1;
+
+ // Set focus to primary display window.
+ mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+ windowInPrimary->setFocus();
+
// Set focus to second display window.
- mDispatcher->setFocusedApplication(application2);
+ mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
+ mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
windowInSecondary->setFocus();
// Update all windows per displays.
@@ -527,13 +534,18 @@
inputWindowHandles.push(windowInPrimary);
mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
- constexpr int32_t SECOND_DISPLAY_ID = 1;
windowInSecondary->setDisplayId(SECOND_DISPLAY_ID);
Vector<sp<InputWindowHandle>> inputWindowHandles_Second;
inputWindowHandles_Second.push(windowInSecondary);
mDispatcher->setInputWindows(inputWindowHandles_Second, SECOND_DISPLAY_ID);
- // Test inject a key down.
+ // Test inject a key down with display id specified.
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
+ << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+ windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_DEFAULT);
+ windowInSecondary->assertNoEvents();
+
+ // Test inject a key down without display id specified.
ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
<< "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
windowInPrimary->assertNoEvents();
@@ -545,6 +557,7 @@
// Expect old focus should receive a cancel event.
windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
+ // TODO(b/111361570): Validate that the event here was marked as canceled.
// Test inject a key down, should timeout because of no target window.
ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 7c56e5c..f4e728b 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -47,6 +47,7 @@
#include "SensorRecord.h"
#include "SensorRegistrationInfo.h"
+#include <ctime>
#include <inttypes.h>
#include <math.h>
#include <sched.h>
@@ -423,6 +424,11 @@
} else {
// Default dump the sensor list and debugging information.
//
+ timespec curTime;
+ clock_gettime(CLOCK_REALTIME, &curTime);
+ struct tm* timeinfo = localtime(&(curTime.tv_sec));
+ result.appendFormat("Captured at: %02d:%02d:%02d.%03d\n", timeinfo->tm_hour,
+ timeinfo->tm_min, timeinfo->tm_sec, (int)ns2ms(curTime.tv_nsec));
result.append("Sensor Device:\n");
result.append(SensorDevice::getInstance().dump().c_str());
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 8afd3b3..9be18fb 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -118,12 +118,6 @@
c->detachLayer(this);
}
- for (auto& point : mRemoteSyncPoints) {
- point->setTransactionApplied();
- }
- for (auto& point : mLocalSyncPoints) {
- point->setFrameAvailable();
- }
mFrameTracker.logAndResetStats(mName);
}
@@ -141,8 +135,6 @@
void Layer::onRemovedFromCurrentState() {
// the layer is removed from SF mCurrentState to mLayersPendingRemoval
- mPendingRemoval = true;
-
if (mCurrentState.zOrderRelativeOf != nullptr) {
sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
if (strongRelative != nullptr) {
@@ -151,7 +143,7 @@
}
mCurrentState.zOrderRelativeOf = nullptr;
}
-
+
for (const auto& child : mCurrentChildren) {
child->onRemovedFromCurrentState();
}
@@ -163,8 +155,13 @@
destroyAllHwcLayers();
- for (const auto& child : mCurrentChildren) {
- child->onRemoved();
+ mRemoved = true;
+
+ for (auto& point : mRemoteSyncPoints) {
+ point->setTransactionApplied();
+ }
+ for (auto& point : mLocalSyncPoints) {
+ point->setFrameAvailable();
}
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 3eb8327..f2cda03 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -345,7 +345,7 @@
virtual bool isCreatedFromMainThread() const { return false; }
- bool isPendingRemoval() const { return mPendingRemoval; }
+ bool isRemoved() const { return mRemoved; }
void writeToProto(LayerProto* layerInfo,
LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing);
@@ -594,12 +594,12 @@
*/
class LayerCleaner {
sp<SurfaceFlinger> mFlinger;
- wp<Layer> mLayer;
+ sp<Layer> mLayer;
protected:
~LayerCleaner() {
// destroy client resources
- mFlinger->onLayerDestroyed(mLayer);
+ mFlinger->removeLayer(mLayer, true);
}
public:
@@ -744,7 +744,7 @@
// Whether filtering is needed b/c of the drawingstate
bool mNeedsFiltering{false};
- bool mPendingRemoval{false};
+ bool mRemoved{false};
// page-flip thread (currently main thread)
bool mProtectedByApp{false}; // application requires protected path to external sink
diff --git a/services/surfaceflinger/LayerStats.cpp b/services/surfaceflinger/LayerStats.cpp
index 9c2d312..c0174ae 100644
--- a/services/surfaceflinger/LayerStats.cpp
+++ b/services/surfaceflinger/LayerStats.cpp
@@ -68,7 +68,7 @@
base::StringAppendF(&key, ",%s", layerCompositionType(layer->hwcCompositionType));
base::StringAppendF(&key, ",%d", layer->isProtected);
base::StringAppendF(&key, ",%s", layerTransform(layer->hwcTransform));
- base::StringAppendF(&key, ",%s", layerPixelFormat(layer->activeBuffer.format));
+ base::StringAppendF(&key, ",%s", layerPixelFormat(layer->activeBuffer.format).c_str());
base::StringAppendF(&key, ",%s", layer->dataspace.c_str());
base::StringAppendF(&key, ",%s",
destinationLocation(layer->hwcFrame.left, layerGlobal.resolution[0],
@@ -162,8 +162,8 @@
return getCompositionName(static_cast<hwc2_composition_t>(compositionType));
}
-const char* LayerStats::layerPixelFormat(int32_t pixelFormat) {
- return decodePixelFormat(pixelFormat).c_str();
+std::string LayerStats::layerPixelFormat(int32_t pixelFormat) {
+ return decodePixelFormat(pixelFormat);
}
std::string LayerStats::scaleRatioWH(const LayerProtoParser::Layer* layer) {
diff --git a/services/surfaceflinger/LayerStats.h b/services/surfaceflinger/LayerStats.h
index 944073b..9de9cce 100644
--- a/services/surfaceflinger/LayerStats.h
+++ b/services/surfaceflinger/LayerStats.h
@@ -50,7 +50,7 @@
// Return the name of the composition type
static const char* layerCompositionType(int32_t compositionType);
// Return the name of the pixel format
- static const char* layerPixelFormat(int32_t pixelFormat);
+ static std::string layerPixelFormat(int32_t pixelFormat);
// Calculate scale ratios of layer's width/height with rotation information
static std::string scaleRatioWH(const LayerProtoParser::Layer* layer);
// Calculate scale ratio from source to destination and convert to string
diff --git a/services/surfaceflinger/RenderEngine/gl/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/gl/ProgramCache.cpp
index 9254aa0..c118248 100644
--- a/services/surfaceflinger/RenderEngine/gl/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/gl/ProgramCache.cpp
@@ -316,7 +316,7 @@
// scale [0.0, maxInLumi] to [0.0, maxOutLumi]
if (maxInLumi <= maxOutLumi) {
- nits *= maxOutLumi / maxInLumi;
+ return color * (maxOutLumi / maxInLumi);
} else {
// three control points
const float x0 = 10.0;
@@ -337,7 +337,7 @@
if (nits < x0) {
// scale [0.0, x0] to [0.0, y0] linearly
float slope = y0 / x0;
- nits *= slope;
+ return color * slope;
} else if (nits < x1) {
// scale [x0, x1] to [y0, y1] linearly
float slope = (y1 - y0) / (x1 - x0);
@@ -355,7 +355,8 @@
}
}
- return color * (nits / max(1e-6, color.y));
+ // color.y is greater than x0 and is thus non-zero
+ return color * (nits / color.y);
}
)__SHADER__";
break;
@@ -386,7 +387,7 @@
if (nits <= x0) {
// scale [0.0, x0] to [0.0, y0] linearly
const float slope = y0 / x0;
- nits *= slope;
+ return color * slope;
} else if (nits <= x1) {
// scale [x0, x1] to [y0, y1] using a curve
float t = (nits - x0) / (x1 - x0);
@@ -401,7 +402,8 @@
nits = (1.0 - t) * (1.0 - t) * y2 + 2.0 * (1.0 - t) * t * c3 + t * t * y3;
}
- return color * (nits / max(1e-6, color.y));
+ // color.y is greater than x0 and is thus non-zero
+ return color * (nits / color.y);
}
)__SHADER__";
break;
@@ -574,7 +576,7 @@
fs << "uniform mat4 inputTransformMatrix;";
fs << R"__SHADER__(
highp vec3 InputTransform(const highp vec3 color) {
- return vec3(inputTransformMatrix * vec4(color, 1.0));
+ return clamp(vec3(inputTransformMatrix * vec4(color, 1.0)), 0.0, 1.0);
}
)__SHADER__";
} else {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 37b32ed..2199ce1 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2852,6 +2852,7 @@
recordBufferingStats(l->getName().string(),
l->getOccupancyHistory(true));
l->onRemoved();
+ mNumLayers -= 1;
}
mLayersPendingRemoval.clear();
}
@@ -3283,7 +3284,7 @@
if (parent == nullptr) {
mCurrentState.layersSortedByZ.add(lbc);
} else {
- if (parent->isPendingRemoval()) {
+ if (parent->isRemoved()) {
ALOGE("addClientLayer called with a removed parent");
return NAME_NOT_FOUND;
}
@@ -3315,7 +3316,7 @@
status_t SurfaceFlinger::removeLayerLocked(const Mutex&, const sp<Layer>& layer,
bool topLevelOnly) {
- if (layer->isPendingRemoval()) {
+ if (layer->isRemoved()) {
return NO_ERROR;
}
@@ -3325,39 +3326,14 @@
if (topLevelOnly) {
return NO_ERROR;
}
-
- sp<Layer> ancestor = p;
- while (ancestor->getParent() != nullptr) {
- ancestor = ancestor->getParent();
- }
- if (mCurrentState.layersSortedByZ.indexOf(ancestor) < 0) {
- ALOGE("removeLayer called with a layer whose parent has been removed");
- return NAME_NOT_FOUND;
- }
-
index = p->removeChild(layer);
} else {
index = mCurrentState.layersSortedByZ.remove(layer);
}
- // As a matter of normal operation, the LayerCleaner will produce a second
- // attempt to remove the surface. The Layer will be kept alive in mDrawingState
- // so we will succeed in promoting it, but it's already been removed
- // from mCurrentState. As long as we can find it in mDrawingState we have no problem
- // otherwise something has gone wrong and we are leaking the layer.
- if (index < 0 && mDrawingState.layersSortedByZ.indexOf(layer) < 0) {
- ALOGE("Failed to find layer (%s) in layer parent (%s).",
- layer->getName().string(),
- (p != nullptr) ? p->getName().string() : "no-parent");
- return BAD_VALUE;
- } else if (index < 0) {
- return NO_ERROR;
- }
-
layer->onRemovedFromCurrentState();
mLayersPendingRemoval.add(layer);
mLayersRemoved = true;
- mNumLayers -= 1 + layer->getChildrenCount();
setTransactionFlags(eTransactionNeeded);
return NO_ERROR;
}
@@ -3560,7 +3536,7 @@
return 0;
}
- if (layer->isPendingRemoval()) {
+ if (layer->isRemoved()) {
ALOGW("Attempting to set client state on removed layer: %s", layer->getName().string());
return 0;
}
@@ -3768,7 +3744,7 @@
return;
}
- if (layer->isPendingRemoval()) {
+ if (layer->isRemoved()) {
ALOGW("Attempting to destroy on removed layer: %s", layer->getName().string());
return;
}
@@ -3945,19 +3921,6 @@
return err;
}
-status_t SurfaceFlinger::onLayerDestroyed(const wp<Layer>& layer)
-{
- // called by ~LayerCleaner() when all references to the IBinder (handle)
- // are gone
- sp<Layer> l = layer.promote();
- if (l == nullptr) {
- // The layer has already been removed, carry on
- return NO_ERROR;
- }
- // If we have a parent, then we can continue to live as long as it does.
- return removeLayer(l, true);
-}
-
// ---------------------------------------------------------------------------
void SurfaceFlinger::onInitializeDisplays() {
@@ -5331,7 +5294,7 @@
auto layerHandle = reinterpret_cast<Layer::Handle*>(layerHandleBinder.get());
auto parent = layerHandle->owner.promote();
- if (parent == nullptr || parent->isPendingRemoval()) {
+ if (parent == nullptr || parent->isRemoved()) {
ALOGE("captureLayers called with a removed parent");
return NAME_NOT_FOUND;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index a0f7c75..9f6eb21 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -561,11 +561,6 @@
// ISurfaceComposerClient::destroySurface()
status_t onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle);
- // called when all clients have released all their references to
- // this layer meaning it is entirely safe to destroy all
- // resources associated to this layer.
- status_t onLayerDestroyed(const wp<Layer>& layer);
-
// remove a layer from SurfaceFlinger immediately
status_t removeLayer(const sp<Layer>& layer, bool topLevelOnly = false);
status_t removeLayerLocked(const Mutex&, const sp<Layer>& layer, bool topLevelOnly = false);
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 3166a8c..0bf54d5 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -2582,6 +2582,37 @@
}
}
+TEST_F(ChildLayerTest, ChildrenSurviveParentDestruction) {
+ sp<SurfaceControl> mGrandChild =
+ mClient->createSurface(String8("Grand Child"), 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mChild.get());
+ fillSurfaceRGBA8(mGrandChild, 111, 111, 111);
+
+ {
+ SCOPED_TRACE("Grandchild visible");
+ ScreenCapture::captureScreen(&mCapture);
+ mCapture->checkPixel(64, 64, 111, 111, 111);
+ }
+
+ mChild->clear();
+
+ {
+ SCOPED_TRACE("After destroying child");
+ ScreenCapture::captureScreen(&mCapture);
+ mCapture->expectFGColor(64, 64);
+ }
+
+ asTransaction([&](Transaction& t) {
+ t.reparent(mGrandChild, mFGSurfaceControl->getHandle());
+ });
+
+ {
+ SCOPED_TRACE("After reparenting grandchild");
+ ScreenCapture::captureScreen(&mCapture);
+ mCapture->checkPixel(64, 64, 111, 111, 111);
+ }
+}
+
TEST_F(ChildLayerTest, DetachChildrenDifferentClient) {
sp<SurfaceComposerClient> mNewComposerClient = new SurfaceComposerClient;
sp<SurfaceControl> mChildNewClient =
diff --git a/services/vr/bufferhubd/buffer_hub_binder.cpp b/services/vr/bufferhubd/buffer_hub_binder.cpp
index 4ff9890..def15f1 100644
--- a/services/vr/bufferhubd/buffer_hub_binder.cpp
+++ b/services/vr/bufferhubd/buffer_hub_binder.cpp
@@ -1,58 +1,28 @@
#include <stdio.h>
-#include <binder/IServiceManager.h>
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
#include <log/log.h>
#include <private/dvr/buffer_hub_binder.h>
namespace android {
namespace dvr {
-status_t BufferHubBinderService::start(
- const std::shared_ptr<BufferHubService> &pdx_service) {
+status_t BufferHubBinderService::start() {
+ ProcessState::self()->startThreadPool();
IPCThreadState::self()->disableBackgroundScheduling(true);
-
- BufferHubBinderService* service = new BufferHubBinderService();
- service->pdx_service_ = pdx_service;
-
- // Not using BinderService::publish because need to get an instance of this
- // class (above). Following code is the same as
- // BinderService::publishAndJoinThreadPool
- sp<IServiceManager> sm = defaultServiceManager();
- status_t result = sm->addService(String16(getServiceName()), service,
- /*allowIsolated =*/ false,
- /*dump flags =*/ IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
- if (result != NO_ERROR) {
+ status_t result = BinderService<BufferHubBinderService>::publish();
+ if (result != OK) {
ALOGE("Publishing bufferhubd failed with error %d", result);
return result;
}
- sp<ProcessState> process_self(ProcessState::self());
- process_self->startThreadPool();
- process_self->giveThreadPoolName();
- IPCThreadState::self()->joinThreadPool();
-
return result;
}
-status_t BufferHubBinderService::dump(int fd, const Vector<String16> &args) {
+status_t BufferHubBinderService::dump(int fd, const Vector<String16> & /* args */) {
+ // TODO(b/115435506): not implemented yet
FILE *out = fdopen(dup(fd), "w");
- // Currently not supporting args, so notify the user.
- if (!args.isEmpty()){
- fprintf(out, "Note: dumpsys bufferhubd currently does not support args."
- "Input arguments are ignored.\n");
- }
-
- // TODO(b/116526156): output real data in this class once we have it
- if (pdx_service_){
- // BufferHubService::Dumpstate(size_t) is not actually using the param
- // So just using 0 as the length
- fprintf(out, "%s", pdx_service_->DumpState(0).c_str());
- } else {
- fprintf(out, "PDX service not registered or died.\n");
- }
+ fprintf(out, "BufferHubBinderService::dump(): Not Implemented.\n");
fclose(out);
return NO_ERROR;
@@ -60,4 +30,4 @@
} // namespace dvr
-} // namespace android
+} // namespace android
\ No newline at end of file
diff --git a/services/vr/bufferhubd/bufferhubd.cpp b/services/vr/bufferhubd/bufferhubd.cpp
index 3e10b26..0ca7edc 100644
--- a/services/vr/bufferhubd/bufferhubd.cpp
+++ b/services/vr/bufferhubd/bufferhubd.cpp
@@ -10,7 +10,7 @@
int main(int, char**) {
int ret = -1;
- std::shared_ptr<android::dvr::BufferHubService> pdx_service;
+ std::shared_ptr<android::pdx::Service> service;
std::unique_ptr<android::pdx::ServiceDispatcher> dispatcher;
// We need to be able to create endpoints with full perms.
@@ -33,16 +33,15 @@
else
ALOGI("New nofile limit is %llu/%llu.", rlim.rlim_cur, rlim.rlim_max);
+ CHECK_ERROR(android::dvr::BufferHubBinderService::start() != android::OK,
+ error, "Failed to create bufferhub binder service\n");
+
dispatcher = android::pdx::ServiceDispatcher::Create();
CHECK_ERROR(!dispatcher, error, "Failed to create service dispatcher\n");
- pdx_service = android::dvr::BufferHubService::Create();
- CHECK_ERROR(!pdx_service, error, "Failed to create bufferhub pdx service\n");
- dispatcher->AddService(pdx_service);
-
- ret = android::dvr::BufferHubBinderService::start(pdx_service);
- CHECK_ERROR(ret != android::NO_ERROR, error,
- "Failed to create bufferhub binder service\n");
+ service = android::dvr::BufferHubService::Create();
+ CHECK_ERROR(!service, error, "Failed to create bufferhubd service\n");
+ dispatcher->AddService(service);
ret = dvrSetSchedulerClass(0, "graphics");
CHECK_ERROR(ret < 0, error, "Failed to set thread priority");
diff --git a/services/vr/bufferhubd/consumer_channel.cpp b/services/vr/bufferhubd/consumer_channel.cpp
index 623c9d6..4ff7adf 100644
--- a/services/vr/bufferhubd/consumer_channel.cpp
+++ b/services/vr/bufferhubd/consumer_channel.cpp
@@ -90,11 +90,6 @@
*this, &ConsumerChannel::OnConsumerRelease, message);
return true;
- case BufferHubRPC::ConsumerSetIgnore::Opcode:
- DispatchRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(
- *this, &ConsumerChannel::OnConsumerSetIgnore, message);
- return true;
-
default:
return false;
}
@@ -120,9 +115,8 @@
if (acquired_ || released_) {
ALOGE(
"ConsumerChannel::OnConsumerAcquire: Acquire when not posted: "
- "ignored=%d acquired=%d released=%d channel_id=%d buffer_id=%d",
- ignored_, acquired_, released_, message.GetChannelId(),
- producer->buffer_id());
+ "acquired=%d released=%d channel_id=%d buffer_id=%d",
+ acquired_, released_, message.GetChannelId(), producer->buffer_id());
return ErrorStatus(EBUSY);
} else {
auto status = producer->OnConsumerAcquire(message);
@@ -144,9 +138,8 @@
if (!acquired_ || released_) {
ALOGE(
"ConsumerChannel::OnConsumerRelease: Release when not acquired: "
- "ignored=%d acquired=%d released=%d channel_id=%d buffer_id=%d",
- ignored_, acquired_, released_, message.GetChannelId(),
- producer->buffer_id());
+ "acquired=%d released=%d channel_id=%d buffer_id=%d",
+ acquired_, released_, message.GetChannelId(), producer->buffer_id());
return ErrorStatus(EBUSY);
} else {
auto status =
@@ -160,36 +153,11 @@
}
}
-Status<void> ConsumerChannel::OnConsumerSetIgnore(Message&, bool ignored) {
- ATRACE_NAME("ConsumerChannel::OnConsumerSetIgnore");
- auto producer = GetProducer();
- if (!producer)
- return ErrorStatus(EPIPE);
-
- ignored_ = ignored;
- if (ignored_ && acquired_) {
- // Update the producer if ignore is set after the consumer acquires the
- // buffer.
- ClearAvailable();
- producer->OnConsumerIgnored();
- acquired_ = false;
- released_ = true;
- }
-
- return {};
-}
-
bool ConsumerChannel::OnProducerPosted() {
- if (ignored_) {
- acquired_ = false;
- released_ = true;
- return false;
- } else {
- acquired_ = false;
- released_ = false;
- SignalAvailable();
- return true;
- }
+ acquired_ = false;
+ released_ = false;
+ SignalAvailable();
+ return true;
}
void ConsumerChannel::OnProducerClosed() {
diff --git a/services/vr/bufferhubd/include/private/dvr/buffer_hub_binder.h b/services/vr/bufferhubd/include/private/dvr/buffer_hub_binder.h
index 07f05cc..c0281fd 100644
--- a/services/vr/bufferhubd/include/private/dvr/buffer_hub_binder.h
+++ b/services/vr/bufferhubd/include/private/dvr/buffer_hub_binder.h
@@ -2,7 +2,6 @@
#define ANDROID_DVR_BUFFER_HUB_BINDER_H
#include <binder/BinderService.h>
-#include <private/dvr/buffer_hub.h>
#include "android/dvr/BnBufferHub.h"
@@ -11,17 +10,14 @@
class BufferHubBinderService : public BinderService<BufferHubBinderService>, public BnBufferHub {
public:
- static status_t start(const std::shared_ptr<BufferHubService> &pdx_service);
+ static status_t start();
static const char* getServiceName() { return "bufferhubd"; }
// Dump bufferhub related information to given fd (usually stdout)
// usage: adb shell dumpsys bufferhubd
virtual status_t dump(int fd, const Vector<String16> &args) override;
-
- private:
- std::shared_ptr<BufferHubService> pdx_service_;
};
} // namespace dvr
} // namespace android
-#endif // ANDROID_DVR_BUFFER_HUB_BINDER_H
+#endif // ANDROID_DVR_BUFFER_HUB_BINDER_H
\ No newline at end of file
diff --git a/services/vr/bufferhubd/include/private/dvr/consumer_channel.h b/services/vr/bufferhubd/include/private/dvr/consumer_channel.h
index 0d70409..84f664d 100644
--- a/services/vr/bufferhubd/include/private/dvr/consumer_channel.h
+++ b/services/vr/bufferhubd/include/private/dvr/consumer_channel.h
@@ -37,12 +37,10 @@
pdx::Status<LocalFence> OnConsumerAcquire(Message& message);
pdx::Status<void> OnConsumerRelease(Message& message,
LocalFence release_fence);
- pdx::Status<void> OnConsumerSetIgnore(Message& message, bool ignore);
uint64_t consumer_state_bit_{0};
bool acquired_{false};
bool released_{true};
- bool ignored_{false}; // True if we are ignoring events.
std::weak_ptr<Channel> producer_;
ConsumerChannel(const ConsumerChannel&) = delete;
diff --git a/services/vr/bufferhubd/include/private/dvr/producer_channel.h b/services/vr/bufferhubd/include/private/dvr/producer_channel.h
index 242198f..b4ea115 100644
--- a/services/vr/bufferhubd/include/private/dvr/producer_channel.h
+++ b/services/vr/bufferhubd/include/private/dvr/producer_channel.h
@@ -58,7 +58,7 @@
pdx::Status<void> OnConsumerRelease(Message& message,
LocalFence release_fence);
- void OnConsumerIgnored();
+ void DecrementPendingConsumers();
void OnConsumerOrphaned(ConsumerChannel* channel);
void AddConsumer(ConsumerChannel* channel);
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index 057d4f4..0b5257d 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -7,8 +7,8 @@
#include <thread>
#include <log/log.h>
-#include <private/dvr/bufferhub_rpc.h>
#include <private/dvr/buffer_channel.h>
+#include <private/dvr/bufferhub_rpc.h>
#include <private/dvr/consumer_channel.h>
#include <private/dvr/producer_channel.h>
#include <sync/sync.h>
@@ -96,8 +96,7 @@
// and also initialize the value to zero.
buffer_state_ =
new (&metadata_header_->buffer_state) std::atomic<uint64_t>(0);
- fence_state_ =
- new (&metadata_header_->fence_state) std::atomic<uint64_t>(0);
+ fence_state_ = new (&metadata_header_->fence_state) std::atomic<uint64_t>(0);
acquire_fence_fd_.Reset(epoll_create1(EPOLL_CLOEXEC));
release_fence_fd_.Reset(epoll_create1(EPOLL_CLOEXEC));
@@ -300,8 +299,8 @@
return CreateConsumer(message);
}
-Status<void> ProducerChannel::OnProducerPost(
- Message&, LocalFence acquire_fence) {
+Status<void> ProducerChannel::OnProducerPost(Message&,
+ LocalFence acquire_fence) {
ATRACE_NAME("ProducerChannel::OnProducerPost");
ALOGD_IF(TRACE, "ProducerChannel::OnProducerPost: buffer_id=%d", buffer_id());
if (!producer_owns_) {
@@ -315,9 +314,9 @@
int ret = epoll_ctl(release_fence_fd_.Get(), EPOLL_CTL_MOD,
dummy_fence_fd_.Get(), &event);
ALOGE_IF(ret < 0,
- "ProducerChannel::OnProducerPost: Failed to modify the shared "
- "release fence to include the dummy fence: %s",
- strerror(errno));
+ "ProducerChannel::OnProducerPost: Failed to modify the shared "
+ "release fence to include the dummy fence: %s",
+ strerror(errno));
eventfd_t dummy_fence_count = 0ULL;
if (eventfd_read(dummy_fence_fd_.Get(), &dummy_fence_count) < 0) {
@@ -474,7 +473,7 @@
}
}
- OnConsumerIgnored();
+ DecrementPendingConsumers();
if (pending_consumers_ == 0) {
// Clear the producer bit atomically to transit into released state. This
// has to done by BufferHub as it requries synchronization among all
@@ -507,21 +506,22 @@
return {};
}
-void ProducerChannel::OnConsumerIgnored() {
+void ProducerChannel::DecrementPendingConsumers() {
if (pending_consumers_ == 0) {
- ALOGE("ProducerChannel::OnConsumerIgnored: no pending consumer.");
+ ALOGE("ProducerChannel::DecrementPendingConsumers: no pending consumer.");
return;
}
--pending_consumers_;
ALOGD_IF(TRACE,
- "ProducerChannel::OnConsumerIgnored: buffer_id=%d %d consumers left",
+ "ProducerChannel::DecrementPendingConsumers: buffer_id=%d %d "
+ "consumers left",
buffer_id(), pending_consumers_);
}
void ProducerChannel::OnConsumerOrphaned(ConsumerChannel* channel) {
// Ignore the orphaned consumer.
- OnConsumerIgnored();
+ DecrementPendingConsumers();
const uint64_t consumer_state_bit = channel->consumer_state_bit();
ALOGE_IF(orphaned_consumer_bit_mask_ & consumer_state_bit,
diff --git a/services/vr/bufferhubd/tests/Android.bp b/services/vr/bufferhubd/tests/Android.bp
index 92bda78..4d1d43f 100644
--- a/services/vr/bufferhubd/tests/Android.bp
+++ b/services/vr/bufferhubd/tests/Android.bp
@@ -6,18 +6,11 @@
"-DTRACE=0",
"-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
],
- header_libs: ["libdvr_headers"],
- static_libs: [
- "libbufferhub",
- "libbufferhubd",
- "libgmock",
- ],
+ static_libs: ["libbufferhubd"],
shared_libs: [
"libbase",
"libbinder",
"liblog",
- "libpdx_default_transport",
- "libui",
"libutils",
],
}
\ No newline at end of file
diff --git a/services/vr/bufferhubd/tests/buffer_hub_binder_service-test.cpp b/services/vr/bufferhubd/tests/buffer_hub_binder_service-test.cpp
index 0b64cf0..e3f2825 100644
--- a/services/vr/bufferhubd/tests/buffer_hub_binder_service-test.cpp
+++ b/services/vr/bufferhubd/tests/buffer_hub_binder_service-test.cpp
@@ -1,8 +1,7 @@
-#include <binder/IServiceManager.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
#include <private/dvr/buffer_hub_binder.h>
+#include <gtest/gtest.h>
+
namespace android {
namespace dvr {
@@ -13,12 +12,8 @@
};
TEST_F(BufferHubBinderServiceTest, TestInitialize) {
- // Create a new service will kill the current one.
- // So just check if Binder service is running
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> service = sm->checkService(
- String16(BufferHubBinderService::getServiceName()));
- EXPECT_THAT(service, ::testing::Ne(nullptr));
+ // Test if start binder server returns OK
+ EXPECT_EQ(BufferHubBinderService::start(), OK);
}
} // namespace