Merge changes from topic 'gralloc1' into nyc-mr1-dev
* changes:
libui: Convert Allocator and Mapper to gralloc1
libui: Adds C++ shim for gralloc1
libui: Add Gralloc1On0Adapter
diff --git a/cmds/dumpstate/bugreport-format.md b/cmds/dumpstate/bugreport-format.md
index d7837ae..ca7d574 100644
--- a/cmds/dumpstate/bugreport-format.md
+++ b/cmds/dumpstate/bugreport-format.md
@@ -15,13 +15,13 @@
format _YYYY-MM-DD-HH-MM-SS_), and Shell simply propagates it as an attachment
in the `ACTION_SEND_MULTIPLE` intent.
-## Version v0 (Android M)
+## Version 0 (Android M)
On _Android M (Marshmallow)_, dumpstate still generates a flat
_bugreport-DATE.txt_ file, but then **Shell** creates a zip file called
_bugreport-DATE.zip_ containing a _bugreport-DATE.txt_ entry and sends that
file as the `ACTION_SEND_MULTIPLE` attachment.
-## Version v1 (Android N)
+## Version 1.0 (Android N)
On _Android N (TBD)_, `dumpstate` generates a zip file directly (unless there
is a failure, in which case it reverts to the flat file that is zipped by
**Shell** and hence the end result is the _v0_ format).
@@ -33,7 +33,7 @@
The zip file also contains 2 metadata entries generated by `dumpstate`:
-- `version.txt`: whose value is **v1**.
+- `version.txt`: whose value is **1.0**.
- `main-entry.txt`: whose value is the name of the flat text entry (i.e.,
_bugreport-BUILD_ID-DATE.txt_ or _bugreport-NEW_NAME.txt_).
@@ -61,16 +61,16 @@
changes become stable.
For example, the initial version during _Android N_ development was
-**v1-dev1**. When `dumpsys` was split in 2 sections but not all tools were
-ready to parse that format, the version was named **v1-dev2**,
+**1.0-dev1**. When `dumpsys` was split in 2 sections but not all tools were
+ready to parse that format, the version was named **1.0-dev2**,
which had to be passed do `dumpsys` explicitly (i.e., trhough a
-`-V v1-dev2` argument). Once that format became stable and tools
-knew how to parse it, the default version became **v1-dev2**.
+`-V 1.0-dev2` argument). Once that format became stable and tools
+knew how to parse it, the default version became **1.0-dev2**.
Similarly, if changes in the file format are made after the initial release of
Android defining that format, then a new _sub-version_ will be used.
For example, if after _Android N_ launches changes are made for the next _N_
-release, the version will be called **v1.1** or something like that.
+release, the version will be called **1.1** or something like that.
Determining version and main entry
-----------------------------------------------
@@ -83,7 +83,7 @@
version = read("version.txt")
main_entry = read("main_entry.txt")
else
- version = v0
+ version = 0
main_entry = entries[0]
fi
```
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 884cdf4..a67d204 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -96,10 +96,9 @@
*
* See bugreport-format.txt for more info.
*/
-// TODO: change to "v1" before final N build
-static std::string VERSION_DEFAULT = "v1-dev4";
+static std::string VERSION_DEFAULT = "1.0";
-static bool is_user_build() {
+bool is_user_build() {
return 0 == strncmp(build_type, "user", PROPERTY_VALUE_MAX - 1);
}
@@ -542,7 +541,7 @@
property_get("ro.build.display.id", build, "(unknown)");
property_get("ro.build.fingerprint", fingerprint, "(unknown)");
property_get("ro.build.type", build_type, "(unknown)");
- property_get("ro.baseband", radio, "(unknown)");
+ property_get("gsm.version.baseband", radio, "(unknown)");
property_get("ro.bootloader", bootloader, "(unknown)");
property_get("gsm.operator.alpha", network, "(unknown)");
strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now));
@@ -622,7 +621,6 @@
return add_zip_entry_from_fd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
}
-/* adds all files from a directory to the zipped bugreport file */
void add_dir(const char *dir, bool recursive) {
if (!zip_writer) {
MYLOGD("Not adding dir %s because zip_writer is not set\n", dir);
@@ -945,19 +943,19 @@
printf("== Running Application Activities\n");
printf("========================================================\n");
- run_command("APP ACTIVITIES", 30, "-t", "30", "dumpsys", "activity", "all", NULL);
+ run_command("APP ACTIVITIES", 30, "dumpsys", "-t", "30", "activity", "all", NULL);
printf("========================================================\n");
printf("== Running Application Services\n");
printf("========================================================\n");
- run_command("APP SERVICES", 30, "-t", "30", "dumpsys", "activity", "service", "all", NULL);
+ run_command("APP SERVICES", 30, "dumpsys", "-t", "30", "activity", "service", "all", NULL);
printf("========================================================\n");
printf("== Running Application Providers\n");
printf("========================================================\n");
- run_command("APP SERVICES", 30, "-t", "30", "dumpsys", "activity", "provider", "all", NULL);
+ run_command("APP SERVICES", 30, "dumpsys", "-t", "30", "activity", "provider", "all", NULL);
printf("========================================================\n");
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 94bfc5a..4769974 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -93,6 +93,9 @@
/* adds a new entry to the existing zip file. */
bool add_zip_entry_from_fd(const std::string& entry_name, int fd);
+/* adds all files from a directory to the zipped bugreport file */
+void add_dir(const char *dir, bool recursive);
+
/* prints the contents of a file */
int dump_file(const char *title, const char *path);
@@ -196,12 +199,15 @@
/** Gets the last modification time of a file, or default time if file is not found. */
time_t get_mtime(int fd, time_t default_mtime);
-/* dump eMMC Extended CSD data */
+/* Dumps eMMC Extended CSD data. */
void dump_emmc_ecsd(const char *ext_csd_path);
-/** gets command-line arguments */
+/** Gets command-line arguments. */
void format_args(int argc, const char *argv[], std::string *args);
+/** Tells if the device is running a user build. */
+bool is_user_build();
+
/*
* Helper class used to report how long it takes for a section to finish.
*
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 3775709..e1cfc9d 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -51,8 +51,10 @@
#define TOKEN_MAX 16 /* max number of arguments in buffer */
#define REPLY_MAX 256 /* largest reply allowed */
+using android::base::EndsWith;
using android::base::Join;
using android::base::Split;
+using android::base::StartsWith;
using android::base::StringPrintf;
namespace android {
@@ -361,6 +363,49 @@
}
int RunPreopt() {
+ // Run the preopt.
+ //
+ // There's one thing we have to be careful about: we may/will be asked to compile an app
+ // living in the system image. This may be a valid request - if the app wasn't compiled,
+ // e.g., if the system image wasn't large enough to include preopted files. However, the
+ // data we have is from the old system, so the driver (the OTA service) can't actually
+ // know. Thus, we will get requests for apps that have preopted components. To avoid
+ // duplication (we'd generate files that are not used and are *not* cleaned up), do two
+ // simple checks:
+ //
+ // 1) Does the apk_path start with the value of ANDROID_ROOT? (~in the system image)
+ // (For simplicity, assume the value of ANDROID_ROOT does not contain a symlink.)
+ //
+ // 2) If you replace the name in the apk_path with "oat," does the path exist?
+ // (=have a subdirectory for preopted files)
+ //
+ // If the answer to both is yes, skip the dexopt.
+ //
+ // Note: while one may think it's OK to call dexopt and it will fail (because APKs should
+ // be stripped), that's not true for APKs signed outside the build system (so the
+ // jar content must be exactly the same).
+
+ // (This is ugly as it's the only thing where we need to understand the contents
+ // of package_parameters_, but it beats postponing the decision or using the call-
+ // backs to do weird things.)
+ constexpr size_t kApkPathIndex = 0;
+ CHECK_GT(DEXOPT_PARAM_COUNT, kApkPathIndex);
+ CHECK(package_parameters_[kApkPathIndex] != nullptr);
+ CHECK(system_properties_.GetProperty(kAndroidRootPathPropertyName) != nullptr);
+ if (StartsWith(package_parameters_[kApkPathIndex],
+ system_properties_.GetProperty(kAndroidRootPathPropertyName)->c_str())) {
+ const char* last_slash = strrchr(package_parameters_[kApkPathIndex], '/');
+ if (last_slash != nullptr) {
+ std::string path(package_parameters_[kApkPathIndex],
+ last_slash - package_parameters_[kApkPathIndex] + 1);
+ CHECK(EndsWith(path, "/"));
+ path = path + "oat";
+ if (access(path.c_str(), F_OK) == 0) {
+ return 0;
+ }
+ }
+ }
+
return dexopt(package_parameters_);
}
diff --git a/cmds/installd/otapreopt_script.sh b/cmds/installd/otapreopt_script.sh
index a31734a..394c244 100644
--- a/cmds/installd/otapreopt_script.sh
+++ b/cmds/installd/otapreopt_script.sh
@@ -18,24 +18,33 @@
# This script will run as a postinstall step to drive otapreopt.
+STATUS_FD="$2"
+
# Maximum number of packages/steps.
MAXIMUM_PACKAGES=1000
PREPARE=$(cmd otadexopt prepare)
-if [ "$PREPARE" != "Success" ] ; then
- echo "Failed to prepare."
- exit 1
-fi
+# Note: Ignore preparation failures. Step and done will fail and exit this.
+# This is necessary to support suspends - the OTA service will keep
+# the state around for us.
+
+PROGRESS=$(cmd otadexopt progress)
+print -u${STATUS_FD} "global_progress $PROGRESS"
i=0
while ((i<MAXIMUM_PACKAGES)) ; do
cmd otadexopt step
+
+ PROGRESS=$(cmd otadexopt progress)
+ print -u${STATUS_FD} "global_progress $PROGRESS"
+
DONE=$(cmd otadexopt done)
- if [ "$DONE" = "OTA complete." ] ; then
- break
+ if [ "$DONE" = "OTA incomplete." ] ; then
+ sleep 1
+ i=$((i+1))
+ continue
fi
- sleep 1
- i=$((i+1))
+ break
done
DONE=$(cmd otadexopt done)
@@ -45,6 +54,7 @@
echo "Complete or error."
fi
+print -u${STATUS_FD} "global_progress 1.0"
cmd otadexopt cleanup
exit 0
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index 09300a2..fe4b1fa 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -66,6 +66,8 @@
virtual void onFrameReplaced(const BufferItem& item) override;
virtual void onBuffersReleased() override;
virtual void onSidebandStreamChanged() override;
+ virtual bool getFrameTimestamps(uint64_t frameNumber,
+ FrameTimestamps* outTimestamps) const override;
private:
// mConsumerListener is a weak reference to the IConsumerListener. This is
// the raison d'etre of ProxyConsumerListener.
diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h
index a75ed98..a85bbb7 100644
--- a/include/gui/BufferQueueProducer.h
+++ b/include/gui/BufferQueueProducer.h
@@ -186,6 +186,10 @@
virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
sp<Fence>* outFence, float outTransformMatrix[16]) override;
+ // See IGraphicBufferProducer::getFrameTimestamps
+ virtual bool getFrameTimestamps(uint64_t frameNumber,
+ FrameTimestamps* outTimestamps) const override;
+
private:
// This is required by the IBinder::DeathRecipient interface
virtual void binderDied(const wp<IBinder>& who);
diff --git a/include/gui/FrameTimestamps.h b/include/gui/FrameTimestamps.h
new file mode 100644
index 0000000..4dc7467
--- /dev/null
+++ b/include/gui/FrameTimestamps.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef ANDROID_GUI_FRAMETIMESTAMPS_H
+#define ANDROID_GUI_FRAMETIMESTAMPS_H
+
+#include <utils/Timers.h>
+#include <utils/Flattenable.h>
+
+namespace android {
+
+struct FrameTimestamps : public LightFlattenablePod<FrameTimestamps> {
+ FrameTimestamps() :
+ frameNumber(0),
+ postedTime(0),
+ acquireTime(0),
+ refreshStartTime(0),
+ glCompositionDoneTime(0),
+ displayRetireTime(0),
+ releaseTime(0) {}
+
+ uint64_t frameNumber;
+ nsecs_t postedTime;
+ nsecs_t acquireTime;
+ nsecs_t refreshStartTime;
+ nsecs_t glCompositionDoneTime;
+ nsecs_t displayRetireTime;
+ nsecs_t releaseTime;
+};
+
+} // namespace android
+#endif
diff --git a/include/gui/IConsumerListener.h b/include/gui/IConsumerListener.h
index 3f39799..1efcf3c 100644
--- a/include/gui/IConsumerListener.h
+++ b/include/gui/IConsumerListener.h
@@ -25,6 +25,8 @@
#include <binder/IInterface.h>
+#include <gui/FrameTimestamps.h>
+
namespace android {
// ----------------------------------------------------------------------------
@@ -78,6 +80,11 @@
// stream is first attached and when it is either detached or replaced by a
// different stream.
virtual void onSidebandStreamChanged() = 0; /* Asynchronous */
+
+ // See IGraphicBufferProducer::getFrameTimestamps
+ // This queries the consumer for the timestamps
+ virtual bool getFrameTimestamps(uint64_t /*frameNumber*/,
+ FrameTimestamps* /*outTimestamps*/) const { return false; }
};
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index 37ae6df..0c24606 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -30,6 +30,8 @@
#include <ui/Rect.h>
#include <ui/Region.h>
+#include <gui/FrameTimestamps.h>
+
namespace android {
// ----------------------------------------------------------------------------
@@ -568,6 +570,14 @@
// Returns NO_ERROR or the status of the Binder transaction
virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
sp<Fence>* outFence, float outTransformMatrix[16]) = 0;
+
+ // Attempts to retrieve timestamp information for the given frame number.
+ // If information for the given frame number is not found, returns false.
+ // Returns true otherwise.
+ //
+ // If a fence has not yet signaled the timestamp returned will be 0;
+ virtual bool getFrameTimestamps(uint64_t /*frameNumber*/,
+ FrameTimestamps* /*outTimestamps*/) const { return false; }
};
// ----------------------------------------------------------------------------
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 646203b..7d9d901 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -134,6 +134,12 @@
status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
sp<Fence>* outFence, float outTransformMatrix[16]);
+ // See IGraphicBufferProducer::getFrameTimestamps
+ bool getFrameTimestamps(uint64_t frameNumber, nsecs_t* outPostedTime,
+ nsecs_t* outAcquireTime, nsecs_t* outRefreshStartTime,
+ nsecs_t* outGlCompositionDoneTime, nsecs_t* outDisplayRetireTime,
+ nsecs_t* outReleaseTime);
+
protected:
virtual ~Surface();
@@ -183,6 +189,7 @@
int dispatchSetSurfaceDamage(va_list args);
int dispatchSetSharedBufferMode(va_list args);
int dispatchSetAutoRefresh(va_list args);
+ int dispatchGetFrameTimestamps(va_list args);
protected:
virtual int dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd);
diff --git a/include/ui/FrameStats.h b/include/ui/FrameStats.h
index 5fdf94d..6bfe635 100644
--- a/include/ui/FrameStats.h
+++ b/include/ui/FrameStats.h
@@ -25,6 +25,7 @@
class FrameStats : public LightFlattenable<FrameStats> {
public:
+ FrameStats() : refreshPeriodNano(0) {};
/*
* Approximate refresh time, in nanoseconds.
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index fb8d620..5f345cf 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -312,17 +312,17 @@
IInterface::asBinder(this).get(),
parcel_fd, size, err, strerror(-err));
- int fd = dup( parcel_fd );
- ALOGE_IF(fd==-1, "cannot dup fd=%d, size=%zd, err=%d (%s)",
- parcel_fd, size, err, strerror(errno));
-
- int access = PROT_READ;
- if (!(flags & READ_ONLY)) {
- access |= PROT_WRITE;
- }
-
Mutex::Autolock _l(mLock);
if (mHeapId == -1) {
+ int fd = dup( parcel_fd );
+ ALOGE_IF(fd==-1, "cannot dup fd=%d, size=%zd, err=%d (%s)",
+ parcel_fd, size, err, strerror(errno));
+
+ int access = PROT_READ;
+ if (!(flags & READ_ONLY)) {
+ access |= PROT_WRITE;
+ }
+
mRealHeap = true;
mBase = mmap(0, size, access, MAP_SHARED, fd, offset);
if (mBase == MAP_FAILED) {
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index 3e30bb2..46feb1c 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -94,12 +94,6 @@
LOCAL_CFLAGS += -DDONT_USE_FENCE_SYNC
endif
-ifeq ($(BOARD_ENABLE_GPU_PROTECTED_CONTENT),true)
- LOCAL_CFLAGS += -DENABLE_GPU_PROTECTED_CONTENT=true
-else
- LOCAL_CFLAGS += -DENABLE_GPU_PROTECTED_CONTENT=false
-endif
-
include $(BUILD_SHARED_LIBRARY)
ifeq (,$(ONE_SHOT_MAKEFILE))
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index ccbb5a2..6de98f5 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -61,6 +61,15 @@
}
}
+bool BufferQueue::ProxyConsumerListener::getFrameTimestamps(
+ uint64_t frameNumber, FrameTimestamps* outTimestamps) const {
+ sp<ConsumerListener> listener(mConsumerListener.promote());
+ if (listener != NULL) {
+ return listener->getFrameTimestamps(frameNumber, outTimestamps);
+ }
+ return false;
+}
+
void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer,
const sp<IGraphicBufferAlloc>& allocator) {
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 07cfb4f..3a0a283 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -1405,6 +1405,22 @@
return NO_ERROR;
}
+bool BufferQueueProducer::getFrameTimestamps(uint64_t frameNumber,
+ FrameTimestamps* outTimestamps) const {
+ ATRACE_CALL();
+ BQ_LOGV("getFrameTimestamps, %" PRIu64, frameNumber);
+ sp<IConsumerListener> listener;
+
+ {
+ Mutex::Autolock lock(mCore->mMutex);
+ listener = mCore->mConsumerListener;
+ }
+ if (listener != NULL) {
+ return listener->getFrameTimestamps(frameNumber, outTimestamps);
+ }
+ return false;
+}
+
void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
// If we're here, it means that a producer we were connected to died.
// We're guaranteed that we are still connected to it because we remove
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index a06c7b5..553b65c 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -135,8 +135,7 @@
bool atEnd = (cropExtLen+1) < extsLen &&
!strcmp(" " PROT_CONTENT_EXT_STR, exts + extsLen - (cropExtLen+1));
bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " ");
- return ENABLE_GPU_PROTECTED_CONTENT &&
- (equal || atStart || atEnd || inMiddle);
+ return equal || atStart || atEnd || inMiddle;
}
static bool hasEglProtectedContent() {
diff --git a/libs/gui/IConsumerListener.cpp b/libs/gui/IConsumerListener.cpp
index cab7dc3..9a06011 100644
--- a/libs/gui/IConsumerListener.cpp
+++ b/libs/gui/IConsumerListener.cpp
@@ -31,6 +31,7 @@
ON_FRAME_AVAILABLE = IBinder::FIRST_CALL_TRANSACTION,
ON_BUFFER_RELEASED,
ON_SIDEBAND_STREAM_CHANGED,
+ GET_FRAME_TIMESTAMPS
};
class BpConsumerListener : public BpInterface<IConsumerListener>
@@ -60,6 +61,42 @@
data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor());
remote()->transact(ON_SIDEBAND_STREAM_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
}
+
+ virtual bool getFrameTimestamps(uint64_t frameNumber,
+ FrameTimestamps* outTimestamps) const {
+ Parcel data, reply;
+ status_t result = data.writeInterfaceToken(
+ IConsumerListener::getInterfaceDescriptor());
+ if (result != NO_ERROR) {
+ ALOGE("getFrameTimestamps failed to write token: %d", result);
+ return false;
+ }
+ result = data.writeUint64(frameNumber);
+ if (result != NO_ERROR) {
+ ALOGE("getFrameTimestamps failed to write: %d", result);
+ return false;
+ }
+ result = remote()->transact(GET_FRAME_TIMESTAMPS, data, &reply);
+ if (result != NO_ERROR) {
+ ALOGE("getFrameTimestamps failed to transact: %d", result);
+ return false;
+ }
+ bool found = false;
+ result = reply.readBool(&found);
+ if (result != NO_ERROR) {
+ ALOGE("getFrameTimestamps failed to read: %d", result);
+ return false;
+ }
+ if (found) {
+ result = reply.read(*outTimestamps);
+ if (result != NO_ERROR) {
+ ALOGE("getFrameTimestamps failed to read timestamps: %d",
+ result);
+ return false;
+ }
+ }
+ return found;
+ }
};
// Out-of-line virtual method definition to trigger vtable emission in this
@@ -88,6 +125,30 @@
CHECK_INTERFACE(IConsumerListener, data, reply);
onSidebandStreamChanged();
return NO_ERROR; }
+ case GET_FRAME_TIMESTAMPS: {
+ CHECK_INTERFACE(IConsumerListener, data, reply);
+ uint64_t frameNumber = 0;
+ status_t result = data.readUint64(&frameNumber);
+ if (result != NO_ERROR) {
+ ALOGE("onTransact failed to read: %d", result);
+ return result;
+ }
+ FrameTimestamps timestamps;
+ bool found = getFrameTimestamps(frameNumber, ×tamps);
+ result = reply->writeBool(found);
+ if (result != NO_ERROR) {
+ ALOGE("onTransact failed to write: %d", result);
+ return result;
+ }
+ if (found) {
+ result = reply->write(timestamps);
+ if (result != NO_ERROR) {
+ ALOGE("onTransact failed to write timestamps: %d", result);
+ return result;
+ }
+ }
+ return NO_ERROR;
+ }
}
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 2c48d83..9317eff 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -55,6 +55,7 @@
SET_AUTO_REFRESH,
SET_DEQUEUE_TIMEOUT,
GET_LAST_QUEUED_BUFFER,
+ GET_FRAME_TIMESTAMPS
};
class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
@@ -418,6 +419,42 @@
*outFence = fence;
return result;
}
+
+ virtual bool getFrameTimestamps(uint64_t frameNumber,
+ FrameTimestamps* outTimestamps) const {
+ Parcel data, reply;
+ status_t result = data.writeInterfaceToken(
+ IGraphicBufferProducer::getInterfaceDescriptor());
+ if (result != NO_ERROR) {
+ ALOGE("getFrameTimestamps failed to write token: %d", result);
+ return false;
+ }
+ result = data.writeUint64(frameNumber);
+ if (result != NO_ERROR) {
+ ALOGE("getFrameTimestamps failed to write: %d", result);
+ return false;
+ }
+ result = remote()->transact(GET_FRAME_TIMESTAMPS, data, &reply);
+ if (result != NO_ERROR) {
+ ALOGE("getFrameTimestamps failed to transact: %d", result);
+ return false;
+ }
+ bool found = false;
+ result = reply.readBool(&found);
+ if (result != NO_ERROR) {
+ ALOGE("getFrameTimestamps failed to read: %d", result);
+ return false;
+ }
+ if (found) {
+ result = reply.read(*outTimestamps);
+ if (result != NO_ERROR) {
+ ALOGE("getFrameTimestamps failed to read timestamps: %d",
+ result);
+ return false;
+ }
+ }
+ return found;
+ }
};
// Out-of-line virtual method definition to trigger vtable emission in this
@@ -659,6 +696,30 @@
}
return NO_ERROR;
}
+ case GET_FRAME_TIMESTAMPS: {
+ CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+ uint64_t frameNumber = 0;
+ status_t result = data.readUint64(&frameNumber);
+ if (result != NO_ERROR) {
+ ALOGE("onTransact failed to read: %d", result);
+ return result;
+ }
+ FrameTimestamps timestamps;
+ bool found = getFrameTimestamps(frameNumber, ×tamps);
+ result = reply->writeBool(found);
+ if (result != NO_ERROR) {
+ ALOGE("onTransact failed to write: %d", result);
+ return result;
+ }
+ if (found) {
+ result = reply->write(timestamps);
+ if (result != NO_ERROR) {
+ ALOGE("onTransact failed to write timestamps: %d", result);
+ return result;
+ }
+ }
+ return NO_ERROR;
+ }
}
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 9d130cd..4739ca4 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -133,6 +133,39 @@
outTransformMatrix);
}
+bool Surface::getFrameTimestamps(uint64_t frameNumber, nsecs_t* outPostedTime,
+ nsecs_t* outAcquireTime, nsecs_t* outRefreshStartTime,
+ nsecs_t* outGlCompositionDoneTime, nsecs_t* outDisplayRetireTime,
+ nsecs_t* outReleaseTime) {
+ ATRACE_CALL();
+
+ FrameTimestamps timestamps;
+ bool found = mGraphicBufferProducer->getFrameTimestamps(frameNumber,
+ ×tamps);
+ if (found) {
+ if (outPostedTime) {
+ *outPostedTime = timestamps.postedTime;
+ }
+ if (outAcquireTime) {
+ *outAcquireTime = timestamps.acquireTime;
+ }
+ if (outRefreshStartTime) {
+ *outRefreshStartTime = timestamps.refreshStartTime;
+ }
+ if (outGlCompositionDoneTime) {
+ *outGlCompositionDoneTime = timestamps.glCompositionDoneTime;
+ }
+ if (outDisplayRetireTime) {
+ *outDisplayRetireTime = timestamps.displayRetireTime;
+ }
+ if (outReleaseTime) {
+ *outReleaseTime = timestamps.releaseTime;
+ }
+ return true;
+ }
+ return false;
+}
+
int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) {
Surface* c = getSelf(window);
return c->setSwapInterval(interval);
@@ -617,6 +650,9 @@
case NATIVE_WINDOW_SET_AUTO_REFRESH:
res = dispatchSetAutoRefresh(args);
break;
+ case NATIVE_WINDOW_GET_FRAME_TIMESTAMPS:
+ res = dispatchGetFrameTimestamps(args);
+ break;
default:
res = NAME_NOT_FOUND;
break;
@@ -737,6 +773,20 @@
return setAutoRefresh(autoRefresh);
}
+int Surface::dispatchGetFrameTimestamps(va_list args) {
+ uint32_t framesAgo = va_arg(args, uint32_t);
+ nsecs_t* outPostedTime = va_arg(args, int64_t*);
+ nsecs_t* outAcquireTime = va_arg(args, int64_t*);
+ nsecs_t* outRefreshStartTime = va_arg(args, int64_t*);
+ nsecs_t* outGlCompositionDoneTime = va_arg(args, int64_t*);
+ nsecs_t* outDisplayRetireTime = va_arg(args, int64_t*);
+ nsecs_t* outReleaseTime = va_arg(args, int64_t*);
+ bool ret = getFrameTimestamps(getNextFrameNumber() - 1 - framesAgo,
+ outPostedTime, outAcquireTime, outRefreshStartTime,
+ outGlCompositionDoneTime, outDisplayRetireTime, outReleaseTime);
+ return ret ? NO_ERROR : BAD_VALUE;
+}
+
int Surface::connect(int api) {
static sp<IProducerListener> listener = new DummyProducerListener();
return connect(api, listener);
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 24394a9..e793852 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -1847,7 +1847,7 @@
}
} else if (red_size == 5 && green_size == 6 && blue_size == 5 &&
alpha_size == 0) {
- format == HAL_PIXEL_FORMAT_RGB_565;
+ format = HAL_PIXEL_FORMAT_RGB_565;
} else {
ALOGE("Invalid native pixel format { r=%d, g=%d, b=%d, a=%d }",
red_size, green_size, blue_size, alpha_size);
diff --git a/services/surfaceflinger/FenceTracker.cpp b/services/surfaceflinger/FenceTracker.cpp
index d415bd5..0e18a93 100644
--- a/services/surfaceflinger/FenceTracker.cpp
+++ b/services/surfaceflinger/FenceTracker.cpp
@@ -26,7 +26,9 @@
FenceTracker::FenceTracker() :
mFrameCounter(0),
mOffset(0),
- mFrames() {}
+ mFrames(),
+ mMutex() {
+}
void FenceTracker::dump(String8* outString) {
Mutex::Autolock lock(mMutex);
@@ -135,31 +137,30 @@
nsecs_t postedTime;
sp<Fence> acquireFence;
sp<Fence> prevReleaseFence;
- int32_t key = layers[i]->getSequence();
+ int32_t layerId = layers[i]->getSequence();
layers[i]->getFenceData(&name, &frameNumber, &glesComposition,
&postedTime, &acquireFence, &prevReleaseFence);
#ifdef USE_HWC2
if (glesComposition) {
frame.layers.emplace(std::piecewise_construct,
- std::forward_as_tuple(key),
+ std::forward_as_tuple(layerId),
std::forward_as_tuple(name, frameNumber, glesComposition,
postedTime, 0, 0, acquireFence, prevReleaseFence));
wasGlesCompositionDone = true;
} else {
frame.layers.emplace(std::piecewise_construct,
- std::forward_as_tuple(key),
+ std::forward_as_tuple(layerId),
std::forward_as_tuple(name, frameNumber, glesComposition,
postedTime, 0, 0, acquireFence, Fence::NO_FENCE));
-
- auto prevLayer = prevFrame.layers.find(key);
+ auto prevLayer = prevFrame.layers.find(layerId);
if (prevLayer != prevFrame.layers.end()) {
prevLayer->second.releaseFence = prevReleaseFence;
}
}
#else
frame.layers.emplace(std::piecewise_construct,
- std::forward_as_tuple(key),
+ std::forward_as_tuple(layerId),
std::forward_as_tuple(name, frameNumber, glesComposition,
postedTime, 0, 0, acquireFence,
glesComposition ? Fence::NO_FENCE : prevReleaseFence));
@@ -168,7 +169,7 @@
}
#endif
frame.layers.emplace(std::piecewise_construct,
- std::forward_as_tuple(key),
+ std::forward_as_tuple(layerId),
std::forward_as_tuple(name, frameNumber, glesComposition,
postedTime, 0, 0, acquireFence, prevReleaseFence));
}
@@ -186,4 +187,33 @@
mFrameCounter++;
}
+bool FenceTracker::getFrameTimestamps(const Layer& layer,
+ uint64_t frameNumber, FrameTimestamps* outTimestamps) {
+ Mutex::Autolock lock(mMutex);
+ checkFencesForCompletion();
+ int32_t layerId = layer.getSequence();
+
+ size_t i = 0;
+ for (; i < MAX_FRAME_HISTORY; i++) {
+ if (mFrames[i].layers.count(layerId) &&
+ mFrames[i].layers[layerId].frameNumber == frameNumber) {
+ break;
+ }
+ }
+ if (i == MAX_FRAME_HISTORY) {
+ return false;
+ }
+
+ const FrameRecord& frameRecord = mFrames[i];
+ const LayerRecord& layerRecord = mFrames[i].layers[layerId];
+ outTimestamps->frameNumber = frameNumber;
+ outTimestamps->postedTime = layerRecord.postedTime;
+ outTimestamps->acquireTime = layerRecord.acquireTime;
+ outTimestamps->refreshStartTime = frameRecord.refreshStartTime;
+ outTimestamps->glCompositionDoneTime = frameRecord.glesCompositionDoneTime;
+ outTimestamps->displayRetireTime = frameRecord.retireTime;
+ outTimestamps->releaseTime = layerRecord.releaseTime;
+ return true;
+}
+
} // namespace android
diff --git a/services/surfaceflinger/FenceTracker.h b/services/surfaceflinger/FenceTracker.h
index 2fcc314..4cb14a5 100644
--- a/services/surfaceflinger/FenceTracker.h
+++ b/services/surfaceflinger/FenceTracker.h
@@ -29,7 +29,7 @@
namespace android {
class Layer;
-
+struct FrameTimestamps;
/*
* Keeps a circular buffer of fence/timestamp data for the last N frames in
* SurfaceFlinger. Gets timestamps for fences after they have signaled.
@@ -40,6 +40,8 @@
void dump(String8* outString);
void addFrame(nsecs_t refreshStartTime, sp<Fence> retireFence,
const Vector<sp<Layer>>& layers, sp<Fence> glDoneFence);
+ bool getFrameTimestamps(const Layer& layer, uint64_t frameNumber,
+ FrameTimestamps* outTimestamps);
protected:
static constexpr size_t MAX_FRAME_HISTORY = 8;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 714edbb..d732c07 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -155,7 +155,8 @@
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
mProducer = new MonitoredProducer(producer, mFlinger);
- mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName);
+ mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName,
+ this);
mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
mSurfaceFlingerConsumer->setContentsChangedListener(this);
mSurfaceFlingerConsumer->setName(mName);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index dbff834..4257c37 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -409,6 +409,11 @@
std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool forceFlush);
+ bool getFrameTimestamps(uint64_t frameNumber,
+ FrameTimestamps* outTimestamps) const {
+ return mFlinger->getFrameTimestamps(*this, frameNumber, outTimestamps);
+ }
+
protected:
// constant
sp<SurfaceFlinger> mFlinger;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 6e62b3c..9f357df 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3609,6 +3609,11 @@
}
}
+bool SurfaceFlinger::getFrameTimestamps(const Layer& layer,
+ uint64_t frameNumber, FrameTimestamps* outTimestamps) {
+ return mFenceTracker.getFrameTimestamps(layer, frameNumber, outTimestamps);
+}
+
// ---------------------------------------------------------------------------
SurfaceFlinger::LayerVector::LayerVector() {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 8263994..28666e2 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -440,6 +440,9 @@
std::vector<OccupancyTracker::Segment>&& history);
void dumpBufferingStats(String8& result) const;
+ bool getFrameTimestamps(const Layer& layer, uint64_t frameNumber,
+ FrameTimestamps* outTimestamps);
+
/* ------------------------------------------------------------------------
* Attributes
*/
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index c71b3bc..ba0a527 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -18,6 +18,7 @@
//#define LOG_NDEBUG 0
#include "SurfaceFlingerConsumer.h"
+#include "Layer.h"
#include <private/gui/SyncFeatures.h>
@@ -251,6 +252,12 @@
}
}
+bool SurfaceFlingerConsumer::getFrameTimestamps(uint64_t frameNumber,
+ FrameTimestamps* outTimestamps) const {
+ sp<const Layer> l = mLayer.promote();
+ return l.get() ? l->getFrameTimestamps(frameNumber, outTimestamps) : false;
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h
index 51b002f..3762659 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.h
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.h
@@ -23,6 +23,8 @@
namespace android {
// ----------------------------------------------------------------------------
+class Layer;
+
/*
* This is a thin wrapper around GLConsumer.
*/
@@ -35,10 +37,10 @@
};
SurfaceFlingerConsumer(const sp<IGraphicBufferConsumer>& consumer,
- uint32_t tex)
+ uint32_t tex, const Layer* layer)
: GLConsumer(consumer, tex, GLConsumer::TEXTURE_EXTERNAL, false, false),
mTransformToDisplayInverse(false), mSurfaceDamage(),
- mPrevReleaseFence(Fence::NO_FENCE)
+ mPrevReleaseFence(Fence::NO_FENCE), mLayer(layer)
{}
class BufferRejecter {
@@ -82,6 +84,9 @@
void releasePendingBuffer();
#endif
+ virtual bool getFrameTimestamps(uint64_t frameNumber,
+ FrameTimestamps* outTimestamps) const override;
+
private:
virtual void onSidebandStreamChanged();
@@ -103,6 +108,9 @@
// The release fence of the already displayed buffer (previous frame).
sp<Fence> mPrevReleaseFence;
+
+ // The layer for this SurfaceFlingerConsumer
+ wp<const Layer> mLayer;
};
// ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 75a45d6..a86c692 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -3596,6 +3596,11 @@
return result;
}
+bool SurfaceFlinger::getFrameTimestamps(const Layer& layer,
+ uint64_t frameNumber, FrameTimestamps* outTimestamps) {
+ return mFenceTracker.getFrameTimestamps(layer, frameNumber, outTimestamps);
+}
+
void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* vaddr,
const sp<const DisplayDevice>& hw, uint32_t minLayerZ, uint32_t maxLayerZ) {
if (DEBUG_SCREENSHOTS) {