Merge "Fix ordering assumption of argument evaluation."
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index 3c00db5..7ac3cc1 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -360,7 +360,8 @@
}
// callback from camera service when frame or image is ready
-void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr)
+void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
+ camera_frame_metadata_t *metadata)
{
sp<CameraListener> listener;
{
@@ -368,7 +369,7 @@
listener = mListener;
}
if (listener != NULL) {
- listener->postData(msgType, dataPtr);
+ listener->postData(msgType, dataPtr, metadata);
}
}
diff --git a/camera/CameraParameters.cpp b/camera/CameraParameters.cpp
index 9392cf2..251615d 100644
--- a/camera/CameraParameters.cpp
+++ b/camera/CameraParameters.cpp
@@ -84,6 +84,9 @@
const char CameraParameters::KEY_VIDEO_SIZE[] = "video-size";
const char CameraParameters::KEY_SUPPORTED_VIDEO_SIZES[] = "video-size-values";
const char CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO[] = "preferred-preview-size-for-video";
+const char CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW[] = "max-num-detected-faces-hw";
+const char CameraParameters::KEY_MAX_NUM_DETECTED_FACES_SW[] = "max-num-detected-faces-sw";
+const char CameraParameters::KEY_RECORDING_HINT[] = "recording-hint";
const char CameraParameters::TRUE[] = "true";
const char CameraParameters::FALSE[] = "false";
diff --git a/camera/ICameraClient.cpp b/camera/ICameraClient.cpp
index cb3bd0c..183429a 100644
--- a/camera/ICameraClient.cpp
+++ b/camera/ICameraClient.cpp
@@ -51,13 +51,18 @@
}
// generic data callback from camera service to app with image data
- void dataCallback(int32_t msgType, const sp<IMemory>& imageData)
+ void dataCallback(int32_t msgType, const sp<IMemory>& imageData,
+ camera_frame_metadata_t *metadata)
{
LOGV("dataCallback");
Parcel data, reply;
data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
data.writeInt32(msgType);
data.writeStrongBinder(imageData->asBinder());
+ if (metadata) {
+ data.writeInt32(metadata->number_of_faces);
+ data.write(metadata->faces, sizeof(camera_face_t) * metadata->number_of_faces);
+ }
remote()->transact(DATA_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
}
@@ -96,7 +101,15 @@
CHECK_INTERFACE(ICameraClient, data, reply);
int32_t msgType = data.readInt32();
sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder());
- dataCallback(msgType, imageData);
+ camera_frame_metadata_t *metadata = NULL;
+ if (data.dataAvail() > 0) {
+ metadata = new camera_frame_metadata_t;
+ metadata->number_of_faces = data.readInt32();
+ metadata->faces = (camera_face_t *) data.readInplace(
+ sizeof(camera_face_t) * metadata->number_of_faces);
+ }
+ dataCallback(msgType, imageData, metadata);
+ if (metadata) delete metadata;
return NO_ERROR;
} break;
case DATA_CALLBACK_TIMESTAMP: {
diff --git a/include/camera/Camera.h b/include/camera/Camera.h
index f701280..234e165 100644
--- a/include/camera/Camera.h
+++ b/include/camera/Camera.h
@@ -59,7 +59,8 @@
{
public:
virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2) = 0;
- virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr) = 0;
+ virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr,
+ camera_frame_metadata_t *metadata) = 0;
virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) = 0;
};
@@ -138,7 +139,8 @@
// ICameraClient interface
virtual void notifyCallback(int32_t msgType, int32_t ext, int32_t ext2);
- virtual void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr);
+ virtual void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
+ camera_frame_metadata_t *metadata);
virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
sp<ICamera> remote();
diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h
index 83d4f6d..48483fd 100644
--- a/include/camera/CameraParameters.h
+++ b/include/camera/CameraParameters.h
@@ -455,6 +455,16 @@
// Example: "176x144,1280x720". Read only.
static const char KEY_SUPPORTED_VIDEO_SIZES[];
+ // The maximum number of detected faces supported by hardware face
+ // detection. If the value is 0, hardware face detection is not supported.
+ // Example: "5". Read only
+ static const char KEY_MAX_NUM_DETECTED_FACES_HW[];
+
+ // The maximum number of detected faces supported by software face
+ // detection. If the value is 0, software face detection is not supported.
+ // Example: "5". Read only
+ static const char KEY_MAX_NUM_DETECTED_FACES_SW[];
+
// Preferred preview frame size in pixels for video recording.
// The width and height must be one of the supported sizes retrieved
// via KEY_SUPPORTED_PREVIEW_SIZES. This key can be used only when
@@ -474,6 +484,17 @@
// Example value: "yuv420sp" or PIXEL_FORMAT_XXX constants. Read only.
static const char KEY_VIDEO_FRAME_FORMAT[];
+ // Sets the hint of the recording mode. If this is true, MediaRecorder.start
+ // may be faster or has less glitches. This should be called before starting
+ // the preview for the best result. But it is allowed to change the hint
+ // while the preview is active. The default value is false.
+ //
+ // The apps can still call Camera.takePicture when the hint is true. The
+ // apps can call MediaRecorder.start when the hint is false. But the
+ // performance may be worse.
+ // Example value: "true" or "false". Read/write.
+ static const char KEY_RECORDING_HINT[];
+
// Value for KEY_ZOOM_SUPPORTED or KEY_SMOOTH_ZOOM_SUPPORTED.
static const char TRUE[];
static const char FALSE[];
diff --git a/include/camera/ICameraClient.h b/include/camera/ICameraClient.h
index 236d0f6..b30aa7a 100644
--- a/include/camera/ICameraClient.h
+++ b/include/camera/ICameraClient.h
@@ -22,6 +22,7 @@
#include <binder/Parcel.h>
#include <binder/IMemory.h>
#include <utils/Timers.h>
+#include <system/camera.h>
namespace android {
@@ -31,7 +32,8 @@
DECLARE_META_INTERFACE(CameraClient);
virtual void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) = 0;
- virtual void dataCallback(int32_t msgType, const sp<IMemory>& data) = 0;
+ virtual void dataCallback(int32_t msgType, const sp<IMemory>& data,
+ camera_frame_metadata_t *metadata) = 0;
virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& data) = 0;
};
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 1136f6c..1a67671 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -130,13 +130,22 @@
MEDIA_PLAYER_PLAYBACK_COMPLETE = 1 << 7
};
-enum media_set_parameter_keys {
- KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX = 1000,
- KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE = 1001,
+// Keep KEY_PARAMETER_* in sync with MediaPlayer.java.
+// The same enum space is used for both set and get, in case there are future keys that
+// can be both set and get. But as of now, all parameters are either set only or get only.
+enum media_parameter_keys {
+ KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX = 1000, // set only
+ KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE = 1001, // set only
// Streaming/buffering parameters
- KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS = 1100,
+ KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS = 1100, // set only
+
+ // Return a Parcel containing a single int, which is the channel count of the
+ // audio track, or zero for error (e.g. no audio track) or unknown.
+ KEY_PARAMETER_AUDIO_CHANNEL_COUNT = 1200, // get only
+
};
+
// ----------------------------------------------------------------------------
// ref-counted object for callbacks
class MediaPlayerListener: virtual public RefBase
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 1ec596e..16554c2 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -590,7 +590,7 @@
audio_io_handle_t AudioRecord::getInput()
{
AutoMutex lock(mLock);
- return getInput_l();
+ return mInput;
}
// must be called with mLock held
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index a11fb80..3dd9249 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -201,11 +201,11 @@
void MediaPlayer::disconnectNativeWindow() {
if (mConnectedWindow != NULL) {
- status_t err = native_window_disconnect(mConnectedWindow.get(),
+ status_t err = native_window_api_disconnect(mConnectedWindow.get(),
NATIVE_WINDOW_API_MEDIA);
if (err != OK) {
- LOGW("native_window_disconnect returned an error: %s (%d)",
+ LOGW("native_window_api_disconnect returned an error: %s (%d)",
strerror(-err), err);
}
}
@@ -224,7 +224,7 @@
}
if (surface != NULL) {
- status_t err = native_window_connect(surface.get(),
+ status_t err = native_window_api_connect(surface.get(),
NATIVE_WINDOW_API_MEDIA);
if (err != OK) {
@@ -274,7 +274,7 @@
sp<ANativeWindow> anw;
if (surfaceTexture != NULL) {
anw = new SurfaceTextureClient(surfaceTexture);
- status_t err = native_window_connect(anw.get(),
+ status_t err = native_window_api_connect(anw.get(),
NATIVE_WINDOW_API_MEDIA);
if (err != OK) {
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 3a3c082..3f4dace 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -132,10 +132,9 @@
LOCAL_STATIC_LIBRARIES += \
libstagefright_chromium_http \
- libchromium_net \
libwebcore \
-LOCAL_SHARED_LIBRARIES += libstlport
+LOCAL_SHARED_LIBRARIES += libstlport libchromium_net
include external/stlport/libstlport.mk
LOCAL_CPPFLAGS += -DCHROMIUM_AVAILABLE=1
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 0098537..67f6c79 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -2238,7 +2238,22 @@
}
status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
- return OK;
+ switch (key) {
+ case KEY_PARAMETER_AUDIO_CHANNEL_COUNT:
+ {
+ int32_t channelCount;
+ if (mAudioTrack == 0 ||
+ !mAudioTrack->getFormat()->findInt32(kKeyChannelCount, &channelCount)) {
+ channelCount = 0;
+ }
+ reply->writeInt32(channelCount);
+ }
+ return OK;
+ default:
+ {
+ return ERROR_UNSUPPORTED;
+ }
+ }
}
bool AwesomePlayer::isStreamingHTTP() const {
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index de66d99..ea8eaa4 100755
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -37,7 +37,8 @@
CameraSourceListener(const sp<CameraSource> &source);
virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2);
- virtual void postData(int32_t msgType, const sp<IMemory> &dataPtr);
+ virtual void postData(int32_t msgType, const sp<IMemory> &dataPtr,
+ camera_frame_metadata_t *metadata);
virtual void postDataTimestamp(
nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
@@ -63,7 +64,8 @@
LOGV("notify(%d, %d, %d)", msgType, ext1, ext2);
}
-void CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr) {
+void CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr,
+ camera_frame_metadata_t *metadata) {
LOGV("postData(%d, ptr:%p, size:%d)",
msgType, dataPtr->pointer(), dataPtr->size());
diff --git a/media/libstagefright/avc_utils.cpp b/media/libstagefright/avc_utils.cpp
index 020e947..8a42e8b 100644
--- a/media/libstagefright/avc_utils.cpp
+++ b/media/libstagefright/avc_utils.cpp
@@ -188,7 +188,7 @@
}
size_t endOffset = offset - 2;
- while (data[endOffset - 1] == 0x00) {
+ while (endOffset > startOffset + 1 && data[endOffset - 1] == 0x00) {
--endOffset;
}
diff --git a/media/libstagefright/chromium_http/support.cpp b/media/libstagefright/chromium_http/support.cpp
index f4b3668..eb10ab7 100644
--- a/media/libstagefright/chromium_http/support.cpp
+++ b/media/libstagefright/chromium_http/support.cpp
@@ -25,6 +25,7 @@
#include "android/net/android_network_library_impl.h"
#include "base/threading/thread.h"
#include "net/base/cert_verifier.h"
+#include "net/base/cookie_monster.h"
#include "net/base/host_resolver.h"
#include "net/base/ssl_config_service.h"
#include "net/http/http_auth_handler_factory.h"
@@ -140,6 +141,8 @@
network_delegate(),
net_log(),
NULL)); // backend_factory
+
+ set_cookie_store(new net::CookieMonster(NULL, NULL));
}
const std::string &SfRequestContext::GetUserAgent(const GURL &url) const {
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 90d64ba..2578d2d 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -544,6 +544,7 @@
firstSeqNumberInPlaylist = 0;
}
+ bool seekDiscontinuity = false;
bool explicitDiscontinuity = false;
bool bandwidthChanged = false;
@@ -580,10 +581,10 @@
// reseting the data source will have had the
// side effect of discarding any previously queued
// bandwidth change discontinuity.
- // Therefore we'll need to treat these explicit
+ // Therefore we'll need to treat these seek
// discontinuities as involving a bandwidth change
// even if they aren't directly.
- explicitDiscontinuity = true;
+ seekDiscontinuity = true;
bandwidthChanged = true;
}
}
@@ -597,11 +598,7 @@
}
if (mSeqNumber < 0) {
- if (mPlaylist->isComplete()) {
- mSeqNumber = firstSeqNumberInPlaylist;
- } else {
- mSeqNumber = firstSeqNumberInPlaylist + mPlaylist->size() / 2;
- }
+ mSeqNumber = firstSeqNumberInPlaylist;
}
int32_t lastSeqNumberInPlaylist =
@@ -704,15 +701,17 @@
bandwidthChanged = false;
}
- if (explicitDiscontinuity || bandwidthChanged) {
+ if (seekDiscontinuity || explicitDiscontinuity || bandwidthChanged) {
// Signal discontinuity.
- LOGI("queueing discontinuity (explicit=%d, bandwidthChanged=%d)",
- explicitDiscontinuity, bandwidthChanged);
+ LOGI("queueing discontinuity (seek=%d, explicit=%d, bandwidthChanged=%d)",
+ seekDiscontinuity, explicitDiscontinuity, bandwidthChanged);
sp<ABuffer> tmp = new ABuffer(188);
memset(tmp->data(), 0, tmp->size());
- tmp->data()[1] = bandwidthChanged;
+
+ // signal a 'hard' discontinuity for explicit or bandwidthChanged.
+ tmp->data()[1] = (explicitDiscontinuity || bandwidthChanged) ? 1 : 0;
mDataSource->queueBuffer(tmp);
}
diff --git a/media/libstagefright/omx/OMXMaster.cpp b/media/libstagefright/omx/OMXMaster.cpp
index 504d470..c8278ab 100644
--- a/media/libstagefright/omx/OMXMaster.cpp
+++ b/media/libstagefright/omx/OMXMaster.cpp
@@ -57,6 +57,9 @@
typedef OMXPluginBase *(*CreateOMXPluginFunc)();
CreateOMXPluginFunc createOMXPlugin =
(CreateOMXPluginFunc)dlsym(
+ mVendorLibHandle, "createOMXPlugin");
+ if (!createOMXPlugin)
+ createOMXPlugin = (CreateOMXPluginFunc)dlsym(
mVendorLibHandle, "_ZN7android15createOMXPluginEv");
if (createOMXPlugin) {
@@ -96,11 +99,19 @@
void OMXMaster::clearPlugins() {
Mutex::Autolock autoLock(mLock);
+ typedef void (*DestroyOMXPluginFunc)(OMXPluginBase*);
+ DestroyOMXPluginFunc destroyOMXPlugin =
+ (DestroyOMXPluginFunc)dlsym(
+ mVendorLibHandle, "destroyOMXPlugin");
+
mPluginByComponentName.clear();
for (List<OMXPluginBase *>::iterator it = mPlugins.begin();
- it != mPlugins.end(); ++it) {
- delete *it;
+ it != mPlugins.end(); ++it) {
+ if (destroyOMXPlugin)
+ destroyOMXPlugin(*it);
+ else
+ delete *it;
*it = NULL;
}
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index a0407b9..fa49592 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -21,7 +21,8 @@
libhardware \
libhardware_legacy \
libeffects \
- libdl
+ libdl \
+ libpowermanager
LOCAL_STATIC_LIBRARIES := \
libcpustats \
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index cb1f921..ec45530 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -53,6 +53,7 @@
#include <audio_effects/effect_visualizer.h>
#include <cpustats/ThreadCpuUsage.h>
+#include <powermanager/PowerManager.h>
// #define DEBUG_CPU_USAGE 10 // log statistics every n wall clock seconds
// ----------------------------------------------------------------------------
@@ -887,14 +888,18 @@
AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id, uint32_t device)
: Thread(false),
mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0),
- mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false), mDevice(device)
+ mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false),
+ mDevice(device)
{
+ mDeathRecipient = new PMDeathRecipient(this);
}
AudioFlinger::ThreadBase::~ThreadBase()
{
mParamCond.broadcast();
mNewParameters.clear();
+ // do not lock the mutex in destructor
+ releaseWakeLock_l();
}
void AudioFlinger::ThreadBase::exit()
@@ -1061,6 +1066,69 @@
return NO_ERROR;
}
+void AudioFlinger::ThreadBase::acquireWakeLock()
+{
+ Mutex::Autolock _l(mLock);
+ acquireWakeLock_l();
+}
+
+void AudioFlinger::ThreadBase::acquireWakeLock_l()
+{
+ if (mPowerManager == 0) {
+ // use checkService() to avoid blocking if power service is not up yet
+ sp<IBinder> binder =
+ defaultServiceManager()->checkService(String16("power"));
+ if (binder == 0) {
+ LOGW("Thread %s cannot connect to the power manager service", mName);
+ } else {
+ mPowerManager = interface_cast<IPowerManager>(binder);
+ binder->linkToDeath(mDeathRecipient);
+ }
+ }
+ if (mPowerManager != 0) {
+ sp<IBinder> binder = new BBinder();
+ status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK,
+ binder,
+ String16(mName));
+ if (status == NO_ERROR) {
+ mWakeLockToken = binder;
+ }
+ LOGV("acquireWakeLock_l() %s status %d", mName, status);
+ }
+}
+
+void AudioFlinger::ThreadBase::releaseWakeLock()
+{
+ Mutex::Autolock _l(mLock);
+ releaseWakeLock_l();
+}
+
+void AudioFlinger::ThreadBase::releaseWakeLock_l()
+{
+ if (mWakeLockToken != 0) {
+ LOGV("releaseWakeLock_l() %s", mName);
+ if (mPowerManager != 0) {
+ mPowerManager->releaseWakeLock(mWakeLockToken, 0);
+ }
+ mWakeLockToken.clear();
+ }
+}
+
+void AudioFlinger::ThreadBase::clearPowerManager()
+{
+ Mutex::Autolock _l(mLock);
+ releaseWakeLock_l();
+ mPowerManager.clear();
+}
+
+void AudioFlinger::ThreadBase::PMDeathRecipient::binderDied(const wp<IBinder>& who)
+{
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0) {
+ thread->clearPowerManager();
+ }
+ LOGW("power manager service died !!!");
+}
// ----------------------------------------------------------------------------
@@ -1072,6 +1140,8 @@
mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output),
mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false)
{
+ snprintf(mName, kNameLength, "AudioOut_%d", id);
+
readOutputParameters();
mMasterVolume = mAudioFlinger->masterVolume();
@@ -1170,12 +1240,7 @@
void AudioFlinger::PlaybackThread::onFirstRef()
{
- const size_t SIZE = 256;
- char buffer[SIZE];
-
- snprintf(buffer, SIZE, "Playback Thread %p", this);
-
- run(buffer, ANDROID_PRIORITY_URGENT_AUDIO);
+ run(mName, ANDROID_PRIORITY_URGENT_AUDIO);
}
// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
@@ -1522,6 +1587,8 @@
const CentralTendencyStatistics& stats = cpu.statistics();
#endif
+ acquireWakeLock();
+
while (!exitPending())
{
#ifdef DEBUG_CPU_USAGE
@@ -1585,10 +1652,12 @@
if (exitPending()) break;
+ releaseWakeLock_l();
// wait until we have something to do...
LOGV("MixerThread %p TID %d going to sleep\n", this, gettid());
mWaitWorkCV.wait(mLock);
LOGV("MixerThread %p TID %d waking up\n", this, gettid());
+ acquireWakeLock_l();
if (mMasterMute == false) {
char value[PROPERTY_VALUE_MAX];
@@ -1689,6 +1758,8 @@
mOutput->stream->common.standby(&mOutput->stream->common);
}
+ releaseWakeLock();
+
LOGV("MixerThread %p exiting", this);
return false;
}
@@ -2176,6 +2247,8 @@
// hardware resources as soon as possible
nsecs_t standbyDelay = microseconds(activeSleepTime*2);
+ acquireWakeLock();
+
while (!exitPending())
{
bool rampVolume;
@@ -2215,9 +2288,11 @@
if (exitPending()) break;
+ releaseWakeLock_l();
LOGV("DirectOutputThread %p TID %d going to sleep\n", this, gettid());
mWaitWorkCV.wait(mLock);
LOGV("DirectOutputThread %p TID %d waking up in active mode\n", this, gettid());
+ acquireWakeLock_l();
if (mMasterMute == false) {
char value[PROPERTY_VALUE_MAX];
@@ -2436,6 +2511,8 @@
mOutput->stream->common.standby(&mOutput->stream->common);
}
+ releaseWakeLock();
+
LOGV("DirectOutputThread %p exiting", this);
return false;
}
@@ -2561,6 +2638,8 @@
uint32_t sleepTime = idleSleepTime;
Vector< sp<EffectChain> > effectChains;
+ acquireWakeLock();
+
while (!exitPending())
{
processConfigEvents();
@@ -2601,9 +2680,12 @@
if (exitPending()) break;
+ releaseWakeLock_l();
LOGV("DuplicatingThread %p TID %d going to sleep\n", this, gettid());
mWaitWorkCV.wait(mLock);
LOGV("DuplicatingThread %p TID %d waking up\n", this, gettid());
+ acquireWakeLock_l();
+
if (mMasterMute == false) {
char value[PROPERTY_VALUE_MAX];
property_get("ro.audio.silent", value, "0");
@@ -2690,6 +2772,8 @@
effectChains.clear();
}
+ releaseWakeLock();
+
return false;
}
@@ -3814,6 +3898,9 @@
mInput(input), mTrack(NULL), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
{
mType = ThreadBase::RECORD;
+
+ snprintf(mName, kNameLength, "AudioIn_%d", id);
+
mReqChannelCount = popcount(channels);
mReqSampleRate = sampleRate;
readInputParameters();
@@ -3831,12 +3918,7 @@
void AudioFlinger::RecordThread::onFirstRef()
{
- const size_t SIZE = 256;
- char buffer[SIZE];
-
- snprintf(buffer, SIZE, "Record Thread %p", this);
-
- run(buffer, PRIORITY_URGENT_AUDIO);
+ run(mName, PRIORITY_URGENT_AUDIO);
}
bool AudioFlinger::RecordThread::threadLoop()
@@ -3847,6 +3929,8 @@
nsecs_t lastWarning = 0;
+ acquireWakeLock();
+
// start recording
while (!exitPending()) {
@@ -3863,10 +3947,12 @@
if (exitPending()) break;
+ releaseWakeLock_l();
LOGV("RecordThread: loop stopping");
// go to sleep
mWaitWorkCV.wait(mLock);
LOGV("RecordThread: loop starting");
+ acquireWakeLock_l();
continue;
}
if (mActiveTrack != 0) {
@@ -3907,8 +3993,6 @@
for (size_t i = 0; i < effectChains.size(); i ++) {
effectChains[i]->process_l();
}
- // enable changes in effect chain
- unlockEffectChains(effectChains);
buffer.frameCount = mFrameCount;
if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
@@ -4008,9 +4092,9 @@
// clear the overflow.
usleep(kRecordThreadSleepUs);
}
- } else {
- unlockEffectChains(effectChains);
}
+ // enable changes in effect chain
+ unlockEffectChains(effectChains);
effectChains.clear();
}
@@ -4021,6 +4105,8 @@
mStartStopCond.broadcast();
+ releaseWakeLock();
+
LOGV("RecordThread %p exiting", this);
return false;
}
@@ -5581,13 +5667,11 @@
}
}
- // Release effect engine here so that it is done immediately. Otherwise it will be released
- // by the destructor when the last strong reference on the this object is released which can
- // happen after next process is called on this effect.
- if (size == 0 && mEffectInterface != NULL) {
- // release effect engine
- EffectRelease(mEffectInterface);
- mEffectInterface = NULL;
+ // Prevent calls to process() and other functions on effect interface from now on.
+ // The effect engine will be released by the destructor when the last strong reference on
+ // this object is released which can happen after next process is called.
+ if (size == 0) {
+ mState = DESTROYED;
}
return size;
@@ -5637,7 +5721,7 @@
mState = IDLE;
}
break;
- default: //IDLE , ACTIVE
+ default: //IDLE , ACTIVE, DESTROYED
break;
}
}
@@ -5646,7 +5730,7 @@
{
Mutex::Autolock _l(mLock);
- if (mEffectInterface == NULL ||
+ if (mState == DESTROYED || mEffectInterface == NULL ||
mConfig.inputCfg.buffer.raw == NULL ||
mConfig.outputCfg.buffer.raw == NULL) {
return;
@@ -5822,6 +5906,12 @@
return status;
}
+status_t AudioFlinger::EffectModule::stop()
+{
+ Mutex::Autolock _l(mLock);
+ return stop_l();
+}
+
status_t AudioFlinger::EffectModule::stop_l()
{
if (mEffectInterface == NULL) {
@@ -5858,7 +5948,7 @@
Mutex::Autolock _l(mLock);
// LOGV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface);
- if (mEffectInterface == NULL) {
+ if (mState == DESTROYED || mEffectInterface == NULL) {
return NO_INIT;
}
status_t status = (*mEffectInterface)->command(mEffectInterface,
@@ -5907,6 +5997,8 @@
case ACTIVE:
mState = STOPPING;
break;
+ case DESTROYED:
+ return NO_ERROR; // simply ignore as we are being destroyed
}
for (size_t i = 1; i < mHandles.size(); i++) {
sp<EffectHandle> h = mHandles[i].promote();
@@ -5928,6 +6020,7 @@
case IDLE:
case STOPPING:
case STOPPED:
+ case DESTROYED:
default:
return false;
}
@@ -5943,6 +6036,7 @@
return true;
case IDLE:
case STARTING:
+ case DESTROYED:
default:
return false;
}
@@ -6544,6 +6638,10 @@
for (i = 0; i < size; i++) {
if (effect == mEffects[i]) {
+ // calling stop here will remove pre-processing effect from the audio HAL.
+ // This is safe as we hold the EffectChain mutex which guarantees that we are not in
+ // the middle of a read from audio HAL
+ mEffects[i]->stop();
if (type == EFFECT_FLAG_TYPE_AUXILIARY) {
delete[] effect->inBuffer();
} else {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index e2cf946..7b6215f 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -43,6 +43,8 @@
#include "AudioBufferProvider.h"
+#include <powermanager/IPowerManager.h>
+
namespace android {
class audio_track_cblk_t;
@@ -287,6 +289,8 @@
status_t dumpBase(int fd, const Vector<String16>& args);
status_t dumpEffectChains(int fd, const Vector<String16>& args);
+ void clearPowerManager();
+
// base for record and playback
class TrackBase : public AudioBufferProvider, public RefBase {
@@ -386,6 +390,21 @@
int mParam;
};
+ class PMDeathRecipient : public IBinder::DeathRecipient {
+ public:
+ PMDeathRecipient(const wp<ThreadBase>& thread) : mThread(thread) {}
+ virtual ~PMDeathRecipient() {}
+
+ // IBinder::DeathRecipient
+ virtual void binderDied(const wp<IBinder>& who);
+
+ private:
+ PMDeathRecipient(const PMDeathRecipient&);
+ PMDeathRecipient& operator = (const PMDeathRecipient&);
+
+ wp<ThreadBase> mThread;
+ };
+
virtual status_t initCheck() const = 0;
int type() const { return mType; }
uint32_t sampleRate() const;
@@ -462,6 +481,11 @@
protected:
+ void acquireWakeLock();
+ void acquireWakeLock_l();
+ void releaseWakeLock();
+ void releaseWakeLock_l();
+
friend class Track;
friend class TrackBase;
friend class PlaybackThread;
@@ -490,6 +514,11 @@
Vector< sp<EffectChain> > mEffectChains;
uint32_t mDevice; // output device for PlaybackThread
// input + output devices for RecordThread
+ static const int kNameLength = 32;
+ char mName[kNameLength];
+ sp<IPowerManager> mPowerManager;
+ sp<IBinder> mWakeLockToken;
+ sp<PMDeathRecipient> mDeathRecipient;
};
// --- PlaybackThread ---
@@ -995,7 +1024,8 @@
STARTING,
ACTIVE,
STOPPING,
- STOPPED
+ STOPPED,
+ DESTROYED
};
int id() { return mId; }
@@ -1040,6 +1070,7 @@
status_t setDevice(uint32_t device);
status_t setVolume(uint32_t *left, uint32_t *right, bool controller);
status_t setMode(uint32_t mode);
+ status_t stop();
status_t dump(int fd, const Vector<String16>& args);
diff --git a/services/camera/libcameraservice/CameraHardwareInterface.h b/services/camera/libcameraservice/CameraHardwareInterface.h
index a583aad..31544b3 100644
--- a/services/camera/libcameraservice/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/CameraHardwareInterface.h
@@ -38,6 +38,7 @@
typedef void (*data_callback)(int32_t msgType,
const sp<IMemory> &dataPtr,
+ camera_frame_metadata_t *metadata,
void* user);
typedef void (*data_callback_timestamp)(nsecs_t timestamp,
@@ -386,7 +387,10 @@
if (mDevice->ops->get_parameters) {
char *temp = mDevice->ops->get_parameters(mDevice);
String8 str_parms(temp);
- free(temp);
+ if (mDevice->ops->put_parameters)
+ mDevice->ops->put_parameters(mDevice, temp);
+ else
+ free(temp);
parms.unflatten(str_parms);
}
return parms;
@@ -439,6 +443,7 @@
static void __data_cb(int32_t msg_type,
const camera_memory_t *data, unsigned int index,
+ camera_frame_metadata_t *metadata,
void *user)
{
LOGV("%s", __FUNCTION__);
@@ -450,7 +455,7 @@
index, mem->mNumBufs);
return;
}
- __this->mDataCb(msg_type, mem->mBuffers[index], __this->mCbUser);
+ __this->mDataCb(msg_type, mem->mBuffers[index], metadata, __this->mCbUser);
}
static void __data_cb_timestamp(nsecs_t timestamp, int32_t msg_type,
diff --git a/services/camera/libcameraservice/CameraHardwareStub.cpp b/services/camera/libcameraservice/CameraHardwareStub.cpp
index 07b5a37..863f19e 100644
--- a/services/camera/libcameraservice/CameraHardwareStub.cpp
+++ b/services/camera/libcameraservice/CameraHardwareStub.cpp
@@ -180,7 +180,7 @@
// Notify the client of a new frame.
if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
- mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, mCallbackCookie);
+ mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, NULL, mCallbackCookie);
// Advance the buffer pointer.
mCurrentPreviewFrame = (mCurrentPreviewFrame + 1) % kBufferCount;
@@ -290,14 +290,14 @@
sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * h * 3 / 2);
FakeCamera cam(w, h);
cam.getNextFrameAsYuv420((uint8_t *)mRawHeap->base());
- mDataCb(CAMERA_MSG_RAW_IMAGE, mem, mCallbackCookie);
+ mDataCb(CAMERA_MSG_RAW_IMAGE, mem, NULL, mCallbackCookie);
}
if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
sp<MemoryHeapBase> heap = new MemoryHeapBase(kCannedJpegSize);
sp<MemoryBase> mem = new MemoryBase(heap, 0, kCannedJpegSize);
memcpy(heap->base(), kCannedJpeg, kCannedJpegSize);
- mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, mCallbackCookie);
+ mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL, mCallbackCookie);
}
return NO_ERROR;
}
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 96b26e7..e193be0 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -350,10 +350,9 @@
dataCallbackTimestamp,
(void *)cameraId);
- // Enable zoom, error, and focus messages by default
- enableMsgType(CAMERA_MSG_ERROR |
- CAMERA_MSG_ZOOM |
- CAMERA_MSG_FOCUS);
+ // Enable zoom, error, focus, and metadata messages by default
+ enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |
+ CAMERA_MSG_PREVIEW_METADATA);
// Callback is disabled by default
mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
@@ -460,10 +459,10 @@
static void disconnectWindow(const sp<ANativeWindow>& window) {
if (window != 0) {
- status_t result = native_window_disconnect(window.get(),
+ status_t result = native_window_api_disconnect(window.get(),
NATIVE_WINDOW_API_CAMERA);
if (result != NO_ERROR) {
- LOGW("native_window_disconnect failed: %s (%d)", strerror(-result),
+ LOGW("native_window_api_disconnect failed: %s (%d)", strerror(-result),
result);
}
}
@@ -526,9 +525,9 @@
}
if (window != 0) {
- result = native_window_connect(window.get(), NATIVE_WINDOW_API_CAMERA);
+ result = native_window_api_connect(window.get(), NATIVE_WINDOW_API_CAMERA);
if (result != NO_ERROR) {
- LOGE("native_window_connect failed: %s (%d)", strerror(-result),
+ LOGE("native_window_api_connect failed: %s (%d)", strerror(-result),
result);
return result;
}
@@ -988,22 +987,22 @@
}
void CameraService::Client::dataCallback(int32_t msgType,
- const sp<IMemory>& dataPtr, void* user) {
+ const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata, void* user) {
LOG2("dataCallback(%d)", msgType);
sp<Client> client = getClientFromCookie(user);
if (client == 0) return;
if (!client->lockIfMessageWanted(msgType)) return;
- if (dataPtr == 0) {
+ if (dataPtr == 0 && metadata == NULL) {
LOGE("Null data returned in data callback");
client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
return;
}
- switch (msgType) {
+ switch (msgType & ~CAMERA_MSG_PREVIEW_METADATA) {
case CAMERA_MSG_PREVIEW_FRAME:
- client->handlePreviewData(dataPtr);
+ client->handlePreviewData(msgType, dataPtr, metadata);
break;
case CAMERA_MSG_POSTVIEW_FRAME:
client->handlePostview(dataPtr);
@@ -1015,7 +1014,7 @@
client->handleCompressedPicture(dataPtr);
break;
default:
- client->handleGenericData(msgType, dataPtr);
+ client->handleGenericData(msgType, dataPtr, metadata);
break;
}
}
@@ -1055,7 +1054,9 @@
}
// preview callback - frame buffer update
-void CameraService::Client::handlePreviewData(const sp<IMemory>& mem) {
+void CameraService::Client::handlePreviewData(int32_t msgType,
+ const sp<IMemory>& mem,
+ camera_frame_metadata_t *metadata) {
ssize_t offset;
size_t size;
sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
@@ -1087,11 +1088,11 @@
// Is the received frame copied out or not?
if (flags & CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
LOG2("frame is copied");
- copyFrameAndPostCopiedFrame(c, heap, offset, size);
+ copyFrameAndPostCopiedFrame(msgType, c, heap, offset, size, metadata);
} else {
LOG2("frame is forwarded");
mLock.unlock();
- c->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem);
+ c->dataCallback(msgType, mem, metadata);
}
} else {
mLock.unlock();
@@ -1105,7 +1106,7 @@
sp<ICameraClient> c = mCameraClient;
mLock.unlock();
if (c != 0) {
- c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem);
+ c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem, NULL);
}
}
@@ -1120,7 +1121,7 @@
sp<ICameraClient> c = mCameraClient;
mLock.unlock();
if (c != 0) {
- c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem);
+ c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem, NULL);
}
}
@@ -1131,7 +1132,7 @@
sp<ICameraClient> c = mCameraClient;
mLock.unlock();
if (c != 0) {
- c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem);
+ c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL);
}
}
@@ -1146,11 +1147,11 @@
}
void CameraService::Client::handleGenericData(int32_t msgType,
- const sp<IMemory>& dataPtr) {
+ const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) {
sp<ICameraClient> c = mCameraClient;
mLock.unlock();
if (c != 0) {
- c->dataCallback(msgType, dataPtr);
+ c->dataCallback(msgType, dataPtr, metadata);
}
}
@@ -1164,8 +1165,9 @@
}
void CameraService::Client::copyFrameAndPostCopiedFrame(
- const sp<ICameraClient>& client, const sp<IMemoryHeap>& heap,
- size_t offset, size_t size) {
+ int32_t msgType, const sp<ICameraClient>& client,
+ const sp<IMemoryHeap>& heap, size_t offset, size_t size,
+ camera_frame_metadata_t *metadata) {
LOG2("copyFrameAndPostCopiedFrame");
// It is necessary to copy out of pmem before sending this to
// the callback. For efficiency, reuse the same MemoryHeapBase
@@ -1197,7 +1199,7 @@
}
mLock.unlock();
- client->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame);
+ client->dataCallback(msgType, frame, metadata);
}
int CameraService::Client::getOrientation(int degrees, bool mirror) {
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index c5fefb8..57abf83 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -140,24 +140,29 @@
// these are static callback functions
static void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user);
- static void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, void* user);
+ static void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
+ camera_frame_metadata_t *metadata, void* user);
static void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr, void* user);
// convert client from cookie
static sp<Client> getClientFromCookie(void* user);
// handlers for messages
void handleShutter(void);
- void handlePreviewData(const sp<IMemory>& mem);
+ void handlePreviewData(int32_t msgType, const sp<IMemory>& mem,
+ camera_frame_metadata_t *metadata);
void handlePostview(const sp<IMemory>& mem);
void handleRawPicture(const sp<IMemory>& mem);
void handleCompressedPicture(const sp<IMemory>& mem);
void handleGenericNotify(int32_t msgType, int32_t ext1, int32_t ext2);
- void handleGenericData(int32_t msgType, const sp<IMemory>& dataPtr);
+ void handleGenericData(int32_t msgType, const sp<IMemory>& dataPtr,
+ camera_frame_metadata_t *metadata);
void handleGenericDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
void copyFrameAndPostCopiedFrame(
+ int32_t msgType,
const sp<ICameraClient>& client,
const sp<IMemoryHeap>& heap,
- size_t offset, size_t size);
+ size_t offset, size_t size,
+ camera_frame_metadata_t *metadata);
int getOrientation(int orientation, bool mirror);