Merge "More native input dispatch work." into gingerbread
diff --git a/include/ui/InputTransport.h b/include/ui/InputTransport.h
index 2dfe2a8..11714d5 100644
--- a/include/ui/InputTransport.h
+++ b/include/ui/InputTransport.h
@@ -33,6 +33,7 @@
#include <semaphore.h>
#include <ui/Input.h>
#include <utils/Errors.h>
+#include <utils/PollLoop.h>
#include <utils/Timers.h>
#include <utils/RefBase.h>
#include <utils/String8.h>
@@ -345,11 +346,15 @@
android::status_t consume(android::InputEvent** event);
+ void setPollLoop(const android::sp<android::PollLoop>& pollLoop) { mPollLoop = pollLoop; }
+ const android::sp<android::PollLoop> getPollLoop() const { return mPollLoop; }
+
virtual void doDefaultKey(android::KeyEvent* keyEvent) = 0;
private:
android::InputConsumer mConsumer;
android::PreallocatedInputEventFactory mInputEventFactory;
+ android::sp<android::PollLoop> mPollLoop;
};
#endif // _UI_INPUT_TRANSPORT_H
diff --git a/include/utils/PollLoop.h b/include/utils/PollLoop.h
index a95fb17..b3651ca 100644
--- a/include/utils/PollLoop.h
+++ b/include/utils/PollLoop.h
@@ -22,12 +22,22 @@
#include <sys/poll.h>
+#include <android/looper.h>
+
+struct ALooper : public android::RefBase {
+protected:
+ virtual ~ALooper() { }
+
+public:
+ ALooper() { }
+};
+
namespace android {
/**
* A basic file descriptor polling loop based on poll() with callbacks.
*/
-class PollLoop : public RefBase {
+class PollLoop : public ALooper {
protected:
virtual ~PollLoop();
@@ -83,6 +93,11 @@
void setCallback(int fd, int events, Callback callback, void* data = NULL);
/**
+ * Like setCallback(), but for the NDK callback function.
+ */
+ void setLooperCallback(int fd, int events, ALooper_callbackFunc* callback, void* data);
+
+ /**
* Removes the callback for a file descriptor, if one exists.
*
* When this method returns, it is safe to close the file descriptor since the poll loop
@@ -100,9 +115,22 @@
*/
bool removeCallback(int fd);
+ /**
+ * Set the given PollLoop to be associated with the
+ * calling thread. There must be a 1:1 relationship between
+ * PollLoop and thread.
+ */
+ static void setForThread(const sp<PollLoop>& pollLoop);
+
+ /**
+ * Return the PollLoop associated with the calling thread.
+ */
+ static sp<PollLoop> getForThread();
+
private:
struct RequestedCallback {
Callback callback;
+ ALooper_callbackFunc* looperCallback;
void* data;
};
@@ -110,6 +138,7 @@
int fd;
int events;
Callback callback;
+ ALooper_callbackFunc* looperCallback;
void* data;
};
@@ -130,8 +159,11 @@
void openWakePipe();
void closeWakePipe();
+ void setCallbackCommon(int fd, int events, Callback callback,
+ ALooper_callbackFunc* looperCallback, void* data);
ssize_t getRequestIndexLocked(int fd);
void wakeAndLock();
+ static void threadDestructor(void *st);
};
} // namespace android
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 48c04a6..e6f46ce 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -17,7 +17,8 @@
#define LOG_TAG "AudioFlinger"
-//#define LOG_NDEBUG 0
+//
+#define LOG_NDEBUG 0
#include <math.h>
#include <signal.h>
@@ -52,6 +53,7 @@
#endif
#include <media/EffectsFactoryApi.h>
+#include <media/EffectVisualizerApi.h>
// ----------------------------------------------------------------------------
// the sim build doesn't have gettid
@@ -4498,6 +4500,11 @@
return EffectGetDescriptor(pUuid, descriptor);
}
+
+// this UUID must match the one defined in media/libeffects/EffectVisualizer.cpp
+static const effect_uuid_t VISUALIZATION_UUID_ =
+ {0xd069d9e0, 0x8329, 0x11df, 0x9168, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+
sp<IEffect> AudioFlinger::createEffect(pid_t pid,
effect_descriptor_t *pDesc,
const sp<IEffectClient>& effectClient,
@@ -4525,6 +4532,15 @@
{
Mutex::Autolock _l(mLock);
+ // check recording permission for visualizer
+ if (memcmp(&pDesc->type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0 ||
+ memcmp(&pDesc->uuid, &VISUALIZATION_UUID_, sizeof(effect_uuid_t)) == 0) {
+ if (!recordingAllowed()) {
+ lStatus = PERMISSION_DENIED;
+ goto Exit;
+ }
+ }
+
if (!EffectIsNullUuid(&pDesc->uuid)) {
// if uuid is specified, request effect descriptor
lStatus = EffectGetDescriptor(&pDesc->uuid, &desc);
@@ -5089,7 +5105,7 @@
if (mState != ACTIVE) {
switch (mState) {
case RESET:
- reset();
+ reset_l();
mState = STARTING;
// clear auxiliary effect input buffer for next accumulation
if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
@@ -5097,14 +5113,14 @@
}
return;
case STARTING:
- start();
+ start_l();
mState = ACTIVE;
break;
case STOPPING:
mState = STOPPED;
break;
case STOPPED:
- stop();
+ stop_l();
mState = IDLE;
return;
}
@@ -5132,7 +5148,7 @@
}
}
-void AudioFlinger::EffectModule::reset()
+void AudioFlinger::EffectModule::reset_l()
{
if (mEffectInterface == NULL) {
return;
@@ -5205,6 +5221,7 @@
status_t AudioFlinger::EffectModule::init()
{
+ Mutex::Autolock _l(mLock);
if (mEffectInterface == NULL) {
return NO_INIT;
}
@@ -5217,7 +5234,7 @@
return status;
}
-status_t AudioFlinger::EffectModule::start()
+status_t AudioFlinger::EffectModule::start_l()
{
if (mEffectInterface == NULL) {
return NO_INIT;
@@ -5231,7 +5248,7 @@
return status;
}
-status_t AudioFlinger::EffectModule::stop()
+status_t AudioFlinger::EffectModule::stop_l()
{
if (mEffectInterface == NULL) {
return NO_INIT;
@@ -5247,7 +5264,8 @@
status_t AudioFlinger::EffectModule::command(int cmdCode, int cmdSize, void *pCmdData, int *replySize, void *pReplyData)
{
- LOGV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface);
+ Mutex::Autolock _l(mLock);
+// LOGV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface);
if (mEffectInterface == NULL) {
return NO_INIT;
@@ -5255,7 +5273,6 @@
status_t status = (*mEffectInterface)->command(mEffectInterface, cmdCode, cmdSize, pCmdData, replySize, pReplyData);
if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
int size = (replySize == NULL) ? 0 : *replySize;
- Mutex::Autolock _l(mLock);
for (size_t i = 1; i < mHandles.size(); i++) {
sp<EffectHandle> h = mHandles[i].promote();
if (h != 0) {
@@ -5322,6 +5339,7 @@
status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
{
+ Mutex::Autolock _l(mLock);
status_t status = NO_ERROR;
// Send volume indication if EFFECT_FLAG_VOLUME_IND is set and read back altered volume
@@ -5347,6 +5365,7 @@
status_t AudioFlinger::EffectModule::setDevice(uint32_t device)
{
+ Mutex::Autolock _l(mLock);
status_t status = NO_ERROR;
if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
// convert device bit field from AudioSystem to EffectApi format.
@@ -5366,6 +5385,7 @@
status_t AudioFlinger::EffectModule::setMode(uint32_t mode)
{
+ Mutex::Autolock _l(mLock);
status_t status = NO_ERROR;
if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) {
// convert audio mode from AudioSystem to EffectApi format.
@@ -5586,7 +5606,7 @@
status_t AudioFlinger::EffectHandle::command(int cmdCode, int cmdSize, void *pCmdData, int *replySize, void *pReplyData)
{
- LOGV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p", cmdCode, mHasControl, (mEffect == 0) ? 0 : mEffect.get());
+// LOGV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p", cmdCode, mHasControl, (mEffect == 0) ? 0 : mEffect.get());
// only get parameter command is permitted for applications not controlling the effect
if (!mHasControl && cmdCode != EFFECT_CMD_GET_PARAM) {
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index 42dca4c..ec3d7f1 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -916,7 +916,7 @@
void process();
status_t command(int cmdCode, int cmdSize, void *pCmdData, int *replySize, void *pReplyData);
- void reset();
+ void reset_l();
status_t configure();
status_t init();
uint32_t state() {
@@ -951,8 +951,8 @@
EffectModule(const EffectModule&);
EffectModule& operator = (const EffectModule&);
- status_t start();
- status_t stop();
+ status_t start_l();
+ status_t stop_l();
// update this table when AudioSystem::audio_devices or audio_device_e (in EffectApi.h) are modified
static const uint32_t sDeviceConvTable[];
diff --git a/libs/utils/PollLoop.cpp b/libs/utils/PollLoop.cpp
index 20a4d13..58fe141 100644
--- a/libs/utils/PollLoop.cpp
+++ b/libs/utils/PollLoop.cpp
@@ -21,6 +21,10 @@
namespace android {
+static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
+static bool gHaveTLS = false;
+static pthread_key_t gTLS = 0;
+
PollLoop::PollLoop() :
mPolling(false), mWaiters(0) {
openWakePipe();
@@ -30,6 +34,41 @@
closeWakePipe();
}
+void PollLoop::threadDestructor(void *st) {
+ PollLoop* const self = static_cast<PollLoop*>(st);
+ if (self != NULL) {
+ self->decStrong((void*)threadDestructor);
+ }
+}
+
+void PollLoop::setForThread(const sp<PollLoop>& pollLoop) {
+ sp<PollLoop> old = getForThread();
+
+ if (pollLoop != NULL) {
+ pollLoop->incStrong((void*)threadDestructor);
+ }
+
+ pthread_setspecific(gTLS, pollLoop.get());
+
+ if (old != NULL) {
+ old->decStrong((void*)threadDestructor);
+ }
+}
+
+sp<PollLoop> PollLoop::getForThread() {
+ if (!gHaveTLS) {
+ pthread_mutex_lock(&gTLSMutex);
+ if (pthread_key_create(&gTLS, threadDestructor) != 0) {
+ pthread_mutex_unlock(&gTLSMutex);
+ return NULL;
+ }
+ gHaveTLS = true;
+ pthread_mutex_unlock(&gTLSMutex);
+ }
+
+ return (PollLoop*)pthread_getspecific(gTLS);
+}
+
void PollLoop::openWakePipe() {
int wakeFds[2];
int result = pipe(wakeFds);
@@ -54,6 +93,7 @@
RequestedCallback requestedCallback;
requestedCallback.callback = NULL;
+ requestedCallback.looperCallback = NULL;
requestedCallback.data = NULL;
mRequestedCallbacks.insertAt(requestedCallback, 0);
}
@@ -123,12 +163,14 @@
if (revents) {
const RequestedCallback& requestedCallback = mRequestedCallbacks.itemAt(i);
Callback callback = requestedCallback.callback;
+ ALooper_callbackFunc* looperCallback = requestedCallback.looperCallback;
- if (callback) {
+ if (callback || looperCallback) {
PendingCallback pendingCallback;
pendingCallback.fd = requestedFd.fd;
pendingCallback.events = requestedFd.revents;
pendingCallback.callback = callback;
+ pendingCallback.looperCallback = looperCallback;
pendingCallback.data = requestedCallback.data;
mPendingCallbacks.push(pendingCallback);
} else {
@@ -172,8 +214,14 @@
LOGD("%p ~ pollOnce - invoking callback for fd %d", this, pendingCallback.fd);
#endif
- bool keep = pendingCallback.callback(pendingCallback.fd, pendingCallback.events,
- pendingCallback.data);
+ bool keep = true;
+ if (pendingCallback.callback != NULL) {
+ keep = pendingCallback.callback(pendingCallback.fd, pendingCallback.events,
+ pendingCallback.data);
+ } else {
+ keep = pendingCallback.looperCallback(pendingCallback.fd, pendingCallback.events,
+ pendingCallback.data) != 0;
+ }
if (! keep) {
removeCallback(pendingCallback.fd);
}
@@ -200,11 +248,22 @@
}
void PollLoop::setCallback(int fd, int events, Callback callback, void* data) {
+ setCallbackCommon(fd, events, callback, NULL, data);
+}
+
+void PollLoop::setLooperCallback(int fd, int events, ALooper_callbackFunc* callback,
+ void* data) {
+ setCallbackCommon(fd, events, NULL, callback, data);
+}
+
+void PollLoop::setCallbackCommon(int fd, int events, Callback callback,
+ ALooper_callbackFunc* looperCallback, void* data) {
+
#if DEBUG_CALLBACKS
LOGD("%p ~ setCallback - fd=%d, events=%d", this, fd, events);
#endif
- if (! events || ! callback) {
+ if (! events || (! callback && ! looperCallback)) {
LOGE("Invalid attempt to set a callback with no selected poll events or no callback.");
removeCallback(fd);
return;
@@ -218,6 +277,7 @@
RequestedCallback requestedCallback;
requestedCallback.callback = callback;
+ requestedCallback.looperCallback = looperCallback;
requestedCallback.data = data;
ssize_t index = getRequestIndexLocked(fd);