summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/audioflinger/A2dpAudioInterface.cpp89
-rw-r--r--services/audioflinger/A2dpAudioInterface.h1
-rw-r--r--services/audioflinger/AudioFlinger.cpp23
-rw-r--r--services/audioflinger/AudioFlinger.h2
-rw-r--r--services/audioflinger/AudioPolicyManagerBase.cpp110
-rw-r--r--services/camera/libcameraservice/CameraHardwareStub.cpp4
-rw-r--r--services/camera/libcameraservice/CameraHardwareStub.h2
-rw-r--r--services/camera/libcameraservice/CameraService.cpp197
-rw-r--r--services/camera/libcameraservice/CameraService.h16
9 files changed, 274 insertions, 170 deletions
diff --git a/services/audioflinger/A2dpAudioInterface.cpp b/services/audioflinger/A2dpAudioInterface.cpp
index 995e31c..aee01ab 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()
@@ -263,44 +266,55 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::set(
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;
+ }
+
+ 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;
+ return bytes;
+ }
Error:
+
+ standby();
+
// Simulate audio output timing in case of error
usleep(((bytes * 1000 )/ frameSize() / sampleRate()) * 1000);
@@ -324,19 +338,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 +379,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 +464,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..cef1926 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;
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index cd9b07e..51b5947 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -343,7 +343,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;
}
@@ -3699,7 +3699,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 +4300,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 +4348,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 +4473,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 +4543,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 +4579,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 +4969,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) {
@@ -5808,7 +5810,8 @@ uint32_t AudioFlinger::EffectModule::deviceAudioSystemToEffectApi(uint32_t devic
const uint32_t AudioFlinger::EffectModule::sModeConvTable[] = {
AUDIO_MODE_NORMAL, // AudioSystem::MODE_NORMAL
AUDIO_MODE_RINGTONE, // AudioSystem::MODE_RINGTONE
- AUDIO_MODE_IN_CALL // AudioSystem::MODE_IN_CALL
+ AUDIO_MODE_IN_CALL, // AudioSystem::MODE_IN_CALL
+ AUDIO_MODE_IN_CALL // AudioSystem::MODE_IN_COMMUNICATION, same conversion as for MODE_IN_CALL
};
int AudioFlinger::EffectModule::modeAudioSystemToEffectApi(uint32_t mode)
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 5917632..f0ef867 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -785,7 +785,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 ee9297f..175f613 100644
--- a/services/audioflinger/AudioPolicyManagerBase.cpp
+++ b/services/audioflinger/AudioPolicyManagerBase.cpp
@@ -235,7 +235,7 @@ void AudioPolicyManagerBase::setPhoneState(int state)
// if leaving call state, handle special case of active streams
// pertaining to sonification strategy see handleIncallSonification()
- if (mPhoneState == AudioSystem::MODE_IN_CALL) {
+ if (isInCall()) {
LOGV("setPhoneState() in call state management: new state is %d", state);
for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
handleIncallSonification(stream, false, true);
@@ -248,16 +248,21 @@ void AudioPolicyManagerBase::setPhoneState(int state)
bool force = false;
// are we entering or starting a call
- if ((oldState != AudioSystem::MODE_IN_CALL) && (state == AudioSystem::MODE_IN_CALL)) {
+ if (!isStateInCall(oldState) && isStateInCall(state)) {
LOGV(" Entering call in setPhoneState()");
// force routing command to audio hardware when starting a call
// even if no device change is needed
force = true;
- } else if ((oldState == AudioSystem::MODE_IN_CALL) && (state != AudioSystem::MODE_IN_CALL)) {
+ } else if (isStateInCall(oldState) && !isStateInCall(state)) {
LOGV(" Exiting call in setPhoneState()");
// force routing command to audio hardware when exiting a call
// even if no device change is needed
force = true;
+ } else if (isStateInCall(state) && (state != oldState)) {
+ LOGV(" Switching between telephony and VoIP in setPhoneState()");
+ // force routing command to audio hardware when switching between telephony and VoIP
+ // even if no device change is needed
+ force = true;
}
// check for device and output changes triggered by new phone state
@@ -272,7 +277,7 @@ void AudioPolicyManagerBase::setPhoneState(int state)
// force routing command to audio hardware when ending call
// even if no device change is needed
- if (oldState == AudioSystem::MODE_IN_CALL && newDevice == 0) {
+ if (isStateInCall(oldState) && newDevice == 0) {
newDevice = hwOutputDesc->device();
}
@@ -280,7 +285,7 @@ void AudioPolicyManagerBase::setPhoneState(int state)
// immediately and delay the route change to avoid sending the ring tone
// tail into the earpiece or headset.
int delayMs = 0;
- if (state == AudioSystem::MODE_IN_CALL && oldState == AudioSystem::MODE_RINGTONE) {
+ if (isStateInCall(state) && oldState == AudioSystem::MODE_RINGTONE) {
// delay the device change command by twice the output latency to have some margin
// and be sure that audio buffers not yet affected by the mute are out when
// we actually apply the route change
@@ -293,7 +298,7 @@ void AudioPolicyManagerBase::setPhoneState(int state)
// if entering in call state, handle special case of active streams
// pertaining to sonification strategy see handleIncallSonification()
- if (state == AudioSystem::MODE_IN_CALL) {
+ if (isStateInCall(state)) {
LOGV("setPhoneState() in call state management: new state is %d", state);
// unmute the ringing tone after a sufficient delay if it was muted before
// setting output device above
@@ -338,7 +343,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;
}
@@ -354,7 +361,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;
@@ -564,7 +574,7 @@ status_t AudioPolicyManagerBase::startOutput(audio_io_handle_t output,
setOutputDevice(output, getNewDevice(output));
// handle special case for sonification while in call
- if (mPhoneState == AudioSystem::MODE_IN_CALL) {
+ if (isInCall()) {
handleIncallSonification(stream, true, false);
}
@@ -589,7 +599,7 @@ status_t AudioPolicyManagerBase::stopOutput(audio_io_handle_t output,
routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream);
// handle special case for sonification while in call
- if (mPhoneState == AudioSystem::MODE_IN_CALL) {
+ if (isInCall()) {
handleIncallSonification(stream, false, false);
}
@@ -738,10 +748,8 @@ status_t AudioPolicyManagerBase::startInput(audio_io_handle_t input)
AudioParameter param = AudioParameter();
param.addInt(String8(AudioParameter::keyRouting), (int)inputDesc->mDevice);
- // use Voice Recognition mode or not for this input based on input source
- int vr_enabled = inputDesc->mInputSource == AUDIO_SOURCE_VOICE_RECOGNITION ? 1 : 0;
- param.addInt(String8("vr_mode"), vr_enabled);
- LOGV("AudioPolicyManager::startInput(%d), setting vr_mode to %d", inputDesc->mInputSource, vr_enabled);
+ param.addInt(String8(AudioParameter::keyInputSource), (int)inputDesc->mInputSource);
+ LOGV("AudioPolicyManager::startInput() input source = %d", inputDesc->mInputSource);
mpClientInterface->setParameters(input, param.toString());
@@ -1000,8 +1008,9 @@ AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clien
#ifdef AUDIO_POLICY_TEST
Thread(false),
#endif //AUDIO_POLICY_TEST
- mPhoneState(AudioSystem::MODE_NORMAL), mRingerMode(0), mMusicStopTime(0),
- mLimitRingtoneVolume(false), mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0),
+ mPhoneState(AudioSystem::MODE_NORMAL), mRingerMode(0),
+ mMusicStopTime(0), mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
+ mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0),
mA2dpSuspended(false)
{
mpClientInterface = clientInterface;
@@ -1343,6 +1352,7 @@ status_t AudioPolicyManagerBase::handleA2dpDisconnection(AudioSystem::audio_devi
void AudioPolicyManagerBase::closeA2dpOutputs()
{
+
LOGV("setDeviceConnectionState() closing A2DP and duplicated output!");
if (mDuplicatedOutput != 0) {
@@ -1493,7 +1503,7 @@ uint32_t AudioPolicyManagerBase::getNewDevice(audio_io_handle_t output, bool fro
// use device for strategy media
// 4: the strategy DTMF is active on the hardware output:
// use device for strategy DTMF
- if (mPhoneState == AudioSystem::MODE_IN_CALL ||
+ if (isInCall() ||
outputDesc->isUsedByStrategy(STRATEGY_PHONE)) {
device = getDeviceForStrategy(STRATEGY_PHONE, fromCache);
} else if (outputDesc->isUsedByStrategy(STRATEGY_SONIFICATION)) {
@@ -1548,7 +1558,7 @@ uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy,
switch (strategy) {
case STRATEGY_DTMF:
- if (mPhoneState != AudioSystem::MODE_IN_CALL) {
+ if (!isInCall()) {
// when off call, DTMF strategy follows the same rules as MEDIA strategy
device = getDeviceForStrategy(STRATEGY_MEDIA, false);
break;
@@ -1561,7 +1571,7 @@ uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy,
// of priority
switch (mForceUse[AudioSystem::FOR_COMMUNICATION]) {
case AudioSystem::FORCE_BT_SCO:
- if (mPhoneState != AudioSystem::MODE_IN_CALL || strategy != STRATEGY_DTMF) {
+ if (!isInCall() || strategy != STRATEGY_DTMF) {
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
if (device) break;
}
@@ -1577,9 +1587,11 @@ 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_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 (mPhoneState != AudioSystem::MODE_IN_CALL) {
+ if (!isInCall()) {
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
if (device) break;
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
@@ -1593,14 +1605,14 @@ uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy,
break;
case AudioSystem::FORCE_SPEAKER:
- if (mPhoneState != AudioSystem::MODE_IN_CALL || strategy != STRATEGY_DTMF) {
+ if (!isInCall() || strategy != STRATEGY_DTMF) {
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
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
- if (mPhoneState != AudioSystem::MODE_IN_CALL) {
+ if (!isInCall()) {
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
if (device) break;
}
@@ -1617,7 +1629,7 @@ uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy,
// If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by
// handleIncallSonification().
- if (mPhoneState == AudioSystem::MODE_IN_CALL) {
+ if (isInCall()) {
device = getDeviceForStrategy(STRATEGY_PHONE, false);
break;
}
@@ -1636,6 +1648,12 @@ uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy,
if (device2 == 0) {
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
}
+ if (device2 == 0) {
+ device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
+ }
+ if (device2 == 0) {
+ device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
+ }
#ifdef WITH_A2DP
if (mA2dpOutput != 0) {
if (strategy == STRATEGY_SONIFICATION && !a2dpUsedForSonification()) {
@@ -1738,6 +1756,7 @@ uint32_t AudioPolicyManagerBase::getDeviceForInputSource(int inputSource)
case AUDIO_SOURCE_DEFAULT:
case AUDIO_SOURCE_MIC:
case AUDIO_SOURCE_VOICE_RECOGNITION:
+ case AUDIO_SOURCE_VOICE_COMMUNICATION:
if (mForceUse[AudioSystem::FOR_RECORD] == AudioSystem::FORCE_BT_SCO &&
mAvailableInputDevices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
device = AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET;
@@ -1800,7 +1819,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) &&
streamDesc.mCanBeMuted) {
volume *= SONIFICATION_HEADSET_VOLUME_FACTOR;
@@ -1838,29 +1859,38 @@ status_t AudioPolicyManagerBase::checkAndSetVolume(int stream, int index, audio_
}
float volume = computeVolume(stream, index, output, device);
- // do not set volume if the float value did not change
- if (volume != mOutputs.valueFor(output)->mCurVolume[stream] || force) {
+ // We actually change the volume if:
+ // - the float value returned by computeVolume() changed
+ // - the force flag is set
+ if (volume != mOutputs.valueFor(output)->mCurVolume[stream] ||
+ force) {
mOutputs.valueFor(output)->mCurVolume[stream] = volume;
LOGV("setStreamVolume() for output %d stream %d, volume %f, delay %d", output, stream, volume, delayMs);
if (stream == AudioSystem::VOICE_CALL ||
stream == AudioSystem::DTMF ||
stream == AudioSystem::BLUETOOTH_SCO) {
- float voiceVolume = -1.0;
// offset value to reflect actual hardware volume that never reaches 0
// 1% corresponds roughly to first step in VOICE_CALL stream volume setting (see AudioService.java)
volume = 0.01 + 0.99 * volume;
- if (stream == AudioSystem::VOICE_CALL) {
- voiceVolume = (float)index/(float)mStreams[stream].mIndexMax;
- } else if (stream == AudioSystem::BLUETOOTH_SCO) {
- voiceVolume = 1.0;
- }
- if (voiceVolume >= 0 && output == mHardwareOutput) {
- mpClientInterface->setVoiceVolume(voiceVolume, delayMs);
- }
}
mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, volume, output, delayMs);
}
+ if (stream == AudioSystem::VOICE_CALL ||
+ stream == AudioSystem::BLUETOOTH_SCO) {
+ float voiceVolume;
+ // Force voice volume to max for bluetooth SCO as volume is managed by the headset
+ if (stream == AudioSystem::VOICE_CALL) {
+ voiceVolume = (float)index/(float)mStreams[stream].mIndexMax;
+ } else {
+ voiceVolume = 1.0;
+ }
+ if (voiceVolume != mLastVoiceVolume && output == mHardwareOutput) {
+ mpClientInterface->setVoiceVolume(voiceVolume, delayMs);
+ mLastVoiceVolume = voiceVolume;
+ }
+ }
+
return NO_ERROR;
}
@@ -1950,6 +1980,16 @@ void AudioPolicyManagerBase::handleIncallSonification(int stream, bool starting,
}
}
+bool AudioPolicyManagerBase::isInCall()
+{
+ return isStateInCall(mPhoneState);
+}
+
+bool AudioPolicyManagerBase::isStateInCall(int state) {
+ return ((state == AudioSystem::MODE_IN_CALL) ||
+ (state == AudioSystem::MODE_IN_COMMUNICATION));
+}
+
bool AudioPolicyManagerBase::needsDirectOuput(AudioSystem::stream_type stream,
uint32_t samplingRate,
uint32_t format,
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..535f07f 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -26,6 +26,7 @@
#include <binder/MemoryBase.h>
#include <binder/MemoryHeapBase.h>
#include <cutils/atomic.h>
+#include <cutils/properties.h>
#include <hardware/hardware.h>
#include <media/AudioSystem.h>
#include <media/mediaplayer.h>
@@ -307,7 +308,6 @@ CameraService::Client::Client(const sp<CameraService>& cameraService,
mClientPid = clientPid;
mUseOverlay = mHardware->useOverlay();
mMsgEnabled = 0;
-
mHardware->setCallbacks(notifyCallback,
dataCallback,
dataCallbackTimestamp,
@@ -324,6 +324,7 @@ CameraService::Client::Client(const sp<CameraService>& cameraService,
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);
@@ -341,18 +342,6 @@ 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();
@@ -470,6 +459,11 @@ void CameraService::Client::disconnect() {
if (mUseOverlay) {
mOverlayRef = 0;
}
+ // Release the held ANativeWindow resources.
+ if (mPreviewWindow != 0) {
+ mPreviewWindow = 0;
+ mHardware->setPreviewWindow(mPreviewWindow);
+ }
mHardware.clear();
mCameraService->removeClient(mCameraClient);
@@ -480,8 +474,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,7 +485,7 @@ 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->asBinder()) {
return result;
}
@@ -502,44 +496,30 @@ status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface) {
sp<Overlay> dummy;
mHardware->setOverlay(dummy);
mOverlayRef = 0;
- } else {
- mSurface->unregisterBuffers();
}
}
- mSurface = surface;
+ if (surface != 0) {
+ mSurface = getISurface(surface);
+ } else {
+ mSurface = 0;
+ }
+ mPreviewWindow = surface;
mOverlayRef = 0;
// If preview has been already started, set overlay or register preview
// buffers now.
if (mHardware->previewEnabled()) {
if (mUseOverlay) {
result = setOverlay();
- } else if (mSurface != 0) {
- result = registerPreviewBuffers();
+ } else 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());
-
- status_t result = mSurface->registerBuffers(buffers);
- if (result != NO_ERROR) {
- LOGE("registerBuffers failed with status %d", result);
- }
- return result;
-}
-
status_t CameraService::Client::setOverlay() {
int w, h;
CameraParameters params(mHardware->getParameters());
@@ -597,16 +577,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 +605,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();
@@ -664,16 +638,12 @@ status_t CameraService::Client::startPreviewMode() {
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 +681,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 +708,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 +806,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;
@@ -836,6 +856,20 @@ status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t a
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 +1030,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;
@@ -1030,7 +1061,6 @@ void CameraService::Client::handleShutter(image_rect_type *size) {
HAL_PIXEL_FORMAT_YCrCb_420_SP, mOrientation, 0,
mHardware->getRawHeap());
- mSurface->registerBuffers(buffers);
IPCThreadState::self()->flushCommands();
}
@@ -1043,12 +1073,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 +1093,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 +1130,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 +1309,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..60e0d04 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,14 @@ 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 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();
@@ -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);
@@ -171,10 +183,12 @@ private:
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;
+ 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.