summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmds/atrace/atrace.cpp2
-rw-r--r--cmds/dumpstate/dumpstate.c25
-rw-r--r--cmds/installd/commands.c20
-rw-r--r--cmds/installd/installd.c6
-rw-r--r--cmds/installd/installd.h1
-rw-r--r--include/binder/Parcel.h6
-rw-r--r--include/gui/BufferItem.h1
-rw-r--r--include/gui/BufferQueue.h2
-rw-r--r--include/gui/BufferQueueProducer.h16
-rw-r--r--include/gui/ConsumerBase.h4
-rw-r--r--include/gui/IConsumerListener.h19
-rw-r--r--include/gui/StreamSplitter.h2
-rw-r--r--include/media/drm/DrmAPI.h2
-rw-r--r--include/private/binder/Static.h7
-rw-r--r--libs/binder/Parcel.cpp93
-rw-r--r--libs/binder/Static.cpp8
-rw-r--r--libs/binder/TextOutput.cpp4
-rw-r--r--libs/gui/BufferItem.cpp2
-rw-r--r--libs/gui/BufferQueue.cpp5
-rw-r--r--libs/gui/BufferQueueProducer.cpp61
-rw-r--r--libs/gui/ConsumerBase.cpp4
-rw-r--r--libs/gui/GLConsumer.cpp6
-rw-r--r--libs/gui/IConsumerListener.cpp20
-rw-r--r--libs/gui/ISurfaceComposer.cpp14
-rw-r--r--libs/gui/LayerState.cpp8
-rw-r--r--libs/gui/StreamSplitter.cpp2
-rw-r--r--libs/gui/tests/BufferQueue_test.cpp2
-rw-r--r--libs/gui/tests/DisconnectWaiter.h2
-rw-r--r--libs/gui/tests/FrameWaiter.h2
-rw-r--r--libs/gui/tests/IGraphicBufferProducer_test.cpp2
-rw-r--r--libs/gui/tests/StreamSplitter_test.cpp2
-rw-r--r--libs/gui/tests/SurfaceTextureGLThreadToGL.h2
-rw-r--r--libs/ui/GraphicBuffer.cpp17
-rw-r--r--opengl/tests/EGLTest/EGL_test.cpp2
-rw-r--r--services/inputflinger/InputDispatcher.cpp25
-rw-r--r--services/inputflinger/InputWindow.h6
-rw-r--r--services/sensorservice/SensorService.cpp111
-rw-r--r--services/sensorservice/SensorService.h21
-rw-r--r--services/surfaceflinger/Android.mk6
-rw-r--r--services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp4
-rw-r--r--services/surfaceflinger/DisplayHardware/FramebufferSurface.h2
-rw-r--r--services/surfaceflinger/Layer.cpp26
-rw-r--r--services/surfaceflinger/Layer.h3
-rw-r--r--services/surfaceflinger/LayerDim.h5
-rw-r--r--services/surfaceflinger/RenderEngine/RenderEngine.cpp4
-rw-r--r--services/surfaceflinger/RenderEngine/RenderEngine.h1
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp28
47 files changed, 444 insertions, 169 deletions
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 9e5c910..f0a52d8 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -77,7 +77,7 @@ static const TracingCategory k_categories[] = {
{ "webview", "WebView", ATRACE_TAG_WEBVIEW, { } },
{ "wm", "Window Manager", ATRACE_TAG_WINDOW_MANAGER, { } },
{ "am", "Activity Manager", ATRACE_TAG_ACTIVITY_MANAGER, { } },
- { "sync", "Sync Manager", ATRACE_TAG_SYNC_MANAGER, { } },
+ { "sm", "Sync Manager", ATRACE_TAG_SYNC_MANAGER, { } },
{ "audio", "Audio", ATRACE_TAG_AUDIO, { } },
{ "video", "Video", ATRACE_TAG_VIDEO, { } },
{ "camera", "Camera", ATRACE_TAG_CAMERA, { } },
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 1fbcef6..f9942e9 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
@@ -75,6 +76,28 @@ static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
}
}
+static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
+{
+ DIR *d;
+ struct dirent *de;
+ char path[PATH_MAX];
+
+ d = opendir(driverpath);
+ if (d == NULL) {
+ return;
+ }
+
+ while ((de = readdir(d))) {
+ if (de->d_type != DT_LNK) {
+ continue;
+ }
+ snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
+ dump_file(title, path);
+ }
+
+ closedir(d);
+}
+
/* dumps the current system state to stdout */
static void dumpstate() {
time_t now = time(NULL);
@@ -107,7 +130,9 @@ static void dumpstate() {
printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
printf("\n");
+ dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
run_command("UPTIME", 10, "uptime", NULL);
+ dump_file("MMC PERF", "/sys/block/mmcblk0/stat");
dump_file("MEMORY INFO", "/proc/meminfo");
run_command("CPU INFO", 10, "top", "-n", "1", "-d", "1", "-m", "30", "-t", NULL);
run_command("PROCRANK", 20, "procrank", NULL);
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index 5cd2593..344a5a3 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -20,6 +20,7 @@
#include <cutils/sched_policy.h>
#include <diskusage/dirsize.h>
#include <selinux/android.h>
+#include <system/thread_defs.h>
/* Directory records that are used in execution of commands. */
dir_rec_t android_data_dir;
@@ -1029,6 +1030,10 @@ int dexopt(const char *apk_path, uid_t uid, bool is_public,
ALOGE("set_sched_policy failed: %s\n", strerror(errno));
exit(70);
}
+ if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
+ ALOGE("setpriority failed: %s\n", strerror(errno));
+ exit(71);
+ }
if (flock(out_fd, LOCK_EX | LOCK_NB) != 0) {
ALOGE("flock(%s) failed: %s\n", out_path, strerror(errno));
exit(67);
@@ -1076,6 +1081,21 @@ fail:
return -1;
}
+int mark_boot_complete(const char* instruction_set)
+{
+ char boot_marker_path[PKG_PATH_MAX];
+ sprintf(boot_marker_path,"%s%s/.booting", DALVIK_CACHE_PREFIX, instruction_set);
+
+ ALOGV("mark_boot_complete : %s", boot_marker_path);
+ if (unlink(boot_marker_path) != 0) {
+ ALOGE("Unable to unlink boot marker at %s, error=%s", boot_marker_path,
+ strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
void mkinnerdirs(char* path, int basepos, mode_t mode, int uid, int gid,
struct stat* statbuf)
{
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index 4864516..86f7468 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -42,6 +42,11 @@ static int do_dexopt(char **arg, char reply[REPLY_MAX] __unused)
return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4], atoi(arg[5]), 0);
}
+static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] __unused)
+{
+ return mark_boot_complete(arg[0] /* instruction set */);
+}
+
static int do_move_dex(char **arg, char reply[REPLY_MAX] __unused)
{
return move_dex(arg[0], arg[1], arg[2]); /* src, dst, instruction_set */
@@ -160,6 +165,7 @@ struct cmdinfo cmds[] = {
{ "ping", 0, do_ping },
{ "install", 4, do_install },
{ "dexopt", 6, do_dexopt },
+ { "markbootcomplete", 1, do_mark_boot_complete },
{ "movedex", 3, do_move_dex },
{ "rmdex", 2, do_rm_dex },
{ "remove", 2, do_remove },
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index 36c3e8c..a3a5c16 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -221,6 +221,7 @@ int get_size(const char *pkgname, userid_t userid, const char *apkpath, const ch
int free_cache(int64_t free_size);
int dexopt(const char *apk_path, uid_t uid, bool is_public, const char *pkgName,
const char *instruction_set, bool vm_safe_mode, bool should_relocate);
+int mark_boot_complete(const char *instruction_set);
int movefiles();
int linklib(const char* target, const char* source, int userId);
int idmap(const char *target_path, const char *overlay_path, uid_t uid);
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 2ee99f8..6a69761 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -205,7 +205,11 @@ public:
// Explicitly close all file descriptors in the parcel.
void closeFileDescriptors();
-
+
+ // Debugging: get metrics on current allocations.
+ static size_t getGlobalAllocSize();
+ static size_t getGlobalAllocCount();
+
private:
typedef void (*release_func)(Parcel* parcel,
const uint8_t* data, size_t dataSize,
diff --git a/include/gui/BufferItem.h b/include/gui/BufferItem.h
index 5effd10..01b6ff4 100644
--- a/include/gui/BufferItem.h
+++ b/include/gui/BufferItem.h
@@ -44,6 +44,7 @@ class BufferItem : public Flattenable<BufferItem> {
// The default value of mBuf, used to indicate this doesn't correspond to a slot.
enum { INVALID_BUFFER_SLOT = -1 };
BufferItem();
+ ~BufferItem();
operator IGraphicBufferConsumer::BufferItem() const;
static const char* scalingModeName(uint32_t scalingMode);
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index 3297b10..1188837 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -62,7 +62,7 @@ public:
public:
ProxyConsumerListener(const wp<ConsumerListener>& consumerListener);
virtual ~ProxyConsumerListener();
- virtual void onFrameAvailable();
+ virtual void onFrameAvailable(const android::BufferItem& item);
virtual void onBuffersReleased();
virtual void onSidebandStreamChanged();
private:
diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h
index 3fc5de2..ed1056a 100644
--- a/include/gui/BufferQueueProducer.h
+++ b/include/gui/BufferQueueProducer.h
@@ -197,6 +197,22 @@ private:
uint32_t mStickyTransform;
+ // This saves the fence from the last queueBuffer, such that the
+ // next queueBuffer call can throttle buffer production. The prior
+ // queueBuffer's fence is not nessessarily available elsewhere,
+ // since the previous buffer might have already been acquired.
+ sp<Fence> mLastQueueBufferFence;
+
+ // Take-a-ticket system for ensuring that onFrame* callbacks are called in
+ // the order that frames are queued. While the BufferQueue lock
+ // (mCore->mMutex) is held, a ticket is retained by the producer. After
+ // dropping the BufferQueue lock, the producer must wait on the condition
+ // variable until the current callback ticket matches its retained ticket.
+ Mutex mCallbackMutex;
+ int mNextCallbackTicket; // Protected by mCore->mMutex
+ int mCurrentCallbackTicket; // Protected by mCallbackMutex
+ Condition mCallbackCondition;
+
}; // class BufferQueueProducer
} // namespace android
diff --git a/include/gui/ConsumerBase.h b/include/gui/ConsumerBase.h
index 100bb26..f7ab5ac 100644
--- a/include/gui/ConsumerBase.h
+++ b/include/gui/ConsumerBase.h
@@ -46,7 +46,7 @@ public:
//
// This is called without any lock held and can be called concurrently
// by multiple threads.
- virtual void onFrameAvailable() = 0;
+ virtual void onFrameAvailable(const BufferItem& item) = 0;
};
virtual ~ConsumerBase();
@@ -106,7 +106,7 @@ protected:
// the ConsumerBase implementation must be called from the derived class.
// The ConsumerBase version of onSidebandStreamChanged does nothing and can
// be overriden by derived classes if they want the notification.
- virtual void onFrameAvailable();
+ virtual void onFrameAvailable(const BufferItem& item);
virtual void onBuffersReleased();
virtual void onSidebandStreamChanged();
diff --git a/include/gui/IConsumerListener.h b/include/gui/IConsumerListener.h
index 260099e..3f39799 100644
--- a/include/gui/IConsumerListener.h
+++ b/include/gui/IConsumerListener.h
@@ -28,6 +28,8 @@
namespace android {
// ----------------------------------------------------------------------------
+class BufferItem;
+
// ConsumerListener is the interface through which the BufferQueue notifies
// the consumer of events that the consumer may wish to react to. Because
// the consumer will generally have a mutex that is locked during calls from
@@ -43,11 +45,24 @@ public:
// frame becomes available for consumption. This means that frames that
// are queued while in asynchronous mode only trigger the callback if no
// previous frames are pending. Frames queued while in synchronous mode
- // always trigger the callback.
+ // always trigger the callback. The item passed to the callback will contain
+ // all of the information about the queued frame except for its
+ // GraphicBuffer pointer, which will always be null.
+ //
+ // This is called without any lock held and can be called concurrently
+ // by multiple threads.
+ virtual void onFrameAvailable(const BufferItem& item) = 0; /* Asynchronous */
+
+ // onFrameReplaced is called from queueBuffer if the frame being queued is
+ // replacing an existing slot in the queue. Any call to queueBuffer that
+ // doesn't call onFrameAvailable will call this callback instead. The item
+ // passed to the callback will contain all of the information about the
+ // queued frame except for its GraphicBuffer pointer, which will always be
+ // null.
//
// This is called without any lock held and can be called concurrently
// by multiple threads.
- virtual void onFrameAvailable() = 0; /* Asynchronous */
+ virtual void onFrameReplaced(const BufferItem& /* item */) {} /* Asynchronous */
// onBuffersReleased is called to notify the buffer consumer that the
// BufferQueue has released its references to one or more GraphicBuffers
diff --git a/include/gui/StreamSplitter.h b/include/gui/StreamSplitter.h
index f927953..8f47eb4 100644
--- a/include/gui/StreamSplitter.h
+++ b/include/gui/StreamSplitter.h
@@ -74,7 +74,7 @@ private:
// can block if there are too many outstanding buffers. If it blocks, it
// will resume when onBufferReleasedByOutput releases a buffer back to the
// input.
- virtual void onFrameAvailable();
+ virtual void onFrameAvailable(const BufferItem& item);
// From IConsumerListener
// We don't care about released buffers because we detach each buffer as
diff --git a/include/media/drm/DrmAPI.h b/include/media/drm/DrmAPI.h
index 4633b7e..49939fd 100644
--- a/include/media/drm/DrmAPI.h
+++ b/include/media/drm/DrmAPI.h
@@ -209,7 +209,9 @@ namespace android {
// confirmed. The persisted record on the client is only removed after positive
// confirmation that the server received the message using releaseSecureStops().
virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops) = 0;
+ virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) = 0;
virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease) = 0;
+ virtual status_t releaseAllSecureStops() = 0;
// Read a property value given the device property string. There are a few forms
// of property access methods, depending on the data type returned.
diff --git a/include/private/binder/Static.h b/include/private/binder/Static.h
index 6a03594..eeb37d7 100644
--- a/include/private/binder/Static.h
+++ b/include/private/binder/Static.h
@@ -34,7 +34,12 @@ extern Vector<int32_t> gTextBuffers;
extern Mutex gProcessMutex;
extern sp<ProcessState> gProcess;
-// For ServiceManager.cpp
+// For Parcel.cpp
+extern Mutex gParcelGlobalAllocSizeLock;
+extern size_t gParcelGlobalAllocSize;
+extern size_t gParcelGlobalAllocCount;
+
+// For IServiceManager.cpp
extern Mutex gDefaultServiceManagerLock;
extern sp<IServiceManager> gDefaultServiceManager;
extern sp<IPermissionController> gPermissionController;
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 1dbb06f..98a3dd7 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -26,7 +26,6 @@
#include <binder/TextOutput.h>
#include <errno.h>
-#include <utils/CallStack.h>
#include <utils/Debug.h>
#include <utils/Log.h>
#include <utils/String8.h>
@@ -36,8 +35,8 @@
#include <cutils/ashmem.h>
#include <private/binder/binder_module.h>
+#include <private/binder/Static.h>
-#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
@@ -50,6 +49,8 @@
#define LOG_REFS(...)
//#define LOG_REFS(...) ALOG(LOG_DEBUG, "Parcel", __VA_ARGS__)
+#define LOG_ALLOC(...)
+//#define LOG_ALLOC(...) ALOG(LOG_DEBUG, "Parcel", __VA_ARGS__)
// ---------------------------------------------------------------------------
@@ -293,12 +294,24 @@ status_t unflatten_binder(const sp<ProcessState>& proc,
Parcel::Parcel()
{
+ LOG_ALLOC("Parcel %p: constructing", this);
initState();
}
Parcel::~Parcel()
{
freeDataNoInit();
+ LOG_ALLOC("Parcel %p: destroyed", this);
+}
+
+size_t Parcel::getGlobalAllocSize() {
+ AutoMutex _l(gParcelGlobalAllocSizeLock);
+ return gParcelGlobalAllocSize;
+}
+
+size_t Parcel::getGlobalAllocCount() {
+ AutoMutex _l(gParcelGlobalAllocSizeLock);
+ return gParcelGlobalAllocCount;
}
const uint8_t* Parcel::data() const
@@ -768,29 +781,6 @@ status_t Parcel::writeFileDescriptor(int fd, bool takeOwnership)
status_t Parcel::writeDupFileDescriptor(int fd)
{
int dupFd = dup(fd);
-
- { // Temporary extra debug validation for b/17477219: a Parcel recipient is
- // getting a positive but invalid fd unexpectedly. Trying to track down
- // where it's coming from.
- int dupErrno = dupFd < 0 ? errno : 0;
- int fdFlags = fcntl(fd, F_GETFD);
- int fdFlagsErrno = fdFlags == -1 ? errno : 0;
- int dupFlags = fcntl(dupFd, F_GETFD);
- int dupFlagsErrno = dupFlags == -1 ? errno : 0;
- if (dupFd < 0 || fdFlags == -1 || dupFlags == -1) {
- ALOGE("Parcel::writeDupFileDescriptor failed:\n"
- " fd=%d flags=%d err=%d(%s)\n"
- " dupFd=%d dupErr=%d(%s) flags=%d err=%d(%s)",
- fd, fdFlags, fdFlagsErrno, strerror(fdFlagsErrno),
- dupFd, dupErrno, strerror(dupErrno),
- dupFlags, dupFlagsErrno, strerror(dupFlagsErrno));
- if (fd < 0 || fdFlags == -1) {
- CallStack(LOG_TAG);
- }
- return -errno;
- }
- }
-
if (dupFd < 0) {
return -errno;
}
@@ -1305,23 +1295,11 @@ status_t Parcel::read(FlattenableHelperInterface& val) const
status_t err = NO_ERROR;
for (size_t i=0 ; i<fd_count && err==NO_ERROR ; i++) {
- int oldfd = this->readFileDescriptor();
- fds[i] = dup(oldfd);
+ fds[i] = dup(this->readFileDescriptor());
if (fds[i] < 0) {
- int dupErrno = errno;
err = BAD_VALUE;
- int flags = fcntl(oldfd, F_GETFD);
- int fcntlErrno = errno;
- const flat_binder_object* flat = readObject(true);
- ALOGE("dup failed in Parcel::read, fd %zu of %zu\n"
- " dup(%d) = %d [errno: %d (%s)]\n"
- " fcntl(%d, F_GETFD) = %d [errno: %d (%s)]\n"
- " flat %p type %d",
- i, fd_count,
- oldfd, fds[i], dupErrno, strerror(dupErrno),
- oldfd, flags, fcntlErrno, strerror(fcntlErrno),
- flat, flat ? flat->type : 0);
- CallStack(LOG_TAG);
+ ALOGE("dup() failed in Parcel::read, i is %zu, fds[i] is %d, fd_count is %zu, error: %s",
+ i, fds[i], fd_count, strerror(errno));
}
}
@@ -1525,11 +1503,20 @@ void Parcel::freeData()
void Parcel::freeDataNoInit()
{
if (mOwner) {
+ LOG_ALLOC("Parcel %p: freeing other owner data", this);
//ALOGI("Freeing data ref of %p (pid=%d)", this, getpid());
mOwner(this, mData, mDataSize, mObjects, mObjectsSize, mOwnerCookie);
} else {
+ LOG_ALLOC("Parcel %p: freeing allocated data", this);
releaseObjects();
- if (mData) free(mData);
+ if (mData) {
+ LOG_ALLOC("Parcel %p: freeing with %zu capacity", this, mDataCapacity);
+ gParcelGlobalAllocSizeLock.lock();
+ gParcelGlobalAllocSize -= mDataCapacity;
+ gParcelGlobalAllocCount--;
+ gParcelGlobalAllocSizeLock.unlock();
+ free(mData);
+ }
if (mObjects) free(mObjects);
}
}
@@ -1558,6 +1545,11 @@ status_t Parcel::restartWrite(size_t desired)
releaseObjects();
if (data) {
+ LOG_ALLOC("Parcel %p: restart from %zu to %zu capacity", this, mDataCapacity, desired);
+ gParcelGlobalAllocSizeLock.lock();
+ gParcelGlobalAllocSize += desired;
+ gParcelGlobalAllocSize -= mDataCapacity;
+ gParcelGlobalAllocSizeLock.unlock();
mData = data;
mDataCapacity = desired;
}
@@ -1637,6 +1629,12 @@ status_t Parcel::continueWrite(size_t desired)
mOwner(this, mData, mDataSize, mObjects, mObjectsSize, mOwnerCookie);
mOwner = NULL;
+ LOG_ALLOC("Parcel %p: taking ownership of %zu capacity", this, desired);
+ gParcelGlobalAllocSizeLock.lock();
+ gParcelGlobalAllocSize += desired;
+ gParcelGlobalAllocCount++;
+ gParcelGlobalAllocSizeLock.unlock();
+
mData = data;
mObjects = objects;
mDataSize = (mDataSize < desired) ? mDataSize : desired;
@@ -1671,6 +1669,12 @@ status_t Parcel::continueWrite(size_t desired)
if (desired > mDataCapacity) {
uint8_t* data = (uint8_t*)realloc(mData, desired);
if (data) {
+ LOG_ALLOC("Parcel %p: continue from %zu to %zu capacity", this, mDataCapacity,
+ desired);
+ gParcelGlobalAllocSizeLock.lock();
+ gParcelGlobalAllocSize += desired;
+ gParcelGlobalAllocSize -= mDataCapacity;
+ gParcelGlobalAllocSizeLock.unlock();
mData = data;
mDataCapacity = desired;
} else if (desired > mDataCapacity) {
@@ -1701,6 +1705,12 @@ status_t Parcel::continueWrite(size_t desired)
ALOGE("continueWrite: %zu/%p/%zu/%zu", mDataCapacity, mObjects, mObjectsCapacity, desired);
}
+ LOG_ALLOC("Parcel %p: allocating with %zu capacity", this, desired);
+ gParcelGlobalAllocSizeLock.lock();
+ gParcelGlobalAllocSize += desired;
+ gParcelGlobalAllocCount++;
+ gParcelGlobalAllocSizeLock.unlock();
+
mData = data;
mDataSize = mDataPos = 0;
ALOGV("continueWrite Setting data size of %p to %zu", this, mDataSize);
@@ -1713,6 +1723,7 @@ status_t Parcel::continueWrite(size_t desired)
void Parcel::initState()
{
+ LOG_ALLOC("Parcel %p: initState", this);
mError = NO_ERROR;
mData = 0;
mDataSize = 0;
diff --git a/libs/binder/Static.cpp b/libs/binder/Static.cpp
index 2062692..b870c34 100644
--- a/libs/binder/Static.cpp
+++ b/libs/binder/Static.cpp
@@ -90,7 +90,13 @@ public:
static LibBinderIPCtStatics gIPCStatics;
-// ------------ ServiceManager.cpp
+// ------------ Parcel.cpp
+
+Mutex gParcelGlobalAllocSizeLock;
+size_t gParcelGlobalAllocSize = 0;
+size_t gParcelGlobalAllocCount = 0;
+
+// ------------ IServiceManager.cpp
Mutex gDefaultServiceManagerLock;
sp<IServiceManager> gDefaultServiceManager;
diff --git a/libs/binder/TextOutput.cpp b/libs/binder/TextOutput.cpp
index db3e858..2ed5188 100644
--- a/libs/binder/TextOutput.cpp
+++ b/libs/binder/TextOutput.cpp
@@ -116,8 +116,8 @@ TextOutput& operator<<(TextOutput& to, double val)
TextOutput& operator<<(TextOutput& to, const void* val)
{
- char buf[16];
- sprintf(buf, "%p", val);
+ char buf[32];
+ snprintf(buf, sizeof(buf), "%p", val);
to.print(buf, strlen(buf));
return to;
}
diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp
index d3fa43e..e6fc791 100644
--- a/libs/gui/BufferItem.cpp
+++ b/libs/gui/BufferItem.cpp
@@ -36,6 +36,8 @@ BufferItem::BufferItem() :
mCrop.makeInvalid();
}
+BufferItem::~BufferItem() {}
+
BufferItem::operator IGraphicBufferConsumer::BufferItem() const {
IGraphicBufferConsumer::BufferItem bufferItem;
bufferItem.mGraphicBuffer = mGraphicBuffer;
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index c49a886..61fd8c4 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -31,10 +31,11 @@ BufferQueue::ProxyConsumerListener::ProxyConsumerListener(
BufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {}
-void BufferQueue::ProxyConsumerListener::onFrameAvailable() {
+void BufferQueue::ProxyConsumerListener::onFrameAvailable(
+ const android::BufferItem& item) {
sp<ConsumerListener> listener(mConsumerListener.promote());
if (listener != NULL) {
- listener->onFrameAvailable();
+ listener->onFrameAvailable(item);
}
}
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index d2fd3b0..16b9747 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -38,7 +38,12 @@ BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core) :
mCore(core),
mSlots(core->mSlots),
mConsumerName(),
- mStickyTransform(0) {}
+ mStickyTransform(0),
+ mLastQueueBufferFence(Fence::NO_FENCE),
+ mCallbackMutex(),
+ mNextCallbackTicket(0),
+ mCurrentCallbackTicket(0),
+ mCallbackCondition() {}
BufferQueueProducer::~BufferQueueProducer() {}
@@ -522,12 +527,7 @@ status_t BufferQueueProducer::queueBuffer(int slot,
if (fence == NULL) {
BQ_LOGE("queueBuffer: fence is NULL");
- // Temporary workaround for b/17946343: soldier-on instead of returning an error. This
- // prevents the client from dying, at the risk of visible corruption due to hwcomposer
- // reading the buffer before the producer is done rendering it. Unless the buffer is the
- // last frame of an animation, the corruption will be transient.
- fence = Fence::NO_FENCE;
- // return BAD_VALUE;
+ return BAD_VALUE;
}
switch (scalingMode) {
@@ -541,7 +541,10 @@ status_t BufferQueueProducer::queueBuffer(int slot,
return BAD_VALUE;
}
- sp<IConsumerListener> listener;
+ sp<IConsumerListener> frameAvailableListener;
+ sp<IConsumerListener> frameReplacedListener;
+ int callbackTicket = 0;
+ BufferItem item;
{ // Autolock scope
Mutex::Autolock lock(mCore->mMutex);
@@ -597,7 +600,6 @@ status_t BufferQueueProducer::queueBuffer(int slot,
++mCore->mFrameCounter;
mSlots[slot].mFrameNumber = mCore->mFrameCounter;
- BufferItem item;
item.mAcquireCalled = mSlots[slot].mAcquireCalled;
item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
item.mCrop = crop;
@@ -618,7 +620,7 @@ status_t BufferQueueProducer::queueBuffer(int slot,
// When the queue is empty, we can ignore mDequeueBufferCannotBlock
// and simply queue this buffer
mCore->mQueue.push_back(item);
- listener = mCore->mConsumerListener;
+ frameAvailableListener = mCore->mConsumerListener;
} else {
// When the queue is not empty, we need to look at the front buffer
// state to see if we need to replace it
@@ -634,9 +636,10 @@ status_t BufferQueueProducer::queueBuffer(int slot,
}
// Overwrite the droppable buffer with the incoming one
*front = item;
+ frameReplacedListener = mCore->mConsumerListener;
} else {
mCore->mQueue.push_back(item);
- listener = mCore->mConsumerListener;
+ frameAvailableListener = mCore->mConsumerListener;
}
}
@@ -647,11 +650,41 @@ status_t BufferQueueProducer::queueBuffer(int slot,
mCore->mTransformHint, mCore->mQueue.size());
ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
+
+ // Take a ticket for the callback functions
+ callbackTicket = mNextCallbackTicket++;
} // Autolock scope
- // Call back without lock held
- if (listener != NULL) {
- listener->onFrameAvailable();
+ // Wait without lock held
+ if (mCore->mConnectedApi == NATIVE_WINDOW_API_EGL) {
+ // Waiting here allows for two full buffers to be queued but not a
+ // third. In the event that frames take varying time, this makes a
+ // small trade-off in favor of latency rather than throughput.
+ mLastQueueBufferFence->waitForever("Throttling EGL Production");
+ mLastQueueBufferFence = fence;
+ }
+
+ // Don't send the GraphicBuffer through the callback, and don't send
+ // the slot number, since the consumer shouldn't need it
+ item.mGraphicBuffer.clear();
+ item.mSlot = BufferItem::INVALID_BUFFER_SLOT;
+
+ // Call back without the main BufferQueue lock held, but with the callback
+ // lock held so we can ensure that callbacks occur in order
+ {
+ Mutex::Autolock lock(mCallbackMutex);
+ while (callbackTicket != mCurrentCallbackTicket) {
+ mCallbackCondition.wait(mCallbackMutex);
+ }
+
+ if (frameAvailableListener != NULL) {
+ frameAvailableListener->onFrameAvailable(item);
+ } else if (frameReplacedListener != NULL) {
+ frameReplacedListener->onFrameReplaced(item);
+ }
+
+ ++mCurrentCallbackTicket;
+ mCallbackCondition.broadcast();
}
return NO_ERROR;
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index e476c9a..95f5507 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -98,7 +98,7 @@ void ConsumerBase::freeBufferLocked(int slotIndex) {
mSlots[slotIndex].mFrameNumber = 0;
}
-void ConsumerBase::onFrameAvailable() {
+void ConsumerBase::onFrameAvailable(const BufferItem& item) {
CB_LOGV("onFrameAvailable");
sp<FrameAvailableListener> listener;
@@ -109,7 +109,7 @@ void ConsumerBase::onFrameAvailable() {
if (listener != NULL) {
CB_LOGV("actually calling onFrameAvailable");
- listener->onFrameAvailable();
+ listener->onFrameAvailable(item);
}
}
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 6ba2ef8..b886c5b 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -505,7 +505,7 @@ status_t GLConsumer::checkAndUpdateEglStateLocked(bool contextCheck) {
if (mEglDisplay == EGL_NO_DISPLAY) {
mEglDisplay = dpy;
}
- if (mEglContext == EGL_NO_DISPLAY) {
+ if (mEglContext == EGL_NO_CONTEXT) {
mEglContext = ctx;
}
}
@@ -1065,6 +1065,7 @@ GLConsumer::EglImage::~EglImage() {
if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
ALOGE("~EglImage: eglDestroyImageKHR failed");
}
+ eglTerminate(mEglDisplay);
}
}
@@ -1079,6 +1080,7 @@ status_t GLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay,
if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
ALOGE("createIfNeeded: eglDestroyImageKHR failed");
}
+ eglTerminate(mEglDisplay);
mEglImage = EGL_NO_IMAGE_KHR;
mEglDisplay = EGL_NO_DISPLAY;
}
@@ -1129,11 +1131,13 @@ EGLImageKHR GLConsumer::EglImage::createImage(EGLDisplay dpy,
// removes this restriction if there is hardware that can support it.
attrs[2] = EGL_NONE;
}
+ eglInitialize(dpy, 0, 0);
EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
if (image == EGL_NO_IMAGE_KHR) {
EGLint error = eglGetError();
ALOGE("error creating EGLImage: %#x", error);
+ eglTerminate(dpy);
}
return image;
}
diff --git a/libs/gui/IConsumerListener.cpp b/libs/gui/IConsumerListener.cpp
index 4ccf0ac..409dfe4 100644
--- a/libs/gui/IConsumerListener.cpp
+++ b/libs/gui/IConsumerListener.cpp
@@ -21,6 +21,7 @@
#include <binder/Parcel.h>
#include <gui/IConsumerListener.h>
+#include <gui/BufferItem.h>
// ---------------------------------------------------------------------------
namespace android {
@@ -39,9 +40,10 @@ public:
: BpInterface<IConsumerListener>(impl) {
}
- virtual void onFrameAvailable() {
+ virtual void onFrameAvailable(const BufferItem& item) {
Parcel data, reply;
data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor());
+ data.write(item);
remote()->transact(ON_FRAME_AVAILABLE, data, &reply, IBinder::FLAG_ONEWAY);
}
@@ -66,18 +68,20 @@ status_t BnConsumerListener::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
- case ON_FRAME_AVAILABLE:
+ case ON_FRAME_AVAILABLE: {
CHECK_INTERFACE(IConsumerListener, data, reply);
- onFrameAvailable();
- return NO_ERROR;
- case ON_BUFFER_RELEASED:
+ BufferItem item;
+ data.read(item);
+ onFrameAvailable(item);
+ return NO_ERROR; }
+ case ON_BUFFER_RELEASED: {
CHECK_INTERFACE(IConsumerListener, data, reply);
onBuffersReleased();
- return NO_ERROR;
- case ON_SIDEBAND_STREAM_CHANGED:
+ return NO_ERROR; }
+ case ON_SIDEBAND_STREAM_CHANGED: {
CHECK_INTERFACE(IConsumerListener, data, reply);
onSidebandStreamChanged();
- return NO_ERROR;
+ return NO_ERROR; }
}
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 81e8336..ebb687a 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -312,19 +312,29 @@ status_t BnSurfaceComposer::onTransact(
case SET_TRANSACTION_STATE: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
size_t count = data.readInt32();
+ if (count > data.dataSize()) {
+ return BAD_VALUE;
+ }
ComposerState s;
Vector<ComposerState> state;
state.setCapacity(count);
for (size_t i=0 ; i<count ; i++) {
- s.read(data);
+ if (s.read(data) == BAD_VALUE) {
+ return BAD_VALUE;
+ }
state.add(s);
}
count = data.readInt32();
+ if (count > data.dataSize()) {
+ return BAD_VALUE;
+ }
DisplayState d;
Vector<DisplayState> displays;
displays.setCapacity(count);
for (size_t i=0 ; i<count ; i++) {
- d.read(data);
+ if (d.read(data) == BAD_VALUE) {
+ return BAD_VALUE;
+ }
displays.add(d);
}
uint32_t flags = data.readInt32();
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 9d3f116..39f8f92 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -55,8 +55,12 @@ status_t layer_state_t::read(const Parcel& input)
alpha = input.readFloat();
flags = input.readInt32();
mask = input.readInt32();
- matrix = *reinterpret_cast<layer_state_t::matrix22_t const *>(
- input.readInplace(sizeof(layer_state_t::matrix22_t)));
+ const void* matrix_data = input.readInplace(sizeof(layer_state_t::matrix22_t));
+ if (matrix_data) {
+ matrix = *reinterpret_cast<layer_state_t::matrix22_t const *>(matrix_data);
+ } else {
+ return BAD_VALUE;
+ }
input.read(crop);
input.read(transparentRegion);
return NO_ERROR;
diff --git a/libs/gui/StreamSplitter.cpp b/libs/gui/StreamSplitter.cpp
index 771b263..5f39905 100644
--- a/libs/gui/StreamSplitter.cpp
+++ b/libs/gui/StreamSplitter.cpp
@@ -98,7 +98,7 @@ void StreamSplitter::setName(const String8 &name) {
mInput->setConsumerName(name);
}
-void StreamSplitter::onFrameAvailable() {
+void StreamSplitter::onFrameAvailable(const BufferItem& /* item */) {
ATRACE_CALL();
Mutex::Autolock lock(mMutex);
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index c781366..96de11f 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -67,7 +67,7 @@ protected:
};
struct DummyConsumer : public BnConsumerListener {
- virtual void onFrameAvailable() {}
+ virtual void onFrameAvailable(const BufferItem& /* item */) {}
virtual void onBuffersReleased() {}
virtual void onSidebandStreamChanged() {}
};
diff --git a/libs/gui/tests/DisconnectWaiter.h b/libs/gui/tests/DisconnectWaiter.h
index 56e96c2..6e6915b 100644
--- a/libs/gui/tests/DisconnectWaiter.h
+++ b/libs/gui/tests/DisconnectWaiter.h
@@ -44,7 +44,7 @@ public:
mPendingFrames--;
}
- virtual void onFrameAvailable() {
+ virtual void onFrameAvailable(const BufferItem& /* item */) {
Mutex::Autolock lock(mMutex);
mPendingFrames++;
mFrameCondition.signal();
diff --git a/libs/gui/tests/FrameWaiter.h b/libs/gui/tests/FrameWaiter.h
index bdedba6..f78fa00 100644
--- a/libs/gui/tests/FrameWaiter.h
+++ b/libs/gui/tests/FrameWaiter.h
@@ -35,7 +35,7 @@ public:
mPendingFrames--;
}
- virtual void onFrameAvailable() {
+ virtual void onFrameAvailable(const BufferItem& /* item */) {
Mutex::Autolock lock(mMutex);
mPendingFrames++;
mCondition.signal();
diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp
index aadfe61..8d5fd8f 100644
--- a/libs/gui/tests/IGraphicBufferProducer_test.cpp
+++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp
@@ -65,7 +65,7 @@ const sp<Fence> QUEUE_BUFFER_INPUT_FENCE = Fence::NO_FENCE;
}; // namespace anonymous
struct DummyConsumer : public BnConsumerListener {
- virtual void onFrameAvailable() {}
+ virtual void onFrameAvailable(const BufferItem& /* item */) {}
virtual void onBuffersReleased() {}
virtual void onSidebandStreamChanged() {}
};
diff --git a/libs/gui/tests/StreamSplitter_test.cpp b/libs/gui/tests/StreamSplitter_test.cpp
index 32ec90d..4e63a6f 100644
--- a/libs/gui/tests/StreamSplitter_test.cpp
+++ b/libs/gui/tests/StreamSplitter_test.cpp
@@ -46,7 +46,7 @@ protected:
};
struct DummyListener : public BnConsumerListener {
- virtual void onFrameAvailable() {}
+ virtual void onFrameAvailable(const BufferItem& /* item */) {}
virtual void onBuffersReleased() {}
virtual void onSidebandStreamChanged() {}
};
diff --git a/libs/gui/tests/SurfaceTextureGLThreadToGL.h b/libs/gui/tests/SurfaceTextureGLThreadToGL.h
index 6410516..14e42ac 100644
--- a/libs/gui/tests/SurfaceTextureGLThreadToGL.h
+++ b/libs/gui/tests/SurfaceTextureGLThreadToGL.h
@@ -130,7 +130,7 @@ protected:
}
// This should be called by GLConsumer on the producer thread.
- virtual void onFrameAvailable() {
+ virtual void onFrameAvailable(const BufferItem& /* item */) {
Mutex::Autolock lock(mMutex);
ALOGV("+onFrameAvailable");
mFrameAvailable = true;
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 9b0bd60..e768f13 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -310,10 +310,19 @@ status_t GraphicBuffer::unflatten(
const size_t numFds = buf[8];
const size_t numInts = buf[9];
+ const size_t maxNumber = UINT_MAX / sizeof(int);
+ if (numFds >= maxNumber || numInts >= (maxNumber - 10)) {
+ width = height = stride = format = usage = 0;
+ handle = NULL;
+ ALOGE("unflatten: numFds or numInts is too large: %d, %d",
+ numFds, numInts);
+ return BAD_VALUE;
+ }
+
const size_t sizeNeeded = (10 + numInts) * sizeof(int);
if (size < sizeNeeded) return NO_MEMORY;
- size_t fdCountNeeded = 0;
+ size_t fdCountNeeded = numFds;
if (count < fdCountNeeded) return NO_MEMORY;
if (handle) {
@@ -328,6 +337,12 @@ status_t GraphicBuffer::unflatten(
format = buf[4];
usage = buf[5];
native_handle* h = native_handle_create(numFds, numInts);
+ if (!h) {
+ width = height = stride = format = usage = 0;
+ handle = NULL;
+ ALOGE("unflatten: native_handle_create failed");
+ return NO_MEMORY;
+ }
memcpy(h->data, fds, numFds*sizeof(int));
memcpy(h->data + numFds, &buf[10], numInts*sizeof(int));
handle = h;
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
index a4364c6..d69a275 100644
--- a/opengl/tests/EGLTest/EGL_test.cpp
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -101,7 +101,7 @@ TEST_F(EGLTest, EGLTerminateSucceedsWithRemainingObjects) {
EXPECT_TRUE(eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs));
struct DummyConsumer : public BnConsumerListener {
- virtual void onFrameAvailable() {}
+ virtual void onFrameAvailable(const BufferItem& /* item */) {}
virtual void onBuffersReleased() {}
virtual void onSidebandStreamChanged() {}
};
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 02fb6f0..603836a 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -477,7 +477,6 @@ sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t display
const InputWindowInfo* windowInfo = windowHandle->getInfo();
if (windowInfo->displayId == displayId) {
int32_t flags = windowInfo->layoutParamsFlags;
- int32_t privateFlags = windowInfo->layoutParamsPrivateFlags;
if (windowInfo->visible) {
if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
@@ -489,11 +488,6 @@ sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t display
}
}
}
-
- if (privateFlags & InputWindowInfo::PRIVATE_FLAG_SYSTEM_ERROR) {
- // Error window is on top but not visible, so touch is dropped.
- return NULL;
- }
}
}
return NULL;
@@ -1190,7 +1184,6 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
int32_t y = int32_t(entry->pointerCoords[pointerIndex].
getAxisValue(AMOTION_EVENT_AXIS_Y));
sp<InputWindowHandle> newTouchedWindowHandle;
- sp<InputWindowHandle> topErrorWindowHandle;
bool isTouchModal = false;
// Traverse windows from front to back to find touched window and outside targets.
@@ -1202,13 +1195,6 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
continue; // wrong display
}
- int32_t privateFlags = windowInfo->layoutParamsPrivateFlags;
- if (privateFlags & InputWindowInfo::PRIVATE_FLAG_SYSTEM_ERROR) {
- if (topErrorWindowHandle == NULL) {
- topErrorWindowHandle = windowHandle;
- }
- }
-
int32_t flags = windowInfo->layoutParamsFlags;
if (windowInfo->visible) {
if (! (flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
@@ -1233,17 +1219,6 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
}
}
- // If there is an error window but it is not taking focus (typically because
- // it is invisible) then wait for it. Any other focused window may in
- // fact be in ANR state.
- if (topErrorWindowHandle != NULL && newTouchedWindowHandle != topErrorWindowHandle) {
- injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- NULL, NULL, nextWakeupTime,
- "Waiting because a system error window is about to be displayed.");
- injectionPermission = INJECTION_PERMISSION_UNKNOWN;
- goto Unresponsive;
- }
-
// Figure out whether splitting will be allowed for this window.
if (newTouchedWindowHandle != NULL
&& newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
diff --git a/services/inputflinger/InputWindow.h b/services/inputflinger/InputWindow.h
index 5879c84..42457ce 100644
--- a/services/inputflinger/InputWindow.h
+++ b/services/inputflinger/InputWindow.h
@@ -64,11 +64,6 @@ struct InputWindowInfo {
FLAG_NEEDS_MENU_KEY = 0x40000000,
};
- // Private Window flags from WindowManager.LayoutParams
- enum {
- PRIVATE_FLAG_SYSTEM_ERROR = 0x00000100,
- };
-
// Window types from WindowManager.LayoutParams
enum {
FIRST_APPLICATION_WINDOW = 1,
@@ -119,7 +114,6 @@ struct InputWindowInfo {
sp<InputChannel> inputChannel;
String8 name;
int32_t layoutParamsFlags;
- int32_t layoutParamsPrivateFlags;
int32_t layoutParamsType;
nsecs_t dispatchingTimeout;
int32_t frameLeft;
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index dc8fa64..c316ef6 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -191,6 +191,8 @@ void SensorService::onFirstRef()
mSensorEventScratch = new sensors_event_t[minBufferSize];
mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize];
+ mAckReceiver = new SensorEventAckReceiver(this);
+ mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);
mInitCheck = NO_ERROR;
run("SensorService", PRIORITY_URGENT_DISPLAY);
}
@@ -386,8 +388,6 @@ bool SensorService::threadLoop()
SensorDevice& device(SensorDevice::getInstance());
const size_t vcount = mVirtualSensorList.size();
- SensorEventAckReceiver sender(this);
- sender.run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);
const int halVersion = device.getHalDeviceVersion();
do {
ssize_t count = device.poll(mSensorEventBuffer, numEventMax);
@@ -408,16 +408,7 @@ bool SensorService::threadLoop()
// result in a deadlock as ~SensorEventConnection() needs to acquire mLock again for
// cleanup. So copy all the strongPointers to a vector before the lock is acquired.
SortedVector< sp<SensorEventConnection> > activeConnections;
- {
- Mutex::Autolock _l(mLock);
- for (size_t i=0 ; i < mActiveConnections.size(); ++i) {
- sp<SensorEventConnection> connection(mActiveConnections[i].promote());
- if (connection != 0) {
- activeConnections.add(connection);
- }
- }
- }
-
+ populateActiveConnections(&activeConnections);
Mutex::Autolock _l(mLock);
// Poll has returned. Hold a wakelock if one of the events is from a wake up sensor. The
// rest of this loop is under a critical section protected by mLock. Acquiring a wakeLock,
@@ -433,8 +424,7 @@ bool SensorService::threadLoop()
}
if (bufferHasWakeUpEvent && !mWakeLockAcquired) {
- acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
- mWakeLockAcquired = true;
+ setWakeLockAcquiredLocked(true);
}
recordLastValueLocked(mSensorEventBuffer, count);
@@ -522,8 +512,7 @@ bool SensorService::threadLoop()
}
if (mWakeLockAcquired && !needsWakeLock) {
- release_wake_lock(WAKE_LOCK_NAME);
- mWakeLockAcquired = false;
+ setWakeLockAcquiredLocked(false);
}
} while (!Thread::exitPending());
@@ -536,11 +525,52 @@ sp<Looper> SensorService::getLooper() const {
return mLooper;
}
+void SensorService::resetAllWakeLockRefCounts() {
+ SortedVector< sp<SensorEventConnection> > activeConnections;
+ populateActiveConnections(&activeConnections);
+ {
+ Mutex::Autolock _l(mLock);
+ for (size_t i=0 ; i < activeConnections.size(); ++i) {
+ if (activeConnections[i] != 0) {
+ activeConnections[i]->resetWakeLockRefCount();
+ }
+ }
+ setWakeLockAcquiredLocked(false);
+ }
+}
+
+void SensorService::setWakeLockAcquiredLocked(bool acquire) {
+ if (acquire) {
+ if (!mWakeLockAcquired) {
+ acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
+ mWakeLockAcquired = true;
+ }
+ mLooper->wake();
+ } else {
+ if (mWakeLockAcquired) {
+ release_wake_lock(WAKE_LOCK_NAME);
+ mWakeLockAcquired = false;
+ }
+ }
+}
+
+
+bool SensorService::isWakeLockAcquired() {
+ Mutex::Autolock _l(mLock);
+ return mWakeLockAcquired;
+}
+
bool SensorService::SensorEventAckReceiver::threadLoop() {
ALOGD("new thread SensorEventAckReceiver");
+ sp<Looper> looper = mService->getLooper();
do {
- sp<Looper> looper = mService->getLooper();
- looper->pollOnce(-1);
+ bool wakeLockAcquired = mService->isWakeLockAcquired();
+ int timeout = -1;
+ if (wakeLockAcquired) timeout = 5000;
+ int ret = looper->pollOnce(timeout);
+ if (ret == ALOOPER_POLL_TIMEOUT) {
+ mService->resetAllWakeLockRefCounts();
+ }
} while(!Thread::exitPending());
return false;
}
@@ -714,10 +744,7 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection,
sensors_event_t& event(mLastEventSeen.editValueFor(handle));
if (event.version == sizeof(sensors_event_t)) {
if (isWakeUpSensorEvent(event) && !mWakeLockAcquired) {
- acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
- mWakeLockAcquired = true;
- ALOGD_IF(DEBUG_CONNECTIONS, "acquired wakelock for on_change sensor %s",
- WAKE_LOCK_NAME);
+ setWakeLockAcquiredLocked(true);
}
connection->sendEvents(&event, 1, NULL);
if (!connection->needsWakeLock() && mWakeLockAcquired) {
@@ -922,8 +949,26 @@ void SensorService::checkWakeLockStateLocked() {
}
}
if (releaseLock) {
- release_wake_lock(WAKE_LOCK_NAME);
- mWakeLockAcquired = false;
+ setWakeLockAcquiredLocked(false);
+ }
+}
+
+void SensorService::sendEventsFromCache(const sp<SensorEventConnection>& connection) {
+ Mutex::Autolock _l(mLock);
+ connection->writeToSocketFromCache();
+ if (connection->needsWakeLock()) {
+ setWakeLockAcquiredLocked(true);
+ }
+}
+
+void SensorService::populateActiveConnections(
+ SortedVector< sp<SensorEventConnection> >* activeConnections) {
+ Mutex::Autolock _l(mLock);
+ for (size_t i=0 ; i < mActiveConnections.size(); ++i) {
+ sp<SensorEventConnection> connection(mActiveConnections[i].promote());
+ if (connection != 0) {
+ activeConnections->add(connection);
+ }
}
}
@@ -1013,6 +1058,11 @@ bool SensorService::SensorEventConnection::needsWakeLock() {
return !mDead && mWakeLockRefCount > 0;
}
+void SensorService::SensorEventConnection::resetWakeLockRefCount() {
+ Mutex::Autolock _l(mConnectionLock);
+ mWakeLockRefCount = 0;
+}
+
void SensorService::SensorEventConnection::dump(String8& result) {
Mutex::Autolock _l(mConnectionLock);
result.appendFormat("\t WakeLockRefCount %d | uid %d | cache size %d | max cache size %d\n",
@@ -1334,11 +1384,14 @@ void SensorService::SensorEventConnection::sendPendingFlushEventsLocked() {
while (flushInfo.mPendingFlushEventsToSend > 0) {
const int sensor_handle = mSensorInfo.keyAt(i);
flushCompleteEvent.meta_data.sensor = sensor_handle;
- if (mService->getSensorFromHandle(sensor_handle).isWakeUpSensor()) {
+ bool wakeUpSensor = mService->getSensorFromHandle(sensor_handle).isWakeUpSensor();
+ if (wakeUpSensor) {
+ ++mWakeLockRefCount;
flushCompleteEvent.flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
}
ssize_t size = SensorEventQueue::write(mChannel, &flushCompleteEvent, 1);
if (size < 0) {
+ if (wakeUpSensor) --mWakeLockRefCount;
return;
}
ALOGD_IF(DEBUG_CONNECTIONS, "sent dropped flush complete event==%d ",
@@ -1348,11 +1401,12 @@ void SensorService::SensorEventConnection::sendPendingFlushEventsLocked() {
}
}
-void SensorService::SensorEventConnection::writeToSocketFromCacheLocked() {
+void SensorService::SensorEventConnection::writeToSocketFromCache() {
// At a time write at most half the size of the receiver buffer in SensorEventQueue OR
// half the size of the socket buffer allocated in BitTube whichever is smaller.
const int maxWriteSize = helpers::min(SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT/2,
int(mService->mSocketBufferSize/(sizeof(sensors_event_t)*2)));
+ Mutex::Autolock _l(mConnectionLock);
// Send pending flush complete events (if any)
sendPendingFlushEventsLocked();
for (int numEventsSent = 0; numEventsSent < mCacheSize;) {
@@ -1503,9 +1557,8 @@ int SensorService::SensorEventConnection::handleEvent(int fd, int events, void*
}
if (events & ALOOPER_EVENT_OUTPUT) {
- // send sensor data that is stored in mEventCache.
- Mutex::Autolock _l(mConnectionLock);
- writeToSocketFromCacheLocked();
+ // send sensor data that is stored in mEventCache for this connection.
+ mService->sendEventsFromCache(this);
}
return 1;
}
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 5e3eeb5..8719487 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -101,7 +101,7 @@ class SensorService :
void sendPendingFlushEventsLocked();
// Writes events from mEventCache to the socket.
- void writeToSocketFromCacheLocked();
+ void writeToSocketFromCache();
// Compute the approximate cache size from the FIFO sizes of various sensors registered for
// this connection. Wake up and non-wake up sensors have separate FIFOs but FIFO may be
@@ -182,6 +182,7 @@ class SensorService :
void setFirstFlushPending(int32_t handle, bool value);
void dump(String8& result);
bool needsWakeLock();
+ void resetWakeLockRefCount();
uid_t getUid() const { return mUid; }
};
@@ -230,12 +231,29 @@ class SensorService :
// corresponding applications, if yes the wakelock is released.
void checkWakeLockState();
void checkWakeLockStateLocked();
+ bool isWakeLockAcquired();
bool isWakeUpSensorEvent(const sensors_event_t& event) const;
SensorRecord * getSensorRecord(int handle);
sp<Looper> getLooper() const;
+ // Reset mWakeLockRefCounts for all SensorEventConnections to zero. This may happen if
+ // SensorService did not receive any acknowledgements from apps which have registered for
+ // wake_up sensors.
+ void resetAllWakeLockRefCounts();
+
+ // Acquire or release wake_lock. If wake_lock is acquired, set the timeout in the looper to
+ // 5 seconds and wake the looper.
+ void setWakeLockAcquiredLocked(bool acquire);
+
+ // Send events from the event cache for this particular connection.
+ void sendEventsFromCache(const sp<SensorEventConnection>& connection);
+
+ // Promote all weak referecences in mActiveConnections vector to strong references and add them
+ // to the output vector.
+ void populateActiveConnections(SortedVector< sp<SensorEventConnection> >* activeConnections);
+
// constants
Vector<Sensor> mSensorList;
Vector<Sensor> mUserSensorListDebug;
@@ -247,6 +265,7 @@ class SensorService :
// supported or not.
uint32_t mSocketBufferSize;
sp<Looper> mLooper;
+ sp<SensorEventAckReceiver> mAckReceiver;
// protected by mLock
mutable Mutex mLock;
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index f1ddbe2..3123b63 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -83,6 +83,12 @@ else
LOCAL_CFLAGS += -DPRESENT_TIME_OFFSET_FROM_VSYNC_NS=0
endif
+ifneq ($(MAX_VIRTUAL_DISPLAY_DIMENSION),)
+ LOCAL_CFLAGS += -DMAX_VIRTUAL_DISPLAY_DIMENSION=$(MAX_VIRTUAL_DISPLAY_DIMENSION)
+else
+ LOCAL_CFLAGS += -DMAX_VIRTUAL_DISPLAY_DIMENSION=0
+endif
+
LOCAL_CFLAGS += -fvisibility=hidden -Werror=format
LOCAL_CFLAGS += -std=c++11
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 342016e..22d3cec 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -68,7 +68,7 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp,
mConsumer->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
}
-status_t FramebufferSurface::beginFrame(bool /* mustRecompose */) {
+status_t FramebufferSurface::beginFrame(bool /*mustRecompose*/) {
return NO_ERROR;
}
@@ -122,7 +122,7 @@ status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>&
}
// Overrides ConsumerBase::onFrameAvailable(), does not call base class impl.
-void FramebufferSurface::onFrameAvailable() {
+void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) {
sp<GraphicBuffer> buf;
sp<Fence> acquireFence;
status_t err = nextBuffer(buf, acquireFence);
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index d0bf22b..8605862 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -56,7 +56,7 @@ public:
private:
virtual ~FramebufferSurface() { }; // this class cannot be overloaded
- virtual void onFrameAvailable();
+ virtual void onFrameAvailable(const BufferItem& item);
virtual void freeBufferLocked(int slotIndex);
virtual void dumpLocked(String8& result, const char* prefix) const;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 91e9a02..c91f0af 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -158,7 +158,7 @@ void Layer::onLayerDisplayed(const sp<const DisplayDevice>& /* hw */,
}
}
-void Layer::onFrameAvailable() {
+void Layer::onFrameAvailable(const BufferItem& /* item */) {
android_atomic_inc(&mQueuedFrames);
mFlinger->signalLayerUpdate();
}
@@ -277,12 +277,17 @@ static Rect reduce(const Rect& win, const Region& exclude) {
Rect Layer::computeBounds() const {
const Layer::State& s(getDrawingState());
+ return computeBounds(s.activeTransparentRegion);
+}
+
+Rect Layer::computeBounds(const Region& activeTransparentRegion) const {
+ const Layer::State& s(getDrawingState());
Rect win(s.active.w, s.active.h);
if (!s.active.crop.isEmpty()) {
win.intersect(s.active.crop, &win);
}
// subtract the transparent region and snap to the bounds
- return reduce(win, s.activeTransparentRegion);
+ return reduce(win, activeTransparentRegion);
}
FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const {
@@ -404,7 +409,22 @@ void Layer::setGeometry(
// apply the layer's transform, followed by the display's global transform
// here we're guaranteed that the layer's transform preserves rects
- Rect frame(s.transform.transform(computeBounds()));
+ Region activeTransparentRegion(s.activeTransparentRegion);
+ if (!s.active.crop.isEmpty()) {
+ Rect activeCrop(s.active.crop);
+ activeCrop = s.transform.transform(activeCrop);
+ activeCrop.intersect(hw->getViewport(), &activeCrop);
+ activeCrop = s.transform.inverse().transform(activeCrop);
+ // mark regions outside the crop as transparent
+ activeTransparentRegion.orSelf(Rect(0, 0, s.active.w, activeCrop.top));
+ activeTransparentRegion.orSelf(Rect(0, activeCrop.bottom,
+ s.active.w, s.active.h));
+ activeTransparentRegion.orSelf(Rect(0, activeCrop.top,
+ activeCrop.left, activeCrop.bottom));
+ activeTransparentRegion.orSelf(Rect(activeCrop.right, activeCrop.top,
+ s.active.w, activeCrop.bottom));
+ }
+ Rect frame(s.transform.transform(computeBounds(activeTransparentRegion)));
frame.intersect(hw->getViewport(), &frame);
const Transform& tr(hw->getTransform());
layer.setFrame(tr.transform(frame));
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 2ef39e8..b705bc2 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -142,6 +142,7 @@ public:
void computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh,
bool useIdentityTransform) const;
+ Rect computeBounds(const Region& activeTransparentRegion) const;
Rect computeBounds() const;
sp<IBinder> getHandle();
@@ -329,7 +330,7 @@ protected:
private:
// Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener
- virtual void onFrameAvailable();
+ virtual void onFrameAvailable(const BufferItem& item);
virtual void onSidebandStreamChanged();
void commitTransaction();
diff --git a/services/surfaceflinger/LayerDim.h b/services/surfaceflinger/LayerDim.h
index 60edd91..a0cfca9 100644
--- a/services/surfaceflinger/LayerDim.h
+++ b/services/surfaceflinger/LayerDim.h
@@ -28,7 +28,7 @@ namespace android {
class LayerDim : public Layer
{
-public:
+public:
LayerDim(SurfaceFlinger* flinger, const sp<Client>& client,
const String8& name, uint32_t w, uint32_t h, uint32_t flags);
virtual ~LayerDim();
@@ -36,8 +36,7 @@ public:
virtual const char* getTypeId() const { return "LayerDim"; }
virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
bool useIdentityTransform) const;
- using Layer::isOpaque;
- virtual bool isOpaque() const { return false; }
+ virtual bool isOpaque(const Layer::State&) const { return false; }
virtual bool isSecure() const { return false; }
virtual bool isFixedSize() const { return true; }
virtual bool isVisible() const;
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index 767b714..7cd42e4 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -219,6 +219,10 @@ void RenderEngine::fillRegionWithColor(const Region& region, uint32_t height,
drawMesh(mesh);
}
+void RenderEngine::flush() {
+ glFlush();
+}
+
void RenderEngine::clearWithColor(float red, float green, float blue, float alpha) {
glClearColor(red, green, blue, alpha);
glClear(GL_COLOR_BUFFER_BIT);
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index acbff9b..8d7529c 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -67,6 +67,7 @@ public:
virtual void dump(String8& result);
// helpers
+ void flush();
void clearWithColor(float red, float green, float blue, float alpha);
void fillRegionWithColor(const Region& region, uint32_t height,
float red, float green, float blue, float alpha);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e767be2..7d6d7c2 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -506,6 +506,9 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,
return BAD_VALUE;
}
+ if (!display.get())
+ return NAME_NOT_FOUND;
+
int32_t type = NAME_NOT_FOUND;
for (int i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
if (display == mBuiltinDisplays[i]) {
@@ -652,7 +655,7 @@ status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& display, int mode) {
virtual bool handler() {
Vector<DisplayInfo> configs;
mFlinger.getDisplayConfigs(mDisplay, &configs);
- if(mMode < 0 || static_cast<size_t>(mMode) >= configs.size()) {
+ if (mMode < 0 || mMode >= static_cast<int>(configs.size())) {
ALOGE("Attempt to set active config = %d for display with %zu configs",
mMode, configs.size());
}
@@ -1331,7 +1334,22 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
// etc.) but no internal state (i.e. a DisplayDevice).
if (state.surface != NULL) {
- hwcDisplayId = allocateHwcDisplayId(state.type);
+ int width = 0;
+ int status = state.surface->query(
+ NATIVE_WINDOW_WIDTH, &width);
+ ALOGE_IF(status != NO_ERROR,
+ "Unable to query width (%d)", status);
+ int height = 0;
+ status = state.surface->query(
+ NATIVE_WINDOW_HEIGHT, &height);
+ ALOGE_IF(status != NO_ERROR,
+ "Unable to query height (%d)", status);
+ if (MAX_VIRTUAL_DISPLAY_DIMENSION == 0 ||
+ (width <= MAX_VIRTUAL_DISPLAY_DIMENSION &&
+ height <= MAX_VIRTUAL_DISPLAY_DIMENSION)) {
+ hwcDisplayId = allocateHwcDisplayId(state.type);
+ }
+
sp<VirtualDisplaySurface> vds = new VirtualDisplaySurface(
*mHwc, hwcDisplayId, state.surface,
bqProducer, bqConsumer, state.displayName);
@@ -3205,6 +3223,8 @@ status_t SurfaceFlinger::captureScreenImplLocked(
EGLSyncKHR sync;
if (!DEBUG_SCREENSHOTS) {
sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
+ // native fence fd will not be populated until flush() is done.
+ getRenderEngine().flush();
} else {
sync = EGL_NO_SYNC_KHR;
}
@@ -3251,10 +3271,8 @@ status_t SurfaceFlinger::captureScreenImplLocked(
} else {
result = BAD_VALUE;
}
+ // queueBuffer takes ownership of syncFd
window->queueBuffer(window, buffer, syncFd);
- if (syncFd != -1) {
- close(syncFd);
- }
}
} else {
result = BAD_VALUE;