summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/audioflinger/A2dpAudioInterface.cpp102
-rw-r--r--services/audioflinger/A2dpAudioInterface.h3
-rw-r--r--services/audioflinger/AudioFlinger.cpp73
-rw-r--r--services/audioflinger/AudioFlinger.h6
-rw-r--r--services/audioflinger/AudioPolicyManagerBase.cpp112
-rw-r--r--services/audioflinger/AudioPolicyService.cpp26
-rw-r--r--services/audioflinger/AudioPolicyService.h5
-rw-r--r--services/camera/libcameraservice/Android.mk3
-rw-r--r--services/camera/libcameraservice/CameraHardwareStub.cpp4
-rw-r--r--services/camera/libcameraservice/CameraHardwareStub.h2
-rw-r--r--services/camera/libcameraservice/CameraService.cpp322
-rw-r--r--services/camera/libcameraservice/CameraService.h27
12 files changed, 366 insertions, 319 deletions
diff --git a/services/audioflinger/A2dpAudioInterface.cpp b/services/audioflinger/A2dpAudioInterface.cpp
index 995e31c..d926cb1 100644
--- a/services/audioflinger/A2dpAudioInterface.cpp
+++ b/services/audioflinger/A2dpAudioInterface.cpp
@@ -23,10 +23,13 @@
#include "A2dpAudioInterface.h"
#include "audio/liba2dp.h"
-
+#include <hardware_legacy/power.h>
namespace android {
+static const char *sA2dpWakeLock = "A2dpOutputStream";
+#define MAX_WRITE_RETRIES 5
+
// ----------------------------------------------------------------------------
//AudioHardwareInterface* A2dpAudioInterface::createA2dpInterface()
@@ -257,52 +260,74 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::set(
if (pRate) *pRate = lRate;
mDevice = device;
+ mBufferDurationUs = ((bufferSize() * 1000 )/ frameSize() / sampleRate()) * 1000;
return NO_ERROR;
}
A2dpAudioInterface::A2dpAudioStreamOut::~A2dpAudioStreamOut()
{
LOGV("A2dpAudioStreamOut destructor");
- standby();
close();
LOGV("A2dpAudioStreamOut destructor returning from close()");
}
ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t bytes)
{
- Mutex::Autolock lock(mLock);
-
- size_t remaining = bytes;
status_t status = -1;
+ {
+ Mutex::Autolock lock(mLock);
- if (!mBluetoothEnabled || mClosing || mSuspended) {
- LOGV("A2dpAudioStreamOut::write(), but bluetooth disabled \
- mBluetoothEnabled %d, mClosing %d, mSuspended %d",
- mBluetoothEnabled, mClosing, mSuspended);
- goto Error;
- }
-
- status = init();
- if (status < 0)
- goto Error;
+ size_t remaining = bytes;
- while (remaining > 0) {
- status = a2dp_write(mData, buffer, remaining);
- if (status <= 0) {
- LOGE("a2dp_write failed err: %d\n", status);
+ if (!mBluetoothEnabled || mClosing || mSuspended) {
+ LOGV("A2dpAudioStreamOut::write(), but bluetooth disabled \
+ mBluetoothEnabled %d, mClosing %d, mSuspended %d",
+ mBluetoothEnabled, mClosing, mSuspended);
goto Error;
}
- remaining -= status;
- buffer = ((char *)buffer) + status;
- }
- mStandby = false;
+ if (mStandby) {
+ acquire_wake_lock (PARTIAL_WAKE_LOCK, sA2dpWakeLock);
+ mStandby = false;
+ mLastWriteTime = systemTime();
+ }
+
+ status = init();
+ if (status < 0)
+ goto Error;
+
+ int retries = MAX_WRITE_RETRIES;
+ while (remaining > 0 && retries) {
+ status = a2dp_write(mData, buffer, remaining);
+ if (status < 0) {
+ LOGE("a2dp_write failed err: %d\n", status);
+ goto Error;
+ }
+ if (status == 0) {
+ retries--;
+ }
+ remaining -= status;
+ buffer = (char *)buffer + status;
+ }
- return bytes;
+ // if A2DP sink runs abnormally fast, sleep a little so that audioflinger mixer thread
+ // does no spin and starve other threads.
+ // NOTE: It is likely that the A2DP headset is being disconnected
+ nsecs_t now = systemTime();
+ if ((uint32_t)ns2us(now - mLastWriteTime) < (mBufferDurationUs >> 2)) {
+ LOGV("A2DP sink runs too fast");
+ usleep(mBufferDurationUs - (uint32_t)ns2us(now - mLastWriteTime));
+ }
+ mLastWriteTime = now;
+ return bytes;
+ }
Error:
+
+ standby();
+
// Simulate audio output timing in case of error
- usleep(((bytes * 1000 )/ frameSize() / sampleRate()) * 1000);
+ usleep(mBufferDurationUs);
return status;
}
@@ -324,19 +349,22 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::init()
status_t A2dpAudioInterface::A2dpAudioStreamOut::standby()
{
- int result = 0;
-
- if (mClosing) {
- LOGV("Ignore standby, closing");
- return result;
- }
-
Mutex::Autolock lock(mLock);
+ return standby_l();
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::standby_l()
+{
+ int result = NO_ERROR;
if (!mStandby) {
- result = a2dp_stop(mData);
- if (result == 0)
- mStandby = true;
+ LOGV_IF(mClosing || !mBluetoothEnabled, "Standby skip stop: closing %d enabled %d",
+ mClosing, mBluetoothEnabled);
+ if (!mClosing && mBluetoothEnabled) {
+ result = a2dp_stop(mData);
+ }
+ release_wake_lock(sA2dpWakeLock);
+ mStandby = true;
}
return result;
@@ -362,6 +390,9 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::setParameters(const String8& ke
key = String8("closing");
if (param.get(key, value) == NO_ERROR) {
mClosing = (value == "true");
+ if (mClosing) {
+ standby();
+ }
param.remove(key);
}
key = AudioParameter::keyRouting;
@@ -444,6 +475,7 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::close()
status_t A2dpAudioInterface::A2dpAudioStreamOut::close_l()
{
+ standby_l();
if (mData) {
LOGV("A2dpAudioStreamOut::close_l() calling a2dp_cleanup(mData)");
a2dp_cleanup(mData);
diff --git a/services/audioflinger/A2dpAudioInterface.h b/services/audioflinger/A2dpAudioInterface.h
index 48154f9..dbe2c6a 100644
--- a/services/audioflinger/A2dpAudioInterface.h
+++ b/services/audioflinger/A2dpAudioInterface.h
@@ -103,6 +103,7 @@ private:
status_t setAddress(const char* address);
status_t setBluetoothEnabled(bool enabled);
status_t setSuspended(bool onOff);
+ status_t standby_l();
private:
int mFd;
@@ -116,6 +117,8 @@ private:
uint32_t mDevice;
bool mClosing;
bool mSuspended;
+ nsecs_t mLastWriteTime;
+ uint32_t mBufferDurationUs;
};
friend class A2dpAudioStreamOut;
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 5935bf9..4ec16c1 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -131,18 +131,21 @@ AudioFlinger::AudioFlinger()
: BnAudioFlinger(),
mAudioHardware(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1)
{
+ Mutex::Autolock _l(mLock);
+
mHardwareStatus = AUDIO_HW_IDLE;
mAudioHardware = AudioHardwareInterface::create();
mHardwareStatus = AUDIO_HW_INIT;
if (mAudioHardware->initCheck() == NO_ERROR) {
- // open 16-bit output stream for s/w mixer
+ AutoMutex lock(mHardwareLock);
mMode = AudioSystem::MODE_NORMAL;
- setMode(mMode);
-
- setMasterVolume(1.0f);
- setMasterMute(false);
+ mHardwareStatus = AUDIO_HW_SET_MODE;
+ mAudioHardware->setMode(mMode);
+ mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
+ mAudioHardware->setMasterVolume(1.0f);
+ mHardwareStatus = AUDIO_HW_IDLE;
} else {
LOGE("Couldn't even initialize the stubbed audio hardware!");
}
@@ -343,7 +346,7 @@ sp<IAudioTrack> AudioFlinger::createTrack(
lSessionId = *sessionId;
} else {
// if no audio session id is provided, create one here
- lSessionId = nextUniqueId();
+ lSessionId = nextUniqueId_l();
if (sessionId != NULL) {
*sessionId = lSessionId;
}
@@ -440,13 +443,16 @@ status_t AudioFlinger::setMasterVolume(float value)
}
// when hw supports master volume, don't scale in sw mixer
- AutoMutex lock(mHardwareLock);
- mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
- if (mAudioHardware->setMasterVolume(value) == NO_ERROR) {
- value = 1.0f;
+ { // scope for the lock
+ AutoMutex lock(mHardwareLock);
+ mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
+ if (mAudioHardware->setMasterVolume(value) == NO_ERROR) {
+ value = 1.0f;
+ }
+ mHardwareStatus = AUDIO_HW_IDLE;
}
- mHardwareStatus = AUDIO_HW_IDLE;
+ Mutex::Autolock _l(mLock);
mMasterVolume = value;
for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
mPlaybackThreads.valueAt(i)->setMasterVolume(value);
@@ -517,6 +523,7 @@ status_t AudioFlinger::setMasterMute(bool muted)
return PERMISSION_DENIED;
}
+ Mutex::Autolock _l(mLock);
mMasterMute = muted;
for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
mPlaybackThreads.valueAt(i)->setMasterMute(muted);
@@ -579,6 +586,7 @@ status_t AudioFlinger::setStreamMute(int stream, bool muted)
return BAD_VALUE;
}
+ AutoMutex lock(mLock);
mStreamTypes[stream].mute = muted;
for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
mPlaybackThreads.valueAt(i)->setStreamMute(stream, muted);
@@ -616,17 +624,6 @@ bool AudioFlinger::streamMute(int stream) const
return mStreamTypes[stream].mute;
}
-bool AudioFlinger::isStreamActive(int stream) const
-{
- Mutex::Autolock _l(mLock);
- for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) {
- if (mPlaybackThreads.valueAt(i)->isStreamActive(stream)) {
- return true;
- }
- }
- return false;
-}
-
status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs)
{
status_t result;
@@ -1283,20 +1280,6 @@ bool AudioFlinger::PlaybackThread::streamMute(int stream) const
return mStreamTypes[stream].mute;
}
-bool AudioFlinger::PlaybackThread::isStreamActive(int stream) const
-{
- Mutex::Autolock _l(mLock);
- size_t count = mActiveTracks.size();
- for (size_t i = 0 ; i < count ; ++i) {
- sp<Track> t = mActiveTracks[i].promote();
- if (t == 0) continue;
- Track* const track = t.get();
- if (t->type() == stream)
- return true;
- }
- return false;
-}
-
// addTrack_l() must be called with ThreadBase::mLock held
status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
{
@@ -3699,7 +3682,7 @@ sp<IAudioRecord> AudioFlinger::openRecord(
if (sessionId != NULL && *sessionId != AudioSystem::SESSION_OUTPUT_MIX) {
lSessionId = *sessionId;
} else {
- lSessionId = nextUniqueId();
+ lSessionId = nextUniqueId_l();
if (sessionId != NULL) {
*sessionId = lSessionId;
}
@@ -4300,7 +4283,7 @@ int AudioFlinger::openOutput(uint32_t *pDevices,
mHardwareStatus = AUDIO_HW_IDLE;
if (output != 0) {
- int id = nextUniqueId();
+ int id = nextUniqueId_l();
if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
(format != AudioSystem::PCM_16_BIT) ||
(channels != AudioSystem::CHANNEL_OUT_STEREO)) {
@@ -4348,7 +4331,7 @@ int AudioFlinger::openDuplicateOutput(int output1, int output2)
return 0;
}
- int id = nextUniqueId();
+ int id = nextUniqueId_l();
DuplicatingThread *thread = new DuplicatingThread(this, thread1, id);
thread->addOutputTrack(thread2);
mPlaybackThreads.add(id, thread);
@@ -4473,7 +4456,7 @@ int AudioFlinger::openInput(uint32_t *pDevices,
}
if (input != 0) {
- int id = nextUniqueId();
+ int id = nextUniqueId_l();
// Start record thread
thread = new RecordThread(this, input, reqSamplingRate, reqChannels, id);
mRecordThreads.add(id, thread);
@@ -4543,7 +4526,8 @@ status_t AudioFlinger::setStreamOutput(uint32_t stream, int output)
int AudioFlinger::newAudioSessionId()
{
- return nextUniqueId();
+ AutoMutex _l(mLock);
+ return nextUniqueId_l();
}
// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
@@ -4578,9 +4562,10 @@ AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(int input) const
return thread;
}
-int AudioFlinger::nextUniqueId()
+// nextUniqueId_l() must be called with AudioFlinger::mLock held
+int AudioFlinger::nextUniqueId_l()
{
- return android_atomic_inc(&mNextUniqueId);
+ return mNextUniqueId++;
}
// ----------------------------------------------------------------------------
@@ -4967,7 +4952,7 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::PlaybackThread::createEffect_l(
LOGV("createEffect_l() got effect %p on chain %p", effect == 0 ? 0 : effect.get(), chain.get());
if (effect == 0) {
- int id = mAudioFlinger->nextUniqueId();
+ int id = mAudioFlinger->nextUniqueId_l();
// Check CPU and memory usage
lStatus = AudioSystem::registerEffect(desc, mId, chain->strategy(), sessionId, id);
if (lStatus != NO_ERROR) {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 5917632..81f2eb4 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -107,8 +107,6 @@ public:
virtual status_t setMicMute(bool state);
virtual bool getMicMute() const;
- virtual bool isStreamActive(int stream) const;
-
virtual status_t setParameters(int ioHandle, const String8& keyValuePairs);
virtual String8 getParameters(int ioHandle, const String8& keys);
@@ -579,8 +577,6 @@ private:
virtual float streamVolume(int stream) const;
virtual bool streamMute(int stream) const;
- bool isStreamActive(int stream) const;
-
sp<Track> createTrack_l(
const sp<AudioFlinger::Client>& client,
int streamType,
@@ -785,7 +781,7 @@ private:
float streamVolumeInternal(int stream) const { return mStreamTypes[stream].volume; }
void audioConfigChanged_l(int event, int ioHandle, void *param2);
- int nextUniqueId();
+ int nextUniqueId_l();
status_t moveEffectChain_l(int session,
AudioFlinger::PlaybackThread *srcThread,
AudioFlinger::PlaybackThread *dstThread,
diff --git a/services/audioflinger/AudioPolicyManagerBase.cpp b/services/audioflinger/AudioPolicyManagerBase.cpp
index 4612af1..afa9acc 100644
--- a/services/audioflinger/AudioPolicyManagerBase.cpp
+++ b/services/audioflinger/AudioPolicyManagerBase.cpp
@@ -312,8 +312,7 @@ void AudioPolicyManagerBase::setPhoneState(int state)
// Flag that ringtone volume must be limited to music volume until we exit MODE_RINGTONE
if (state == AudioSystem::MODE_RINGTONE &&
- (hwOutputDesc->mRefCount[AudioSystem::MUSIC] ||
- (systemTime() - mMusicStopTime) < seconds(SONIFICATION_HEADSET_MUSIC_DELAY))) {
+ isStreamActive(AudioSystem::MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY)) {
mLimitRingtoneVolume = true;
} else {
mLimitRingtoneVolume = false;
@@ -343,7 +342,9 @@ void AudioPolicyManagerBase::setForceUse(AudioSystem::force_use usage, AudioSyst
break;
case AudioSystem::FOR_MEDIA:
if (config != AudioSystem::FORCE_HEADPHONES && config != AudioSystem::FORCE_BT_A2DP &&
- config != AudioSystem::FORCE_WIRED_ACCESSORY && config != AudioSystem::FORCE_NONE) {
+ config != AudioSystem::FORCE_WIRED_ACCESSORY &&
+ config != AudioSystem::FORCE_ANALOG_DOCK &&
+ config != AudioSystem::FORCE_DIGITAL_DOCK && config != AudioSystem::FORCE_NONE) {
LOGW("setForceUse() invalid config %d for FOR_MEDIA", config);
return;
}
@@ -359,7 +360,10 @@ void AudioPolicyManagerBase::setForceUse(AudioSystem::force_use usage, AudioSyst
break;
case AudioSystem::FOR_DOCK:
if (config != AudioSystem::FORCE_NONE && config != AudioSystem::FORCE_BT_CAR_DOCK &&
- config != AudioSystem::FORCE_BT_DESK_DOCK && config != AudioSystem::FORCE_WIRED_ACCESSORY) {
+ config != AudioSystem::FORCE_BT_DESK_DOCK &&
+ config != AudioSystem::FORCE_WIRED_ACCESSORY &&
+ config != AudioSystem::FORCE_ANALOG_DOCK &&
+ config != AudioSystem::FORCE_DIGITAL_DOCK) {
LOGW("setForceUse() invalid config %d for FOR_DOCK", config);
}
forceVolumeReeval = true;
@@ -473,6 +477,7 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str
outputDesc->mLatency = 0;
outputDesc->mFlags = (AudioSystem::output_flags)(flags | AudioSystem::OUTPUT_FLAG_DIRECT);
outputDesc->mRefCount[stream] = 0;
+ outputDesc->mStopTime[stream] = 0;
output = mpClientInterface->openOutput(&outputDesc->mDevice,
&outputDesc->mSamplingRate,
&outputDesc->mFormat,
@@ -601,10 +606,8 @@ status_t AudioPolicyManagerBase::stopOutput(audio_io_handle_t output,
if (outputDesc->mRefCount[stream] > 0) {
// decrement usage count of this stream on the output
outputDesc->changeRefCount(stream, -1);
- // store time at which the last music track was stopped - see computeVolume()
- if (stream == AudioSystem::MUSIC) {
- mMusicStopTime = systemTime();
- }
+ // store time at which the stream was stopped - see isStreamActive()
+ outputDesc->mStopTime[stream] = systemTime();
setOutputDevice(output, getNewDevice(output));
@@ -914,6 +917,19 @@ status_t AudioPolicyManagerBase::unregisterEffect(int id)
return NO_ERROR;
}
+bool AudioPolicyManagerBase::isStreamActive(int stream, uint32_t inPastMs) const
+{
+ nsecs_t sysTime = systemTime();
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ if (mOutputs.valueAt(i)->mRefCount[stream] != 0 ||
+ ns2ms(sysTime - mOutputs.valueAt(i)->mStopTime[stream]) < inPastMs) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
status_t AudioPolicyManagerBase::dump(int fd)
{
const size_t SIZE = 256;
@@ -1004,7 +1020,7 @@ AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clien
Thread(false),
#endif //AUDIO_POLICY_TEST
mPhoneState(AudioSystem::MODE_NORMAL), mRingerMode(0),
- mMusicStopTime(0), mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
+ mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0),
mA2dpSuspended(false)
{
@@ -1047,25 +1063,27 @@ AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clien
updateDeviceForStrategy();
#ifdef AUDIO_POLICY_TEST
- AudioParameter outputCmd = AudioParameter();
- outputCmd.addInt(String8("set_id"), 0);
- mpClientInterface->setParameters(mHardwareOutput, outputCmd.toString());
-
- mTestDevice = AudioSystem::DEVICE_OUT_SPEAKER;
- mTestSamplingRate = 44100;
- mTestFormat = AudioSystem::PCM_16_BIT;
- mTestChannels = AudioSystem::CHANNEL_OUT_STEREO;
- mTestLatencyMs = 0;
- mCurOutput = 0;
- mDirectOutput = false;
- for (int i = 0; i < NUM_TEST_OUTPUTS; i++) {
- mTestOutputs[i] = 0;
- }
+ if (mHardwareOutput != 0) {
+ AudioParameter outputCmd = AudioParameter();
+ outputCmd.addInt(String8("set_id"), 0);
+ mpClientInterface->setParameters(mHardwareOutput, outputCmd.toString());
+
+ mTestDevice = AudioSystem::DEVICE_OUT_SPEAKER;
+ mTestSamplingRate = 44100;
+ mTestFormat = AudioSystem::PCM_16_BIT;
+ mTestChannels = AudioSystem::CHANNEL_OUT_STEREO;
+ mTestLatencyMs = 0;
+ mCurOutput = 0;
+ mDirectOutput = false;
+ for (int i = 0; i < NUM_TEST_OUTPUTS; i++) {
+ mTestOutputs[i] = 0;
+ }
- const size_t SIZE = 256;
- char buffer[SIZE];
- snprintf(buffer, SIZE, "AudioPolicyManagerTest");
- run(buffer, ANDROID_PRIORITY_AUDIO);
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ snprintf(buffer, SIZE, "AudioPolicyManagerTest");
+ run(buffer, ANDROID_PRIORITY_AUDIO);
+ }
#endif //AUDIO_POLICY_TEST
}
@@ -1086,6 +1104,11 @@ AudioPolicyManagerBase::~AudioPolicyManagerBase()
mInputs.clear();
}
+status_t AudioPolicyManagerBase::initCheck()
+{
+ return (mHardwareOutput == 0) ? NO_INIT : NO_ERROR;
+}
+
#ifdef AUDIO_POLICY_TEST
bool AudioPolicyManagerBase::threadLoop()
{
@@ -1347,6 +1370,7 @@ status_t AudioPolicyManagerBase::handleA2dpDisconnection(AudioSystem::audio_devi
void AudioPolicyManagerBase::closeA2dpOutputs()
{
+
LOGV("setDeviceConnectionState() closing A2DP and duplicated output!");
if (mDuplicatedOutput != 0) {
@@ -1581,6 +1605,12 @@ uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy,
if (device) break;
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
if (device) break;
+ device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
+ if (device) break;
+ device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
+ if (device) break;
+ device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
+ if (device) break;
#ifdef WITH_A2DP
// when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
if (!isInCall()) {
@@ -1597,10 +1627,12 @@ uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy,
break;
case AudioSystem::FORCE_SPEAKER:
- if (!isInCall() || strategy != STRATEGY_DTMF) {
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
- if (device) break;
- }
+ device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
+ if (device) break;
+ device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
+ if (device) break;
+ device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
+ if (device) break;
#ifdef WITH_A2DP
// when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
// A2DP speaker when forcing to speaker output
@@ -1633,12 +1665,18 @@ uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy,
// FALL THROUGH
case STRATEGY_MEDIA: {
- uint32_t device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
+ uint32_t device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
if (device2 == 0) {
- device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
+ device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
}
if (device2 == 0) {
- device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
+ device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
+ }
+ if (device2 == 0) {
+ device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
+ }
+ if (device2 == 0) {
+ device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
}
#ifdef WITH_A2DP
if (mA2dpOutput != 0) {
@@ -1805,7 +1843,9 @@ float AudioPolicyManagerBase::computeVolume(int stream, int index, audio_io_hand
(AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP |
AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
AudioSystem::DEVICE_OUT_WIRED_HEADSET |
- AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)) &&
+ AudioSystem::DEVICE_OUT_WIRED_HEADPHONE |
+ AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET |
+ AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)) &&
((getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION) ||
(stream == AudioSystem::SYSTEM)) &&
streamDesc.mCanBeMuted) {
@@ -2007,6 +2047,7 @@ AudioPolicyManagerBase::AudioOutputDescriptor::AudioOutputDescriptor()
mRefCount[i] = 0;
mCurVolume[i] = -1.0;
mMuteCount[i] = 0;
+ mStopTime[i] = 0;
}
}
@@ -2057,7 +2098,6 @@ uint32_t AudioPolicyManagerBase::AudioOutputDescriptor::strategyRefCount(routing
return refCount;
}
-
status_t AudioPolicyManagerBase::AudioOutputDescriptor::dump(int fd)
{
const size_t SIZE = 256;
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index f24e08e..b04672d 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -68,6 +68,8 @@ AudioPolicyService::AudioPolicyService()
{
char value[PROPERTY_VALUE_MAX];
+ Mutex::Autolock _l(mLock);
+
// start tone playback thread
mTonePlaybackThread = new AudioCommandThread(String8(""));
// start audio commands thread
@@ -88,9 +90,18 @@ AudioPolicyService::AudioPolicyService()
}
#endif
- // load properties
- property_get("ro.camera.sound.forced", value, "0");
- mpPolicyManager->setSystemProperty("ro.camera.sound.forced", value);
+ if ((mpPolicyManager != NULL) && (mpPolicyManager->initCheck() != NO_ERROR)) {
+ delete mpPolicyManager;
+ mpPolicyManager = NULL;
+ }
+
+ if (mpPolicyManager == NULL) {
+ LOGE("Could not create AudioPolicyManager");
+ } else {
+ // load properties
+ property_get("ro.camera.sound.forced", value, "0");
+ mpPolicyManager->setSystemProperty("ro.camera.sound.forced", value);
+ }
}
AudioPolicyService::~AudioPolicyService()
@@ -383,6 +394,15 @@ status_t AudioPolicyService::unregisterEffect(int id)
return mpPolicyManager->unregisterEffect(id);
}
+bool AudioPolicyService::isStreamActive(int stream, uint32_t inPastMs) const
+{
+ if (mpPolicyManager == NULL) {
+ return 0;
+ }
+ Mutex::Autolock _l(mLock);
+ return mpPolicyManager->isStreamActive(stream, inPastMs);
+}
+
void AudioPolicyService::binderDied(const wp<IBinder>& who) {
LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(),
IPCThreadState::self()->getCallingPid());
diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h
index 558f455..54af1f1 100644
--- a/services/audioflinger/AudioPolicyService.h
+++ b/services/audioflinger/AudioPolicyService.h
@@ -88,6 +88,7 @@ public:
int session,
int id);
virtual status_t unregisterEffect(int id);
+ virtual bool isStreamActive(int stream, uint32_t inPastMs = 0) const;
virtual status_t onTransact(
uint32_t code,
@@ -230,8 +231,8 @@ private:
status_t dumpPermissionDenial(int fd);
- Mutex mLock; // prevents concurrent access to AudioPolicy manager functions changing device
- // connection stated our routing
+ mutable Mutex mLock; // prevents concurrent access to AudioPolicy manager functions changing
+ // device connection state or routing
AudioPolicyInterface* mpPolicyManager; // the platform specific policy manager
sp <AudioCommandThread> mAudioCommandThread; // audio commands thread
sp <AudioCommandThread> mTonePlaybackThread; // tone playback thread
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index 87975af..b52fc69 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -49,7 +49,8 @@ LOCAL_SHARED_LIBRARIES:= \
libcutils \
libmedia \
libcamera_client \
- libsurfaceflinger_client
+ libsurfaceflinger_client \
+ libgui
LOCAL_MODULE:= libcameraservice
diff --git a/services/camera/libcameraservice/CameraHardwareStub.cpp b/services/camera/libcameraservice/CameraHardwareStub.cpp
index b3e0ee6..07b5a37 100644
--- a/services/camera/libcameraservice/CameraHardwareStub.cpp
+++ b/services/camera/libcameraservice/CameraHardwareStub.cpp
@@ -101,9 +101,9 @@ CameraHardwareStub::~CameraHardwareStub()
mFakeCamera = 0; // paranoia
}
-sp<IMemoryHeap> CameraHardwareStub::getPreviewHeap() const
+status_t CameraHardwareStub::setPreviewWindow(const sp<ANativeWindow>& buf)
{
- return mPreviewHeap;
+ return NO_ERROR;
}
sp<IMemoryHeap> CameraHardwareStub::getRawHeap() const
diff --git a/services/camera/libcameraservice/CameraHardwareStub.h b/services/camera/libcameraservice/CameraHardwareStub.h
index d3427ba..9b66a76 100644
--- a/services/camera/libcameraservice/CameraHardwareStub.h
+++ b/services/camera/libcameraservice/CameraHardwareStub.h
@@ -29,7 +29,7 @@ namespace android {
class CameraHardwareStub : public CameraHardwareInterface {
public:
- virtual sp<IMemoryHeap> getPreviewHeap() const;
+ virtual status_t setPreviewWindow(const sp<ANativeWindow>& buf);
virtual sp<IMemoryHeap> getRawHeap() const;
virtual void setCallbacks(notify_callback notify_cb,
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index a64ddcf..3d8ca7a 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -26,11 +26,12 @@
#include <binder/MemoryBase.h>
#include <binder/MemoryHeapBase.h>
#include <cutils/atomic.h>
+#include <cutils/properties.h>
+#include <gui/SurfaceTextureClient.h>
#include <hardware/hardware.h>
#include <media/AudioSystem.h>
#include <media/mediaplayer.h>
#include <surfaceflinger/ISurface.h>
-#include <ui/Overlay.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/String16.h>
@@ -305,9 +306,9 @@ CameraService::Client::Client(const sp<CameraService>& cameraService,
mCameraId = cameraId;
mCameraFacing = cameraFacing;
mClientPid = clientPid;
- mUseOverlay = mHardware->useOverlay();
mMsgEnabled = 0;
-
+ mSurface = 0;
+ mPreviewWindow = 0;
mHardware->setCallbacks(notifyCallback,
dataCallback,
dataCallbackTimestamp,
@@ -317,42 +318,21 @@ CameraService::Client::Client(const sp<CameraService>& cameraService,
enableMsgType(CAMERA_MSG_ERROR |
CAMERA_MSG_ZOOM |
CAMERA_MSG_FOCUS);
- mOverlayW = 0;
- mOverlayH = 0;
// Callback is disabled by default
mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT);
- mOrientationChanged = false;
+ mPlayShutterSound = true;
cameraService->setCameraBusy(cameraId);
cameraService->loadSound();
LOG1("Client::Client X (pid %d)", callingPid);
}
-static void *unregister_surface(void *arg) {
- ISurface *surface = (ISurface *)arg;
- surface->unregisterBuffers();
- IPCThreadState::self()->flushCommands();
- return NULL;
-}
-
// tear down the client
CameraService::Client::~Client() {
int callingPid = getCallingPid();
LOG1("Client::~Client E (pid %d, this %p)", callingPid, this);
- if (mSurface != 0 && !mUseOverlay) {
- pthread_t thr;
- // We unregister the buffers in a different thread because binder does
- // not let us make sychronous transactions in a binder destructor (that
- // is, upon our reaching a refcount of zero.)
- pthread_create(&thr,
- NULL, // attr
- unregister_surface,
- mSurface.get());
- pthread_join(thr, NULL);
- }
-
// set mClientPid to let disconnet() tear down the hardware
mClientPid = callingPid;
disconnect();
@@ -466,9 +446,11 @@ void CameraService::Client::disconnect() {
mHardware->cancelPicture();
// Release the hardware resources.
mHardware->release();
- // Release the held overlay resources.
- if (mUseOverlay) {
- mOverlayRef = 0;
+
+ // Release the held ANativeWindow resources.
+ if (mPreviewWindow != 0) {
+ mPreviewWindow = 0;
+ mHardware->setPreviewWindow(mPreviewWindow);
}
mHardware.clear();
@@ -480,8 +462,8 @@ void CameraService::Client::disconnect() {
// ----------------------------------------------------------------------------
-// set the ISurface that the preview will use
-status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface) {
+// set the Surface that the preview will use
+status_t CameraService::Client::setPreviewDisplay(const sp<Surface>& surface) {
LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());
Mutex::Autolock lock(mLock);
status_t result = checkPidAndHardware();
@@ -491,100 +473,64 @@ status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface) {
// return if no change in surface.
// asBinder() is safe on NULL (returns NULL)
- if (surface->asBinder() == mSurface->asBinder()) {
+ if (getISurface(surface)->asBinder() == mSurface) {
return result;
}
if (mSurface != 0) {
LOG1("clearing old preview surface %p", mSurface.get());
- if (mUseOverlay) {
- // Force the destruction of any previous overlay
- sp<Overlay> dummy;
- mHardware->setOverlay(dummy);
- mOverlayRef = 0;
- } else {
- mSurface->unregisterBuffers();
- }
}
- mSurface = surface;
- mOverlayRef = 0;
- // If preview has been already started, set overlay or register preview
+ mSurface = getISurface(surface)->asBinder();
+ mPreviewWindow = surface;
+
+ // If preview has been already started, register preview
// buffers now.
if (mHardware->previewEnabled()) {
- if (mUseOverlay) {
- result = setOverlay();
- } else if (mSurface != 0) {
- result = registerPreviewBuffers();
+ if (mPreviewWindow != 0) {
+ native_window_set_buffers_transform(mPreviewWindow.get(),
+ mOrientation);
+ result = mHardware->setPreviewWindow(mPreviewWindow);
}
}
return result;
}
-status_t CameraService::Client::registerPreviewBuffers() {
- int w, h;
- CameraParameters params(mHardware->getParameters());
- params.getPreviewSize(&w, &h);
-
- // FIXME: don't use a hardcoded format here.
- ISurface::BufferHeap buffers(w, h, w, h,
- HAL_PIXEL_FORMAT_YCrCb_420_SP,
- mOrientation,
- 0,
- mHardware->getPreviewHeap());
+// set the SurfaceTexture that the preview will use
+status_t CameraService::Client::setPreviewTexture(
+ const sp<ISurfaceTexture>& surfaceTexture) {
+ LOG1("setPreviewTexture(%p) (pid %d)", surfaceTexture.get(),
+ getCallingPid());
+ Mutex::Autolock lock(mLock);
+ status_t result = checkPidAndHardware();
+ if (result != NO_ERROR) return result;
- status_t result = mSurface->registerBuffers(buffers);
- if (result != NO_ERROR) {
- LOGE("registerBuffers failed with status %d", result);
+ // return if no change in surface.
+ // asBinder() is safe on NULL (returns NULL)
+ if (surfaceTexture->asBinder() == mSurface) {
+ return result;
}
- return result;
-}
-
-status_t CameraService::Client::setOverlay() {
- int w, h;
- CameraParameters params(mHardware->getParameters());
- params.getPreviewSize(&w, &h);
- if (w != mOverlayW || h != mOverlayH || mOrientationChanged) {
- // Force the destruction of any previous overlay
- sp<Overlay> dummy;
- mHardware->setOverlay(dummy);
- mOverlayRef = 0;
- mOrientationChanged = false;
+ if (mSurface != 0) {
+ LOG1("clearing old preview surface %p", mSurface.get());
}
-
- status_t result = NO_ERROR;
- if (mSurface == 0) {
- result = mHardware->setOverlay(NULL);
+ mSurface = surfaceTexture->asBinder();
+ if (surfaceTexture != 0) {
+ mPreviewWindow = new SurfaceTextureClient(surfaceTexture);
} else {
- if (mOverlayRef == 0) {
- // FIXME:
- // Surfaceflinger may hold onto the previous overlay reference for some
- // time after we try to destroy it. retry a few times. In the future, we
- // should make the destroy call block, or possibly specify that we can
- // wait in the createOverlay call if the previous overlay is in the
- // process of being destroyed.
- for (int retry = 0; retry < 50; ++retry) {
- mOverlayRef = mSurface->createOverlay(w, h, OVERLAY_FORMAT_DEFAULT,
- mOrientation);
- if (mOverlayRef != 0) break;
- LOGW("Overlay create failed - retrying");
- usleep(20000);
- }
- if (mOverlayRef == 0) {
- LOGE("Overlay Creation Failed!");
- return -EINVAL;
- }
- result = mHardware->setOverlay(new Overlay(mOverlayRef));
- }
- }
- if (result != NO_ERROR) {
- LOGE("mHardware->setOverlay() failed with status %d\n", result);
- return result;
+ mPreviewWindow = 0;
}
- mOverlayW = w;
- mOverlayH = h;
+ // If preview has been already started, set overlay or register preview
+ // buffers now.
+ if (mHardware->previewEnabled()) {
+ // XXX: What if the new preview window is 0?
+ if (mPreviewWindow != 0) {
+ native_window_set_buffers_transform(mPreviewWindow.get(),
+ mOrientation);
+ result = mHardware->setPreviewWindow(mPreviewWindow);
+ }
+ }
return result;
}
@@ -597,16 +543,10 @@ void CameraService::Client::setPreviewCallbackFlag(int callback_flag) {
if (checkPidAndHardware() != NO_ERROR) return;
mPreviewCallbackFlag = callback_flag;
-
- // If we don't use overlay, we always need the preview frame for display.
- // If we do use overlay, we only need the preview frame if the user
- // wants the data.
- if (mUseOverlay) {
- if(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK) {
- enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
- } else {
- disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
- }
+ if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK) {
+ enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+ } else {
+ disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
}
}
@@ -631,14 +571,14 @@ status_t CameraService::Client::startCameraMode(camera_mode mode) {
switch(mode) {
case CAMERA_PREVIEW_MODE:
- if (mSurface == 0) {
+ if (mSurface == 0 && mPreviewWindow == 0) {
LOG1("mSurface is not set yet.");
// still able to start preview in this case.
}
return startPreviewMode();
case CAMERA_RECORDING_MODE:
- if (mSurface == 0) {
- LOGE("mSurface must be set before startRecordingMode.");
+ if (mSurface == 0 && mPreviewWindow == 0) {
+ LOGE("mSurface or mPreviewWindow must be set before startRecordingMode.");
return INVALID_OPERATION;
}
return startRecordingMode();
@@ -656,25 +596,13 @@ status_t CameraService::Client::startPreviewMode() {
return NO_ERROR;
}
- if (mUseOverlay) {
- // If preview display has been set, set overlay now.
- if (mSurface != 0) {
- result = setOverlay();
- }
- if (result != NO_ERROR) return result;
- result = mHardware->startPreview();
- } else {
- enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
- result = mHardware->startPreview();
- if (result != NO_ERROR) return result;
- // If preview display has been set, register preview buffers now.
- if (mSurface != 0) {
- // Unregister here because the surface may be previously registered
- // with the raw (snapshot) heap.
- mSurface->unregisterBuffers();
- result = registerPreviewBuffers();
- }
+ if (mPreviewWindow != 0) {
+ native_window_set_buffers_transform(mPreviewWindow.get(),
+ mOrientation);
}
+ mHardware->setPreviewWindow(mPreviewWindow);
+ result = mHardware->startPreview();
+
return result;
}
@@ -711,13 +639,10 @@ void CameraService::Client::stopPreview() {
Mutex::Autolock lock(mLock);
if (checkPidAndHardware() != NO_ERROR) return;
+
disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
mHardware->stopPreview();
- if (mSurface != 0 && !mUseOverlay) {
- mSurface->unregisterBuffers();
- }
-
mPreviewBuffer.clear();
}
@@ -741,6 +666,30 @@ void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem) {
mHardware->releaseRecordingFrame(mem);
}
+int32_t CameraService::Client::getNumberOfVideoBuffers() const {
+ LOG1("getNumberOfVideoBuffers");
+ Mutex::Autolock lock(mLock);
+ if (checkPidAndHardware() != NO_ERROR) return 0;
+ return mHardware->getNumberOfVideoBuffers();
+}
+
+sp<IMemory> CameraService::Client::getVideoBuffer(int32_t index) const {
+ LOG1("getVideoBuffer: %d", index);
+ Mutex::Autolock lock(mLock);
+ if (checkPidAndHardware() != NO_ERROR) return 0;
+ return mHardware->getVideoBuffer(index);
+}
+
+status_t CameraService::Client::storeMetaDataInBuffers(bool enabled)
+{
+ LOG1("storeMetaDataInBuffers: %s", enabled? "true": "false");
+ Mutex::Autolock lock(mLock);
+ if (checkPidAndHardware() != NO_ERROR) {
+ return UNKNOWN_ERROR;
+ }
+ return mHardware->storeMetaDataInBuffers(enabled);
+}
+
bool CameraService::Client::previewEnabled() {
LOG1("previewEnabled (pid %d)", getCallingPid());
@@ -815,6 +764,35 @@ String8 CameraService::Client::getParameters() const {
return params;
}
+// enable shutter sound
+status_t CameraService::Client::enableShutterSound(bool enable) {
+ LOG1("enableShutterSound (pid %d)", getCallingPid());
+
+ status_t result = checkPidAndHardware();
+ if (result != NO_ERROR) return result;
+
+ if (enable) {
+ mPlayShutterSound = true;
+ return OK;
+ }
+
+ // Disabling shutter sound may not be allowed. In that case only
+ // allow the mediaserver process to disable the sound.
+ char value[PROPERTY_VALUE_MAX];
+ property_get("ro.camera.sound.forced", value, "0");
+ if (strcmp(value, "0") != 0) {
+ // Disabling shutter sound is not allowed. Deny if the current
+ // process is not mediaserver.
+ if (getCallingPid() != getpid()) {
+ LOGE("Failed to disable shutter sound. Permission denied (pid %d)", getCallingPid());
+ return PERMISSION_DENIED;
+ }
+ }
+
+ mPlayShutterSound = false;
+ return OK;
+}
+
status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
LOG1("sendCommand (pid %d)", getCallingPid());
int orientation;
@@ -833,9 +811,22 @@ status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t a
if (mOrientation != orientation) {
mOrientation = orientation;
- if (mOverlayRef != 0) mOrientationChanged = true;
}
return OK;
+ } else if (cmd == CAMERA_CMD_ENABLE_SHUTTER_SOUND) {
+ switch (arg1) {
+ case 0:
+ enableShutterSound(false);
+ break;
+ case 1:
+ enableShutterSound(true);
+ break;
+ default:
+ return BAD_VALUE;
+ }
+ return OK;
+ } else if (cmd == CAMERA_CMD_PLAY_RECORDING_SOUND) {
+ mCameraService->playSound(SOUND_RECORDING);
}
return mHardware->sendCommand(cmd, arg1, arg2);
@@ -996,11 +987,8 @@ void CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp,
// "size" is the width and height of yuv picture for registerBuffer.
// If it is NULL, use the picture size from parameters.
void CameraService::Client::handleShutter(image_rect_type *size) {
- mCameraService->playSound(SOUND_SHUTTER);
-
- // Screen goes black after the buffer is unregistered.
- if (mSurface != 0 && !mUseOverlay) {
- mSurface->unregisterBuffers();
+ if (mPlayShutterSound) {
+ mCameraService->playSound(SOUND_SHUTTER);
}
sp<ICameraClient> c = mCameraClient;
@@ -1011,29 +999,6 @@ void CameraService::Client::handleShutter(image_rect_type *size) {
}
disableMsgType(CAMERA_MSG_SHUTTER);
- // It takes some time before yuvPicture callback to be called.
- // Register the buffer for raw image here to reduce latency.
- if (mSurface != 0 && !mUseOverlay) {
- int w, h;
- CameraParameters params(mHardware->getParameters());
- if (size == NULL) {
- params.getPictureSize(&w, &h);
- } else {
- w = size->width;
- h = size->height;
- w &= ~1;
- h &= ~1;
- LOG1("Snapshot image width=%d, height=%d", w, h);
- }
- // FIXME: don't use hardcoded format constants here
- ISurface::BufferHeap buffers(w, h, w, h,
- HAL_PIXEL_FORMAT_YCrCb_420_SP, mOrientation, 0,
- mHardware->getRawHeap());
-
- mSurface->registerBuffers(buffers);
- IPCThreadState::self()->flushCommands();
- }
-
mLock.unlock();
}
@@ -1043,12 +1008,6 @@ void CameraService::Client::handlePreviewData(const sp<IMemory>& mem) {
size_t size;
sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
- if (!mUseOverlay) {
- if (mSurface != 0) {
- mSurface->postBuffer(offset);
- }
- }
-
// local copy of the callback flags
int flags = mPreviewCallbackFlag;
@@ -1069,9 +1028,7 @@ void CameraService::Client::handlePreviewData(const sp<IMemory>& mem) {
mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
FRAME_CALLBACK_FLAG_ENABLE_MASK);
- if (mUseOverlay) {
- disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
- }
+ disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
}
if (c != 0) {
@@ -1108,11 +1065,6 @@ void CameraService::Client::handleRawPicture(const sp<IMemory>& mem) {
size_t size;
sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
- // Put the YUV version of the snapshot in the preview display.
- if (mSurface != 0 && !mUseOverlay) {
- mSurface->postBuffer(offset);
- }
-
sp<ICameraClient> c = mCameraClient;
mLock.unlock();
if (c != 0) {
@@ -1292,4 +1244,12 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) {
return NO_ERROR;
}
+sp<ISurface> CameraService::getISurface(const sp<Surface>& surface) {
+ if (surface != 0) {
+ return surface->getISurface();
+ } else {
+ return sp<ISurface>(0);
+ }
+}
+
}; // namespace android
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index f09773d..ccb9cf7 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -79,6 +79,12 @@ private:
sp<MediaPlayer> mSoundPlayer[NUM_SOUNDS];
int mSoundRef; // reference count (release all MediaPlayer when 0)
+ // Used by Client objects to extract the ISurface from a Surface object.
+ // This is used because making Client a friend class of Surface would
+ // require including this header in Surface.h since Client is a nested
+ // class.
+ static sp<ISurface> getISurface(const sp<Surface>& surface);
+
class Client : public BnCamera
{
public:
@@ -87,11 +93,15 @@ private:
virtual status_t connect(const sp<ICameraClient>& client);
virtual status_t lock();
virtual status_t unlock();
- virtual status_t setPreviewDisplay(const sp<ISurface>& surface);
+ virtual status_t setPreviewDisplay(const sp<Surface>& surface);
+ virtual status_t setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture);
virtual void setPreviewCallbackFlag(int flag);
virtual status_t startPreview();
virtual void stopPreview();
virtual bool previewEnabled();
+ virtual int32_t getNumberOfVideoBuffers() const;
+ virtual sp<IMemory> getVideoBuffer(int32_t index) const;
+ virtual status_t storeMetaDataInBuffers(bool enabled);
virtual status_t startRecording();
virtual void stopRecording();
virtual bool recordingEnabled();
@@ -121,7 +131,6 @@ private:
// these are internal functions used to set up preview buffers
status_t registerPreviewBuffers();
- status_t setOverlay();
// camera operation mode
enum camera_mode {
@@ -133,6 +142,9 @@ private:
status_t startPreviewMode();
status_t startRecordingMode();
+ // internal function used by sendCommand to enable/disable shutter sound.
+ status_t enableShutterSound(bool enable);
+
// 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);
@@ -163,18 +175,15 @@ private:
int mCameraFacing; // immutable after constructor
pid_t mClientPid;
sp<CameraHardwareInterface> mHardware; // cleared after disconnect()
- bool mUseOverlay; // immutable after constructor
- sp<OverlayRef> mOverlayRef;
- int mOverlayW;
- int mOverlayH;
int mPreviewCallbackFlag;
int mOrientation; // Current display orientation
- // True if display orientation has been changed. This is only used in overlay.
- int mOrientationChanged;
+ bool mPlayShutterSound;
// Ensures atomicity among the public methods
mutable Mutex mLock;
- sp<ISurface> mSurface;
+ // This is a binder of Surface or SurfaceTexture.
+ sp<IBinder> mSurface;
+ sp<ANativeWindow> mPreviewWindow;
// If the user want us to return a copy of the preview frame (instead
// of the original one), we allocate mPreviewBuffer and reuse it if possible.