Merge "Fix camera orientation by swapping horizontal and vertical flips when needed." into lmp-dev
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 0d71bbd..fb40193 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -77,18 +77,24 @@
{ "webview", "WebView", ATRACE_TAG_WEBVIEW, { } },
{ "wm", "Window Manager", ATRACE_TAG_WINDOW_MANAGER, { } },
{ "am", "Activity Manager", ATRACE_TAG_ACTIVITY_MANAGER, { } },
+ { "sync", "Sync Manager", ATRACE_TAG_SYNC_MANAGER, { } },
{ "audio", "Audio", ATRACE_TAG_AUDIO, { } },
{ "video", "Video", ATRACE_TAG_VIDEO, { } },
{ "camera", "Camera", ATRACE_TAG_CAMERA, { } },
{ "hal", "Hardware Modules", ATRACE_TAG_HAL, { } },
+ { "app", "Application", ATRACE_TAG_APP, { } },
{ "res", "Resource Loading", ATRACE_TAG_RESOURCES, { } },
{ "dalvik", "Dalvik VM", ATRACE_TAG_DALVIK, { } },
{ "rs", "RenderScript", ATRACE_TAG_RS, { } },
{ "bionic", "Bionic C Library", ATRACE_TAG_BIONIC, { } },
+ { "power", "Power Management", ATRACE_TAG_POWER, { } },
{ "sched", "CPU Scheduling", 0, {
{ REQ, "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" },
{ REQ, "/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable" },
} },
+ { "irq", "IRQ Events", 0, {
+ { REQ, "/sys/kernel/debug/tracing/events/irq/enable" },
+ } },
{ "freq", "CPU Frequency", 0, {
{ REQ, "/sys/kernel/debug/tracing/events/power/cpu_frequency/enable" },
{ OPT, "/sys/kernel/debug/tracing/events/power/clock_set_rate/enable" },
@@ -123,6 +129,12 @@
{ "workq", "Kernel Workqueues", 0, {
{ REQ, "/sys/kernel/debug/tracing/events/workqueue/enable" },
} },
+ { "memreclaim", "Kernel Memory Reclaim", 0, {
+ { REQ, "/sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_begin/enable" },
+ { REQ, "/sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_end/enable" },
+ { REQ, "/sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_wake/enable" },
+ { REQ, "/sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_sleep/enable" },
+ } },
};
/* Command line options */
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index bd721c8..26edb5f 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -17,6 +17,7 @@
#include <inttypes.h>
#include <sys/capability.h>
#include "installd.h"
+#include <cutils/sched_policy.h>
#include <diskusage/dirsize.h>
#include <selinux/android.h>
@@ -754,7 +755,7 @@
sprintf(dex2oat_Xmx_arg, "-Xmx%s", dex2oat_Xmx_flag);
}
if (skip_compilation) {
- strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=interpret-only");
+ strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-none");
have_dex2oat_compiler_filter_flag = true;
} else if (have_dex2oat_compiler_filter_flag) {
sprintf(dex2oat_compiler_filter_arg, "--compiler-filter=%s", dex2oat_compiler_filter_flag);
@@ -950,6 +951,10 @@
ALOGE("capset failed: %s\n", strerror(errno));
exit(66);
}
+ if (set_sched_policy(0, SP_BACKGROUND) < 0) {
+ ALOGE("set_sched_policy failed: %s\n", strerror(errno));
+ exit(70);
+ }
if (flock(out_fd, LOCK_EX | LOCK_NB) != 0) {
ALOGE("flock(%s) failed: %s\n", out_path, strerror(errno));
exit(67);
diff --git a/include/gui/SensorEventQueue.h b/include/gui/SensorEventQueue.h
index 4e8a2d2..019308d 100644
--- a/include/gui/SensorEventQueue.h
+++ b/include/gui/SensorEventQueue.h
@@ -27,7 +27,7 @@
#include <gui/BitTube.h>
// ----------------------------------------------------------------------------
-#define WAKE_UP_SENSOR_EVENT_NEEDS_ACK (1 << 31)
+#define WAKE_UP_SENSOR_EVENT_NEEDS_ACK (1U << 31)
struct ALooper;
struct ASensorEvent;
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 35ab7f6..f2cf018 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -145,6 +145,7 @@
int dispatchSetUsage(va_list args);
int dispatchLock(va_list args);
int dispatchUnlockAndPost(va_list args);
+ int dispatchSetSidebandStream(va_list args);
protected:
virtual int dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd);
diff --git a/include/input/IInputFlinger.h b/include/input/IInputFlinger.h
deleted file mode 100644
index 79ff12a..0000000
--- a/include/input/IInputFlinger.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2013 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 _LIBINPUT_IINPUT_FLINGER_H
-#define _LIBINPUT_IINPUT_FLINGER_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <binder/IInterface.h>
-
-namespace android {
-
-/*
- * This class defines the Binder IPC interface for accessing various
- * InputFlinger features.
- */
-class IInputFlinger : public IInterface {
-public:
- DECLARE_META_INTERFACE(InputFlinger);
-
- virtual status_t doSomething() = 0;
-};
-
-
-/**
- * Binder implementation.
- */
-class BnInputFlinger : public BnInterface<IInputFlinger> {
-public:
- enum {
- DO_SOMETHING_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
- };
-
- virtual status_t onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags = 0);
-};
-
-} // namespace android
-
-#endif // _LIBINPUT_IINPUT_FLINGER_H
diff --git a/include/media/hardware/HardwareAPI.h b/include/media/hardware/HardwareAPI.h
index 88e7ad3..90150c6 100644
--- a/include/media/hardware/HardwareAPI.h
+++ b/include/media/hardware/HardwareAPI.h
@@ -214,6 +214,27 @@
MediaImage sMediaImage;
};
+// A pointer to this struct is passed to OMX_SetParameter or OMX_GetParameter
+// when the extension index for the
+// 'OMX.google.android.index.configureVideoTunnelMode' extension is given.
+// If the extension is supported then tunneled playback mode should be supported
+// by the codec. If bTunneled is set to OMX_TRUE then the video decoder should
+// operate in "tunneled" mode and output its decoded frames directly to the
+// sink. In this case nAudioHwSync is the HW SYNC ID of the audio HAL Output
+// stream to sync the video with. If bTunneled is set to OMX_FALSE, "tunneled"
+// mode should be disabled and nAudioHwSync should be ignored.
+// OMX_GetParameter is used to query tunneling configuration. bTunneled should
+// return whether decoder is operating in tunneled mode, and if it is,
+// pSidebandWindow should contain the codec allocated sideband window handle.
+struct ConfigureVideoTunnelModeParams {
+ OMX_U32 nSize; // IN
+ OMX_VERSIONTYPE nVersion; // IN
+ OMX_U32 nPortIndex; // IN
+ OMX_BOOL bTunneled; // IN/OUT
+ OMX_U32 nAudioHwSync; // IN
+ OMX_PTR pSidebandWindow; // OUT
+};
+
} // namespace android
extern android::OMXPluginBase *createOMXPlugin();
diff --git a/libs/gui/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp
index bff55d1..cefd7f1 100644
--- a/libs/gui/CpuConsumer.cpp
+++ b/libs/gui/CpuConsumer.cpp
@@ -93,41 +93,62 @@
int buf = b.mBuf;
- if (b.mFence.get()) {
- err = b.mFence->waitForever("CpuConsumer::lockNextBuffer");
- if (err != OK) {
- CC_LOGE("Failed to wait for fence of acquired buffer: %s (%d)",
- strerror(-err), err);
- return err;
- }
- }
-
void *bufferPointer = NULL;
android_ycbcr ycbcr = android_ycbcr();
- if (mSlots[buf].mGraphicBuffer->getPixelFormat() ==
- HAL_PIXEL_FORMAT_YCbCr_420_888) {
- err = mSlots[buf].mGraphicBuffer->lockYCbCr(
- GraphicBuffer::USAGE_SW_READ_OFTEN,
- b.mCrop,
- &ycbcr);
+ if (b.mFence.get()) {
+ if (mSlots[buf].mGraphicBuffer->getPixelFormat() ==
+ HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ err = mSlots[buf].mGraphicBuffer->lockAsyncYCbCr(
+ GraphicBuffer::USAGE_SW_READ_OFTEN,
+ b.mCrop,
+ &ycbcr,
+ b.mFence->dup());
- if (err != OK) {
- CC_LOGE("Unable to lock YCbCr buffer for CPU reading: %s (%d)",
- strerror(-err), err);
- return err;
+ if (err != OK) {
+ CC_LOGE("Unable to lock YCbCr buffer for CPU reading: %s (%d)",
+ strerror(-err), err);
+ return err;
+ }
+ bufferPointer = ycbcr.y;
+ } else {
+ err = mSlots[buf].mGraphicBuffer->lockAsync(
+ GraphicBuffer::USAGE_SW_READ_OFTEN,
+ b.mCrop,
+ &bufferPointer,
+ b.mFence->dup());
+
+ if (err != OK) {
+ CC_LOGE("Unable to lock buffer for CPU reading: %s (%d)",
+ strerror(-err), err);
+ return err;
+ }
}
- bufferPointer = ycbcr.y;
} else {
- err = mSlots[buf].mGraphicBuffer->lock(
- GraphicBuffer::USAGE_SW_READ_OFTEN,
- b.mCrop,
- &bufferPointer);
+ if (mSlots[buf].mGraphicBuffer->getPixelFormat() ==
+ HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ err = mSlots[buf].mGraphicBuffer->lockYCbCr(
+ GraphicBuffer::USAGE_SW_READ_OFTEN,
+ b.mCrop,
+ &ycbcr);
- if (err != OK) {
- CC_LOGE("Unable to lock buffer for CPU reading: %s (%d)",
- strerror(-err), err);
- return err;
+ if (err != OK) {
+ CC_LOGE("Unable to lock YCbCr buffer for CPU reading: %s (%d)",
+ strerror(-err), err);
+ return err;
+ }
+ bufferPointer = ycbcr.y;
+ } else {
+ err = mSlots[buf].mGraphicBuffer->lock(
+ GraphicBuffer::USAGE_SW_READ_OFTEN,
+ b.mCrop,
+ &bufferPointer);
+
+ if (err != OK) {
+ CC_LOGE("Unable to lock buffer for CPU reading: %s (%d)",
+ strerror(-err), err);
+ return err;
+ }
}
}
@@ -189,14 +210,22 @@
status_t CpuConsumer::releaseAcquiredBufferLocked(int lockedIdx) {
status_t err;
+ int fd = -1;
- err = mAcquiredBuffers[lockedIdx].mGraphicBuffer->unlock();
+ err = mAcquiredBuffers[lockedIdx].mGraphicBuffer->unlockAsync(&fd);
if (err != OK) {
CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__,
lockedIdx);
return err;
}
int buf = mAcquiredBuffers[lockedIdx].mSlot;
+ if (CC_LIKELY(fd != -1)) {
+ sp<Fence> fence(new Fence(fd));
+ addReleaseFenceLocked(
+ mAcquiredBuffers[lockedIdx].mSlot,
+ mSlots[buf].mGraphicBuffer,
+ fence);
+ }
// release the buffer if it hasn't already been freed by the BufferQueue.
// This can happen, for example, when the producer of this buffer
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 86451be..b56030e 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -24,6 +24,7 @@
#include <utils/Log.h>
#include <utils/Trace.h>
+#include <utils/NativeHandle.h>
#include <ui/Fence.h>
@@ -443,6 +444,9 @@
case NATIVE_WINDOW_API_DISCONNECT:
res = dispatchDisconnect(args);
break;
+ case NATIVE_WINDOW_SET_SIDEBAND_STREAM:
+ res = dispatchSetSidebandStream(args);
+ break;
default:
res = NAME_NOT_FOUND;
break;
@@ -533,6 +537,12 @@
return unlockAndPost();
}
+int Surface::dispatchSetSidebandStream(va_list args) {
+ native_handle_t* sH = va_arg(args, native_handle_t*);
+ sp<NativeHandle> sidebandHandle = NativeHandle::create(sH, false);
+ setSidebandStream(sidebandHandle);
+ return OK;
+}
int Surface::connect(int api) {
ATRACE_CALL();
diff --git a/libs/input/Android.mk b/libs/input/Android.mk
index 944ac7f..f1921a4 100644
--- a/libs/input/Android.mk
+++ b/libs/input/Android.mk
@@ -27,7 +27,6 @@
deviceSources := \
$(commonSources) \
- IInputFlinger.cpp \
InputTransport.cpp \
VelocityControl.cpp \
VelocityTracker.cpp
diff --git a/libs/input/IInputFlinger.cpp b/libs/input/IInputFlinger.cpp
deleted file mode 100644
index e009731..0000000
--- a/libs/input/IInputFlinger.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2013 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 <stdint.h>
-#include <sys/types.h>
-
-#include <binder/Parcel.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-
-#include <input/IInputFlinger.h>
-
-
-namespace android {
-
-class BpInputFlinger : public BpInterface<IInputFlinger> {
-public:
- BpInputFlinger(const sp<IBinder>& impl) :
- BpInterface<IInputFlinger>(impl) { }
-
- virtual status_t doSomething() {
- Parcel data, reply;
- data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor());
- remote()->transact(BnInputFlinger::DO_SOMETHING_TRANSACTION, data, &reply);
- return reply.readInt32();
- }
-};
-
-IMPLEMENT_META_INTERFACE(InputFlinger, "android.input.IInputFlinger");
-
-
-status_t BnInputFlinger::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
- switch(code) {
- case DO_SOMETHING_TRANSACTION: {
- CHECK_INTERFACE(IInputFlinger, data, reply);
- reply->writeInt32(0);
- break;
- }
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
- return NO_ERROR;
-}
-
-};
diff --git a/services/inputflinger/Android.mk b/services/inputflinger/Android.mk
index 2edc07d..85edbe5 100644
--- a/services/inputflinger/Android.mk
+++ b/services/inputflinger/Android.mk
@@ -22,8 +22,7 @@
InputListener.cpp \
InputManager.cpp \
InputReader.cpp \
- InputWindow.cpp \
- InputFlinger.cpp
+ InputWindow.cpp
LOCAL_SHARED_LIBRARIES := \
libbinder \
@@ -49,19 +48,3 @@
LOCAL_MODULE := libinputflinger
include $(BUILD_SHARED_LIBRARY)
-
-########################################################################
-# build input flinger executable
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- main.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libbinder \
- libinputflinger \
- libutils
-
-LOCAL_MODULE := inputflinger
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/inputflinger/InputFlinger.cpp b/services/inputflinger/InputFlinger.cpp
deleted file mode 100644
index 9ea6ce5..0000000
--- a/services/inputflinger/InputFlinger.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "InputFlinger"
-
-#include "InputFlinger.h"
-
-#include <stdint.h>
-#include <unistd.h>
-
-#include <sys/types.h>
-
-#include <binder/IPCThreadState.h>
-#include <binder/PermissionCache.h>
-#include <cutils/log.h>
-#include <private/android_filesystem_config.h>
-
-namespace android {
-
-const String16 sAccessInputFlingerPermission("android.permission.ACCESS_INPUT_FLINGER");
-const String16 sDumpPermission("android.permission.DUMP");
-
-
-InputFlinger::InputFlinger() :
- BnInputFlinger() {
- ALOGI("InputFlinger is starting");
-}
-
-InputFlinger::~InputFlinger() {
-}
-
-status_t InputFlinger::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
- switch (code) {
- case DO_SOMETHING_TRANSACTION:
- const IPCThreadState* ipc = IPCThreadState::self();
- const int pid = ipc->getCallingPid();
- const int uid = ipc->getCallingUid();
- if (!PermissionCache::checkPermission(sAccessInputFlingerPermission, pid, uid)) {
- ALOGE("Permission Denial: "
- "can't access InputFlinger from pid=%d, uid=%d", pid, uid);
- return PERMISSION_DENIED;
- }
- break;
- }
-
- return BnInputFlinger::onTransact(code, data, reply, flags);
-}
-
-status_t InputFlinger::dump(int fd, const Vector<String16>& args) {
- String8 result;
- const IPCThreadState* ipc = IPCThreadState::self();
- const int pid = ipc->getCallingPid();
- const int uid = ipc->getCallingUid();
- if ((uid != AID_SHELL)
- && !PermissionCache::checkPermission(sDumpPermission, pid, uid)) {
- result.appendFormat("Permission Denial: "
- "can't dump SurfaceFlinger from pid=%d, uid=%d\n", pid, uid);
- } else {
- dumpInternal(result);
- }
- write(fd, result.string(), result.size());
- return OK;
-}
-
-void InputFlinger::dumpInternal(String8& result) {
- result.append("INPUT FLINGER (dumpsys inputflinger)\n");
- result.append("... nothing here yet...\n");
-}
-
-status_t InputFlinger::doSomething() {
- ALOGI("Did something...");
- return OK;
-}
-
-}; // namespace android
diff --git a/services/inputflinger/InputFlinger.h b/services/inputflinger/InputFlinger.h
deleted file mode 100644
index 731ab17..0000000
--- a/services/inputflinger/InputFlinger.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2013 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_INPUT_FLINGER_H
-#define ANDROID_INPUT_FLINGER_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <cutils/compiler.h>
-#include <input/IInputFlinger.h>
-#include <utils/String8.h>
-#include <utils/String16.h>
-
-namespace android {
-
-class InputFlinger : public BnInputFlinger {
-public:
- static char const* getServiceName() ANDROID_API {
- return "inputflinger";
- }
-
- InputFlinger() ANDROID_API;
-
- // IBinder interface
- virtual status_t onTransact(uint32_t code,
- const Parcel& data, Parcel* reply, uint32_t flags);
- virtual status_t dump(int fd, const Vector<String16>& args);
-
- // IInputFlinger interface
- virtual status_t doSomething();
-
-private:
- virtual ~InputFlinger();
-
- void dumpInternal(String8& result);
-};
-
-} // namespace android
-
-#endif // ANDROID_INPUT_FLINGER_H
diff --git a/services/inputflinger/main.cpp b/services/inputflinger/main.cpp
deleted file mode 100644
index 0a517cc..0000000
--- a/services/inputflinger/main.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2013 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 <binder/BinderService.h>
-#include "InputFlinger.h"
-
-using namespace android;
-
-int main(int, char**) {
- ProcessState::self()->setThreadPoolMaxThreadCount(4);
- BinderService<InputFlinger>::publishAndJoinThreadPool(true);
- return 0;
-}
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 3934509..80845a2 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -54,6 +54,11 @@
SENSORS_HARDWARE_MODULE_ID, strerror(-err));
if (mSensorDevice) {
+ if (mSensorDevice->common.version == SENSORS_DEVICE_API_VERSION_1_1 ||
+ mSensorDevice->common.version == SENSORS_DEVICE_API_VERSION_1_2) {
+ ALOGE(">>>> WARNING <<< Upgrade sensor HAL to version 1_3");
+ }
+
sensor_t const* list;
ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
mActivationCount.setCapacity(count);
@@ -74,6 +79,7 @@
sensor_t const* list;
ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
+ result.appendFormat("halVersion %d\n", getHalDeviceVersion());
result.appendFormat("%d h/w sensors:\n", int(count));
Mutex::Autolock _l(mLock);
@@ -210,24 +216,8 @@
}
const int halVersion = getHalDeviceVersion();
- if (halVersion >= SENSORS_DEVICE_API_VERSION_1_1) {
- if (flags & SENSORS_BATCH_DRY_RUN) {
- return mSensorDevice->batch(mSensorDevice, handle, flags, samplingPeriodNs,
- maxBatchReportLatencyNs);
- } else {
- // Call h/w with dry run to see if the given parameters are feasible or not. Return if
- // there is an error.
- status_t errDryRun(NO_ERROR);
- errDryRun = mSensorDevice->batch(mSensorDevice, handle, flags | SENSORS_BATCH_DRY_RUN,
- samplingPeriodNs, maxBatchReportLatencyNs);
- if (errDryRun != NO_ERROR) {
- ALOGD_IF(DEBUG_CONNECTIONS, "SensorDevice::batch dry run error %s",
- strerror(-errDryRun));
- return errDryRun;
- }
- }
- } else if (maxBatchReportLatencyNs != 0) {
- // Batch is not supported on older devices.
+ if (halVersion < SENSORS_DEVICE_API_VERSION_1_1 && maxBatchReportLatencyNs != 0) {
+ // Batch is not supported on older devices return invalid operation.
return INVALID_OPERATION;
}
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 8fe79d0..bee5062 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -218,69 +218,85 @@
const Sensor& s(mSensorList[i]);
const sensors_event_t& e(mLastEventSeen.valueFor(s.getHandle()));
result.appendFormat(
- "%-48s| %-32s| %-48s| 0x%08x | \"%s\"\n\t",
+ "%-15s| %-10s| %-20s| 0x%08x | \"%s\" | type=%d |",
s.getName().string(),
s.getVendor().string(),
s.getStringType().string(),
s.getHandle(),
- s.getRequiredPermission().string());
+ s.getRequiredPermission().string(),
+ s.getType());
const int reportingMode = s.getReportingMode();
if (reportingMode == AREPORTING_MODE_CONTINUOUS) {
- result.append("continuous |");
+ result.append(" continuous | ");
} else if (reportingMode == AREPORTING_MODE_ON_CHANGE) {
- result.append("on-change | ");
+ result.append(" on-change | ");
} else if (reportingMode == AREPORTING_MODE_ONE_SHOT) {
- result.append("one-shot | ");
+ result.append(" one-shot | ");
} else {
- result.append("special-trigger | ");
+ result.append(" special-trigger | ");
+ }
+
+ if (s.getMaxDelay() > 0) {
+ result.appendFormat("minRate=%.2fHz | ", 1e6f / s.getMaxDelay());
+ } else {
+ result.appendFormat("maxDelay=%dus |", s.getMaxDelay());
}
if (s.getMinDelay() > 0) {
- result.appendFormat("maxRate=%7.2fHz | ", 1e6f / s.getMinDelay());
+ result.appendFormat("maxRate=%.2fHz | ", 1e6f / s.getMinDelay());
} else {
- result.appendFormat("minDelay=%5dus |", s.getMinDelay());
+ result.appendFormat("minDelay=%dus |", s.getMinDelay());
}
if (s.getFifoMaxEventCount() > 0) {
result.appendFormat("FifoMax=%d events | ",
s.getFifoMaxEventCount());
} else {
- result.append("no batching support | ");
+ result.append("no batching | ");
+ }
+
+ if (s.isWakeUpSensor()) {
+ result.appendFormat("wakeUp | ");
+ } else {
+ result.appendFormat("non-wakeUp | ");
}
switch (s.getType()) {
case SENSOR_TYPE_ROTATION_VECTOR:
case SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR:
result.appendFormat(
- "last=<%5.1f,%5.1f,%5.1f,%5.1f,%5.1f>\n",
- e.data[0], e.data[1], e.data[2], e.data[3], e.data[4]);
+ "last=<%5.1f,%5.1f,%5.1f,%5.1f,%5.1f, %" PRId64 ">\n",
+ e.data[0], e.data[1], e.data[2], e.data[3], e.data[4], e.timestamp);
break;
case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
result.appendFormat(
- "last=<%5.1f,%5.1f,%5.1f,%5.1f,%5.1f,%5.1f>\n",
- e.data[0], e.data[1], e.data[2], e.data[3], e.data[4], e.data[5]);
+ "last=<%5.1f,%5.1f,%5.1f,%5.1f,%5.1f,%5.1f, %" PRId64 ">\n",
+ e.data[0], e.data[1], e.data[2], e.data[3], e.data[4], e.data[5],
+ e.timestamp);
break;
case SENSOR_TYPE_GAME_ROTATION_VECTOR:
result.appendFormat(
- "last=<%5.1f,%5.1f,%5.1f,%5.1f>\n",
- e.data[0], e.data[1], e.data[2], e.data[3]);
+ "last=<%5.1f,%5.1f,%5.1f,%5.1f, %" PRId64 ">\n",
+ e.data[0], e.data[1], e.data[2], e.data[3], e.timestamp);
break;
case SENSOR_TYPE_SIGNIFICANT_MOTION:
case SENSOR_TYPE_STEP_DETECTOR:
- result.appendFormat( "last=<%f>\n", e.data[0]);
+ result.appendFormat( "last=<%f %" PRId64 ">\n", e.data[0], e.timestamp);
break;
case SENSOR_TYPE_STEP_COUNTER:
- result.appendFormat( "last=<%" PRIu64 ">\n", e.u64.step_counter);
+ result.appendFormat( "last=<%" PRIu64 ", %" PRId64 ">\n", e.u64.step_counter,
+ e.timestamp);
break;
default:
// default to 3 values
result.appendFormat(
- "last=<%5.1f,%5.1f,%5.1f>\n",
- e.data[0], e.data[1], e.data[2]);
+ "last=<%5.1f,%5.1f,%5.1f, %" PRId64 ">\n",
+ e.data[0], e.data[1], e.data[2], e.timestamp);
break;
}
+ result.append("\n");
}
SensorFusion::getInstance().dump(result);
SensorDevice::getInstance().dump(result);
@@ -294,7 +310,8 @@
mActiveSensors.valueAt(i)->getNumConnections());
}
- result.appendFormat("%zu Max Socket Buffer size\n", mSocketBufferSize);
+ result.appendFormat("Max Socket Buffer size = %d events\n",
+ mSocketBufferSize/sizeof(sensors_event_t));
result.appendFormat("WakeLock Status: %s \n", mWakeLockAcquired ? "acquired" : "not held");
result.appendFormat("%zd active connections\n", mActiveConnections.size());
@@ -520,6 +537,11 @@
return sensor != NULL && sensor->getSensor().isWakeUpSensor();
}
+
+SensorService::SensorRecord * SensorService::getSensorRecord(int handle) {
+ return mActiveSensors.valueFor(handle);
+}
+
Vector<Sensor> SensorService::getSensorList()
{
char value[PROPERTY_VALUE_MAX];
@@ -658,18 +680,20 @@
samplingPeriodNs = minDelayNs;
}
- ALOGD_IF(DEBUG_CONNECTIONS, "Calling batch handle==%d flags=%d rate=%" PRId64 " timeout== %" PRId64,
+ ALOGD_IF(DEBUG_CONNECTIONS, "Calling batch handle==%d flags=%d"
+ "rate=%" PRId64 " timeout== %" PRId64"",
handle, reservedFlags, samplingPeriodNs, maxBatchReportLatencyNs);
status_t err = sensor->batch(connection.get(), handle, reservedFlags, samplingPeriodNs,
maxBatchReportLatencyNs);
- if (err == NO_ERROR) {
- connection->setFirstFlushPending(handle, true);
+
+ if (err == NO_ERROR && sensor->getSensor().getReportingMode() != AREPORTING_MODE_ONE_SHOT) {
status_t err_flush = sensor->flush(connection.get(), handle);
// Flush may return error if the sensor is not activated or the underlying h/w sensor does
// not support flush.
- if (err_flush != NO_ERROR) {
- connection->setFirstFlushPending(handle, false);
+ if (err_flush == NO_ERROR) {
+ connection->setFirstFlushPending(handle, true);
+ rec->addPendingFlushConnection(connection.get());
}
}
@@ -775,7 +799,13 @@
ALOGE("flush called on a one-shot sensor");
return INVALID_OPERATION;
}
- return sensor->flush(connection.get(), handle);
+
+ status_t ret = sensor->flush(connection.get(), handle);
+ if (ret == NO_ERROR) {
+ SensorRecord* rec = mActiveSensors.valueFor(handle);
+ if (rec != NULL) rec->addPendingFlushConnection(connection);
+ }
+ return ret;
}
@@ -823,6 +853,7 @@
mWakeLockAcquired = false;
}
}
+
// ---------------------------------------------------------------------------
SensorService::SensorRecord::SensorRecord(
const sp<SensorEventConnection>& connection)
@@ -847,9 +878,37 @@
if (index >= 0) {
mConnections.removeItemsAt(index, 1);
}
+ // Remove this connections from the queue of flush() calls made on this sensor.
+ for (Vector< wp<SensorEventConnection> >::iterator it =
+ mPendingFlushConnections.begin(); it != mPendingFlushConnections.end();) {
+ if (it->unsafe_get() == connection.unsafe_get()) {
+ it = mPendingFlushConnections.erase(it);
+ } else {
+ ++it;
+ }
+ }
return mConnections.size() ? false : true;
}
+void SensorService::SensorRecord::addPendingFlushConnection(
+ const sp<SensorEventConnection>& connection) {
+ mPendingFlushConnections.add(connection);
+}
+
+void SensorService::SensorRecord::removeFirstPendingFlushConnection() {
+ if (mPendingFlushConnections.size() > 0) {
+ mPendingFlushConnections.removeAt(0);
+ }
+}
+
+SensorService::SensorEventConnection *
+SensorService::SensorRecord::getFirstPendingFlushConnection() {
+ if (mPendingFlushConnections.size() > 0) {
+ return mPendingFlushConnections[0].unsafe_get();
+ }
+ return NULL;
+}
+
// ---------------------------------------------------------------------------
SensorService::SensorEventConnection::SensorEventConnection(
@@ -890,13 +949,13 @@
result.appendFormat("\t %d WakeLockRefCount \n", mWakeLockRefCount);
for (size_t i = 0; i < mSensorInfo.size(); ++i) {
const FlushInfo& flushInfo = mSensorInfo.valueAt(i);
- result.appendFormat("\t %s | status: %s | pending flush events %d | flush calls %d| uid %d|"
+ result.appendFormat("\t %s 0x%08x | status: %s | pending flush events %d | uid %d|"
"cache size: %d max cache size %d\n",
mService->getSensorName(mSensorInfo.keyAt(i)).string(),
+ mSensorInfo.keyAt(i),
flushInfo.mFirstFlushPending ? "First flush pending" :
"active",
flushInfo.mPendingFlushEventsToSend,
- flushInfo.mNumFlushCalls,
mUid,
mCacheSize,
mMaxCacheSize);
@@ -905,7 +964,7 @@
mEventsReceived,
mEventsSent,
mEventsSentFromCache,
- mEventsReceived - (mEventsSentFromCache +
+ mEventsReceived - (mEventsSentFromCache
mEventsSent + mCacheSize));
#endif
@@ -961,15 +1020,15 @@
if (scratch) {
size_t i=0;
while (i<numEvents) {
- int32_t curr = buffer[i].sensor;
+ int32_t sensor_handle = buffer[i].sensor;
if (buffer[i].type == SENSOR_TYPE_META_DATA) {
ALOGD_IF(DEBUG_CONNECTIONS, "flush complete event sensor==%d ",
buffer[i].meta_data.sensor);
- // Setting curr to the correct sensor to ensure the sensor events per connection are
+ // Setting sensor_handle to the correct sensor to ensure the sensor events per connection are
// filtered correctly. buffer[i].sensor is zero for meta_data events.
- curr = buffer[i].meta_data.sensor;
+ sensor_handle = buffer[i].meta_data.sensor;
}
- ssize_t index = mSensorInfo.indexOfKey(curr);
+ ssize_t index = mSensorInfo.indexOfKey(sensor_handle);
// Check if this connection has registered for this sensor. If not continue to the
// next sensor_event.
if (index < 0) {
@@ -977,16 +1036,16 @@
continue;
}
- // Check if there is a pending flush_complete event for this sensor on this connection.
FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
- if (buffer[i].type == SENSOR_TYPE_META_DATA) {
- if (flushInfo.mFirstFlushPending == true) {
- // This is the first flush before activate is called. Events can now be sent for
- // this sensor on this connection.
- ALOGD_IF(DEBUG_CONNECTIONS, "First flush event for sensor==%d ",
- buffer[i].meta_data.sensor);
+ // Check if there is a pending flush_complete event for this sensor on this connection.
+ if (buffer[i].type == SENSOR_TYPE_META_DATA && flushInfo.mFirstFlushPending == true) {
+ SensorService::SensorRecord *rec = mService->getSensorRecord(sensor_handle);
+ if (rec && rec->getFirstPendingFlushConnection() == this) {
+ rec->removeFirstPendingFlushConnection();
flushInfo.mFirstFlushPending = false;
++i;
+ ALOGD_IF(DEBUG_CONNECTIONS, "First flush event for sensor==%d ",
+ buffer[i].meta_data.sensor);
continue;
}
}
@@ -1000,26 +1059,28 @@
do {
if (buffer[i].type == SENSOR_TYPE_META_DATA) {
- // Send flush complete event only if flush() has been explicitly called by
- // this app else ignore.
- if (flushInfo.mNumFlushCalls > 0) {
+ // Check if this connection has called flush() on this sensor. Only if
+ // a flush() has been explicitly called, send a flush_complete_event.
+ SensorService::SensorRecord *rec = mService->getSensorRecord(sensor_handle);
+ if (rec && rec->getFirstPendingFlushConnection() == this) {
+ rec->removeFirstPendingFlushConnection();
scratch[count++] = buffer[i];
- flushInfo.mNumFlushCalls--;
}
++i;
} else {
// Regular sensor event, just copy it to the scratch buffer.
scratch[count++] = buffer[i++];
}
- } while ((i<numEvents) && ((buffer[i].sensor == curr) ||
+ } while ((i<numEvents) && ((buffer[i].sensor == sensor_handle) ||
(buffer[i].type == SENSOR_TYPE_META_DATA &&
- buffer[i].meta_data.sensor == curr)));
+ buffer[i].meta_data.sensor == sensor_handle)));
}
} else {
scratch = const_cast<sensors_event_t *>(buffer);
count = numEvents;
}
+ sendPendingFlushEventsLocked();
// Early return if there are no events for this connection.
if (count == 0) {
return status_t(NO_ERROR);
@@ -1035,6 +1096,12 @@
memcpy(&mEventCache[mCacheSize], scratch, count * sizeof(sensors_event_t));
mCacheSize += count;
} else {
+ // Check if any new sensors have registered on this connection which may have increased
+ // the max cache size that is desired.
+ if (mCacheSize + count < computeMaxCacheSizeLocked()) {
+ reAllocateCacheLocked(scratch, count);
+ return status_t(NO_ERROR);
+ }
// Some events need to be dropped.
int remaningCacheSize = mMaxCacheSize - mCacheSize;
if (remaningCacheSize != 0) {
@@ -1054,15 +1121,22 @@
return status_t(NO_ERROR);
}
- int numWakeUpSensorEvents = countWakeUpSensorEventsLocked(scratch, count);
- mWakeLockRefCount += numWakeUpSensorEvents;
+ int index_wake_up_event = findWakeUpSensorEventLocked(scratch, count);
+ if (index_wake_up_event >= 0) {
+ scratch[index_wake_up_event].flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
+ ++mWakeLockRefCount;
+ }
// NOTE: ASensorEvent and sensors_event_t are the same type.
ssize_t size = SensorEventQueue::write(mChannel,
reinterpret_cast<ASensorEvent const*>(scratch), count);
if (size < 0) {
// Write error, copy events to local cache.
- mWakeLockRefCount -= numWakeUpSensorEvents;
+ if (index_wake_up_event >= 0) {
+ // If there was a wake_up sensor_event, reset the flag.
+ scratch[index_wake_up_event].flags &= ~WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
+ --mWakeLockRefCount;
+ }
if (mEventCache == NULL) {
mMaxCacheSize = computeMaxCacheSizeLocked();
mEventCache = new sensors_event_t[mMaxCacheSize];
@@ -1087,53 +1161,81 @@
return size < 0 ? status_t(size) : status_t(NO_ERROR);
}
+void SensorService::SensorEventConnection::reAllocateCacheLocked(sensors_event_t const* scratch,
+ int count) {
+ sensors_event_t *eventCache_new;
+ const int new_cache_size = computeMaxCacheSizeLocked();
+ // Allocate new cache, copy over events from the old cache & scratch, free up memory.
+ eventCache_new = new sensors_event_t[new_cache_size];
+ memcpy(eventCache_new, mEventCache, mCacheSize * sizeof(sensors_event_t));
+ memcpy(&eventCache_new[mCacheSize], scratch, count * sizeof(sensors_event_t));
+
+ ALOGD_IF(DEBUG_CONNECTIONS, "reAllocateCacheLocked maxCacheSize=%d %d", mMaxCacheSize,
+ new_cache_size);
+
+ delete mEventCache;
+ mEventCache = eventCache_new;
+ mCacheSize += count;
+ mMaxCacheSize = new_cache_size;
+}
+
+void SensorService::SensorEventConnection::sendPendingFlushEventsLocked() {
+ ASensorEvent flushCompleteEvent;
+ flushCompleteEvent.type = SENSOR_TYPE_META_DATA;
+ flushCompleteEvent.sensor = 0;
+ // Loop through all the sensors for this connection and check if there are any pending
+ // flush complete events to be sent.
+ for (size_t i = 0; i < mSensorInfo.size(); ++i) {
+ FlushInfo& flushInfo = mSensorInfo.editValueAt(i);
+ while (flushInfo.mPendingFlushEventsToSend > 0) {
+ flushCompleteEvent.meta_data.sensor = mSensorInfo.keyAt(i);
+ ssize_t size = SensorEventQueue::write(mChannel, &flushCompleteEvent, 1);
+ if (size < 0) {
+ return;
+ }
+ ALOGD_IF(DEBUG_CONNECTIONS, "sent dropped flush complete event==%d ",
+ flushCompleteEvent.meta_data.sensor);
+ flushInfo.mPendingFlushEventsToSend--;
+ }
+ }
+}
+
void SensorService::SensorEventConnection::writeToSocketFromCacheLocked() {
// At a time write at most half the size of the receiver buffer in SensorEventQueue.
const int maxWriteSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT/2;
- // Send pending flush events (if any) before sending events from the buffer.
- {
- ASensorEvent flushCompleteEvent;
- flushCompleteEvent.type = SENSOR_TYPE_META_DATA;
- flushCompleteEvent.sensor = 0;
- // Loop through all the sensors for this connection and check if there are any pending
- // flush complete events to be sent.
- for (size_t i = 0; i < mSensorInfo.size(); ++i) {
- FlushInfo& flushInfo = mSensorInfo.editValueAt(i);
- while (flushInfo.mPendingFlushEventsToSend > 0) {
- flushCompleteEvent.meta_data.sensor = mSensorInfo.keyAt(i);
- ssize_t size = SensorEventQueue::write(mChannel, &flushCompleteEvent, 1);
- if (size < 0) {
- return;
- }
- ALOGD_IF(DEBUG_CONNECTIONS, "sent dropped flush complete event==%d ",
- flushCompleteEvent.meta_data.sensor);
- flushInfo.mPendingFlushEventsToSend--;
- }
- }
- }
+ sendPendingFlushEventsLocked();
// Write "count" events at a time.
for (int numEventsSent = 0; numEventsSent < mCacheSize;) {
- const int count = (mCacheSize - numEventsSent) < maxWriteSize ?
+ const int numEventsToWrite = (mCacheSize - numEventsSent) < maxWriteSize ?
mCacheSize - numEventsSent : maxWriteSize;
- int numWakeUpSensorEvents =
- countWakeUpSensorEventsLocked(mEventCache + numEventsSent, count);
- mWakeLockRefCount += numWakeUpSensorEvents;
+ int index_wake_up_event =
+ findWakeUpSensorEventLocked(mEventCache + numEventsSent, numEventsToWrite);
+ if (index_wake_up_event >= 0) {
+ mEventCache[index_wake_up_event + numEventsSent].flags |=
+ WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
+ ++mWakeLockRefCount;
+ }
ssize_t size = SensorEventQueue::write(mChannel,
reinterpret_cast<ASensorEvent const*>(mEventCache + numEventsSent),
- count);
+ numEventsToWrite);
if (size < 0) {
+ if (index_wake_up_event >= 0) {
+ // If there was a wake_up sensor_event, reset the flag.
+ mEventCache[index_wake_up_event + numEventsSent].flags &=
+ ~WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
+ --mWakeLockRefCount;
+ }
memmove(mEventCache, &mEventCache[numEventsSent],
(mCacheSize - numEventsSent) * sizeof(sensors_event_t));
ALOGD_IF(DEBUG_CONNECTIONS, "wrote %d events from cache size==%d ",
- numEventsSent, mCacheSize);
+ numEventsSent, mCacheSize);
mCacheSize -= numEventsSent;
- mWakeLockRefCount -= numWakeUpSensorEvents;
return;
}
- numEventsSent += count;
+ numEventsSent += numEventsToWrite;
#if DEBUG_CONNECTIONS
- mEventsSentFromCache += count;
+ mEventsSentFromCache += numEventsToWrite;
#endif
}
ALOGD_IF(DEBUG_CONNECTIONS, "wrote all events from cache size=%d ", mCacheSize);
@@ -1159,15 +1261,14 @@
return;
}
-int SensorService::SensorEventConnection::countWakeUpSensorEventsLocked(
- sensors_event_t* scratch, const int count) {
+int SensorService::SensorEventConnection::findWakeUpSensorEventLocked(
+ sensors_event_t const* scratch, const int count) {
for (int i = 0; i < count; ++i) {
if (mService->isWakeUpSensorEvent(scratch[i])) {
- scratch[i].flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
- return 1;
+ return i;
}
}
- return 0;
+ return -1;
}
sp<BitTube> SensorService::SensorEventConnection::getSensorChannel() const
@@ -1211,9 +1312,7 @@
flushInfo.mPendingFlushEventsToSend++;
} else {
status_t err_flush = mService->flushSensor(this, handle);
- if (err_flush == NO_ERROR) {
- flushInfo.mNumFlushCalls++;
- } else {
+ if (err_flush != NO_ERROR) {
ALOGE("Flush error handle=%d %s", handle, strerror(-err_flush));
}
err = (err_flush != NO_ERROR) ? err_flush : err;
@@ -1280,9 +1379,9 @@
}
if (fifoWakeUpSensors + fifoNonWakeUpSensors == 0) {
// It is extremely unlikely that there is a write failure in non batch mode. Return a cache
- // size of 100.
+ // size that is equal to that of the batch mode.
ALOGI("Write failure in non-batch mode");
- return 100;
+ return MAX_SOCKET_BUFFER_SIZE_BATCHED/sizeof(sensors_event_t);
}
return fifoWakeUpSensors + fifoNonWakeUpSensors;
}
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 3cdc825..15759ae 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -44,7 +44,6 @@
#define MAX_SOCKET_BUFFER_SIZE_BATCHED 100 * 1024
// For older HALs which don't support batching, use a smaller socket buffer size.
#define SOCKET_BUFFER_SIZE_NON_BATCHED 4 * 1024
-#define WAKE_UP_SENSOR_EVENT_NEEDS_ACK (1U << 31)
struct sensors_poll_device_t;
struct sensors_module_t;
@@ -89,11 +88,17 @@
// sent separately before the next batch of events.
void countFlushCompleteEventsLocked(sensors_event_t* scratch, int numEventsDropped);
- // Check if there are any wake up events in the buffer. If yes, increment the ref count.
- // Increment it by exactly one unit for each packet sent on the socket. SOCK_SEQPACKET for
- // the socket ensures that either the entire packet is read or dropped.
- // Return 1 if mWakeLockRefCount has been incremented, zero if not.
- int countWakeUpSensorEventsLocked(sensors_event_t* scratch, int count);
+ // Check if there are any wake up events in the buffer. If yes, return the index of the
+ // first wake_up sensor event in the buffer else return -1. This wake_up sensor event will
+ // have the flag WAKE_UP_SENSOR_EVENT_NEEDS_ACK set. Exactly one event per packet will have
+ // the wake_up flag set. SOCK_SEQPACKET ensures that either the entire packet is read or
+ // dropped.
+ int findWakeUpSensorEventLocked(sensors_event_t const* scratch, int count);
+
+ // Send pending flush_complete events. There may have been flush_complete_events that are
+ // dropped which need to be sent separately before other events. On older HALs (1_0) this
+ // method emulates the behavior of flush().
+ void sendPendingFlushEventsLocked();
// Writes events from mEventCache to the socket.
void writeToSocketFromCacheLocked();
@@ -103,6 +108,10 @@
// shared amongst wake-up sensors and non-wake up sensors.
int computeMaxCacheSizeLocked() const;
+ // When more sensors register, the maximum cache size desired may change. Compute max cache
+ // size, reallocate memory and copy over events from the older cache.
+ void reAllocateCacheLocked(sensors_event_t const* scratch, int count);
+
// LooperCallback method. If there is data to read on this fd, it is an ack from the
// app that it has read events from a wake up sensor, decrement mWakeLockRefCount.
// If this fd is available for writing send the data from the cache.
@@ -124,11 +133,7 @@
// Every activate is preceded by a flush. Only after the first flush complete is
// received, the events for the sensor are sent on that *connection*.
bool mFirstFlushPending;
- // Number of time flush() was called on this connection. This is incremented every time
- // flush() is called and decremented when flush_complete_event is received.
- int mNumFlushCalls;
- FlushInfo() : mPendingFlushEventsToSend(0), mFirstFlushPending(false),
- mNumFlushCalls(0) {}
+ FlushInfo() : mPendingFlushEventsToSend(0), mFirstFlushPending(false) {}
};
// protected by SensorService::mLock. Key for this vector is the sensor handle.
KeyedVector<int, FlushInfo> mSensorInfo;
@@ -157,11 +162,18 @@
class SensorRecord {
SortedVector< wp<SensorEventConnection> > mConnections;
+ // A queue of all flush() calls made on this sensor. Flush complete events will be
+ // sent in this order.
+ Vector< wp<SensorEventConnection> > mPendingFlushConnections;
public:
SensorRecord(const sp<SensorEventConnection>& connection);
bool addConnection(const sp<SensorEventConnection>& connection);
bool removeConnection(const wp<SensorEventConnection>& connection);
size_t getNumConnections() const { return mConnections.size(); }
+
+ void addPendingFlushConnection(const sp<SensorEventConnection>& connection);
+ void removeFirstPendingFlushConnection();
+ SensorEventConnection * getFirstPendingFlushConnection();
};
class SensorEventAckReceiver : public Thread {
@@ -194,6 +206,8 @@
void checkWakeLockStateLocked();
bool isWakeUpSensorEvent(const sensors_event_t& event) const;
+ SensorRecord * getSensorRecord(int handle);
+
sp<Looper> getLooper() const;
// constants
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index bbe2aa1..b9c70e0 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3111,6 +3111,7 @@
*/
result = native_window_dequeue_buffer_and_wait(window, &buffer);
if (result == NO_ERROR) {
+ int syncFd = -1;
// create an EGLImage from the buffer so we can later
// turn it into a texture
EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT,
@@ -3127,27 +3128,41 @@
renderScreenImplLocked(hw, sourceCrop, reqWidth, reqHeight,
minLayerZ, maxLayerZ, true, useIdentityTransform);
- // Create a sync point and wait on it, so we know the buffer is
- // ready before we pass it along. We can't trivially call glFlush(),
- // so we use a wait flag instead.
- // TODO: pass a sync fd to queueBuffer() and let the consumer wait.
- EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, NULL);
- if (sync != EGL_NO_SYNC_KHR) {
- EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync,
- EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 2000000000 /*2 sec*/);
- EGLint eglErr = eglGetError();
- eglDestroySyncKHR(mEGLDisplay, sync);
- if (result == EGL_TIMEOUT_EXPIRED_KHR) {
- ALOGW("captureScreen: fence wait timed out");
- } else {
- ALOGW_IF(eglErr != EGL_SUCCESS,
- "captureScreen: error waiting on EGL fence: %#x", eglErr);
- }
+ // Attempt to create a sync khr object that can produce a sync point. If that
+ // isn't available, create a non-dupable sync object in the fallback path and
+ // wait on it directly.
+ EGLSyncKHR sync;
+ if (!DEBUG_SCREENSHOTS) {
+ sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
} else {
- ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError());
- // not fatal
+ sync = EGL_NO_SYNC_KHR;
}
-
+ if (sync != EGL_NO_SYNC_KHR) {
+ // get the sync fd
+ syncFd = eglDupNativeFenceFDANDROID(mEGLDisplay, sync);
+ if (syncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+ ALOGW("captureScreen: failed to dup sync khr object");
+ syncFd = -1;
+ }
+ eglDestroySyncKHR(mEGLDisplay, sync);
+ } else {
+ // fallback path
+ sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, NULL);
+ if (sync != EGL_NO_SYNC_KHR) {
+ EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync,
+ EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 2000000000 /*2 sec*/);
+ EGLint eglErr = eglGetError();
+ if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+ ALOGW("captureScreen: fence wait timed out");
+ } else {
+ ALOGW_IF(eglErr != EGL_SUCCESS,
+ "captureScreen: error waiting on EGL fence: %#x", eglErr);
+ }
+ eglDestroySyncKHR(mEGLDisplay, sync);
+ } else {
+ ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError());
+ }
+ }
if (DEBUG_SCREENSHOTS) {
uint32_t* pixels = new uint32_t[reqWidth*reqHeight];
getRenderEngine().readPixels(0, 0, reqWidth, reqHeight, pixels);
@@ -3165,7 +3180,10 @@
} else {
result = BAD_VALUE;
}
- window->queueBuffer(window, buffer, -1);
+ window->queueBuffer(window, buffer, syncFd);
+ if (syncFd != -1) {
+ close(syncFd);
+ }
}
} else {
result = BAD_VALUE;