Merge "Atrace: store app list in multiple sysprops" into nyc-dev
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index ea14c66..b731c53 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -95,6 +95,10 @@
// TODO: change to "v1" before final N build
static std::string VERSION_DEFAULT = "v1-dev4";
+static bool is_user_build() {
+ return 0 == strncmp(build_type, "user", PROPERTY_VALUE_MAX - 1);
+}
+
/* gets the tombstone data, according to the bugreport type: if zipped gets all tombstones,
* otherwise gets just those modified in the last half an hour. */
static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
@@ -872,7 +876,7 @@
char ril_dumpstate_timeout[PROPERTY_VALUE_MAX] = {0};
property_get("ril.dumpstate.timeout", ril_dumpstate_timeout, "30");
if (strnlen(ril_dumpstate_timeout, PROPERTY_VALUE_MAX - 1) > 0) {
- if (0 == strncmp(build_type, "user", PROPERTY_VALUE_MAX - 1)) {
+ if (is_user_build()) {
// su does not exist on user builds, so try running without it.
// This way any implementations of vril-dump that do not require
// root can run on user builds.
@@ -976,6 +980,15 @@
return false;
}
+ if (is_user_build()) {
+ MYLOGD("Removing temporary file %s\n", bugreport_path.c_str())
+ if (remove(bugreport_path.c_str())) {
+ ALOGW("remove(%s): %s\n", bugreport_path.c_str(), strerror(errno));
+ }
+ } else {
+ MYLOGD("Keeping temporary file %s on non-user build\n", bugreport_path.c_str())
+ }
+
return true;
}
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index f4d894b..60118a8 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -725,7 +725,7 @@
static void run_dex2oat(int zip_fd, int oat_fd, int image_fd, const char* input_file_name,
const char* output_file_name, int swap_fd, const char *instruction_set,
const char* compiler_filter, bool vm_safe_mode, bool debuggable, bool post_bootcomplete,
- int profile_fd) {
+ int profile_fd, const char* shared_libraries) {
static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
@@ -887,7 +887,8 @@
+ (debuggable ? 1 : 0)
+ (have_app_image_format ? 1 : 0)
+ dex2oat_flags_count
- + (profile_fd == -1 ? 0 : 1)];
+ + (profile_fd == -1 ? 0 : 1)
+ + (shared_libraries != nullptr ? 4 : 0)];
int i = 0;
argv[i++] = DEX2OAT_BIN;
argv[i++] = zip_fd_arg;
@@ -940,6 +941,12 @@
if (profile_fd != -1) {
argv[i++] = profile_arg;
}
+ if (shared_libraries != nullptr) {
+ argv[i++] = RUNTIME_ARG;
+ argv[i++] = "-classpath";
+ argv[i++] = RUNTIME_ARG;
+ argv[i++] = shared_libraries;
+ }
// Do not add after dex2oat_flags, they should override others for debugging.
argv[i] = NULL;
@@ -1311,7 +1318,7 @@
int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* instruction_set,
int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
- const char* volume_uuid ATTRIBUTE_UNUSED)
+ const char* volume_uuid ATTRIBUTE_UNUSED, const char* shared_libraries)
{
struct utimbuf ut;
struct stat input_stat;
@@ -1463,7 +1470,7 @@
}
run_dex2oat(input_fd, out_fd, image_fd, input_file_name, out_path, swap_fd,
instruction_set, compiler_filter, vm_safe_mode, debuggable, boot_complete,
- reference_profile_fd);
+ reference_profile_fd, shared_libraries);
} else {
ALOGE("Invalid dexopt needed: %d\n", dexopt_needed);
exit(73);
diff --git a/cmds/installd/commands.h b/cmds/installd/commands.h
index 81c13b4..41cc209 100644
--- a/cmds/installd/commands.h
+++ b/cmds/installd/commands.h
@@ -56,7 +56,7 @@
int dexopt(const char *apk_path, uid_t uid, const char *pkgName, const char *instruction_set,
int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
- const char* volume_uuid);
+ const char* volume_uuid, const char* shared_libraries);
int mark_boot_complete(const char *instruction_set);
int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId);
int idmap(const char *target_path, const char *overlay_path, uid_t uid);
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index eb51e70..e8fce91 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -266,7 +266,8 @@
arg[5], // oat_dir
dexopt_flags,
arg[7], // compiler_filter
- parse_null(arg[8])); // volume_uuid
+ parse_null(arg[8]), // volume_uuid
+ parse_null(arg[9])); // shared_libraries
}
static int do_merge_profiles(char **arg, char reply[REPLY_MAX])
@@ -414,7 +415,7 @@
{ "create_user_data", 4, do_create_user_data },
{ "destroy_user_data", 3, do_destroy_user_data },
- { "dexopt", 9, do_dexopt },
+ { "dexopt", 10, do_dexopt },
{ "markbootcomplete", 1, do_mark_boot_complete },
{ "rmdex", 2, do_rm_dex },
{ "freecache", 2, do_free_cache },
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 245694a..ac511ec 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -365,7 +365,8 @@
package_parameters_[5], // oat_dir
atoi(package_parameters_[6]), // dexopt_flags
package_parameters_[7], // compiler_filter
- ParseNull(package_parameters_[8])); // volume_uuid
+ ParseNull(package_parameters_[8]), // volume_uuid
+ ParseNull(package_parameters_[9])); // shared_libraries
return ret;
}
@@ -483,7 +484,7 @@
// to compile, instead of the A properties we could get from init/get_property.
SystemProperties system_properties_;
- const char* package_parameters_[9];
+ const char* package_parameters_[10];
// Store environment values we need to set.
std::vector<std::string> environ_;
diff --git a/cmds/servicemanager/servicemanager.rc b/cmds/servicemanager/servicemanager.rc
index 1ba339d..aee7bd8 100644
--- a/cmds/servicemanager/servicemanager.rc
+++ b/cmds/servicemanager/servicemanager.rc
@@ -11,4 +11,5 @@
onrestart restart inputflinger
onrestart restart drm
onrestart restart cameraserver
+ writepid /dev/cpuset/system-background/tasks
diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h
index 7256f73..a75ed98 100644
--- a/include/gui/BufferQueueProducer.h
+++ b/include/gui/BufferQueueProducer.h
@@ -184,7 +184,7 @@
// See IGraphicBufferProducer::getLastQueuedBuffer
virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
- sp<Fence>* outFence) override;
+ sp<Fence>* outFence, float outTransformMatrix[16]) override;
private:
// This is required by the IBinder::DeathRecipient interface
@@ -227,6 +227,9 @@
// since the previous buffer might have already been acquired.
sp<Fence> mLastQueueBufferFence;
+ Rect mLastQueuedCrop;
+ uint32_t mLastQueuedTransform;
+
// 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
diff --git a/include/gui/GLConsumer.h b/include/gui/GLConsumer.h
index 8de3302..6267625 100644
--- a/include/gui/GLConsumer.h
+++ b/include/gui/GLConsumer.h
@@ -132,6 +132,12 @@
// functions.
void getTransformMatrix(float mtx[16]);
+ // Computes the transform matrix documented by getTransformMatrix
+ // from the BufferItem sub parts.
+ static void computeTransformMatrix(float outTransform[16],
+ const sp<GraphicBuffer>& buf, const Rect& cropRect,
+ uint32_t transform, bool filtering);
+
// getTimestamp retrieves the timestamp associated with the texture image
// set by the most recent call to updateTexImage.
//
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index 049406c..37ae6df 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -563,9 +563,11 @@
// the queue, outBuffer will be populated with nullptr and outFence will be
// populated with Fence::NO_FENCE
//
+ // outTransformMatrix is not modified if outBuffer is null.
+ //
// Returns NO_ERROR or the status of the Binder transaction
virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
- sp<Fence>* outFence) = 0;
+ sp<Fence>* outFence, float outTransformMatrix[16]) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/gui/Sensor.h b/include/gui/Sensor.h
index 353003c..3f60741 100644
--- a/include/gui/Sensor.h
+++ b/include/gui/Sensor.h
@@ -52,12 +52,18 @@
TYPE_PROXIMITY = ASENSOR_TYPE_PROXIMITY
};
- typedef struct {
- uint8_t b[16];
- } uuid_t;
+ struct uuid_t{
+ union {
+ uint8_t b[16];
+ int64_t i64[2];
+ };
+ uuid_t(const uint8_t (&uuid)[16]) { memcpy(b, uuid, sizeof(b));}
+ uuid_t() : b{0} {}
+ };
Sensor(const char * name = "");
Sensor(struct sensor_t const* hwSensor, int halVersion = 0);
+ Sensor(struct sensor_t const& hwSensor, const uuid_t& uuid, int halVersion = 0);
~Sensor();
const String8& getName() const;
@@ -81,6 +87,7 @@
uint32_t getFlags() const;
bool isWakeUpSensor() const;
bool isDynamicSensor() const;
+ bool hasAdditionalInfo() const;
int32_t getReportingMode() const;
const uuid_t& getUuid() const;
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index bbf427d..646203b 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -130,8 +130,9 @@
bool waitForNextFrame(uint64_t lastFrame, nsecs_t timeout);
// See IGraphicBufferProducer::getLastQueuedBuffer
+ // See GLConsumer::getTransformMatrix for outTransformMatrix format
status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
- sp<Fence>* outFence);
+ sp<Fence>* outFence, float outTransformMatrix[16]);
protected:
virtual ~Surface();
diff --git a/include/media/openmax/OMX_VideoExt.h b/include/media/openmax/OMX_VideoExt.h
index 4bb5f9a..bf15ee4 100644
--- a/include/media/openmax/OMX_VideoExt.h
+++ b/include/media/openmax/OMX_VideoExt.h
@@ -77,35 +77,35 @@
/** VP9 profiles */
typedef enum OMX_VIDEO_VP9PROFILETYPE {
- OMX_VIDEO_VP9Profile0 = 0x1,
- OMX_VIDEO_VP9Profile1 = 0x2,
- OMX_VIDEO_VP9Profile2 = 0x4,
- OMX_VIDEO_VP9Profile3 = 0x8,
+ OMX_VIDEO_VP9Profile0 = 0x1,
+ OMX_VIDEO_VP9Profile1 = 0x2,
+ OMX_VIDEO_VP9Profile2 = 0x4,
+ OMX_VIDEO_VP9Profile3 = 0x8,
// HDR profiles also support passing HDR metadata
- OMX_VIDEO_VP9Profile2HDR = 0x1000,
- OMX_VIDEO_VP9Profile3HDR = 0x2000,
+ OMX_VIDEO_VP9Profile2HDR = 0x1000,
+ OMX_VIDEO_VP9Profile3HDR = 0x2000,
OMX_VIDEO_VP9ProfileUnknown = 0x6EFFFFFF,
- OMX_VIDEO_VP9ProfileMax = 0x7FFFFFFF
+ OMX_VIDEO_VP9ProfileMax = 0x7FFFFFFF
} OMX_VIDEO_VP9PROFILETYPE;
/** VP9 levels */
typedef enum OMX_VIDEO_VP9LEVELTYPE {
- OMX_VIDEO_VP9Level1 = 0x0,
- OMX_VIDEO_VP9Level11 = 0x1,
- OMX_VIDEO_VP9Level2 = 0x2,
- OMX_VIDEO_VP9Level21 = 0x4,
- OMX_VIDEO_VP9Level3 = 0x8,
- OMX_VIDEO_VP9Level31 = 0x10,
- OMX_VIDEO_VP9Level4 = 0x20,
- OMX_VIDEO_VP9Level41 = 0x40,
- OMX_VIDEO_VP9Level5 = 0x80,
- OMX_VIDEO_VP9Level51 = 0x100,
- OMX_VIDEO_VP9Level52 = 0x200,
- OMX_VIDEO_VP9Level6 = 0x400,
- OMX_VIDEO_VP9Level61 = 0x800,
- OMX_VIDEO_VP9Level62 = 0x1000,
+ OMX_VIDEO_VP9Level1 = 0x1,
+ OMX_VIDEO_VP9Level11 = 0x2,
+ OMX_VIDEO_VP9Level2 = 0x4,
+ OMX_VIDEO_VP9Level21 = 0x8,
+ OMX_VIDEO_VP9Level3 = 0x10,
+ OMX_VIDEO_VP9Level31 = 0x20,
+ OMX_VIDEO_VP9Level4 = 0x40,
+ OMX_VIDEO_VP9Level41 = 0x80,
+ OMX_VIDEO_VP9Level5 = 0x100,
+ OMX_VIDEO_VP9Level51 = 0x200,
+ OMX_VIDEO_VP9Level52 = 0x400,
+ OMX_VIDEO_VP9Level6 = 0x800,
+ OMX_VIDEO_VP9Level61 = 0x1000,
+ OMX_VIDEO_VP9Level62 = 0x2000,
OMX_VIDEO_VP9LevelUnknown = 0x6EFFFFFF,
- OMX_VIDEO_VP9LevelMax = 0x7FFFFFFF
+ OMX_VIDEO_VP9LevelMax = 0x7FFFFFFF
} OMX_VIDEO_VP9LEVELTYPE;
/** VP8 Param */
@@ -262,6 +262,7 @@
OMX_VIDEO_DolbyVisionProfileDvheDtr = 0x10,
OMX_VIDEO_DolbyVisionProfileDvheStn = 0x20,
OMX_VIDEO_DolbyVisionProfileDvheDth = 0x40,
+ OMX_VIDEO_DolbyVisionProfileDvheDtb = 0x80,
OMX_VIDEO_DolbyVisionProfileMax = 0x7FFFFFFF
} OMX_VIDEO_DOLBYVISIONPROFILETYPE;
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 620cf89..3e26e05 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -31,6 +31,7 @@
#include <gui/BufferItem.h>
#include <gui/BufferQueueCore.h>
#include <gui/BufferQueueProducer.h>
+#include <gui/GLConsumer.h>
#include <gui/IConsumerListener.h>
#include <gui/IGraphicBufferAlloc.h>
#include <gui/IProducerListener.h>
@@ -844,30 +845,31 @@
mCore->mQueue.push_back(item);
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
- BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
- if (front->mIsDroppable) {
+ // When the queue is not empty, we need to look at the last buffer
+ // in the queue to see if we need to replace it
+ const BufferItem& last = mCore->mQueue.itemAt(
+ mCore->mQueue.size() - 1);
+ if (last.mIsDroppable) {
- if (!front->mIsStale) {
- mSlots[front->mSlot].mBufferState.freeQueued();
+ if (!last.mIsStale) {
+ mSlots[last.mSlot].mBufferState.freeQueued();
// After leaving shared buffer mode, the shared buffer will
// still be around. Mark it as no longer shared if this
// operation causes it to be free.
if (!mCore->mSharedBufferMode &&
- mSlots[front->mSlot].mBufferState.isFree()) {
- mSlots[front->mSlot].mBufferState.mShared = false;
+ mSlots[last.mSlot].mBufferState.isFree()) {
+ mSlots[last.mSlot].mBufferState.mShared = false;
}
// Don't put the shared buffer on the free list.
- if (!mSlots[front->mSlot].mBufferState.isShared()) {
- mCore->mActiveBuffers.erase(front->mSlot);
- mCore->mFreeBuffers.push_back(front->mSlot);
+ if (!mSlots[last.mSlot].mBufferState.isShared()) {
+ mCore->mActiveBuffers.erase(last.mSlot);
+ mCore->mFreeBuffers.push_back(last.mSlot);
}
}
// Overwrite the droppable buffer with the incoming one
- *front = item;
+ mCore->mQueue.editItemAt(mCore->mQueue.size() - 1) = item;
frameReplacedListener = mCore->mConsumerListener;
} else {
mCore->mQueue.push_back(item);
@@ -922,6 +924,8 @@
mLastQueueBufferFence->waitForever("Throttling EGL Production");
}
mLastQueueBufferFence = fence;
+ mLastQueuedCrop = item.mCrop;
+ mLastQueuedTransform = item.mTransform;
return NO_ERROR;
}
@@ -1279,11 +1283,14 @@
// freeBufferLocked puts this slot on the free slots list. Since
// we then attached a buffer, move the slot to free buffer list.
- mCore->mFreeSlots.erase(slot);
mCore->mFreeBuffers.push_front(*slot);
BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d",
*slot);
+
+ // Make sure the erase is done after all uses of the slot
+ // iterator since it will be invalid after this point.
+ mCore->mFreeSlots.erase(slot);
}
mCore->mIsAllocating = false;
@@ -1368,7 +1375,7 @@
}
status_t BufferQueueProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
- sp<Fence>* outFence) {
+ sp<Fence>* outFence, float outTransformMatrix[16]) {
ATRACE_CALL();
BQ_LOGV("getLastQueuedBuffer");
@@ -1382,6 +1389,14 @@
*outBuffer = mSlots[mCore->mLastQueuedSlot].mGraphicBuffer;
*outFence = mLastQueueBufferFence;
+ // Currently only SurfaceFlinger internally ever changes
+ // GLConsumer's filtering mode, so we just use 'true' here as
+ // this is slightly specialized for the current client of this API,
+ // which does want filtering.
+ GLConsumer::computeTransformMatrix(outTransformMatrix,
+ mSlots[mCore->mLastQueuedSlot].mGraphicBuffer, mLastQueuedCrop,
+ mLastQueuedTransform, true /* filter */);
+
return NO_ERROR;
}
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 3acd3ab..ac8bc6e 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -44,6 +44,8 @@
EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
#define CROP_EXT_STR "EGL_ANDROID_image_crop"
+#define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
+#define EGL_PROTECTED_CONTENT_EXT 0x32C0
namespace android {
@@ -123,6 +125,26 @@
return hasIt;
}
+static bool hasEglProtectedContentImpl() {
+ EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
+ size_t cropExtLen = strlen(PROT_CONTENT_EXT_STR);
+ size_t extsLen = strlen(exts);
+ bool equal = !strcmp(PROT_CONTENT_EXT_STR, exts);
+ bool atStart = !strncmp(PROT_CONTENT_EXT_STR " ", exts, cropExtLen+1);
+ bool atEnd = (cropExtLen+1) < extsLen &&
+ !strcmp(" " PROT_CONTENT_EXT_STR, exts + extsLen - (cropExtLen+1));
+ bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " ");
+ return equal || atStart || atEnd || inMiddle;
+}
+
+static bool hasEglProtectedContent() {
+ // Only compute whether the extension is present once the first time this
+ // function is called.
+ static bool hasIt = hasEglProtectedContentImpl();
+ return hasIt;
+}
+
static bool isEglImageCroppable(const Rect& crop) {
return hasEglAndroidImageCrop() && (crop.left == 0 && crop.top == 0);
}
@@ -787,26 +809,40 @@
void GLConsumer::computeCurrentTransformMatrixLocked() {
GLC_LOGV("computeCurrentTransformMatrixLocked");
+ sp<GraphicBuffer> buf = (mCurrentTextureImage == nullptr) ?
+ nullptr : mCurrentTextureImage->graphicBuffer();
+ if (buf == nullptr) {
+ GLC_LOGD("computeCurrentTransformMatrixLocked: "
+ "mCurrentTextureImage is NULL");
+ }
+ computeTransformMatrix(mCurrentTransformMatrix, buf,
+ isEglImageCroppable(mCurrentCrop) ? Rect::EMPTY_RECT : mCurrentCrop,
+ mCurrentTransform, mFilteringEnabled);
+}
+
+void GLConsumer::computeTransformMatrix(float outTransform[16],
+ const sp<GraphicBuffer>& buf, const Rect& cropRect, uint32_t transform,
+ bool filtering) {
float xform[16];
for (int i = 0; i < 16; i++) {
xform[i] = mtxIdentity[i];
}
- if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
+ if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
float result[16];
mtxMul(result, xform, mtxFlipH);
for (int i = 0; i < 16; i++) {
xform[i] = result[i];
}
}
- if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
+ if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
float result[16];
mtxMul(result, xform, mtxFlipV);
for (int i = 0; i < 16; i++) {
xform[i] = result[i];
}
}
- if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+ if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
float result[16];
mtxMul(result, xform, mtxRot90);
for (int i = 0; i < 16; i++) {
@@ -814,59 +850,49 @@
}
}
- sp<GraphicBuffer> buf = (mCurrentTextureImage == NULL) ?
- NULL : mCurrentTextureImage->graphicBuffer();
-
- if (buf == NULL) {
- GLC_LOGD("computeCurrentTransformMatrixLocked: mCurrentTextureImage is NULL");
- }
-
float mtxBeforeFlipV[16];
- if (!isEglImageCroppable(mCurrentCrop)) {
- Rect cropRect = mCurrentCrop;
+ if (!cropRect.isEmpty()) {
float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
float bufferWidth = buf->getWidth();
float bufferHeight = buf->getHeight();
- if (!cropRect.isEmpty()) {
- float shrinkAmount = 0.0f;
- if (mFilteringEnabled) {
- // In order to prevent bilinear sampling beyond the edge of the
- // crop rectangle we may need to shrink it by 2 texels in each
- // dimension. Normally this would just need to take 1/2 a texel
- // off each end, but because the chroma channels of YUV420 images
- // are subsampled we may need to shrink the crop region by a whole
- // texel on each side.
- switch (buf->getPixelFormat()) {
- case PIXEL_FORMAT_RGBA_8888:
- case PIXEL_FORMAT_RGBX_8888:
- case PIXEL_FORMAT_RGB_888:
- case PIXEL_FORMAT_RGB_565:
- case PIXEL_FORMAT_BGRA_8888:
- // We know there's no subsampling of any channels, so we
- // only need to shrink by a half a pixel.
- shrinkAmount = 0.5;
- break;
+ float shrinkAmount = 0.0f;
+ if (filtering) {
+ // In order to prevent bilinear sampling beyond the edge of the
+ // crop rectangle we may need to shrink it by 2 texels in each
+ // dimension. Normally this would just need to take 1/2 a texel
+ // off each end, but because the chroma channels of YUV420 images
+ // are subsampled we may need to shrink the crop region by a whole
+ // texel on each side.
+ switch (buf->getPixelFormat()) {
+ case PIXEL_FORMAT_RGBA_8888:
+ case PIXEL_FORMAT_RGBX_8888:
+ case PIXEL_FORMAT_RGB_888:
+ case PIXEL_FORMAT_RGB_565:
+ case PIXEL_FORMAT_BGRA_8888:
+ // We know there's no subsampling of any channels, so we
+ // only need to shrink by a half a pixel.
+ shrinkAmount = 0.5;
+ break;
- default:
- // If we don't recognize the format, we must assume the
- // worst case (that we care about), which is YUV420.
- shrinkAmount = 1.0;
- break;
- }
+ default:
+ // If we don't recognize the format, we must assume the
+ // worst case (that we care about), which is YUV420.
+ shrinkAmount = 1.0;
+ break;
}
+ }
- // Only shrink the dimensions that are not the size of the buffer.
- if (cropRect.width() < bufferWidth) {
- tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
- sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
- bufferWidth;
- }
- if (cropRect.height() < bufferHeight) {
- ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
- bufferHeight;
- sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
- bufferHeight;
- }
+ // Only shrink the dimensions that are not the size of the buffer.
+ if (cropRect.width() < bufferWidth) {
+ tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
+ sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
+ bufferWidth;
+ }
+ if (cropRect.height() < bufferHeight) {
+ ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
+ bufferHeight;
+ sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
+ bufferHeight;
}
float crop[16] = {
sx, 0, 0, 0,
@@ -886,7 +912,7 @@
// coordinate of 0, so GLConsumer must behave the same way. We don't
// want to expose this to applications, however, so we must add an
// additional vertical flip to the transform after all the other transforms.
- mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV);
+ mtxMul(outTransform, mtxFlipV, mtxBeforeFlipV);
}
nsecs_t GLConsumer::getTimestamp() {
@@ -1174,12 +1200,17 @@
const sp<GraphicBuffer>& graphicBuffer, const Rect& crop) {
EGLClientBuffer cbuf =
static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer());
+ const bool createProtectedImage =
+ (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) &&
+ hasEglProtectedContent();
EGLint attrs[] = {
EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
EGL_IMAGE_CROP_LEFT_ANDROID, crop.left,
EGL_IMAGE_CROP_TOP_ANDROID, crop.top,
EGL_IMAGE_CROP_RIGHT_ANDROID, crop.right,
EGL_IMAGE_CROP_BOTTOM_ANDROID, crop.bottom,
+ createProtectedImage ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
+ createProtectedImage ? EGL_TRUE : EGL_NONE,
EGL_NONE,
};
if (!crop.isValid()) {
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index c36fcad..2c48d83 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -382,7 +382,7 @@
}
virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
- sp<Fence>* outFence) override {
+ sp<Fence>* outFence, float outTransformMatrix[16]) override {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
status_t result = remote()->transact(GET_LAST_QUEUED_BUFFER, data,
@@ -395,8 +395,15 @@
if (result != NO_ERROR) {
return result;
}
- sp<GraphicBuffer> buffer(new GraphicBuffer);
- result = reply.read(*buffer);
+ bool hasBuffer = reply.readBool();
+ sp<GraphicBuffer> buffer;
+ if (hasBuffer) {
+ buffer = new GraphicBuffer();
+ result = reply.read(*buffer);
+ if (result == NO_ERROR) {
+ result = reply.read(outTransformMatrix, sizeof(float) * 16);
+ }
+ }
if (result != NO_ERROR) {
ALOGE("getLastQueuedBuffer failed to read buffer: %d", result);
return result;
@@ -626,12 +633,21 @@
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
sp<GraphicBuffer> buffer(nullptr);
sp<Fence> fence(Fence::NO_FENCE);
- status_t result = getLastQueuedBuffer(&buffer, &fence);
+ float transform[16] = {};
+ status_t result = getLastQueuedBuffer(&buffer, &fence, transform);
reply->writeInt32(result);
if (result != NO_ERROR) {
return result;
}
- result = reply->write(*buffer);
+ if (!buffer.get()) {
+ reply->writeBool(false);
+ } else {
+ reply->writeBool(true);
+ result = reply->write(*buffer);
+ if (result == NO_ERROR) {
+ reply->write(transform, sizeof(float) * 16);
+ }
+ }
if (result != NO_ERROR) {
ALOGE("getLastQueuedBuffer failed to write buffer: %d", result);
return result;
diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp
index 0340d6b..cc865d1 100644
--- a/libs/gui/Sensor.cpp
+++ b/libs/gui/Sensor.cpp
@@ -14,69 +14,70 @@
* limitations under the License.
*/
+
+#include <binder/AppOpsManager.h>
+#include <binder/IServiceManager.h>
+#include <gui/Sensor.h>
+#include <hardware/sensors.h>
+#include <log/log.h>
+#include <utils/Errors.h>
+#include <utils/String8.h>
+#include <utils/Flattenable.h>
+
#include <inttypes.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/limits.h>
-#include <utils/Errors.h>
-#include <utils/String8.h>
-#include <utils/Flattenable.h>
-
-#include <hardware/sensors.h>
-
-#include <binder/AppOpsManager.h>
-#include <binder/IServiceManager.h>
-
-#include <gui/Sensor.h>
-#include <log/log.h>
-
// ----------------------------------------------------------------------------
namespace android {
// ----------------------------------------------------------------------------
-Sensor::Sensor(const char * name)
- : mName(name), mHandle(0), mType(0),
- mMinValue(0), mMaxValue(0), mResolution(0),
- mPower(0), mMinDelay(0), mVersion(0), mFifoReservedEventCount(0),
- mFifoMaxEventCount(0), mRequiredAppOp(0),
- mMaxDelay(0), mFlags(0)
-{
+Sensor::Sensor(const char * name) :
+ mName(name), mHandle(0), mType(0),
+ mMinValue(0), mMaxValue(0), mResolution(0),
+ mPower(0), mMinDelay(0), mVersion(0), mFifoReservedEventCount(0),
+ mFifoMaxEventCount(0), mRequiredAppOp(0),
+ mMaxDelay(0), mFlags(0) {
}
-Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion)
-{
- mName = hwSensor->name;
- mVendor = hwSensor->vendor;
- mVersion = hwSensor->version;
- mHandle = hwSensor->handle;
- mType = hwSensor->type;
+Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion) :
+ Sensor(*hwSensor, uuid_t(), halVersion) {
+}
+
+Sensor::Sensor(struct sensor_t const& hwSensor, const uuid_t& uuid, int halVersion) {
+ mName = hwSensor.name;
+ mVendor = hwSensor.vendor;
+ mVersion = hwSensor.version;
+ mHandle = hwSensor.handle;
+ mType = hwSensor.type;
mMinValue = 0; // FIXME: minValue
- mMaxValue = hwSensor->maxRange; // FIXME: maxValue
- mResolution = hwSensor->resolution;
- mPower = hwSensor->power;
- mMinDelay = hwSensor->minDelay;
+ mMaxValue = hwSensor.maxRange; // FIXME: maxValue
+ mResolution = hwSensor.resolution;
+ mPower = hwSensor.power;
+ mMinDelay = hwSensor.minDelay;
mFlags = 0;
+ mUuid = uuid;
// Set fifo event count zero for older devices which do not support batching. Fused
// sensors also have their fifo counts set to zero.
if (halVersion > SENSORS_DEVICE_API_VERSION_1_0) {
- mFifoReservedEventCount = hwSensor->fifoReservedEventCount;
- mFifoMaxEventCount = hwSensor->fifoMaxEventCount;
+ mFifoReservedEventCount = hwSensor.fifoReservedEventCount;
+ mFifoMaxEventCount = hwSensor.fifoMaxEventCount;
} else {
mFifoReservedEventCount = 0;
mFifoMaxEventCount = 0;
}
if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
- if (hwSensor->maxDelay > INT_MAX) {
+ if (hwSensor.maxDelay > INT_MAX) {
// Max delay is declared as a 64 bit integer for 64 bit architectures. But it should
// always fit in a 32 bit integer, log error and cap it to INT_MAX.
ALOGE("Sensor maxDelay overflow error %s %" PRId64, mName.string(),
- static_cast<int64_t>(hwSensor->maxDelay));
+ static_cast<int64_t>(hwSensor.maxDelay));
mMaxDelay = INT_MAX;
} else {
- mMaxDelay = static_cast<int32_t>(hwSensor->maxDelay);
+ mMaxDelay = static_cast<int32_t>(hwSensor.maxDelay);
}
} else {
// For older hals set maxDelay to 0.
@@ -245,11 +246,11 @@
break;
default:
// Only pipe the stringType, requiredPermission and flags for custom sensors.
- if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor->stringType) {
- mStringType = hwSensor->stringType;
+ if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor.stringType) {
+ mStringType = hwSensor.stringType;
}
- if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor->requiredPermission) {
- mRequiredPermission = hwSensor->requiredPermission;
+ if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor.requiredPermission) {
+ mRequiredPermission = hwSensor.requiredPermission;
if (!strcmp(mRequiredPermission, SENSOR_PERMISSION_BODY_SENSORS)) {
AppOpsManager appOps;
mRequiredAppOp = appOps.permissionToOpCode(String16(SENSOR_PERMISSION_BODY_SENSORS));
@@ -257,7 +258,7 @@
}
if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
- mFlags = static_cast<uint32_t>(hwSensor->flags);
+ mFlags = static_cast<uint32_t>(hwSensor.flags);
} else {
// This is an OEM defined sensor on an older HAL. Use minDelay to determine the
// reporting mode of the sensor.
@@ -272,31 +273,28 @@
break;
}
+ if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
+ // Wake-up flag of HAL 1.3 and above is set here
+ mFlags |= (hwSensor.flags & SENSOR_FLAG_WAKE_UP);
+
+ // Log error if the reporting mode is not as expected, but respect HAL setting.
+ int actualReportingMode = (hwSensor.flags & REPORTING_MODE_MASK) >> REPORTING_MODE_SHIFT;
+ int expectedReportingMode = (mFlags & REPORTING_MODE_MASK) >> REPORTING_MODE_SHIFT;
+ if (actualReportingMode != expectedReportingMode) {
+ ALOGE("Reporting Mode incorrect: sensor %s handle=%#010" PRIx32 " type=%" PRId32 " "
+ "actual=%d expected=%d",
+ mName.string(), mHandle, mType, actualReportingMode, expectedReportingMode);
+ }
+ }
+
+ // Feature flags
// Set DYNAMIC_SENSOR_MASK and ADDITIONAL_INFO_MASK flag here. Compatible with HAL 1_3.
if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
- mFlags |= (hwSensor->flags & (DYNAMIC_SENSOR_MASK | ADDITIONAL_INFO_MASK));
+ mFlags |= (hwSensor.flags & (DYNAMIC_SENSOR_MASK | ADDITIONAL_INFO_MASK));
}
-
// Set DATA_INJECTION flag here. Defined in HAL 1_4.
if (halVersion >= SENSORS_DEVICE_API_VERSION_1_4) {
- mFlags |= (hwSensor->flags & DATA_INJECTION_MASK);
- }
-
- // For the newer HALs log errors if reporting mask flags are set incorrectly.
- if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
- // Wake-up flag is set here.
- mFlags |= (hwSensor->flags & SENSOR_FLAG_WAKE_UP);
- if (mFlags != hwSensor->flags) {
- int actualReportingMode =
- (hwSensor->flags & REPORTING_MODE_MASK) >> REPORTING_MODE_SHIFT;
- int expectedReportingMode = (mFlags & REPORTING_MODE_MASK) >> REPORTING_MODE_SHIFT;
- if (actualReportingMode != expectedReportingMode) {
- ALOGE("Reporting Mode incorrect: sensor %s handle=%d type=%d "
- "actual=%d expected=%d",
- mName.string(), mHandle, mType, actualReportingMode, expectedReportingMode);
- }
-
- }
+ mFlags |= (hwSensor.flags & DATA_INJECTION_MASK);
}
if (mRequiredPermission.length() > 0) {
@@ -311,8 +309,7 @@
}
}
-Sensor::~Sensor()
-{
+Sensor::~Sensor() {
}
const String8& Sensor::getName() const {
@@ -392,11 +389,15 @@
}
bool Sensor::isWakeUpSensor() const {
- return mFlags & SENSOR_FLAG_WAKE_UP;
+ return (mFlags & SENSOR_FLAG_WAKE_UP) != 0;
}
bool Sensor::isDynamicSensor() const {
- return mFlags & SENSOR_FLAG_DYNAMIC_SENSOR;
+ return (mFlags & SENSOR_FLAG_DYNAMIC_SENSOR) != 0;
+}
+
+bool Sensor::hasAdditionalInfo() const {
+ return (mFlags & SENSOR_FLAG_ADDITIONAL_INFO) != 0;
}
int32_t Sensor::getReportingMode() const {
@@ -407,8 +408,7 @@
return mUuid;
}
-size_t Sensor::getFlattenedSize() const
-{
+size_t Sensor::getFlattenedSize() const {
size_t fixedSize =
sizeof(mVersion) + sizeof(mHandle) + sizeof(mType) +
sizeof(mMinValue) + sizeof(mMaxValue) + sizeof(mResolution) +
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index b304633..6811269 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -128,8 +128,9 @@
}
status_t Surface::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
- sp<Fence>* outFence) {
- return mGraphicBufferProducer->getLastQueuedBuffer(outBuffer, outFence);
+ sp<Fence>* outFence, float outTransformMatrix[16]) {
+ return mGraphicBufferProducer->getLastQueuedBuffer(outBuffer, outFence,
+ outTransformMatrix);
}
int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) {
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 9876d94..85d63b4 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -842,8 +842,10 @@
// Make sure we got the second buffer back
sp<GraphicBuffer> returnedBuffer;
sp<Fence> returnedFence;
+ float transform[16];
ASSERT_EQ(OK,
- mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence));
+ mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence,
+ transform));
ASSERT_EQ(secondBuffer->getNativeBuffer()->handle,
returnedBuffer->getNativeBuffer()->handle);
}
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index df639cd..00bfc24 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -117,6 +117,7 @@
"EGL_KHR_create_context_no_error "
"EGL_KHR_mutable_render_buffer "
"EGL_EXT_yuv_surface "
+ "EGL_EXT_protected_content "
;
// extensions not exposed to applications but used by the ANDROID system
@@ -605,7 +606,6 @@
EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
if (result == EGL_TRUE) {
_s.terminate();
- dp->removeSurface(surface);
}
return result;
}
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index c368bad..e335a6c 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -90,31 +90,6 @@
return false;
}
-void egl_display_t::addContext(egl_context_t* context) {
- Mutex::Autolock _l(lock);
- contexts.add(context);
-}
-
-void egl_display_t::removeContext(egl_context_t* context) {
- Mutex::Autolock _l(lock);
- contexts.remove(context);
-}
-
-void egl_display_t::removeSurface(EGLSurface surface) const {
- Mutex::Autolock _l(lock);
- for (size_t i = 0; i < contexts.size(); i++) {
- egl_context_t* context = contexts[i];
- if (context->read == surface) {
- SurfaceRef _r(get_surface(context->read));
- _r.release();
- }
- if (context->draw == surface) {
- SurfaceRef _d(get_surface(context->draw));
- _d.release();
- }
- }
-}
-
EGLDisplay egl_display_t::getFromNativeDisplay(EGLNativeDisplayType disp) {
if (uintptr_t(disp) >= NUM_DISPLAYS)
return NULL;
diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h
index 0ede705..2d86295 100644
--- a/opengl/libs/EGL/egl_display.h
+++ b/opengl/libs/EGL/egl_display.h
@@ -68,13 +68,6 @@
// add reference to this object. returns true if this is a valid object.
bool getObject(egl_object_t* object) const;
- // add context to this display's list
- void addContext(egl_context_t* context);
- // remove context from this display's list
- void removeContext(egl_context_t* context);
- // search for surface on all contexts and remove the references
- void removeSurface(EGLSurface surface) const;
-
// These notifications allow the display to keep track of how many window
// surfaces exist, which it uses to decide whether to hibernate the
// underlying EGL implementation. They can be called by any thread without
@@ -142,7 +135,6 @@
mutable Mutex lock, refLock;
mutable Condition refCond;
SortedVector<egl_object_t*> objects;
- SortedVector<egl_context_t*> contexts;
String8 mVendorString;
String8 mVersionString;
String8 mClientApiString;
diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp
index 8859387..918faa8 100644
--- a/opengl/libs/EGL/egl_object.cpp
+++ b/opengl/libs/EGL/egl_object.cpp
@@ -91,12 +91,6 @@
egl_connection_t const* cnx, int version) :
egl_object_t(get_display_nowake(dpy)), dpy(dpy), context(context),
config(config), read(0), draw(0), cnx(cnx), version(version) {
- get_display_nowake(dpy)->addContext(this);
-}
-
-void egl_context_t::terminate() {
- display->removeContext(this);
- egl_object_t::terminate();
}
void egl_context_t::onLooseCurrent() {
diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h
index 8268900..17a8304 100644
--- a/opengl/libs/EGL/egl_object.h
+++ b/opengl/libs/EGL/egl_object.h
@@ -40,12 +40,11 @@
class egl_display_t;
class egl_object_t {
+ egl_display_t *display;
mutable volatile int32_t count;
protected:
virtual ~egl_object_t();
- virtual void terminate();
- egl_display_t *display;
public:
egl_object_t(egl_display_t* display);
@@ -56,6 +55,7 @@
inline egl_display_t* getDisplay() const { return display; }
private:
+ void terminate();
static bool get(egl_display_t const* display, egl_object_t* object);
public:
@@ -143,7 +143,6 @@
class egl_context_t: public egl_object_t {
protected:
~egl_context_t() {}
- void terminate() override;
public:
typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
index 85e96d6..5a36961 100644
--- a/services/sensorservice/Android.mk
+++ b/services/sensorservice/Android.mk
@@ -2,21 +2,22 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- BatteryService.cpp \
- CorrectedGyroSensor.cpp \
+ BatteryService.cpp \
+ CorrectedGyroSensor.cpp \
Fusion.cpp \
GravitySensor.cpp \
LinearAccelerationSensor.cpp \
OrientationSensor.cpp \
+ RecentEventLogger.cpp \
RotationVectorSensor.cpp \
SensorDevice.cpp \
+ SensorEventConnection.cpp \
SensorFusion.cpp \
SensorInterface.cpp \
- SensorService.cpp \
- SensorEventConnection.cpp \
- MostRecentEventLogger.cpp \
- SensorRecord.cpp \
SensorList.cpp \
+ SensorRecord.cpp \
+ SensorService.cpp \
+ SensorServiceUtils.cpp \
LOCAL_CFLAGS:= -DLOG_TAG=\"SensorService\"
@@ -26,14 +27,14 @@
LOCAL_CFLAGS += -fvisibility=hidden
LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libhardware \
- libhardware_legacy \
- libutils \
- liblog \
- libbinder \
- libui \
- libgui
+ libcutils \
+ libhardware \
+ libhardware_legacy \
+ libutils \
+ liblog \
+ libbinder \
+ libui \
+ libgui
LOCAL_MODULE:= libsensorservice
@@ -44,12 +45,12 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- main_sensorservice.cpp
+ main_sensorservice.cpp
LOCAL_SHARED_LIBRARIES := \
- libsensorservice \
- libbinder \
- libutils
+ libsensorservice \
+ libbinder \
+ libutils
LOCAL_CFLAGS := -Wall -Werror -Wextra
diff --git a/services/sensorservice/MostRecentEventLogger.cpp b/services/sensorservice/MostRecentEventLogger.cpp
deleted file mode 100644
index a5d8456..0000000
--- a/services/sensorservice/MostRecentEventLogger.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "MostRecentEventLogger.h"
-
-#include <inttypes.h>
-
-namespace android {
-
-SensorService::MostRecentEventLogger::MostRecentEventLogger(int sensorType) :
- mNextInd(0), mSensorType(sensorType) {
-
- mBufSize = (sensorType == SENSOR_TYPE_STEP_COUNTER ||
- sensorType == SENSOR_TYPE_SIGNIFICANT_MOTION ||
- sensorType == SENSOR_TYPE_ACCELEROMETER) ? LOG_SIZE : LOG_SIZE_LARGE;
-
- mTrimmedSensorEventArr = new TrimmedSensorEvent *[mBufSize];
- mSensorType = sensorType;
- for (int i = 0; i < mBufSize; ++i) {
- mTrimmedSensorEventArr[i] = new TrimmedSensorEvent(mSensorType);
- }
-}
-
-void SensorService::MostRecentEventLogger::addEvent(const sensors_event_t& event) {
- TrimmedSensorEvent *curr_event = mTrimmedSensorEventArr[mNextInd];
- curr_event->mTimestamp = event.timestamp;
- if (mSensorType == SENSOR_TYPE_STEP_COUNTER) {
- curr_event->mStepCounter = event.u64.step_counter;
- } else {
- memcpy(curr_event->mData, event.data,
- sizeof(float) * SensorService::getNumEventsForSensorType(mSensorType));
- }
- time_t rawtime = time(NULL);
- struct tm * timeinfo = localtime(&rawtime);
- curr_event->mHour = timeinfo->tm_hour;
- curr_event->mMin = timeinfo->tm_min;
- curr_event->mSec = timeinfo->tm_sec;
- mNextInd = (mNextInd + 1) % mBufSize;
-}
-
-void SensorService::MostRecentEventLogger::printBuffer(String8& result) const {
- const int numData = SensorService::getNumEventsForSensorType(mSensorType);
- int i = mNextInd, eventNum = 1;
- result.appendFormat("last %d events = < ", mBufSize);
- do {
- if (TrimmedSensorEvent::isSentinel(*mTrimmedSensorEventArr[i])) {
- // Sentinel, ignore.
- i = (i + 1) % mBufSize;
- continue;
- }
- result.appendFormat("%d) ", eventNum++);
- if (mSensorType == SENSOR_TYPE_STEP_COUNTER) {
- result.appendFormat("%" PRIu64 ",", mTrimmedSensorEventArr[i]->mStepCounter);
- } else {
- for (int j = 0; j < numData; ++j) {
- result.appendFormat("%5.1f,", mTrimmedSensorEventArr[i]->mData[j]);
- }
- }
- result.appendFormat("%" PRId64 " %02d:%02d:%02d ", mTrimmedSensorEventArr[i]->mTimestamp,
- mTrimmedSensorEventArr[i]->mHour, mTrimmedSensorEventArr[i]->mMin,
- mTrimmedSensorEventArr[i]->mSec);
- i = (i + 1) % mBufSize;
- } while (i != mNextInd);
- result.appendFormat(">\n");
-}
-
-bool SensorService::MostRecentEventLogger::populateLastEvent(sensors_event_t *event) {
- int lastEventInd = (mNextInd - 1 + mBufSize) % mBufSize;
- // Check if the buffer is empty.
- if (TrimmedSensorEvent::isSentinel(*mTrimmedSensorEventArr[lastEventInd])) {
- return false;
- }
- event->version = sizeof(sensors_event_t);
- event->type = mSensorType;
- event->timestamp = mTrimmedSensorEventArr[lastEventInd]->mTimestamp;
- if (mSensorType == SENSOR_TYPE_STEP_COUNTER) {
- event->u64.step_counter = mTrimmedSensorEventArr[lastEventInd]->mStepCounter;
- } else {
- memcpy(event->data, mTrimmedSensorEventArr[lastEventInd]->mData,
- sizeof(float) * SensorService::getNumEventsForSensorType(mSensorType));
- }
- return true;
-}
-
-SensorService::MostRecentEventLogger::~MostRecentEventLogger() {
- for (int i = 0; i < mBufSize; ++i) {
- delete mTrimmedSensorEventArr[i];
- }
- delete [] mTrimmedSensorEventArr;
-}
-
-// -----------------------------------------------------------------------------
-SensorService::MostRecentEventLogger::TrimmedSensorEvent::TrimmedSensorEvent(int sensorType) {
- mTimestamp = -1;
- const int numData = SensorService::getNumEventsForSensorType(sensorType);
- if (sensorType == SENSOR_TYPE_STEP_COUNTER) {
- mStepCounter = 0;
- } else {
- mData = new float[numData];
- for (int i = 0; i < numData; ++i) {
- mData[i] = -1.0;
- }
- }
- mHour = mMin = mSec = INT32_MIN;
-}
-
-bool SensorService::MostRecentEventLogger::TrimmedSensorEvent::
- isSentinel(const TrimmedSensorEvent& event) {
- return (event.mHour == INT32_MIN && event.mMin == INT32_MIN && event.mSec == INT32_MIN);
-}
-
-} // namespace android
diff --git a/services/sensorservice/MostRecentEventLogger.h b/services/sensorservice/MostRecentEventLogger.h
deleted file mode 100644
index 68c1661..0000000
--- a/services/sensorservice/MostRecentEventLogger.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2010 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_MOST_RECENT_EVENT_LOGGER_H
-#define ANDROID_MOST_RECENT_EVENT_LOGGER_H
-
-#include "SensorService.h"
-
-namespace android {
-
-class SensorService;
-
-// A circular buffer of TrimmedSensorEvents. The size of this buffer is typically 10. The last N
-// events generated from the sensor are stored in this buffer. The buffer is NOT cleared when the
-// sensor unregisters and as a result very old data in the dumpsys output can be seen, which is an
-// intended behavior.
-class SensorService::MostRecentEventLogger {
-public:
- MostRecentEventLogger(int sensorType);
- void addEvent(const sensors_event_t& event);
- void printBuffer(String8& buffer) const;
- bool populateLastEvent(sensors_event_t *event);
- ~MostRecentEventLogger();
-
-private:
- // sensor_event_t with only the data and the timestamp.
- static const size_t LOG_SIZE = 10;
- static const size_t LOG_SIZE_LARGE = 50;
-
- struct TrimmedSensorEvent {
- union {
- float *mData;
- uint64_t mStepCounter;
- };
- // Timestamp from the sensors_event_t.
- int64_t mTimestamp;
- // HH:MM:SS local time at which this sensor event is read at SensorService. Useful
- // for debugging.
- int32_t mHour, mMin, mSec;
-
- TrimmedSensorEvent(int sensorType);
- static bool isSentinel(const TrimmedSensorEvent& event);
-
- ~TrimmedSensorEvent() {
- delete [] mData;
- }
- };
-
- int mNextInd;
- int mSensorType;
- int mBufSize;
- TrimmedSensorEvent ** mTrimmedSensorEventArr;
-};
-
-} // namespace android;
-
-#endif // ANDROID_MOST_RECENT_EVENT_LOGGER_H
-
diff --git a/services/sensorservice/RecentEventLogger.cpp b/services/sensorservice/RecentEventLogger.cpp
new file mode 100644
index 0000000..dba7211
--- /dev/null
+++ b/services/sensorservice/RecentEventLogger.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "RecentEventLogger.h"
+#include "SensorServiceUtils.h"
+
+#include <utils/Timers.h>
+
+#include <inttypes.h>
+
+namespace android {
+namespace SensorServiceUtil {
+
+namespace {
+ constexpr size_t LOG_SIZE = 10;
+ constexpr size_t LOG_SIZE_LARGE = 50; // larger samples for debugging
+}// unnamed namespace
+
+RecentEventLogger::RecentEventLogger(int sensorType) :
+ mSensorType(sensorType), mEventSize(eventSizeBySensorType(mSensorType)),
+ mRecentEvents(logSizeBySensorType(sensorType)) {
+ // blank
+}
+
+void RecentEventLogger::addEvent(const sensors_event_t& event) {
+ std::lock_guard<std::mutex> lk(mLock);
+ mRecentEvents.emplace(event);
+}
+
+bool RecentEventLogger::isEmpty() const {
+ return mRecentEvents.size() == 0;
+}
+
+std::string RecentEventLogger::dump() const {
+ std::lock_guard<std::mutex> lk(mLock);
+
+ //TODO: replace String8 with std::string completely in this function
+ String8 buffer;
+
+ buffer.appendFormat("last %zu events\n", mRecentEvents.size());
+ int j = 0;
+ for (int i = mRecentEvents.size() - 1; i >= 0; --i) {
+ const auto& ev = mRecentEvents[i];
+ struct tm * timeinfo = localtime(&(ev.mWallTime.tv_sec));
+ buffer.appendFormat("\t%2d (ts=%.9f, wall=%02d:%02d:%02d.%03d) ",
+ ++j, ev.mEvent.timestamp/1e9, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec,
+ (int) ns2ms(ev.mWallTime.tv_nsec));
+
+ // data
+ if (mSensorType == SENSOR_TYPE_STEP_COUNTER) {
+ buffer.appendFormat("%" PRIu64 ", ", ev.mEvent.u64.step_counter);
+ } else {
+ for (size_t k = 0; k < mEventSize; ++k) {
+ buffer.appendFormat("%.2f, ", ev.mEvent.data[k]);
+ }
+ }
+ buffer.append("\n");
+ }
+ return std::string(buffer.string());
+}
+
+bool RecentEventLogger::populateLastEvent(sensors_event_t *event) const {
+ std::lock_guard<std::mutex> lk(mLock);
+
+ if (mRecentEvents.size()) {
+ *event = mRecentEvents[mRecentEvents.size()-1].mEvent;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+size_t RecentEventLogger::logSizeBySensorType(int sensorType) {
+ return (sensorType == SENSOR_TYPE_STEP_COUNTER ||
+ sensorType == SENSOR_TYPE_SIGNIFICANT_MOTION ||
+ sensorType == SENSOR_TYPE_ACCELEROMETER) ? LOG_SIZE_LARGE : LOG_SIZE;
+}
+
+RecentEventLogger::SensorEventLog::SensorEventLog(const sensors_event_t& e) : mEvent(e) {
+ clock_gettime(CLOCK_REALTIME, &mWallTime);
+}
+
+} // namespace SensorServiceUtil
+} // namespace android
diff --git a/services/sensorservice/RecentEventLogger.h b/services/sensorservice/RecentEventLogger.h
new file mode 100644
index 0000000..4f9bc4a
--- /dev/null
+++ b/services/sensorservice/RecentEventLogger.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 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_SENSOR_SERVICE_UTIL_RECENT_EVENT_LOGGER_H
+#define ANDROID_SENSOR_SERVICE_UTIL_RECENT_EVENT_LOGGER_H
+
+#include "RingBuffer.h"
+#include "SensorServiceUtils.h"
+
+#include <hardware/sensors.h>
+#include <utils/String8.h>
+
+#include <mutex>
+
+namespace android {
+namespace SensorServiceUtil {
+
+// A circular buffer that record the last N events of a sensor type for debugging. The size of this
+// buffer depends on sensor type and is controlled by logSizeBySensorType(). The last N events
+// generated from the sensor are stored in this buffer. The buffer is NOT cleared when the sensor
+// unregisters and as a result very old data in the dumpsys output can be seen, which is an intended
+// behavior.
+class RecentEventLogger : public Dumpable {
+public:
+ RecentEventLogger(int sensorType);
+ void addEvent(const sensors_event_t& event);
+ bool populateLastEvent(sensors_event_t *event) const;
+ bool isEmpty() const;
+ virtual ~RecentEventLogger() {}
+
+ // Dumpable interface
+ virtual std::string dump() const override;
+
+protected:
+ struct SensorEventLog {
+ SensorEventLog(const sensors_event_t& e);
+ timespec mWallTime;
+ sensors_event_t mEvent;
+ };
+
+ const int mSensorType;
+ const size_t mEventSize;
+
+ mutable std::mutex mLock;
+ RingBuffer<SensorEventLog> mRecentEvents;
+
+private:
+ static size_t logSizeBySensorType(int sensorType);
+};
+
+} // namespace SensorServiceUtil
+} // namespace android;
+
+#endif // ANDROID_SENSOR_SERVICE_UTIL_RECENT_EVENT_LOGGER_H
+
diff --git a/services/sensorservice/RingBuffer.h b/services/sensorservice/RingBuffer.h
new file mode 100644
index 0000000..ec98a01
--- /dev/null
+++ b/services/sensorservice/RingBuffer.h
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 2015 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_SENSOR_SERVICE_UTIL_RING_BUFFER_H
+#define ANDROID_SENSOR_SERVICE_UTIL_RING_BUFFER_H
+
+#include <utils/Log.h>
+#include <cutils/compiler.h>
+
+#include <iterator>
+#include <utility>
+#include <vector>
+
+namespace android {
+namespace SensorServiceUtil {
+
+/**
+ * A RingBuffer class that maintains an array of objects that can grow up to a certain size.
+ * Elements added to the RingBuffer are inserted in the logical front of the buffer, and
+ * invalidate all current iterators for that RingBuffer object.
+ */
+template <class T>
+class RingBuffer final {
+public:
+
+ /**
+ * Construct a RingBuffer that can grow up to the given length.
+ */
+ RingBuffer(size_t length);
+
+ /**
+ * Forward iterator to this class. Implements an std:forward_iterator.
+ */
+ class iterator : public std::iterator<std::forward_iterator_tag, T> {
+ public:
+ iterator(T* ptr, size_t size, size_t pos, size_t ctr);
+
+ iterator& operator++();
+
+ iterator operator++(int);
+
+ bool operator==(const iterator& rhs);
+
+ bool operator!=(const iterator& rhs);
+
+ T& operator*();
+
+ T* operator->();
+
+ private:
+ T* mPtr;
+ size_t mSize;
+ size_t mPos;
+ size_t mCtr;
+ };
+
+ /**
+ * Constant forward iterator to this class. Implements an std:forward_iterator.
+ */
+ class const_iterator : public std::iterator<std::forward_iterator_tag, T> {
+ public:
+ const_iterator(const T* ptr, size_t size, size_t pos, size_t ctr);
+
+ const_iterator& operator++();
+
+ const_iterator operator++(int);
+
+ bool operator==(const const_iterator& rhs);
+
+ bool operator!=(const const_iterator& rhs);
+
+ const T& operator*();
+
+ const T* operator->();
+
+ private:
+ const T* mPtr;
+ size_t mSize;
+ size_t mPos;
+ size_t mCtr;
+ };
+
+ /**
+ * Adds item to the front of this RingBuffer. If the RingBuffer is at its maximum length,
+ * this will result in the last element being replaced (this is done using the element's
+ * assignment operator).
+ *
+ * All current iterators are invalidated.
+ */
+ void add(const T& item);
+
+ /**
+ * Moves item to the front of this RingBuffer. Following a call to this, item should no
+ * longer be used. If the RingBuffer is at its maximum length, this will result in the
+ * last element being replaced (this is done using the element's assignment operator).
+ *
+ * All current iterators are invalidated.
+ */
+ void add(T&& item);
+
+ /**
+ * Construct item in-place in the front of this RingBuffer using the given arguments. If
+ * the RingBuffer is at its maximum length, this will result in the last element being
+ * replaced (this is done using the element's assignment operator).
+ *
+ * All current iterators are invalidated.
+ */
+ template <class... Args>
+ void emplace(Args&&... args);
+
+ /**
+ * Get an iterator to the front of this RingBuffer.
+ */
+ iterator begin();
+
+ /**
+ * Get an iterator to the end of this RingBuffer.
+ */
+ iterator end();
+
+ /**
+ * Get a const_iterator to the front of this RingBuffer.
+ */
+ const_iterator begin() const;
+
+ /**
+ * Get a const_iterator to the end of this RingBuffer.
+ */
+ const_iterator end() const;
+
+ /**
+ * Return a reference to the element at a given index. If the index is out of range for
+ * this ringbuffer, [0, size), the behavior for this is undefined.
+ */
+ T& operator[](size_t index);
+
+ /**
+ * Return a const reference to the element at a given index. If the index is out of range
+ * for this ringbuffer, [0, size), the behavior for this is undefined.
+ */
+ const T& operator[](size_t index) const;
+
+ /**
+ * Return the current size of this RingBuffer.
+ */
+ size_t size() const;
+
+ /**
+ * Remove all elements from this RingBuffer and set the size to 0.
+ */
+ void clear();
+
+private:
+ size_t mFrontIdx;
+ size_t mMaxBufferSize;
+ std::vector<T> mBuffer;
+}; // class RingBuffer
+
+
+template <class T>
+RingBuffer<T>::RingBuffer(size_t length) : mFrontIdx{0}, mMaxBufferSize{length} {}
+
+template <class T>
+RingBuffer<T>::iterator::iterator(T* ptr, size_t size, size_t pos, size_t ctr) :
+ mPtr{ptr}, mSize{size}, mPos{pos}, mCtr{ctr} {}
+
+template <class T>
+typename RingBuffer<T>::iterator& RingBuffer<T>::iterator::operator++() {
+ ++mCtr;
+
+ if (CC_UNLIKELY(mCtr == mSize)) {
+ mPos = mSize;
+ return *this;
+ }
+
+ mPos = ((CC_UNLIKELY(mPos == 0)) ? mSize - 1 : mPos - 1);
+ return *this;
+}
+
+template <class T>
+typename RingBuffer<T>::iterator RingBuffer<T>::iterator::operator++(int) {
+ iterator tmp{mPtr, mSize, mPos, mCtr};
+ ++(*this);
+ return tmp;
+}
+
+template <class T>
+bool RingBuffer<T>::iterator::operator==(const iterator& rhs) {
+ return (mPtr + mPos) == (rhs.mPtr + rhs.mPos);
+}
+
+template <class T>
+bool RingBuffer<T>::iterator::operator!=(const iterator& rhs) {
+ return (mPtr + mPos) != (rhs.mPtr + rhs.mPos);
+}
+
+template <class T>
+T& RingBuffer<T>::iterator::operator*() {
+ return *(mPtr + mPos);
+}
+
+template <class T>
+T* RingBuffer<T>::iterator::operator->() {
+ return mPtr + mPos;
+}
+
+template <class T>
+RingBuffer<T>::const_iterator::const_iterator(const T* ptr, size_t size, size_t pos, size_t ctr) :
+ mPtr{ptr}, mSize{size}, mPos{pos}, mCtr{ctr} {}
+
+template <class T>
+typename RingBuffer<T>::const_iterator& RingBuffer<T>::const_iterator::operator++() {
+ ++mCtr;
+
+ if (CC_UNLIKELY(mCtr == mSize)) {
+ mPos = mSize;
+ return *this;
+ }
+
+ mPos = ((CC_UNLIKELY(mPos == 0)) ? mSize - 1 : mPos - 1);
+ return *this;
+}
+
+template <class T>
+typename RingBuffer<T>::const_iterator RingBuffer<T>::const_iterator::operator++(int) {
+ const_iterator tmp{mPtr, mSize, mPos, mCtr};
+ ++(*this);
+ return tmp;
+}
+
+template <class T>
+bool RingBuffer<T>::const_iterator::operator==(const const_iterator& rhs) {
+ return (mPtr + mPos) == (rhs.mPtr + rhs.mPos);
+}
+
+template <class T>
+bool RingBuffer<T>::const_iterator::operator!=(const const_iterator& rhs) {
+ return (mPtr + mPos) != (rhs.mPtr + rhs.mPos);
+}
+
+template <class T>
+const T& RingBuffer<T>::const_iterator::operator*() {
+ return *(mPtr + mPos);
+}
+
+template <class T>
+const T* RingBuffer<T>::const_iterator::operator->() {
+ return mPtr + mPos;
+}
+
+template <class T>
+void RingBuffer<T>::add(const T& item) {
+ if (mBuffer.size() < mMaxBufferSize) {
+ mBuffer.push_back(item);
+ mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
+ return;
+ }
+
+ mBuffer[mFrontIdx] = item;
+ mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
+}
+
+template <class T>
+void RingBuffer<T>::add(T&& item) {
+ if (mBuffer.size() != mMaxBufferSize) {
+ mBuffer.push_back(std::forward<T>(item));
+ mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
+ return;
+ }
+
+ // Only works for types with move assignment operator
+ mBuffer[mFrontIdx] = std::forward<T>(item);
+ mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
+}
+
+template <class T>
+template <class... Args>
+void RingBuffer<T>::emplace(Args&&... args) {
+ if (mBuffer.size() != mMaxBufferSize) {
+ mBuffer.emplace_back(std::forward<Args>(args)...);
+ mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
+ return;
+ }
+
+ // Only works for types with move assignment operator
+ mBuffer[mFrontIdx] = T(std::forward<Args>(args)...);
+ mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
+}
+
+template <class T>
+typename RingBuffer<T>::iterator RingBuffer<T>::begin() {
+ size_t tmp = (mBuffer.size() == 0) ? 0 : mBuffer.size() - 1;
+ return iterator(mBuffer.data(), mBuffer.size(), (mFrontIdx == 0) ? tmp : mFrontIdx - 1, 0);
+}
+
+template <class T>
+typename RingBuffer<T>::iterator RingBuffer<T>::end() {
+ size_t s = mBuffer.size();
+ return iterator(mBuffer.data(), s, s, s);
+}
+
+template <class T>
+typename RingBuffer<T>::const_iterator RingBuffer<T>::begin() const {
+ size_t tmp = (mBuffer.size() == 0) ? 0 : mBuffer.size() - 1;
+ return const_iterator(mBuffer.data(), mBuffer.size(),
+ (mFrontIdx == 0) ? tmp : mFrontIdx - 1, 0);
+}
+
+template <class T>
+typename RingBuffer<T>::const_iterator RingBuffer<T>::end() const {
+ size_t s = mBuffer.size();
+ return const_iterator(mBuffer.data(), s, s, s);
+}
+
+template <class T>
+T& RingBuffer<T>::operator[](size_t index) {
+ LOG_ALWAYS_FATAL_IF(index >= mBuffer.size(), "Index %zu out of bounds, size is %zu.",
+ index, mBuffer.size());
+ size_t pos = (index >= mFrontIdx) ?
+ mBuffer.size() - 1 - (index - mFrontIdx) : mFrontIdx - 1 - index;
+ return mBuffer[pos];
+}
+
+template <class T>
+const T& RingBuffer<T>::operator[](size_t index) const {
+ LOG_ALWAYS_FATAL_IF(index >= mBuffer.size(), "Index %zu out of bounds, size is %zu.",
+ index, mBuffer.size());
+ size_t pos = (index >= mFrontIdx) ?
+ mBuffer.size() - 1 - (index - mFrontIdx) : mFrontIdx - 1 - index;
+ return mBuffer[pos];
+}
+
+template <class T>
+size_t RingBuffer<T>::size() const {
+ return mBuffer.size();
+}
+
+template <class T>
+void RingBuffer<T>::clear() {
+ mBuffer.clear();
+ mFrontIdx = 0;
+}
+
+} // namespace SensorServiceUtil
+}; // namespace android
+
+#endif // ANDROID_SENSOR_SERVICE_UTIL_RING_BUFFER_H
+
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 179b1c5..4fbaa50 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -39,8 +39,7 @@
SensorDevice::SensorDevice()
: mSensorDevice(0),
- mSensorModule(0)
-{
+ mSensorModule(0) {
status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
(hw_module_t const**)&mSensorModule);
@@ -84,37 +83,43 @@
}
}
-void SensorDevice::dump(String8& result)
-{
- if (!mSensorModule) return;
- sensor_t const* list;
- ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
+std::string SensorDevice::dump() const {
+ if (!mSensorModule) return "HAL not initialized\n";
- result.appendFormat("halVersion 0x%08x\n", getHalDeviceVersion());
- result.appendFormat("%d h/w sensors:\n", int(count));
+ String8 result;
+ sensor_t const* list;
+ int count = mSensorModule->get_sensors_list(mSensorModule, &list);
+
+ result.appendFormat("HAL: %s (%s), version %#010x\n",
+ mSensorModule->common.name,
+ mSensorModule->common.author,
+ getHalDeviceVersion());
+ result.appendFormat("Total %d h/w sensors, %zu running:\n", count, mActivationCount.size());
Mutex::Autolock _l(mLock);
- for (size_t i=0 ; i<size_t(count) ; i++) {
+ for (int i = 0 ; i < count ; i++) {
const Info& info = mActivationCount.valueFor(list[i].handle);
if (info.batchParams.isEmpty()) continue;
- result.appendFormat("handle=0x%08x, active-count=%zu, batch_period(ms)={ ", list[i].handle,
+ result.appendFormat("0x%08x) active-count = %zu; ", list[i].handle,
info.batchParams.size());
+
+ result.append("sampling_period(ms) = {");
for (size_t j = 0; j < info.batchParams.size(); j++) {
const BatchParams& params = info.batchParams.valueAt(j);
- result.appendFormat("%4.1f%s", params.batchDelay / 1e6f,
+ result.appendFormat("%.1f%s", params.batchDelay / 1e6f,
j < info.batchParams.size() - 1 ? ", " : "");
}
- result.appendFormat(" }, selected=%4.1f ms\n", info.bestBatchParams.batchDelay / 1e6f);
+ result.appendFormat("}, selected = %.1f ms; ", info.bestBatchParams.batchDelay / 1e6f);
- result.appendFormat("handle=0x%08x, active-count=%zu, batch_timeout(ms)={ ", list[i].handle,
- info.batchParams.size());
+ result.append("batching_period(ms) = {");
for (size_t j = 0; j < info.batchParams.size(); j++) {
BatchParams params = info.batchParams.valueAt(j);
- result.appendFormat("%4.1f%s", params.batchTimeout / 1e6f,
+ result.appendFormat("%.1f%s", params.batchTimeout / 1e6f,
j < info.batchParams.size() - 1 ? ", " : "");
}
- result.appendFormat(" }, selected=%4.1f ms\n", info.bestBatchParams.batchTimeout / 1e6f);
+ result.appendFormat("}, selected = %.1f ms\n", info.bestBatchParams.batchTimeout / 1e6f);
}
+ return result.string();
}
ssize_t SensorDevice::getSensorList(sensor_t const** list) {
@@ -143,8 +148,7 @@
info.removeBatchParamsForIdent(ident);
}
-status_t SensorDevice::activate(void* ident, int handle, int enabled)
-{
+status_t SensorDevice::activate(void* ident, int handle, int enabled) {
if (!mSensorDevice) return NO_INIT;
status_t err(NO_ERROR);
bool actuateHardware = false;
@@ -293,8 +297,7 @@
return err;
}
-status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodNs)
-{
+status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodNs) {
if (!mSensorDevice) return NO_INIT;
if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index c12630a..68bb853 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -17,21 +17,44 @@
#ifndef ANDROID_SENSOR_DEVICE_H
#define ANDROID_SENSOR_DEVICE_H
-#include <stdint.h>
-#include <sys/types.h>
+#include "SensorServiceUtils.h"
+#include <gui/Sensor.h>
#include <utils/KeyedVector.h>
#include <utils/Singleton.h>
#include <utils/String8.h>
-#include <gui/Sensor.h>
+#include <stdint.h>
+#include <sys/types.h>
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
+using SensorServiceUtil::Dumpable;
-class SensorDevice : public Singleton<SensorDevice> {
+class SensorDevice : public Singleton<SensorDevice>, public Dumpable {
+public:
+ ssize_t getSensorList(sensor_t const** list);
+ void handleDynamicSensorConnection(int handle, bool connected);
+ status_t initCheck() const;
+ int getHalDeviceVersion() const;
+ ssize_t poll(sensors_event_t* buffer, size_t count);
+ status_t activate(void* ident, int handle, int enabled);
+ status_t batch(void* ident, int handle, int flags, int64_t samplingPeriodNs,
+ int64_t maxBatchReportLatencyNs);
+ // Call batch with timeout zero instead of calling setDelay() for newer devices.
+ status_t setDelay(void* ident, int handle, int64_t ns);
+ status_t flush(void* ident, int handle);
+ status_t setMode(uint32_t mode);
+ void disableAllSensors();
+ void enableAllSensors();
+ void autoDisable(void *ident, int handle);
+ status_t injectSensorData(const sensors_event_t *event);
+
+ // Dumpable
+ virtual std::string dump() const;
+private:
friend class Singleton<SensorDevice>;
sensors_poll_device_1_t* mSensorDevice;
struct sensors_module_t* mSensorModule;
@@ -87,24 +110,6 @@
bool isClientDisabled(void* ident);
bool isClientDisabledLocked(void* ident);
-public:
- ssize_t getSensorList(sensor_t const** list);
- void handleDynamicSensorConnection(int handle, bool connected);
- status_t initCheck() const;
- int getHalDeviceVersion() const;
- ssize_t poll(sensors_event_t* buffer, size_t count);
- status_t activate(void* ident, int handle, int enabled);
- status_t batch(void* ident, int handle, int flags, int64_t samplingPeriodNs,
- int64_t maxBatchReportLatencyNs);
- // Call batch with timeout zero instead of calling setDelay() for newer devices.
- status_t setDelay(void* ident, int handle, int64_t ns);
- status_t flush(void* ident, int handle);
- status_t setMode(uint32_t mode);
- void disableAllSensors();
- void enableAllSensors();
- void autoDisable(void *ident, int handle);
- status_t injectSensorData(const sensors_event_t *event);
- void dump(String8& result);
};
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/SensorInterface.cpp b/services/sensorservice/SensorInterface.cpp
index cb24229..73a6db5 100644
--- a/services/sensorservice/SensorInterface.cpp
+++ b/services/sensorservice/SensorInterface.cpp
@@ -34,12 +34,21 @@
mSensor(&sensor, mSensorDevice.getHalDeviceVersion()) {
}
+BaseSensor::BaseSensor(const sensor_t& sensor, const uint8_t (&uuid)[16]) :
+ mSensorDevice(SensorDevice::getInstance()),
+ mSensor(sensor, Sensor::uuid_t(uuid), mSensorDevice.getHalDeviceVersion()) {
+}
+
// ---------------------------------------------------------------------------
HardwareSensor::HardwareSensor(const sensor_t& sensor):
BaseSensor(sensor) {
}
+HardwareSensor::HardwareSensor(const sensor_t& sensor, const uint8_t (&uuid)[16]):
+ BaseSensor(sensor, uuid) {
+}
+
HardwareSensor::~HardwareSensor() {
}
diff --git a/services/sensorservice/SensorInterface.h b/services/sensorservice/SensorInterface.h
index d1cee41..dafcf2d 100644
--- a/services/sensorservice/SensorInterface.h
+++ b/services/sensorservice/SensorInterface.h
@@ -48,6 +48,7 @@
class BaseSensor : public SensorInterface {
public:
BaseSensor(const sensor_t& sensor);
+ BaseSensor(const sensor_t& sensor, const uint8_t (&uuid)[16]);
// Not all sensors need to support batching.
virtual status_t batch(void* ident, int handle, int, int64_t samplingPeriodNs,
@@ -74,6 +75,7 @@
class HardwareSensor : public BaseSensor {
public:
HardwareSensor(const sensor_t& sensor);
+ HardwareSensor(const sensor_t& sensor, const uint8_t (&uuid)[16]);
virtual ~HardwareSensor();
diff --git a/services/sensorservice/SensorList.cpp b/services/sensorservice/SensorList.cpp
index c23e21f..f6d3d94 100644
--- a/services/sensorservice/SensorList.cpp
+++ b/services/sensorservice/SensorList.cpp
@@ -19,6 +19,8 @@
#include <hardware/sensors.h>
#include <utils/String8.h>
+#include <cinttypes>
+
namespace android {
namespace SensorServiceUtil {
@@ -119,17 +121,17 @@
std::string SensorList::dump() const {
String8 result;
- result.append("Sensor List:\n");
forEachSensor([&result] (const Sensor& s) -> bool {
result.appendFormat(
- "%-15s| %-10s| version=%d |%-20s| 0x%08x | \"%s\" | type=%d |",
+ "%#010x) %-25s | %-15s | ver: %" PRId32 " | type: %20s(%" PRId32
+ ") | perm: %s\n\t",
+ s.getHandle(),
s.getName().string(),
s.getVendor().string(),
s.getVersion(),
s.getStringType().string(),
- s.getHandle(),
- s.getRequiredPermission().string(),
- s.getType());
+ s.getType(),
+ s.getRequiredPermission().size() ? s.getRequiredPermission().string() : "n/a");
const int reportingMode = s.getReportingMode();
if (reportingMode == AREPORTING_MODE_CONTINUOUS) {
@@ -147,18 +149,19 @@
if (s.getMaxDelay() > 0) {
result.appendFormat("minRate=%.2fHz | ", 1e6f / s.getMaxDelay());
} else {
- result.appendFormat("maxDelay=%dus | ", s.getMaxDelay());
+ result.appendFormat("maxDelay=%" PRId32 "us | ", s.getMaxDelay());
}
if (s.getMinDelay() > 0) {
result.appendFormat("maxRate=%.2fHz | ", 1e6f / s.getMinDelay());
} else {
- result.appendFormat("minDelay=%dus | ", s.getMinDelay());
+ result.appendFormat("minDelay=%" PRId32 "us | ", s.getMinDelay());
}
if (s.getFifoMaxEventCount() > 0) {
- result.appendFormat("FifoMax=%d events | ",
- s.getFifoMaxEventCount());
+ result.appendFormat("FIFO (max,reserved) = (%" PRIu32 ", %" PRIu32 ") events | ",
+ s.getFifoMaxEventCount(),
+ s.getFifoReservedEventCount());
} else {
result.append("no batching | ");
}
@@ -169,6 +172,20 @@
result.appendFormat("non-wakeUp | ");
}
+ if (s.isDynamicSensor()) {
+ result.appendFormat("dynamic, ");
+ }
+ if (s.hasAdditionalInfo()) {
+ result.appendFormat("has-additional-info, ");
+ }
+ result.append("| ");
+
+ if (s.isDynamicSensor()) {
+ result.append("uuid: ");
+ for (uint8_t i : s.getUuid().b) {
+ result.appendFormat("%02x", i);
+ }
+ }
result.append("\n");
return true;
});
diff --git a/services/sensorservice/SensorList.h b/services/sensorservice/SensorList.h
index ffde619..8209d96 100644
--- a/services/sensorservice/SensorList.h
+++ b/services/sensorservice/SensorList.h
@@ -14,18 +14,18 @@
* limitations under the License.
*/
-#ifndef ANDROID_SENSOR_LIST_H
-#define ANDROID_SENSOR_LIST_H
+#ifndef ANDROID_SENSOR_SERVICE_UTIL_SENSOR_LIST_H
+#define ANDROID_SENSOR_SERVICE_UTIL_SENSOR_LIST_H
#include "SensorInterface.h"
+#include "SensorServiceUtils.h"
#include <gui/Sensor.h>
#include <utils/String8.h>
#include <utils/Vector.h>
-#include <mutex>
#include <map>
-#include <string>
+#include <mutex>
#include <unordered_set>
#include <vector>
@@ -34,13 +34,6 @@
namespace SensorServiceUtil {
-class Dumpable {
-public:
- virtual std::string dump() const;
- virtual void setFormat(std::string ) {}
- virtual ~Dumpable() {}
-};
-
class SensorList : public Dumpable {
public:
// After SensorInterface * is added into SensorList, it can be assumed that SensorList own the
@@ -142,4 +135,4 @@
} // namespace SensorServiceUtil
} // namespace android
-#endif // ANDROID_SENSOR_LIST_H
+#endif // ANDROID_SENSOR_SERVICE_UTIL_SENSOR_LIST_H
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index b7a8740..6caa85b 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -36,11 +36,10 @@
#include "SensorInterface.h"
#include "SensorService.h"
-#include "SensorEventConnection.h"
#include "SensorEventAckReceiver.h"
+#include "SensorEventConnection.h"
#include "SensorRecord.h"
#include "SensorRegistrationInfo.h"
-#include "MostRecentEventLogger.h"
#include <inttypes.h>
#include <math.h>
@@ -86,7 +85,6 @@
(1<<SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR) |
(1<<SENSOR_TYPE_GAME_ROTATION_VECTOR);
- mLastEventSeen.setCapacity(count);
for (ssize_t i=0 ; i<count ; i++) {
bool useThisSensor=true;
@@ -218,25 +216,27 @@
const Sensor& SensorService::registerSensor(SensorInterface* s, bool isDebug, bool isVirtual) {
int handle = s->getSensor().getHandle();
+ int type = s->getSensor().getType();
if (mSensors.add(handle, s, isDebug, isVirtual)){
- mLastEventSeen.add(handle, nullptr);
+ mRecentEvent.emplace(handle, new RecentEventLogger(type));
return s->getSensor();
} else {
return mSensors.getNonSensor();
}
}
-const Sensor& SensorService::registerDynamicSensor(SensorInterface* s, bool isDebug) {
+const Sensor& SensorService::registerDynamicSensorLocked(SensorInterface* s, bool isDebug) {
return registerSensor(s, isDebug);
}
-bool SensorService::unregisterDynamicSensor(int handle) {
+bool SensorService::unregisterDynamicSensorLocked(int handle) {
bool ret = mSensors.remove(handle);
- MostRecentEventLogger *buf = mLastEventSeen.valueFor(handle);
- if (buf) {
- delete buf;
+
+ const auto i = mRecentEvent.find(handle);
+ if (i != mRecentEvent.end()) {
+ delete i->second;
+ mRecentEvent.erase(i);
}
- mLastEventSeen.removeItem(handle);
return ret;
}
@@ -245,6 +245,9 @@
}
SensorService::~SensorService() {
+ for (auto && entry : mRecentEvent) {
+ delete entry.second;
+ }
}
status_t SensorService::dump(int fd, const Vector<String16>& args) {
@@ -313,25 +316,25 @@
} else {
// Default dump the sensor list and debugging information.
//
+ result.append("Sensor Device:\n");
+ result.append(SensorDevice::getInstance().dump().c_str());
+
+ result.append("Sensor List:\n");
result.append(mSensors.dump().c_str());
+ result.append("Fusion States:\n");
SensorFusion::getInstance().dump(result);
- SensorDevice::getInstance().dump(result);
result.append("Recent Sensor events:\n");
- auto& lastEvents = mLastEventSeen;
- mSensors.forEachSensor([&result, &lastEvents] (const Sensor& s) -> bool {
- int bufIndex = lastEvents.indexOfKey(s.getHandle());
- if (bufIndex >= 0) {
- const MostRecentEventLogger* buf = lastEvents.valueAt(bufIndex);
- if (buf != nullptr && s.getRequiredPermission().isEmpty()) {
- result.appendFormat("%s (handle:0x%08x): ",
- s.getName().string(), s.getHandle());
- buf->printBuffer(result);
- }
- }
- return true;
- });
+ for (auto&& i : mRecentEvent) {
+ sp<SensorInterface> s = mSensors.getInterface(i.first);
+ if (!i.second->isEmpty() &&
+ s->getSensor().getRequiredPermission().isEmpty()) {
+ // if there is events and sensor does not need special permission.
+ result.appendFormat("%s: ", s->getSensor().getName().string());
+ result.append(i.second->dump().c_str());
+ }
+ }
result.append("Active sensors:\n");
for (size_t i=0 ; i<mActiveSensors.size() ; i++) {
@@ -554,17 +557,19 @@
handle, dynamicSensor.type, dynamicSensor.name);
if (mSensors.isNewHandle(handle)) {
+ const auto& uuid = mSensorEventBuffer[i].dynamic_sensor_meta.uuid;
sensor_t s = dynamicSensor;
// make sure the dynamic sensor flag is set
s.flags |= DYNAMIC_SENSOR_MASK;
// force the handle to be consistent
s.handle = handle;
- SensorInterface *si = new HardwareSensor(s);
+
+ SensorInterface *si = new HardwareSensor(s, uuid);
// This will release hold on dynamic sensor meta, so it should be called
// after Sensor object is created.
device.handleDynamicSensorConnection(handle, true /*connected*/);
- registerDynamicSensor(si);
+ registerDynamicSensorLocked(si);
} else {
ALOGE("Handle %d has been used, cannot use again before reboot.", handle);
}
@@ -573,7 +578,7 @@
ALOGI("Dynamic sensor handle 0x%x disconnected", handle);
device.handleDynamicSensorConnection(handle, false /*connected*/);
- if (!unregisterDynamicSensor(handle)) {
+ if (!unregisterDynamicSensorLocked(handle)) {
ALOGE("Dynamic sensor release error.");
}
@@ -674,16 +679,14 @@
for (size_t i = 0; i < count; i++) {
if (buffer[i].type == SENSOR_TYPE_META_DATA ||
buffer[i].type == SENSOR_TYPE_DYNAMIC_SENSOR_META ||
- buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO ||
- mLastEventSeen.indexOfKey(buffer[i].sensor) <0 ) {
+ buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {
continue;
}
- MostRecentEventLogger* &circular_buf = mLastEventSeen.editValueFor(buffer[i].sensor);
- if (circular_buf == NULL) {
- circular_buf = new MostRecentEventLogger(buffer[i].type);
+ auto logger = mRecentEvent.find(buffer[i].sensor);
+ if (logger != mRecentEvent.end()) {
+ logger->second->addEvent(buffer[i]);
}
- circular_buf->addEvent(buffer[i]);
}
}
@@ -881,14 +884,14 @@
if (sensor->getSensor().getReportingMode() == AREPORTING_MODE_ON_CHANGE) {
// NOTE: The wake_up flag of this event may get set to
// WAKE_UP_SENSOR_EVENT_NEEDS_ACK if this is a wake_up event.
- MostRecentEventLogger *circular_buf = mLastEventSeen.valueFor(handle);
- if (circular_buf) {
+
+ auto logger = mRecentEvent.find(handle);
+ if (logger != mRecentEvent.end()) {
sensors_event_t event;
- memset(&event, 0, sizeof(event));
// It is unlikely that this buffer is empty as the sensor is already active.
// One possible corner case may be two applications activating an on-change
// sensor at the same time.
- if(circular_buf->populateLastEvent(&event)) {
+ if(logger->second->populateLastEvent(&event)) {
event.sensor = handle;
if (event.version == sizeof(sensors_event_t)) {
if (isWakeUpSensorEvent(event) && !mWakeLockAcquired) {
@@ -1179,31 +1182,5 @@
return (packageName.contains(mWhiteListedPackage.string()));
}
-int SensorService::getNumEventsForSensorType(int sensor_event_type) {
- if (sensor_event_type >= SENSOR_TYPE_DEVICE_PRIVATE_BASE) {
- return 16;
- }
- switch (sensor_event_type) {
- case SENSOR_TYPE_ROTATION_VECTOR:
- case SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR:
- return 5;
-
- case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
- case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
- return 6;
-
- case SENSOR_TYPE_GAME_ROTATION_VECTOR:
- return 4;
-
- case SENSOR_TYPE_SIGNIFICANT_MOTION:
- case SENSOR_TYPE_STEP_DETECTOR:
- case SENSOR_TYPE_STEP_COUNTER:
- return 1;
-
- default:
- return 3;
- }
-}
-
}; // namespace android
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 6473edb..0d04478 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -18,6 +18,7 @@
#define ANDROID_SENSOR_SERVICE_H
#include "SensorList.h"
+#include "RecentEventLogger.h"
#include <binder/BinderService.h>
#include <cutils/compiler.h>
@@ -35,6 +36,7 @@
#include <stdint.h>
#include <sys/types.h>
+#include <unordered_map>
#include <unordered_set>
#if __clang__
@@ -56,6 +58,7 @@
namespace android {
// ---------------------------------------------------------------------------
class SensorInterface;
+using namespace SensorServiceUtil;
class SensorService :
public BinderService<SensorService>,
@@ -86,8 +89,6 @@
// nested class/struct for internal use
class SensorRecord;
class SensorEventAckReceiver;
- struct TrimmedSensorEvent;
- class MostRecentEventLogger;
struct SensorRegistrationInfo;
enum Mode {
@@ -155,7 +156,6 @@
virtual int isDataInjectionEnabled();
virtual status_t dump(int fd, const Vector<String16>& args);
- static int getNumEventsForSensorType(int sensor_event_type);
String8 getSensorName(int handle) const;
bool isVirtualSensor(int handle) const;
sp<SensorInterface> getSensorInterfaceFromHandle(int handle) const;
@@ -165,8 +165,8 @@
const Sensor& registerSensor(SensorInterface* sensor,
bool isDebug = false, bool isVirtual = false);
const Sensor& registerVirtualSensor(SensorInterface* sensor, bool isDebug = false);
- const Sensor& registerDynamicSensor(SensorInterface* sensor, bool isDebug = false);
- bool unregisterDynamicSensor(int handle);
+ const Sensor& registerDynamicSensorLocked(SensorInterface* sensor, bool isDebug = false);
+ bool unregisterDynamicSensorLocked(int handle);
status_t cleanupWithoutDisable(const sp<SensorEventConnection>& connection, int handle);
status_t cleanupWithoutDisableLocked(const sp<SensorEventConnection>& connection, int handle);
void cleanupAutoDisabledSensorLocked(const sp<SensorEventConnection>& connection,
@@ -208,7 +208,7 @@
status_t resetToNormalMode();
status_t resetToNormalModeLocked();
- SensorServiceUtil::SensorList mSensors;
+ SensorList mSensors;
status_t mInitCheck;
// Socket buffersize used to initialize BitTube. This size depends on whether batching is
@@ -225,7 +225,7 @@
bool mWakeLockAcquired;
sensors_event_t *mSensorEventBuffer, *mSensorEventScratch;
SensorEventConnection const **mMapFlushEventsToConnections;
- KeyedVector<int32_t, MostRecentEventLogger*> mLastEventSeen;
+ std::unordered_map<int, RecentEventLogger*> mRecentEvent;
Mode mCurrentOperatingMode;
// This packagaName is set when SensorService is in RESTRICTED or DATA_INJECTION mode. Only
diff --git a/services/sensorservice/SensorServiceUtils.cpp b/services/sensorservice/SensorServiceUtils.cpp
new file mode 100644
index 0000000..1996a00
--- /dev/null
+++ b/services/sensorservice/SensorServiceUtils.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "SensorServiceUtils.h"
+
+#include <hardware/sensors.h>
+
+namespace android {
+namespace SensorServiceUtil {
+
+// Keep in sync with sSensorReportingMode in Sensor.java
+size_t eventSizeBySensorType(int type) {
+ if (type >= SENSOR_TYPE_DEVICE_PRIVATE_BASE) {
+ return 16;
+ }
+ switch (type) {
+ case SENSOR_TYPE_POSE_6DOF:
+ return 16;
+
+ case SENSOR_TYPE_ROTATION_VECTOR:
+ case SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR:
+ return 5;
+
+ case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
+ case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
+ return 6;
+
+ case SENSOR_TYPE_GAME_ROTATION_VECTOR:
+ return 4;
+
+ case SENSOR_TYPE_SIGNIFICANT_MOTION:
+ case SENSOR_TYPE_STEP_DETECTOR:
+ case SENSOR_TYPE_STEP_COUNTER:
+ case SENSOR_TYPE_HEART_RATE:
+ case SENSOR_TYPE_TILT_DETECTOR:
+ case SENSOR_TYPE_WAKE_GESTURE:
+ case SENSOR_TYPE_GLANCE_GESTURE:
+ case SENSOR_TYPE_PICK_UP_GESTURE:
+ case SENSOR_TYPE_WRIST_TILT_GESTURE:
+ case SENSOR_TYPE_DEVICE_ORIENTATION:
+ case SENSOR_TYPE_STATIONARY_DETECT:
+ case SENSOR_TYPE_MOTION_DETECT:
+ case SENSOR_TYPE_HEART_BEAT:
+ return 1;
+
+ default:
+ return 3;
+ }
+}
+
+} // namespace SensorServiceUtil
+} // namespace android;
diff --git a/services/sensorservice/SensorServiceUtils.h b/services/sensorservice/SensorServiceUtils.h
new file mode 100644
index 0000000..1558feb
--- /dev/null
+++ b/services/sensorservice/SensorServiceUtils.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 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_SENSOR_SERVICE_UTIL
+#define ANDROID_SENSOR_SERVICE_UTIL
+
+#include <cstddef>
+#include <string>
+
+namespace android {
+namespace SensorServiceUtil {
+
+class Dumpable {
+public:
+ virtual std::string dump() const = 0;
+ virtual void setFormat(std::string ) {}
+ virtual ~Dumpable() {}
+};
+
+size_t eventSizeBySensorType(int type);
+
+} // namespace SensorServiceUtil
+} // namespace android;
+
+#endif // ANDROID_SENSOR_SERVICE_UTIL
diff --git a/services/sensorservice/tests/sensorservicetest.cpp b/services/sensorservice/tests/sensorservicetest.cpp
index cfdf6a3..186b60c 100644
--- a/services/sensorservice/tests/sensorservicetest.cpp
+++ b/services/sensorservice/tests/sensorservicetest.cpp
@@ -62,7 +62,7 @@
int main()
{
- SensorManager mgr(String16("Sensor Service Test"));
+ SensorManager& mgr = SensorManager::getInstanceForPackage(String16("Sensor Service Test"));
Sensor const* const* list;
ssize_t count = mgr.getSensorList(&list);
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 7e4e797..bc8dfbb 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -606,7 +606,8 @@
}
status_t VirtualDisplaySurface::getLastQueuedBuffer(
- sp<GraphicBuffer>* /*outBuffer*/, sp<Fence>* /*outFence*/) {
+ sp<GraphicBuffer>* /*outBuffer*/, sp<Fence>* /*outFence*/,
+ float[16] /* outTransformMatrix*/) {
ALOGE("getLastQueuedBuffer not supported on VirtualDisplaySurface");
return INVALID_OPERATION;
}
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index bd1cfb1..29563b6 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -127,7 +127,7 @@
virtual status_t setAutoRefresh(bool autoRefresh) override;
virtual status_t setDequeueTimeout(nsecs_t timeout) override;
virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
- sp<Fence>* outFence) override;
+ sp<Fence>* outFence, float outTransformMatrix[16]) override;
//
// Utility methods
@@ -254,4 +254,3 @@
// ---------------------------------------------------------------------------
#endif // ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
-
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 6ccd4ff..c640f58 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -251,7 +251,7 @@
ALOGE("Can't replace a frame on an empty queue");
return;
}
- mQueueItems.editItemAt(0) = item;
+ mQueueItems.editItemAt(mQueueItems.size() - 1) = item;
// Wake up any pending callbacks
mLastFrameNumberReceived = item.mFrameNumber;
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index e689127..faab62c 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -144,8 +144,9 @@
}
status_t MonitoredProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
- sp<Fence>* outFence) {
- return mProducer->getLastQueuedBuffer(outBuffer, outFence);
+ sp<Fence>* outFence, float outTransformMatrix[16]) {
+ return mProducer->getLastQueuedBuffer(outBuffer, outFence,
+ outTransformMatrix);
}
IBinder* MonitoredProducer::onAsBinder() {
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
index d2b4b43..ce756dc 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -60,7 +60,7 @@
virtual uint64_t getNextFrameNumber() const override;
virtual status_t setDequeueTimeout(nsecs_t timeout) override;
virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
- sp<Fence>* outFence) override;
+ sp<Fence>* outFence, float outTransformMatrix[16]) override;
virtual IBinder* onAsBinder();
virtual status_t setSharedBufferMode(bool sharedBufferMode) override;
virtual status_t setAutoRefresh(bool autoRefresh) override;
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index e7f10b3..28b172d 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -116,7 +116,7 @@
};
void AddImplicitLayers() {
- if (!driver::Debuggable())
+ if (!is_instance_ || !driver::Debuggable())
return;
ParseDebugVulkanLayers();
@@ -367,6 +367,14 @@
// chaining.
class LayerChain {
public:
+ struct ActiveLayer {
+ LayerRef ref;
+ union {
+ VkLayerInstanceLink instance_link;
+ VkLayerDeviceLink device_link;
+ };
+ };
+
static VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
const VkAllocationCallbacks* allocator,
VkInstance* instance_out);
@@ -382,15 +390,10 @@
static void DestroyDevice(VkDevice dev,
const VkAllocationCallbacks* allocator);
- private:
- struct ActiveLayer {
- LayerRef ref;
- union {
- VkLayerInstanceLink instance_link;
- VkLayerDeviceLink device_link;
- };
- };
+ static const ActiveLayer* GetActiveLayers(VkPhysicalDevice physical_dev,
+ uint32_t& count);
+ private:
LayerChain(bool is_instance, const VkAllocationCallbacks& allocator);
~LayerChain();
@@ -398,6 +401,11 @@
uint32_t layer_count,
const char* const* extension_names,
uint32_t extension_count);
+ VkResult ActivateLayers(VkPhysicalDevice physical_dev,
+ const char* const* layer_names,
+ uint32_t layer_count,
+ const char* const* extension_names,
+ uint32_t extension_count);
ActiveLayer* AllocateLayerArray(uint32_t count) const;
VkResult LoadLayer(ActiveLayer& layer, const char* name);
void SetupLayerLinks();
@@ -507,8 +515,6 @@
if (!layer_count) {
// point head of chain to the driver
get_instance_proc_addr_ = driver::GetInstanceProcAddr;
- if (!is_instance_)
- get_device_proc_addr_ = driver::GetDeviceProcAddr;
return VK_SUCCESS;
}
@@ -532,10 +538,76 @@
return VK_SUCCESS;
}
+VkResult LayerChain::ActivateLayers(VkPhysicalDevice physical_dev,
+ const char* const* layer_names,
+ uint32_t layer_count,
+ const char* const* extension_names,
+ uint32_t extension_count) {
+ uint32_t instance_layer_count;
+ const ActiveLayer* instance_layers =
+ GetActiveLayers(physical_dev, instance_layer_count);
+
+ // log a message if the application device layer array is not empty nor an
+ // exact match of the instance layer array.
+ if (layer_count) {
+ bool exact_match = (instance_layer_count == layer_count);
+ if (exact_match) {
+ for (uint32_t i = 0; i < instance_layer_count; i++) {
+ const Layer& l = *instance_layers[i].ref;
+ if (strcmp(GetLayerProperties(l).layerName, layer_names[i])) {
+ exact_match = false;
+ break;
+ }
+ }
+ }
+
+ if (!exact_match) {
+ ALOGW("Device layers");
+ for (uint32_t i = 0; i < layer_count; i++)
+ ALOGW(" %s", layer_names[i]);
+ ALOGW(
+ "disagree with instance layers and are overridden by "
+ "instance layers");
+ }
+ }
+
+ VkResult result =
+ override_extensions_.Parse(extension_names, extension_count);
+ if (result != VK_SUCCESS)
+ return result;
+
+ if (!instance_layer_count) {
+ // point head of chain to the driver
+ get_instance_proc_addr_ = driver::GetInstanceProcAddr;
+ get_device_proc_addr_ = driver::GetDeviceProcAddr;
+
+ return VK_SUCCESS;
+ }
+
+ layers_ = AllocateLayerArray(instance_layer_count);
+ if (!layers_)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ for (uint32_t i = 0; i < instance_layer_count; i++) {
+ const Layer& l = *instance_layers[i].ref;
+
+ // no need to and cannot chain non-global layers
+ if (!IsLayerGlobal(l))
+ continue;
+
+ // this never fails
+ new (&layers_[layer_count_++]) ActiveLayer{GetLayerRef(l), {}};
+ }
+
+ SetupLayerLinks();
+
+ return VK_SUCCESS;
+}
+
LayerChain::ActiveLayer* LayerChain::AllocateLayerArray(uint32_t count) const {
VkSystemAllocationScope scope = (is_instance_)
? VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE
- : VK_SYSTEM_ALLOCATION_SCOPE_DEVICE;
+ : VK_SYSTEM_ALLOCATION_SCOPE_COMMAND;
return reinterpret_cast<ActiveLayer*>(allocator_.pfnAllocation(
allocator_.pUserData, sizeof(ActiveLayer) * count, alignof(ActiveLayer),
@@ -543,18 +615,20 @@
}
VkResult LayerChain::LoadLayer(ActiveLayer& layer, const char* name) {
- if (is_instance_)
- new (&layer) ActiveLayer{GetInstanceLayerRef(name), {}};
- else
- new (&layer) ActiveLayer{GetDeviceLayerRef(name), {}};
+ const Layer* l = FindLayer(name);
+ if (!l) {
+ ALOGW("Failed to find layer %s", name);
+ return VK_ERROR_LAYER_NOT_PRESENT;
+ }
+ new (&layer) ActiveLayer{GetLayerRef(*l), {}};
if (!layer.ref) {
- ALOGE("Failed to load layer %s", name);
+ ALOGW("Failed to open layer %s", name);
layer.ref.~LayerRef();
return VK_ERROR_LAYER_NOT_PRESENT;
}
- ALOGI("Loaded %s layer %s", (is_instance_) ? "instance" : "device", name);
+ ALOGI("Loaded layer %s", name);
return VK_SUCCESS;
}
@@ -698,8 +772,6 @@
// initialize InstanceData
InstanceData& data = GetData(instance);
- data.instance = instance;
-
if (!InitDispatchTable(instance, get_instance_proc_addr_,
enabled_extensions_)) {
if (data.dispatch.DestroyInstance)
@@ -763,13 +835,8 @@
return result;
// call down the chain
- //
- // TODO Instance call chain available at
- // GetData(physical_dev).dispatch.CreateDevice is ignored. Is that
- // right?
- VkInstance instance = GetData(physical_dev).instance;
- PFN_vkCreateDevice create_device = reinterpret_cast<PFN_vkCreateDevice>(
- get_instance_proc_addr_(instance, "vkCreateDevice"));
+ PFN_vkCreateDevice create_device =
+ GetData(physical_dev).dispatch.CreateDevice;
VkDevice dev;
result = create_device(physical_dev, create_info, allocator, &dev);
if (result != VK_SUCCESS)
@@ -785,8 +852,8 @@
return VK_ERROR_INITIALIZATION_FAILED;
}
- StealLayers(data);
-
+ // no StealLayers so that active layers are destroyed with this
+ // LayerChain
*dev_out = dev;
return VK_SUCCESS;
@@ -872,10 +939,18 @@
}
bool LayerChain::IsLayerExtension(const char* name) const {
- for (uint32_t i = 0; i < layer_count_; i++) {
- const ActiveLayer& layer = layers_[i];
- if (layer.ref.SupportsExtension(name))
- return true;
+ if (is_instance_) {
+ for (uint32_t i = 0; i < layer_count_; i++) {
+ const ActiveLayer& layer = layers_[i];
+ if (FindLayerInstanceExtension(*layer.ref, name))
+ return true;
+ }
+ } else {
+ for (uint32_t i = 0; i < layer_count_; i++) {
+ const ActiveLayer& layer = layers_[i];
+ if (FindLayerDeviceExtension(*layer.ref, name))
+ return true;
+ }
}
return false;
@@ -990,10 +1065,10 @@
? *allocator
: driver::GetData(physical_dev).allocator);
- VkResult result = chain.ActivateLayers(create_info->ppEnabledLayerNames,
- create_info->enabledLayerCount,
- create_info->ppEnabledExtensionNames,
- create_info->enabledExtensionCount);
+ VkResult result = chain.ActivateLayers(
+ physical_dev, create_info->ppEnabledLayerNames,
+ create_info->enabledLayerCount, create_info->ppEnabledExtensionNames,
+ create_info->enabledExtensionCount);
if (result != VK_SUCCESS)
return result;
@@ -1032,19 +1107,15 @@
void LayerChain::DestroyDevice(VkDevice device,
const VkAllocationCallbacks* allocator) {
DeviceData& data = GetData(device);
-
- ActiveLayer* layers = reinterpret_cast<ActiveLayer*>(data.layers);
- uint32_t layer_count = data.layer_count;
-
- VkAllocationCallbacks local_allocator;
- if (!allocator)
- local_allocator = driver::GetData(device).allocator;
-
// this also destroys DeviceData
data.dispatch.DestroyDevice(device, allocator);
+}
- DestroyLayers(layers, layer_count,
- (allocator) ? *allocator : local_allocator);
+const LayerChain::ActiveLayer* LayerChain::GetActiveLayers(
+ VkPhysicalDevice physical_dev,
+ uint32_t& count) {
+ count = GetData(physical_dev).layer_count;
+ return reinterpret_cast<const ActiveLayer*>(GetData(physical_dev).layers);
}
// ----------------------------------------------------------------------------
@@ -1098,13 +1169,19 @@
if (!EnsureInitialized())
return VK_ERROR_INITIALIZATION_FAILED;
- uint32_t count =
- EnumerateInstanceLayers(pProperties ? *pPropertyCount : 0, pProperties);
+ uint32_t count = GetLayerCount();
- if (!pProperties || *pPropertyCount > count)
+ if (!pProperties) {
*pPropertyCount = count;
+ return VK_SUCCESS;
+ }
- return *pPropertyCount < count ? VK_INCOMPLETE : VK_SUCCESS;
+ uint32_t copied = std::min(*pPropertyCount, count);
+ for (uint32_t i = 0; i < copied; i++)
+ pProperties[i] = GetLayerProperties(GetLayer(i));
+ *pPropertyCount = copied;
+
+ return (copied == count) ? VK_SUCCESS : VK_INCOMPLETE;
}
VkResult EnumerateInstanceExtensionProperties(
@@ -1115,9 +1192,13 @@
return VK_ERROR_INITIALIZATION_FAILED;
if (pLayerName) {
- const VkExtensionProperties* props;
+ const Layer* layer = FindLayer(pLayerName);
+ if (!layer)
+ return VK_ERROR_LAYER_NOT_PRESENT;
+
uint32_t count;
- GetInstanceLayerExtensions(pLayerName, &props, &count);
+ const VkExtensionProperties* props =
+ GetLayerInstanceExtensions(*layer, count);
if (!pProperties || *pPropertyCount > count)
*pPropertyCount = count;
@@ -1135,15 +1216,21 @@
VkResult EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,
uint32_t* pPropertyCount,
VkLayerProperties* pProperties) {
- (void)physicalDevice;
+ uint32_t count;
+ const LayerChain::ActiveLayer* layers =
+ LayerChain::GetActiveLayers(physicalDevice, count);
- uint32_t count =
- EnumerateDeviceLayers(pProperties ? *pPropertyCount : 0, pProperties);
-
- if (!pProperties || *pPropertyCount > count)
+ if (!pProperties) {
*pPropertyCount = count;
+ return VK_SUCCESS;
+ }
- return *pPropertyCount < count ? VK_INCOMPLETE : VK_SUCCESS;
+ uint32_t copied = std::min(*pPropertyCount, count);
+ for (uint32_t i = 0; i < copied; i++)
+ pProperties[i] = GetLayerProperties(*layers[i].ref);
+ *pPropertyCount = copied;
+
+ return (copied == count) ? VK_SUCCESS : VK_INCOMPLETE;
}
VkResult EnumerateDeviceExtensionProperties(
@@ -1152,9 +1239,16 @@
uint32_t* pPropertyCount,
VkExtensionProperties* pProperties) {
if (pLayerName) {
- const VkExtensionProperties* props;
+ // EnumerateDeviceLayerProperties enumerates active layers for
+ // backward compatibility. The extension query here should work for
+ // all layers.
+ const Layer* layer = FindLayer(pLayerName);
+ if (!layer)
+ return VK_ERROR_LAYER_NOT_PRESENT;
+
uint32_t count;
- GetDeviceLayerExtensions(pLayerName, &props, &count);
+ const VkExtensionProperties* props =
+ GetLayerDeviceExtensions(*layer, count);
if (!pProperties || *pPropertyCount > count)
*pPropertyCount = count;
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 17ccc72..b02f5b4 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -480,17 +480,20 @@
if (hook->type == ProcHook::GLOBAL)
return hook->proc;
+ // v0 layers expect
+ //
+ // vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice");
+ //
+ // to work.
+ if (strcmp(pName, "vkCreateDevice") == 0)
+ return hook->proc;
+
ALOGE(
"Invalid use of vkGetInstanceProcAddr to query %s without an "
"instance",
pName);
- // Some naughty layers expect
- //
- // vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice");
- //
- // to work.
- return (strcmp(pName, "vkCreateDevice") == 0) ? hook->proc : nullptr;
+ return nullptr;
}
PFN_vkVoidFunction proc;
diff --git a/vulkan/libvulkan/driver.h b/vulkan/libvulkan/driver.h
index 85b36b6..2b1f545 100644
--- a/vulkan/libvulkan/driver.h
+++ b/vulkan/libvulkan/driver.h
@@ -40,9 +40,6 @@
struct InstanceData {
InstanceDispatchTable dispatch;
- // for VkPhysicalDevice->VkInstance mapping
- VkInstance instance;
-
// LayerChain::ActiveLayer array
void* layers;
uint32_t layer_count;
@@ -54,10 +51,6 @@
struct DeviceData {
DeviceDispatchTable dispatch;
-
- // LayerChain::ActiveLayer array
- void* layers;
- uint32_t layer_count;
};
} // namespace api
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index 6b53a9a..f9b1002 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -43,75 +43,119 @@
// probably want to intern strings, etc., and will need some custom/manual data
// structures.
-// TODO(jessehall): Currently we have separate lists for instance and device
-// layers. Most layers are both; we should use one entry for each layer name,
-// with a mask saying what kind(s) it is.
-
namespace vulkan {
namespace api {
struct Layer {
VkLayerProperties properties;
size_t library_idx;
- std::vector<VkExtensionProperties> extensions;
+
+ // true if the layer intercepts vkCreateDevice and device commands
+ bool is_global;
+
+ std::vector<VkExtensionProperties> instance_extensions;
+ std::vector<VkExtensionProperties> device_extensions;
};
namespace {
-std::mutex g_library_mutex;
-struct LayerLibrary {
- std::string path;
- void* dlhandle;
- size_t refcount;
-};
-std::vector<LayerLibrary> g_layer_libraries;
-std::vector<Layer> g_instance_layers;
-std::vector<Layer> g_device_layers;
+class LayerLibrary {
+ public:
+ LayerLibrary(const std::string& path)
+ : path_(path), dlhandle_(nullptr), refcount_(0) {}
-void AddLayerLibrary(const std::string& path) {
- ALOGV("examining layer library '%s'", path.c_str());
-
- void* dlhandle = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL);
- if (!dlhandle) {
- ALOGW("failed to load layer library '%s': %s", path.c_str(), dlerror());
- return;
+ LayerLibrary(LayerLibrary&& other)
+ : path_(std::move(other.path_)),
+ dlhandle_(other.dlhandle_),
+ refcount_(other.refcount_) {
+ other.dlhandle_ = nullptr;
+ other.refcount_ = 0;
}
+ LayerLibrary(const LayerLibrary&) = delete;
+ LayerLibrary& operator=(const LayerLibrary&) = delete;
+
+ // these are thread-safe
+ bool Open();
+ void Close();
+
+ bool EnumerateLayers(size_t library_idx,
+ std::vector<Layer>& instance_layers) const;
+
+ void* GetGPA(const Layer& layer,
+ const char* gpa_name,
+ size_t gpa_name_len) const;
+
+ private:
+ const std::string path_;
+
+ std::mutex mutex_;
+ void* dlhandle_;
+ size_t refcount_;
+};
+
+bool LayerLibrary::Open() {
+ std::lock_guard<std::mutex> lock(mutex_);
+
+ if (refcount_++ == 0) {
+ dlhandle_ = dlopen(path_.c_str(), RTLD_NOW | RTLD_LOCAL);
+ ALOGV("Opening library %s", path_.c_str());
+ if (!dlhandle_) {
+ ALOGE("failed to load layer library '%s': %s", path_.c_str(),
+ dlerror());
+ refcount_ = 0;
+ return false;
+ }
+ }
+ ALOGV("Refcount on activate is %zu", refcount_);
+ return true;
+}
+
+void LayerLibrary::Close() {
+ std::lock_guard<std::mutex> lock(mutex_);
+
+ if (--refcount_ == 0) {
+ ALOGV("Closing library %s", path_.c_str());
+ dlclose(dlhandle_);
+ dlhandle_ = nullptr;
+ }
+ ALOGV("Refcount on destruction is %zu", refcount_);
+}
+
+bool LayerLibrary::EnumerateLayers(size_t library_idx,
+ std::vector<Layer>& instance_layers) const {
PFN_vkEnumerateInstanceLayerProperties enumerate_instance_layers =
reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
- dlsym(dlhandle, "vkEnumerateInstanceLayerProperties"));
+ dlsym(dlhandle_, "vkEnumerateInstanceLayerProperties"));
PFN_vkEnumerateInstanceExtensionProperties enumerate_instance_extensions =
reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
- dlsym(dlhandle, "vkEnumerateInstanceExtensionProperties"));
- PFN_vkEnumerateDeviceLayerProperties enumerate_device_layers =
- reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>(
- dlsym(dlhandle, "vkEnumerateDeviceLayerProperties"));
- PFN_vkEnumerateDeviceExtensionProperties enumerate_device_extensions =
- reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(
- dlsym(dlhandle, "vkEnumerateDeviceExtensionProperties"));
- if (!((enumerate_instance_layers && enumerate_instance_extensions) ||
- (enumerate_device_layers && enumerate_device_extensions))) {
- ALOGV(
- "layer library '%s' has neither instance nor device enumeraion "
- "functions",
- path.c_str());
- dlclose(dlhandle);
- return;
+ dlsym(dlhandle_, "vkEnumerateInstanceExtensionProperties"));
+ if (!enumerate_instance_layers || !enumerate_instance_extensions) {
+ ALOGV("layer library '%s' misses some instance enumeraion functions",
+ path_.c_str());
+ return false;
}
- VkResult result;
+ // device functions are optional
+ PFN_vkEnumerateDeviceLayerProperties enumerate_device_layers =
+ reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>(
+ dlsym(dlhandle_, "vkEnumerateDeviceLayerProperties"));
+ PFN_vkEnumerateDeviceExtensionProperties enumerate_device_extensions =
+ reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(
+ dlsym(dlhandle_, "vkEnumerateDeviceExtensionProperties"));
+
+ // get layer counts
uint32_t num_instance_layers = 0;
uint32_t num_device_layers = 0;
- if (enumerate_instance_layers) {
- result = enumerate_instance_layers(&num_instance_layers, nullptr);
+ VkResult result = enumerate_instance_layers(&num_instance_layers, nullptr);
+ if (result != VK_SUCCESS || !num_instance_layers) {
if (result != VK_SUCCESS) {
ALOGW(
"vkEnumerateInstanceLayerProperties failed for library '%s': "
"%d",
- path.c_str(), result);
- dlclose(dlhandle);
- return;
+ path_.c_str(), result);
}
+ return false;
}
if (enumerate_device_layers) {
result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
@@ -119,23 +163,19 @@
if (result != VK_SUCCESS) {
ALOGW(
"vkEnumerateDeviceLayerProperties failed for library '%s': %d",
- path.c_str(), result);
- dlclose(dlhandle);
- return;
+ path_.c_str(), result);
+ return false;
}
}
+
+ // get layer properties
VkLayerProperties* properties = static_cast<VkLayerProperties*>(alloca(
(num_instance_layers + num_device_layers) * sizeof(VkLayerProperties)));
- if (num_instance_layers > 0) {
- result = enumerate_instance_layers(&num_instance_layers, properties);
- if (result != VK_SUCCESS) {
- ALOGW(
- "vkEnumerateInstanceLayerProperties failed for library '%s': "
- "%d",
- path.c_str(), result);
- dlclose(dlhandle);
- return;
- }
+ result = enumerate_instance_layers(&num_instance_layers, properties);
+ if (result != VK_SUCCESS) {
+ ALOGW("vkEnumerateInstanceLayerProperties failed for library '%s': %d",
+ path_.c_str(), result);
+ return false;
}
if (num_device_layers > 0) {
result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
@@ -143,102 +183,121 @@
if (result != VK_SUCCESS) {
ALOGW(
"vkEnumerateDeviceLayerProperties failed for library '%s': %d",
- path.c_str(), result);
- dlclose(dlhandle);
- return;
+ path_.c_str(), result);
+ return false;
}
}
- size_t library_idx = g_layer_libraries.size();
- size_t prev_num_instance_layers = g_instance_layers.size();
- size_t prev_num_device_layers = g_device_layers.size();
- g_instance_layers.reserve(prev_num_instance_layers + num_instance_layers);
- g_device_layers.reserve(prev_num_device_layers + num_device_layers);
+ // append layers to instance_layers
+ size_t prev_num_instance_layers = instance_layers.size();
+ instance_layers.reserve(prev_num_instance_layers + num_instance_layers);
for (size_t i = 0; i < num_instance_layers; i++) {
const VkLayerProperties& props = properties[i];
Layer layer;
layer.properties = props;
layer.library_idx = library_idx;
+ layer.is_global = false;
- if (enumerate_instance_extensions) {
- uint32_t count = 0;
- result =
- enumerate_instance_extensions(props.layerName, &count, nullptr);
- if (result != VK_SUCCESS) {
- ALOGW(
- "vkEnumerateInstanceExtensionProperties(%s) failed for "
- "library "
- "'%s': %d",
- props.layerName, path.c_str(), result);
- g_instance_layers.resize(prev_num_instance_layers);
- dlclose(dlhandle);
- return;
- }
- layer.extensions.resize(count);
- result = enumerate_instance_extensions(props.layerName, &count,
- layer.extensions.data());
- if (result != VK_SUCCESS) {
- ALOGW(
- "vkEnumerateInstanceExtensionProperties(%s) failed for "
- "library "
- "'%s': %d",
- props.layerName, path.c_str(), result);
- g_instance_layers.resize(prev_num_instance_layers);
- dlclose(dlhandle);
- return;
+ uint32_t count = 0;
+ result =
+ enumerate_instance_extensions(props.layerName, &count, nullptr);
+ if (result != VK_SUCCESS) {
+ ALOGW(
+ "vkEnumerateInstanceExtensionProperties(%s) failed for library "
+ "'%s': %d",
+ props.layerName, path_.c_str(), result);
+ instance_layers.resize(prev_num_instance_layers);
+ return false;
+ }
+ layer.instance_extensions.resize(count);
+ result = enumerate_instance_extensions(
+ props.layerName, &count, layer.instance_extensions.data());
+ if (result != VK_SUCCESS) {
+ ALOGW(
+ "vkEnumerateInstanceExtensionProperties(%s) failed for library "
+ "'%s': %d",
+ props.layerName, path_.c_str(), result);
+ instance_layers.resize(prev_num_instance_layers);
+ return false;
+ }
+
+ for (size_t j = 0; j < num_device_layers; j++) {
+ const auto& dev_props = properties[num_instance_layers + j];
+ if (memcmp(&props, &dev_props, sizeof(props)) == 0) {
+ layer.is_global = true;
+ break;
}
}
- g_instance_layers.push_back(layer);
- ALOGV(" added instance layer '%s'", props.layerName);
- }
- for (size_t i = 0; i < num_device_layers; i++) {
- const VkLayerProperties& props = properties[num_instance_layers + i];
-
- Layer layer;
- layer.properties = props;
- layer.library_idx = library_idx;
-
- if (enumerate_device_extensions) {
- uint32_t count;
+ if (layer.is_global && enumerate_device_extensions) {
result = enumerate_device_extensions(
VK_NULL_HANDLE, props.layerName, &count, nullptr);
if (result != VK_SUCCESS) {
ALOGW(
"vkEnumerateDeviceExtensionProperties(%s) failed for "
- "library "
- "'%s': %d",
- props.layerName, path.c_str(), result);
- g_instance_layers.resize(prev_num_instance_layers);
- g_device_layers.resize(prev_num_device_layers);
- dlclose(dlhandle);
- return;
+ "library '%s': %d",
+ props.layerName, path_.c_str(), result);
+ instance_layers.resize(prev_num_instance_layers);
+ return false;
}
- layer.extensions.resize(count);
- result =
- enumerate_device_extensions(VK_NULL_HANDLE, props.layerName,
- &count, layer.extensions.data());
+ layer.device_extensions.resize(count);
+ result = enumerate_device_extensions(
+ VK_NULL_HANDLE, props.layerName, &count,
+ layer.device_extensions.data());
if (result != VK_SUCCESS) {
ALOGW(
"vkEnumerateDeviceExtensionProperties(%s) failed for "
- "library "
- "'%s': %d",
- props.layerName, path.c_str(), result);
- g_instance_layers.resize(prev_num_instance_layers);
- g_device_layers.resize(prev_num_device_layers);
- dlclose(dlhandle);
- return;
+ "library '%s': %d",
+ props.layerName, path_.c_str(), result);
+ instance_layers.resize(prev_num_instance_layers);
+ return false;
}
}
- g_device_layers.push_back(layer);
- ALOGV(" added device layer '%s'", props.layerName);
+ instance_layers.push_back(layer);
+ ALOGV(" added %s layer '%s'",
+ (layer.is_global) ? "global" : "instance", props.layerName);
}
- dlclose(dlhandle);
+ return true;
+}
- g_layer_libraries.push_back(LayerLibrary{path, nullptr, 0});
+void* LayerLibrary::GetGPA(const Layer& layer,
+ const char* gpa_name,
+ size_t gpa_name_len) const {
+ void* gpa;
+ size_t layer_name_len =
+ std::max(size_t{2}, strlen(layer.properties.layerName));
+ char* name = static_cast<char*>(alloca(layer_name_len + gpa_name_len + 1));
+ strcpy(name, layer.properties.layerName);
+ strcpy(name + layer_name_len, gpa_name);
+ if (!(gpa = dlsym(dlhandle_, name))) {
+ strcpy(name, "vk");
+ strcpy(name + 2, gpa_name);
+ gpa = dlsym(dlhandle_, name);
+ }
+ return gpa;
+}
+
+std::vector<LayerLibrary> g_layer_libraries;
+std::vector<Layer> g_instance_layers;
+
+void AddLayerLibrary(const std::string& path) {
+ ALOGV("examining layer library '%s'", path.c_str());
+
+ LayerLibrary library(path);
+ if (!library.Open())
+ return;
+
+ if (!library.EnumerateLayers(g_layer_libraries.size(), g_instance_layers)) {
+ library.Close();
+ return;
+ }
+
+ library.Close();
+
+ g_layer_libraries.emplace_back(std::move(library));
}
void DiscoverLayersInDirectory(const std::string& dir_path) {
@@ -271,71 +330,21 @@
closedir(directory);
}
+const VkExtensionProperties* FindExtension(
+ const std::vector<VkExtensionProperties>& extensions,
+ const char* name) {
+ auto it = std::find_if(extensions.cbegin(), extensions.cend(),
+ [=](const VkExtensionProperties& ext) {
+ return (strcmp(ext.extensionName, name) == 0);
+ });
+ return (it != extensions.cend()) ? &*it : nullptr;
+}
+
void* GetLayerGetProcAddr(const Layer& layer,
const char* gpa_name,
size_t gpa_name_len) {
const LayerLibrary& library = g_layer_libraries[layer.library_idx];
- void* gpa;
- size_t layer_name_len = std::max(size_t{2}, strlen(layer.properties.layerName));
- char* name = static_cast<char*>(alloca(layer_name_len + gpa_name_len + 1));
- strcpy(name, layer.properties.layerName);
- strcpy(name + layer_name_len, gpa_name);
- if (!(gpa = dlsym(library.dlhandle, name))) {
- strcpy(name, "vk");
- strcpy(name + 2, gpa_name);
- gpa = dlsym(library.dlhandle, name);
- }
- return gpa;
-}
-
-uint32_t EnumerateLayers(const std::vector<Layer>& layers,
- uint32_t count,
- VkLayerProperties* properties) {
- uint32_t n = std::min(count, static_cast<uint32_t>(layers.size()));
- for (uint32_t i = 0; i < n; i++) {
- properties[i] = layers[i].properties;
- }
- return static_cast<uint32_t>(layers.size());
-}
-
-void GetLayerExtensions(const std::vector<Layer>& layers,
- const char* name,
- const VkExtensionProperties** properties,
- uint32_t* count) {
- auto layer =
- std::find_if(layers.cbegin(), layers.cend(), [=](const Layer& entry) {
- return strcmp(entry.properties.layerName, name) == 0;
- });
- if (layer == layers.cend()) {
- *properties = nullptr;
- *count = 0;
- } else {
- *properties = layer->extensions.data();
- *count = static_cast<uint32_t>(layer->extensions.size());
- }
-}
-
-LayerRef GetLayerRef(std::vector<Layer>& layers, const char* name) {
- for (uint32_t id = 0; id < layers.size(); id++) {
- if (strcmp(name, layers[id].properties.layerName) == 0) {
- LayerLibrary& library = g_layer_libraries[layers[id].library_idx];
- std::lock_guard<std::mutex> lock(g_library_mutex);
- if (library.refcount++ == 0) {
- library.dlhandle =
- dlopen(library.path.c_str(), RTLD_NOW | RTLD_LOCAL);
- ALOGV("Opening library %s", library.path.c_str());
- if (!library.dlhandle) {
- ALOGE("failed to load layer library '%s': %s",
- library.path.c_str(), dlerror());
- library.refcount = 0;
- return LayerRef(nullptr);
- }
- }
- ALOGV("Refcount on activate is %zu", library.refcount);
- return LayerRef(&layers[id]);
- }
- }
- return LayerRef(nullptr);
+ return library.GetGPA(layer, gpa_name, gpa_name_len);
}
} // anonymous namespace
@@ -347,59 +356,68 @@
DiscoverLayersInDirectory(LoaderData::GetInstance().layer_path.c_str());
}
-uint32_t EnumerateInstanceLayers(uint32_t count,
- VkLayerProperties* properties) {
- return EnumerateLayers(g_instance_layers, count, properties);
+uint32_t GetLayerCount() {
+ return static_cast<uint32_t>(g_instance_layers.size());
}
-uint32_t EnumerateDeviceLayers(uint32_t count, VkLayerProperties* properties) {
- return EnumerateLayers(g_device_layers, count, properties);
+const Layer& GetLayer(uint32_t index) {
+ return g_instance_layers[index];
}
-void GetInstanceLayerExtensions(const char* name,
- const VkExtensionProperties** properties,
- uint32_t* count) {
- GetLayerExtensions(g_instance_layers, name, properties, count);
+const Layer* FindLayer(const char* name) {
+ auto layer =
+ std::find_if(g_instance_layers.cbegin(), g_instance_layers.cend(),
+ [=](const Layer& entry) {
+ return strcmp(entry.properties.layerName, name) == 0;
+ });
+ return (layer != g_instance_layers.cend()) ? &*layer : nullptr;
}
-void GetDeviceLayerExtensions(const char* name,
- const VkExtensionProperties** properties,
- uint32_t* count) {
- GetLayerExtensions(g_device_layers, name, properties, count);
+const VkLayerProperties& GetLayerProperties(const Layer& layer) {
+ return layer.properties;
}
-LayerRef GetInstanceLayerRef(const char* name) {
- return GetLayerRef(g_instance_layers, name);
+bool IsLayerGlobal(const Layer& layer) {
+ return layer.is_global;
}
-LayerRef GetDeviceLayerRef(const char* name) {
- return GetLayerRef(g_device_layers, name);
+const VkExtensionProperties* GetLayerInstanceExtensions(const Layer& layer,
+ uint32_t& count) {
+ count = static_cast<uint32_t>(layer.instance_extensions.size());
+ return layer.instance_extensions.data();
}
-LayerRef::LayerRef(Layer* layer) : layer_(layer) {}
+const VkExtensionProperties* GetLayerDeviceExtensions(const Layer& layer,
+ uint32_t& count) {
+ count = static_cast<uint32_t>(layer.device_extensions.size());
+ return layer.device_extensions.data();
+}
+
+const VkExtensionProperties* FindLayerInstanceExtension(const Layer& layer,
+ const char* name) {
+ return FindExtension(layer.instance_extensions, name);
+}
+
+const VkExtensionProperties* FindLayerDeviceExtension(const Layer& layer,
+ const char* name) {
+ return FindExtension(layer.device_extensions, name);
+}
+
+LayerRef GetLayerRef(const Layer& layer) {
+ LayerLibrary& library = g_layer_libraries[layer.library_idx];
+ return LayerRef((library.Open()) ? &layer : nullptr);
+}
+
+LayerRef::LayerRef(const Layer* layer) : layer_(layer) {}
LayerRef::~LayerRef() {
if (layer_) {
LayerLibrary& library = g_layer_libraries[layer_->library_idx];
- std::lock_guard<std::mutex> lock(g_library_mutex);
- if (--library.refcount == 0) {
- ALOGV("Closing library %s", library.path.c_str());
- dlclose(library.dlhandle);
- library.dlhandle = nullptr;
- }
- ALOGV("Refcount on destruction is %zu", library.refcount);
+ library.Close();
}
}
-const char* LayerRef::GetName() const {
- return layer_->properties.layerName;
-}
-
-uint32_t LayerRef::GetSpecVersion() {
- return layer_->properties.specVersion;
-}
-
-LayerRef::LayerRef(LayerRef&& other) : layer_(std::move(other.layer_)) {
+LayerRef::LayerRef(LayerRef&& other) : layer_(other.layer_) {
other.layer_ = nullptr;
}
@@ -415,12 +433,5 @@
: nullptr;
}
-bool LayerRef::SupportsExtension(const char* name) const {
- return std::find_if(layer_->extensions.cbegin(), layer_->extensions.cend(),
- [=](const VkExtensionProperties& ext) {
- return strcmp(ext.extensionName, name) == 0;
- }) != layer_->extensions.cend();
-}
-
} // namespace api
} // namespace vulkan
diff --git a/vulkan/libvulkan/layers_extensions.h b/vulkan/libvulkan/layers_extensions.h
index 7e7bfd3..79fe59d 100644
--- a/vulkan/libvulkan/layers_extensions.h
+++ b/vulkan/libvulkan/layers_extensions.h
@@ -23,40 +23,44 @@
namespace api {
struct Layer;
+
class LayerRef {
public:
- LayerRef(Layer* layer);
+ LayerRef(const Layer* layer);
LayerRef(LayerRef&& other);
~LayerRef();
LayerRef(const LayerRef&) = delete;
LayerRef& operator=(const LayerRef&) = delete;
- const char* GetName() const;
- uint32_t GetSpecVersion();
-
// provides bool-like behavior
operator const Layer*() const { return layer_; }
PFN_vkGetInstanceProcAddr GetGetInstanceProcAddr() const;
PFN_vkGetDeviceProcAddr GetGetDeviceProcAddr() const;
- bool SupportsExtension(const char* name) const;
-
private:
- Layer* layer_;
+ const Layer* layer_;
};
void DiscoverLayers();
-uint32_t EnumerateInstanceLayers(uint32_t count, VkLayerProperties* properties);
-uint32_t EnumerateDeviceLayers(uint32_t count, VkLayerProperties* properties);
-void GetInstanceLayerExtensions(const char* name,
- const VkExtensionProperties** properties,
- uint32_t* count);
-void GetDeviceLayerExtensions(const char* name,
- const VkExtensionProperties** properties,
- uint32_t* count);
-LayerRef GetInstanceLayerRef(const char* name);
-LayerRef GetDeviceLayerRef(const char* name);
+
+uint32_t GetLayerCount();
+const Layer& GetLayer(uint32_t index);
+const Layer* FindLayer(const char* name);
+
+const VkLayerProperties& GetLayerProperties(const Layer& layer);
+bool IsLayerGlobal(const Layer& layer);
+const VkExtensionProperties* GetLayerInstanceExtensions(const Layer& layer,
+ uint32_t& count);
+const VkExtensionProperties* GetLayerDeviceExtensions(const Layer& layer,
+ uint32_t& count);
+
+const VkExtensionProperties* FindLayerInstanceExtension(const Layer& layer,
+ const char* name);
+const VkExtensionProperties* FindLayerDeviceExtension(const Layer& layer,
+ const char* name);
+
+LayerRef GetLayerRef(const Layer& layer);
} // namespace api
} // namespace vulkan
diff --git a/vulkan/libvulkan/stubhal.cpp b/vulkan/libvulkan/stubhal.cpp
index 89fcebb..a74d370 100644
--- a/vulkan/libvulkan/stubhal.cpp
+++ b/vulkan/libvulkan/stubhal.cpp
@@ -83,7 +83,7 @@
std::lock_guard<std::mutex> lock(g_instance_mutex);
ssize_t idx =
reinterpret_cast<hwvulkan_dispatch_t*>(instance) - &g_instances[0];
- ALOG_ASSERT(idx >= 0 && idx < g_instance_used.size(),
+ ALOG_ASSERT(idx >= 0 && static_cast<size_t>(idx) < g_instance_used.size(),
"DestroyInstance: invalid instance handle");
g_instance_used[static_cast<size_t>(idx)] = false;
}
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index e990cf4..69e8e84 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -329,6 +329,17 @@
int err;
VkResult result = VK_SUCCESS;
+ ALOGV("vkCreateSwapchainKHR: surface=0x%" PRIx64
+ " minImageCount=%u imageFormat=%u imageColorSpace=%u"
+ " imageExtent=%ux%u imageUsage=%#x preTransform=%u presentMode=%u"
+ " oldSwapchain=0x%" PRIx64,
+ reinterpret_cast<uint64_t>(create_info->surface),
+ create_info->minImageCount, create_info->imageFormat,
+ create_info->imageColorSpace, create_info->imageExtent.width,
+ create_info->imageExtent.height, create_info->imageUsage,
+ create_info->preTransform, create_info->presentMode,
+ reinterpret_cast<uint64_t>(create_info->oldSwapchain));
+
if (!allocator)
allocator = &GetData(device).allocator;
@@ -348,9 +359,32 @@
"swapchain present mode %d not supported",
create_info->presentMode);
+ Surface& surface = *SurfaceFromHandle(create_info->surface);
+
+ // -- Reset the native window --
+ // The native window might have been used previously, and had its properties
+ // changed from defaults. That will affect the answer we get for queries
+ // like MIN_UNDEQUED_BUFFERS. Reset to a known/default state before we
+ // attempt such queries.
+
+ err = native_window_set_buffer_count(surface.window.get(), 0);
+ if (err != 0) {
+ ALOGE("native_window_set_buffer_count(0) failed: %s (%d)",
+ strerror(-err), err);
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ err = surface.window->setSwapInterval(surface.window.get(), 1);
+ if (err != 0) {
+ // TODO(jessehall): Improve error reporting. Can we enumerate possible
+ // errors and translate them to valid Vulkan result codes?
+ ALOGE("native_window->setSwapInterval(1) failed: %s (%d)",
+ strerror(-err), err);
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
// -- Configure the native window --
- Surface& surface = *SurfaceFromHandle(create_info->surface);
const auto& dispatch = GetData(device).driver;
int native_format = HAL_PIXEL_FORMAT_RGBA_8888;
@@ -451,8 +485,8 @@
if (err != 0) {
// TODO(jessehall): Improve error reporting. Can we enumerate possible
// errors and translate them to valid Vulkan result codes?
- ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
- err);
+ ALOGE("native_window_set_buffer_count(%d) failed: %s (%d)", num_images,
+ strerror(-err), err);
return VK_ERROR_INITIALIZATION_FAILED;
}
@@ -477,14 +511,14 @@
return VK_ERROR_INITIALIZATION_FAILED;
}
- err = surface.window->setSwapInterval(
- surface.window.get(),
- create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ? 0 : 1);
+ int swap_interval =
+ create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ? 0 : 1;
+ err = surface.window->setSwapInterval(surface.window.get(), swap_interval);
if (err != 0) {
// TODO(jessehall): Improve error reporting. Can we enumerate possible
// errors and translate them to valid Vulkan result codes?
- ALOGE("native_window->setSwapInterval failed: %s (%d)", strerror(-err),
- err);
+ ALOGE("native_window->setSwapInterval(%d) failed: %s (%d)",
+ swap_interval, strerror(-err), err);
return VK_ERROR_INITIALIZATION_FAILED;
}
diff --git a/vulkan/nulldrv/null_driver.cpp b/vulkan/nulldrv/null_driver.cpp
index 6f57238..f29cb68 100644
--- a/vulkan/nulldrv/null_driver.cpp
+++ b/vulkan/nulldrv/null_driver.cpp
@@ -19,6 +19,7 @@
#include <algorithm>
#include <array>
#include <inttypes.h>
+#include <stdlib.h>
#include <string.h>
#include <log/log.h>
@@ -186,6 +187,58 @@
AllocHandle(type, &device->next_handle[type]));
}
+VKAPI_ATTR void* DefaultAllocate(void*,
+ size_t size,
+ size_t alignment,
+ VkSystemAllocationScope) {
+ void* ptr = nullptr;
+ // Vulkan requires 'alignment' to be a power of two, but posix_memalign
+ // additionally requires that it be at least sizeof(void*).
+ int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
+ return ret == 0 ? ptr : nullptr;
+}
+
+VKAPI_ATTR void* DefaultReallocate(void*,
+ void* ptr,
+ size_t size,
+ size_t alignment,
+ VkSystemAllocationScope) {
+ if (size == 0) {
+ free(ptr);
+ return nullptr;
+ }
+
+ // TODO(jessehall): Right now we never shrink allocations; if the new
+ // request is smaller than the existing chunk, we just continue using it.
+ // The null driver never reallocs, so this doesn't matter. If that changes,
+ // or if this code is copied into some other project, this should probably
+ // have a heuristic to allocate-copy-free when doing so will save "enough"
+ // space.
+ size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
+ if (size <= old_size)
+ return ptr;
+
+ void* new_ptr = nullptr;
+ if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0)
+ return nullptr;
+ if (ptr) {
+ memcpy(new_ptr, ptr, std::min(old_size, size));
+ free(ptr);
+ }
+ return new_ptr;
+}
+
+VKAPI_ATTR void DefaultFree(void*, void* ptr) {
+ free(ptr);
+}
+
+const VkAllocationCallbacks kDefaultAllocCallbacks = {
+ .pUserData = nullptr,
+ .pfnAllocation = DefaultAllocate,
+ .pfnReallocation = DefaultReallocate,
+ .pfnFree = DefaultFree,
+};
+
} // namespace
namespace null_driver {
@@ -239,10 +292,8 @@
VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
const VkAllocationCallbacks* allocator,
VkInstance* out_instance) {
- // Assume the loader provided alloc callbacks even if the app didn't.
- ALOG_ASSERT(
- allocator,
- "Missing alloc callbacks, loader or app should have provided them");
+ if (!allocator)
+ allocator = &kDefaultAllocCallbacks;
VkInstance_T* instance =
static_cast<VkInstance_T*>(allocator->pfnAllocation(
diff --git a/vulkan/tools/vkinfo.cpp b/vulkan/tools/vkinfo.cpp
index e97e5f5..62d8240 100644
--- a/vulkan/tools/vkinfo.cpp
+++ b/vulkan/tools/vkinfo.cpp
@@ -162,8 +162,11 @@
uint32_t num_extensions = 0;
for (const auto& desired_ext : kDesiredExtensions) {
bool available = HasExtension(info.extensions, desired_ext);
- for (size_t i = 0; !available && i < info.layer_extensions.size(); i++)
- available = HasExtension(info.layer_extensions[i], desired_ext);
+ if (options.validate) {
+ for (size_t i = 0; !available && i < info.layer_extensions.size();
+ i++)
+ available = HasExtension(info.layer_extensions[i], desired_ext);
+ }
if (available)
extensions[num_extensions++] = desired_ext;
}
@@ -179,12 +182,11 @@
// clang-format off
const char *kValidationLayers[] = {
"VK_LAYER_GOOGLE_threading",
+ "VK_LAYER_LUNARG_parameter_validation",
"VK_LAYER_LUNARG_device_limits",
- "VK_LAYER_LUNARG_draw_state",
- "VK_LAYER_LUNARG_image",
- "VK_LAYER_LUNARG_mem_tracker",
"VK_LAYER_LUNARG_object_tracker",
- "VK_LAYER_LUNARG_param_checker",
+ "VK_LAYER_LUNARG_image",
+ "VK_LAYER_LUNARG_core_validation",
"VK_LAYER_LUNARG_swapchain",
"VK_LAYER_GOOGLE_unique_objects"
};
@@ -236,8 +238,12 @@
uint32_t num_extensions = 0;
for (const auto& desired_ext : kDesiredExtensions) {
bool available = HasExtension(info->extensions, desired_ext);
- for (size_t i = 0; !available && i < info->layer_extensions.size(); i++)
- available = HasExtension(info->layer_extensions[i], desired_ext);
+ if (options.validate) {
+ for (size_t i = 0; !available && i < info->layer_extensions.size();
+ i++)
+ available =
+ HasExtension(info->layer_extensions[i], desired_ext);
+ }
if (available)
extensions[num_extensions++] = desired_ext;
}
@@ -245,12 +251,11 @@
// clang-format off
const char *kValidationLayers[] = {
"VK_LAYER_GOOGLE_threading",
+ "VK_LAYER_LUNARG_parameter_validation",
"VK_LAYER_LUNARG_device_limits",
- "VK_LAYER_LUNARG_draw_state",
- "VK_LAYER_LUNARG_image",
- "VK_LAYER_LUNARG_mem_tracker",
"VK_LAYER_LUNARG_object_tracker",
- "VK_LAYER_LUNARG_param_checker",
+ "VK_LAYER_LUNARG_image",
+ "VK_LAYER_LUNARG_core_validation",
"VK_LAYER_LUNARG_swapchain",
"VK_LAYER_GOOGLE_unique_objects"
};