Merge "RTSP: append track URL to base URL" into mnc-dev
diff --git a/cmds/stagefright/muxer.cpp b/cmds/stagefright/muxer.cpp
index 0029aec..0d04760 100644
--- a/cmds/stagefright/muxer.cpp
+++ b/cmds/stagefright/muxer.cpp
@@ -142,8 +142,13 @@
CHECK_EQ(err, (status_t)OK);
ssize_t newTrackIndex = muxer->addTrack(format);
- CHECK_GE(newTrackIndex, 0);
- trackIndexMap.add(i, newTrackIndex);
+ if (newTrackIndex < 0) {
+ fprintf(stderr, "%s track (%d) unsupported by muxer\n",
+ isAudio ? "audio" : "video",
+ i);
+ } else {
+ trackIndexMap.add(i, newTrackIndex);
+ }
}
int64_t muxerStartTimeUs = ALooper::GetNowUs();
@@ -162,7 +167,12 @@
ALOGV("saw input eos, err %d", err);
sawInputEOS = true;
break;
+ } else if (trackIndexMap.indexOfKey(trackIndex) < 0) {
+ // ALOGV("skipping input from unsupported track %zu", trackIndex);
+ extractor->advance();
+ continue;
} else {
+ // ALOGV("reading sample from track index %zu\n", trackIndex);
err = extractor->readSampleData(newBuffer);
CHECK_EQ(err, (status_t)OK);
diff --git a/include/media/AudioIoDescriptor.h b/include/media/AudioIoDescriptor.h
index 2437901..c94b738 100644
--- a/include/media/AudioIoDescriptor.h
+++ b/include/media/AudioIoDescriptor.h
@@ -33,12 +33,31 @@
class AudioIoDescriptor : public RefBase {
public:
AudioIoDescriptor() :
+ mIoHandle(AUDIO_IO_HANDLE_NONE),
mSamplingRate(0), mFormat(AUDIO_FORMAT_DEFAULT), mChannelMask(AUDIO_CHANNEL_NONE),
- mFrameCount(0), mLatency(0) {}
+ mFrameCount(0), mLatency(0)
+ {
+ memset(&mPatch, 0, sizeof(struct audio_patch));
+ }
virtual ~AudioIoDescriptor() {}
+ audio_port_handle_t getDeviceId() {
+ if (mPatch.num_sources != 0 && mPatch.num_sinks != 0) {
+ if (mPatch.sources[0].type == AUDIO_PORT_TYPE_MIX) {
+ // this is an output mix
+ // FIXME: the API only returns the first device in case of multiple device selection
+ return mPatch.sinks[0].id;
+ } else {
+ // this is an input mix
+ return mPatch.sources[0].id;
+ }
+ }
+ return AUDIO_PORT_HANDLE_NONE;
+ }
+
audio_io_handle_t mIoHandle;
+ struct audio_patch mPatch;
uint32_t mSamplingRate;
audio_format_t mFormat;
audio_channel_mask_t mChannelMask;
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index b743c11..c4c7b0e 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -178,6 +178,8 @@
int sessionId = AUDIO_SESSION_ALLOCATE,
transfer_type transferType = TRANSFER_DEFAULT,
audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
+ int uid = -1,
+ pid_t pid = -1,
const audio_attributes_t* pAttributes = NULL);
/* Terminates the AudioRecord and unregisters it from AudioFlinger.
@@ -214,6 +216,8 @@
int sessionId = AUDIO_SESSION_ALLOCATE,
transfer_type transferType = TRANSFER_DEFAULT,
audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
+ int uid = -1,
+ pid_t pid = -1,
const audio_attributes_t* pAttributes = NULL);
/* Result of constructing the AudioRecord. This must be checked for successful initialization
@@ -390,6 +394,39 @@
* TODO Document this method.
*/
audio_port_handle_t getInputDevice();
+
+ /* Returns the ID of the audio device actually used by the input to which this AudioRecord
+ * is attached.
+ * A value of AUDIO_PORT_HANDLE_NONE indicates the AudioRecord is not attached to any input.
+ *
+ * Parameters:
+ * none.
+ */
+ audio_port_handle_t getRoutedDeviceId();
+
+ /* Add an AudioDeviceCallback. The caller will be notified when the audio device
+ * to which this AudioRecord is routed is updated.
+ * Replaces any previously installed callback.
+ * Parameters:
+ * callback: The callback interface
+ * Returns NO_ERROR if successful.
+ * INVALID_OPERATION if the same callback is already installed.
+ * NO_INIT or PREMISSION_DENIED if AudioFlinger service is not reachable
+ * BAD_VALUE if the callback is NULL
+ */
+ status_t addAudioDeviceCallback(
+ const sp<AudioSystem::AudioDeviceCallback>& callback);
+
+ /* remove an AudioDeviceCallback.
+ * Parameters:
+ * callback: The callback interface
+ * Returns NO_ERROR if successful.
+ * INVALID_OPERATION if the callback is not installed
+ * BAD_VALUE if the callback is NULL
+ */
+ status_t removeAudioDeviceCallback(
+ const sp<AudioSystem::AudioDeviceCallback>& callback);
+
private:
/* If nonContig is non-NULL, it is an output parameter that will be set to the number of
* additional non-contiguous frames that are predicted to be available immediately,
@@ -577,11 +614,14 @@
sp<DeathNotifier> mDeathNotifier;
uint32_t mSequence; // incremented for each new IAudioRecord attempt
+ int mClientUid;
+ pid_t mClientPid;
audio_attributes_t mAttributes;
// For Device Selection API
// a value of AUDIO_PORT_HANDLE_NONE indicated default (AudioPolicyManager) routing.
audio_port_handle_t mSelectedDeviceId;
+ sp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
};
}; // namespace android
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 0cbcdb1..3241e9c 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -332,8 +332,26 @@
};
- static status_t addAudioPortCallback(const sp<AudioPortCallback>& callBack);
- static status_t removeAudioPortCallback(const sp<AudioPortCallback>& callBack);
+ static status_t addAudioPortCallback(const sp<AudioPortCallback>& callback);
+ static status_t removeAudioPortCallback(const sp<AudioPortCallback>& callback);
+
+ class AudioDeviceCallback : public RefBase
+ {
+ public:
+
+ AudioDeviceCallback() {}
+ virtual ~AudioDeviceCallback() {}
+
+ virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo,
+ audio_port_handle_t deviceId) = 0;
+ };
+
+ static status_t addAudioDeviceCallback(const sp<AudioDeviceCallback>& callback,
+ audio_io_handle_t audioIo);
+ static status_t removeAudioDeviceCallback(const sp<AudioDeviceCallback>& callback,
+ audio_io_handle_t audioIo);
+
+ static audio_port_handle_t getDeviceIdForIo(audio_io_handle_t audioIo);
private:
@@ -359,10 +377,20 @@
// values for output/input parameters up-to-date in client process
virtual void ioConfigChanged(audio_io_config_event event,
const sp<AudioIoDescriptor>& ioDesc);
+
+
+ status_t addAudioDeviceCallback(const sp<AudioDeviceCallback>& callback,
+ audio_io_handle_t audioIo);
+ status_t removeAudioDeviceCallback(const sp<AudioDeviceCallback>& callback,
+ audio_io_handle_t audioIo);
+
+ audio_port_handle_t getDeviceIdForIo(audio_io_handle_t audioIo);
+
private:
Mutex mLock;
- DefaultKeyedVector<audio_io_handle_t, sp<AudioIoDescriptor> > mIoDescriptors;
-
+ DefaultKeyedVector<audio_io_handle_t, sp<AudioIoDescriptor> > mIoDescriptors;
+ DefaultKeyedVector<audio_io_handle_t, Vector < sp<AudioDeviceCallback> > >
+ mAudioDeviceCallbacks;
// cached values for recording getInputBufferSize() queries
size_t mInBuffSize; // zero indicates cache is invalid
uint32_t mInSamplingRate;
@@ -377,8 +405,8 @@
AudioPolicyServiceClient() {
}
- status_t addAudioPortCallback(const sp<AudioPortCallback>& callBack);
- status_t removeAudioPortCallback(const sp<AudioPortCallback>& callBack);
+ status_t addAudioPortCallback(const sp<AudioPortCallback>& callback);
+ status_t removeAudioPortCallback(const sp<AudioPortCallback>& callback);
// DeathRecipient
virtual void binderDied(const wp<IBinder>& who);
@@ -393,6 +421,9 @@
Vector <sp <AudioPortCallback> > mAudioPortCallbacks;
};
+ static const sp<AudioFlingerClient> getAudioFlingerClient();
+ static sp<AudioIoDescriptor> getIoDescriptor(audio_io_handle_t ioHandle);
+
static sp<AudioFlingerClient> gAudioFlingerClient;
static sp<AudioPolicyServiceClient> gAudioPolicyServiceClient;
friend class AudioFlingerClient;
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 0ccd19e..458f4b4 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -510,7 +510,7 @@
*/
status_t setOutputDevice(audio_port_handle_t deviceId);
- /* Returns the ID of the audio device used for output of this AudioTrack.
+ /* Returns the ID of the audio device selected for this AudioTrack.
* A value of AUDIO_PORT_HANDLE_NONE indicates default (AudioPolicyManager) routing.
*
* Parameters:
@@ -518,6 +518,15 @@
*/
audio_port_handle_t getOutputDevice();
+ /* Returns the ID of the audio device actually used by the output to which this AudioTrack is
+ * attached.
+ * A value of AUDIO_PORT_HANDLE_NONE indicates the audio track is not attached to any output.
+ *
+ * Parameters:
+ * none.
+ */
+ audio_port_handle_t getRoutedDeviceId();
+
/* Returns the unique session ID associated with this track.
*
* Parameters:
@@ -664,6 +673,28 @@
*/
status_t getTimestamp(AudioTimestamp& timestamp);
+ /* Add an AudioDeviceCallback. The caller will be notified when the audio device to which this
+ * AudioTrack is routed is updated.
+ * Replaces any previously installed callback.
+ * Parameters:
+ * callback: The callback interface
+ * Returns NO_ERROR if successful.
+ * INVALID_OPERATION if the same callback is already installed.
+ * NO_INIT or PREMISSION_DENIED if AudioFlinger service is not reachable
+ * BAD_VALUE if the callback is NULL
+ */
+ status_t addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);
+
+ /* remove an AudioDeviceCallback.
+ * Parameters:
+ * callback: The callback interface
+ * Returns NO_ERROR if successful.
+ * INVALID_OPERATION if the callback is not installed
+ * BAD_VALUE if the callback is NULL
+ */
+ status_t removeAudioDeviceCallback(
+ const sp<AudioSystem::AudioDeviceCallback>& callback);
+
protected:
/* copying audio tracks is not allowed */
AudioTrack(const AudioTrack& other);
@@ -885,6 +916,8 @@
uint32_t mSequence; // incremented for each new IAudioTrack attempt
int mClientUid;
pid_t mClientPid;
+
+ sp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
};
class TimedAudioTrack : public AudioTrack
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index 046345c..3f7fd09 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -89,6 +89,7 @@
size_t *pFrameCount,
track_flags_t *flags,
pid_t tid, // -1 means unused, otherwise must be valid non-0
+ int clientUid,
int *sessionId,
size_t *notificationFrames,
sp<IMemory>& cblk,
diff --git a/include/media/stagefright/MediaSync.h b/include/media/stagefright/MediaSync.h
index a349986..d1d634d 100644
--- a/include/media/stagefright/MediaSync.h
+++ b/include/media/stagefright/MediaSync.h
@@ -75,11 +75,11 @@
// Called when MediaSync is used to render video. It should be called
// before createInputSurface().
- status_t configureSurface(const sp<IGraphicBufferProducer> &output);
+ status_t setSurface(const sp<IGraphicBufferProducer> &output);
// Called when audio track is used as media clock source. It should be
// called before updateQueuedAudioData().
- status_t configureAudioTrack(const sp<AudioTrack> &audioTrack);
+ status_t setAudioTrack(const sp<AudioTrack> &audioTrack);
// Create a surface for client to render video frames. This is the surface
// on which the client should render video frames. Those video frames will
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 23015c0..3868f13 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -85,6 +85,8 @@
int sessionId,
transfer_type transferType,
audio_input_flags_t flags,
+ int uid,
+ pid_t pid,
const audio_attributes_t* pAttributes)
: mStatus(NO_INIT),
mOpPackageName(opPackageName),
@@ -96,7 +98,7 @@
{
mStatus = set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user,
notificationFrames, false /*threadCanCallJava*/, sessionId, transferType, flags,
- pAttributes);
+ uid, pid, pAttributes);
}
AudioRecord::~AudioRecord()
@@ -112,6 +114,10 @@
mAudioRecordThread->requestExitAndWait();
mAudioRecordThread.clear();
}
+ // No lock here: worst case we remove a NULL callback which will be a nop
+ if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) {
+ AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput);
+ }
IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this);
mAudioRecord.clear();
mCblkMemory.clear();
@@ -136,12 +142,15 @@
int sessionId,
transfer_type transferType,
audio_input_flags_t flags,
+ int uid,
+ pid_t pid,
const audio_attributes_t* pAttributes)
{
ALOGV("set(): inputSource %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
- "notificationFrames %u, sessionId %d, transferType %d, flags %#x, opPackageName %s",
+ "notificationFrames %u, sessionId %d, transferType %d, flags %#x, opPackageName %s "
+ "uid %d, pid %d",
inputSource, sampleRate, format, channelMask, frameCount, notificationFrames,
- sessionId, transferType, flags, String8(mOpPackageName).string());
+ sessionId, transferType, flags, String8(mOpPackageName).string(), uid, pid);
switch (transferType) {
case TRANSFER_DEFAULT:
@@ -228,6 +237,19 @@
}
ALOGV("set(): mSessionId %d", mSessionId);
+ int callingpid = IPCThreadState::self()->getCallingPid();
+ int mypid = getpid();
+ if (uid == -1 || (callingpid != mypid)) {
+ mClientUid = IPCThreadState::self()->getCallingUid();
+ } else {
+ mClientUid = uid;
+ }
+ if (pid == -1 || (callingpid != mypid)) {
+ mClientPid = callingpid;
+ } else {
+ mClientPid = pid;
+ }
+
mFlags = flags;
mCbf = cbf;
@@ -286,6 +308,8 @@
mNewPosition = mProxy->getPosition() + mUpdatePeriod;
int32_t flags = android_atomic_acquire_load(&mCblk->mFlags);
+ mActive = true;
+
status_t status = NO_ERROR;
if (!(flags & CBLK_INVALID)) {
status = mAudioRecord->start(event, triggerSession);
@@ -298,9 +322,9 @@
}
if (status != NO_ERROR) {
+ mActive = false;
ALOGE("start() status %d", status);
} else {
- mActive = true;
sp<AudioRecordThread> t = mAudioRecordThread;
if (t != 0) {
t->resume();
@@ -425,6 +449,11 @@
AutoMutex lock(mLock);
if (mSelectedDeviceId != deviceId) {
mSelectedDeviceId = deviceId;
+ // stop capture so that audio policy manager does not reject the new instance start request
+ // as only one capture can be active at a time.
+ if (mAudioRecord != 0 && mActive) {
+ mAudioRecord->stop();
+ }
android_atomic_or(CBLK_INVALID, &mCblk->mFlags);
}
return NO_ERROR;
@@ -435,6 +464,14 @@
return mSelectedDeviceId;
}
+audio_port_handle_t AudioRecord::getRoutedDeviceId() {
+ AutoMutex lock(mLock);
+ if (mInput == AUDIO_IO_HANDLE_NONE) {
+ return AUDIO_PORT_HANDLE_NONE;
+ }
+ return AudioSystem::getDeviceIdForIo(mInput);
+}
+
// -------------------------------------------------------------------------
// must be called with mLock held
@@ -478,6 +515,10 @@
}
}
+ if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) {
+ AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput);
+ }
+
audio_io_handle_t input;
status_t status = AudioSystem::getInputForAttr(&mAttributes, &input,
(audio_session_t)mSessionId,
@@ -513,6 +554,7 @@
&temp,
&trackFlags,
tid,
+ mClientUid,
&mSessionId,
¬ificationFrames,
iMem,
@@ -609,6 +651,10 @@
mDeathNotifier = new DeathNotifier(this);
IInterface::asBinder(mAudioRecord)->linkToDeath(mDeathNotifier, this);
+ if (mDeviceCallback != 0) {
+ AudioSystem::addAudioDeviceCallback(mDeviceCallback, mInput);
+ }
+
return NO_ERROR;
}
@@ -1054,6 +1100,48 @@
return result;
}
+status_t AudioRecord::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback)
+{
+ if (callback == 0) {
+ ALOGW("%s adding NULL callback!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ AutoMutex lock(mLock);
+ if (mDeviceCallback == callback) {
+ ALOGW("%s adding same callback!", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+ status_t status = NO_ERROR;
+ if (mInput != AUDIO_IO_HANDLE_NONE) {
+ if (mDeviceCallback != 0) {
+ ALOGW("%s callback already present!", __FUNCTION__);
+ AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput);
+ }
+ status = AudioSystem::addAudioDeviceCallback(callback, mInput);
+ }
+ mDeviceCallback = callback;
+ return status;
+}
+
+status_t AudioRecord::removeAudioDeviceCallback(
+ const sp<AudioSystem::AudioDeviceCallback>& callback)
+{
+ if (callback == 0) {
+ ALOGW("%s removing NULL callback!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ AutoMutex lock(mLock);
+ if (mDeviceCallback != callback) {
+ ALOGW("%s removing different callback!", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+ if (mInput != AUDIO_IO_HANDLE_NONE) {
+ AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput);
+ }
+ mDeviceCallback = 0;
+ return NO_ERROR;
+}
+
// =========================================================================
void AudioRecord::DeathNotifier::binderDied(const wp<IBinder>& who __unused)
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 85ed2b1..4c2e77b 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -76,6 +76,25 @@
return af;
}
+const sp<AudioSystem::AudioFlingerClient> AudioSystem::getAudioFlingerClient()
+{
+ // calling get_audio_flinger() will initialize gAudioFlingerClient if needed
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return 0;
+ Mutex::Autolock _l(gLock);
+ return gAudioFlingerClient;
+}
+
+sp<AudioIoDescriptor> AudioSystem::getIoDescriptor(audio_io_handle_t ioHandle)
+{
+ sp<AudioIoDescriptor> desc;
+ const sp<AudioFlingerClient> afc = getAudioFlingerClient();
+ if (afc != 0) {
+ desc = afc->getIoDescriptor(ioHandle);
+ }
+ return desc;
+}
+
/* static */ status_t AudioSystem::checkAudioFlinger()
{
if (defaultServiceManager()->checkService(String16("media.audio_flinger")) != 0) {
@@ -249,9 +268,7 @@
{
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
-
- LOG_ALWAYS_FATAL_IF(gAudioFlingerClient == 0);
- sp<AudioIoDescriptor> outputDesc = gAudioFlingerClient->getIoDescriptor(output);
+ sp<AudioIoDescriptor> outputDesc = getIoDescriptor(output);
if (outputDesc == 0) {
ALOGV("getOutputSamplingRate() no output descriptor for output %d in gOutputs", output);
*samplingRate = af->sampleRate(output);
@@ -290,9 +307,7 @@
{
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
-
- LOG_ALWAYS_FATAL_IF(gAudioFlingerClient == 0);
- sp<AudioIoDescriptor> outputDesc = gAudioFlingerClient->getIoDescriptor(output);
+ sp<AudioIoDescriptor> outputDesc = getIoDescriptor(output);
if (outputDesc == 0) {
*frameCount = af->frameCount(output);
} else {
@@ -329,9 +344,7 @@
{
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
-
- LOG_ALWAYS_FATAL_IF(gAudioFlingerClient == 0);
- sp<AudioIoDescriptor> outputDesc = gAudioFlingerClient->getIoDescriptor(output);
+ sp<AudioIoDescriptor> outputDesc = getIoDescriptor(output);
if (outputDesc == 0) {
*latency = af->latency(output);
} else {
@@ -346,10 +359,11 @@
status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, audio_format_t format,
audio_channel_mask_t channelMask, size_t* buffSize)
{
- const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
- if (af == 0) return PERMISSION_DENIED;
- LOG_ALWAYS_FATAL_IF(gAudioFlingerClient == 0);
- return gAudioFlingerClient->getInputBufferSize(sampleRate, format, channelMask, buffSize);
+ const sp<AudioFlingerClient> afc = getAudioFlingerClient();
+ if (afc == 0) {
+ return NO_INIT;
+ }
+ return afc->getInputBufferSize(sampleRate, format, channelMask, buffSize);
}
status_t AudioSystem::setVoiceVolume(float value)
@@ -446,47 +460,77 @@
if (ioDesc == 0 || ioDesc->mIoHandle == AUDIO_IO_HANDLE_NONE) return;
- Mutex::Autolock _l(mLock);
+ audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE;
+ Vector < sp<AudioDeviceCallback> > callbacks;
- switch (event) {
- case AUDIO_OUTPUT_OPENED:
- case AUDIO_INPUT_OPENED: {
- if (getIoDescriptor(ioDesc->mIoHandle) != 0) {
- ALOGV("ioConfigChanged() opening already existing output! %d", ioDesc->mIoHandle);
- break;
- }
- mIoDescriptors.add(ioDesc->mIoHandle, ioDesc);
- ALOGV("ioConfigChanged() new %s opened %d samplingRate %u, format %#x channel mask %#x "
- "frameCount %zu", event == AUDIO_OUTPUT_OPENED ? "output" : "input",
- ioDesc->mIoHandle, ioDesc->mSamplingRate, ioDesc->mFormat, ioDesc->mChannelMask,
- ioDesc->mFrameCount);
- } break;
- case AUDIO_OUTPUT_CLOSED:
- case AUDIO_INPUT_CLOSED: {
- if (getIoDescriptor(ioDesc->mIoHandle) == 0) {
- ALOGW("ioConfigChanged() closing unknown %s %d",
+ {
+ Mutex::Autolock _l(mLock);
+
+ switch (event) {
+ case AUDIO_OUTPUT_OPENED:
+ case AUDIO_INPUT_OPENED: {
+ if (getIoDescriptor(ioDesc->mIoHandle) != 0) {
+ ALOGV("ioConfigChanged() opening already existing output! %d", ioDesc->mIoHandle);
+ break;
+ }
+ mIoDescriptors.add(ioDesc->mIoHandle, ioDesc);
+
+ if (ioDesc->getDeviceId() != AUDIO_PORT_HANDLE_NONE) {
+ deviceId = ioDesc->getDeviceId();
+ ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(ioDesc->mIoHandle);
+ if (ioIndex >= 0) {
+ callbacks = mAudioDeviceCallbacks.valueAt(ioIndex);
+ }
+ }
+ ALOGV("ioConfigChanged() new %s opened %d samplingRate %u, format %#x channel mask %#x "
+ "frameCount %zu deviceId %d", event == AUDIO_OUTPUT_OPENED ? "output" : "input",
+ ioDesc->mIoHandle, ioDesc->mSamplingRate, ioDesc->mFormat, ioDesc->mChannelMask,
+ ioDesc->mFrameCount, ioDesc->getDeviceId());
+ } break;
+ case AUDIO_OUTPUT_CLOSED:
+ case AUDIO_INPUT_CLOSED: {
+ if (getIoDescriptor(ioDesc->mIoHandle) == 0) {
+ ALOGW("ioConfigChanged() closing unknown %s %d",
+ event == AUDIO_OUTPUT_CLOSED ? "output" : "input", ioDesc->mIoHandle);
+ break;
+ }
+ ALOGV("ioConfigChanged() %s %d closed",
event == AUDIO_OUTPUT_CLOSED ? "output" : "input", ioDesc->mIoHandle);
- break;
- }
- ALOGV("ioConfigChanged() %s %d closed", event == AUDIO_OUTPUT_CLOSED ? "output" : "input",
- ioDesc->mIoHandle);
- mIoDescriptors.removeItem(ioDesc->mIoHandle);
+ mIoDescriptors.removeItem(ioDesc->mIoHandle);
+ mAudioDeviceCallbacks.removeItem(ioDesc->mIoHandle);
+ } break;
+
+ case AUDIO_OUTPUT_CONFIG_CHANGED:
+ case AUDIO_INPUT_CONFIG_CHANGED: {
+ sp<AudioIoDescriptor> oldDesc = getIoDescriptor(ioDesc->mIoHandle);
+ if (oldDesc == 0) {
+ ALOGW("ioConfigChanged() modifying unknown output! %d", ioDesc->mIoHandle);
+ break;
+ }
+
+ deviceId = oldDesc->getDeviceId();
+ mIoDescriptors.replaceValueFor(ioDesc->mIoHandle, ioDesc);
+
+ if (deviceId != ioDesc->getDeviceId()) {
+ deviceId = ioDesc->getDeviceId();
+ ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(ioDesc->mIoHandle);
+ if (ioIndex >= 0) {
+ callbacks = mAudioDeviceCallbacks.valueAt(ioIndex);
+ }
+ }
+ ALOGV("ioConfigChanged() new config for %s %d samplingRate %u, format %#x "
+ "channel mask %#x frameCount %zu deviceId %d",
+ event == AUDIO_OUTPUT_CONFIG_CHANGED ? "output" : "input",
+ ioDesc->mIoHandle, ioDesc->mSamplingRate, ioDesc->mFormat,
+ ioDesc->mChannelMask, ioDesc->mFrameCount, ioDesc->getDeviceId());
+
} break;
-
- case AUDIO_OUTPUT_CONFIG_CHANGED:
- case AUDIO_INPUT_CONFIG_CHANGED: {
- if (getIoDescriptor(ioDesc->mIoHandle) == 0) {
- ALOGW("ioConfigChanged() modifying unknown output! %d", ioDesc->mIoHandle);
- break;
}
- mIoDescriptors.replaceValueFor(ioDesc->mIoHandle, ioDesc);
- ALOGV("ioConfigChanged() new config for %s %d samplingRate %u, format %#x "
- "channel mask %#x frameCount %zu",
- event == AUDIO_OUTPUT_CONFIG_CHANGED ? "output" : "input",
- ioDesc->mIoHandle, ioDesc->mSamplingRate, ioDesc->mFormat,
- ioDesc->mChannelMask, ioDesc->mFrameCount);
- } break;
+ }
+ // callbacks.size() != 0 => ioDesc->mIoHandle and deviceId are valid
+ for (size_t i = 0; i < callbacks.size(); i++) {
+ callbacks[i]->onAudioDeviceUpdate(ioDesc->mIoHandle, deviceId);
}
}
@@ -532,7 +576,56 @@
return desc;
}
-/*static*/ void AudioSystem::setErrorCallback(audio_error_callback cb)
+status_t AudioSystem::AudioFlingerClient::addAudioDeviceCallback(
+ const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
+{
+ Mutex::Autolock _l(mLock);
+ Vector < sp<AudioDeviceCallback> > callbacks;
+ ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(audioIo);
+ if (ioIndex >= 0) {
+ callbacks = mAudioDeviceCallbacks.valueAt(ioIndex);
+ }
+
+ for (size_t cbIndex = 0; cbIndex < callbacks.size(); cbIndex++) {
+ if (callbacks[cbIndex] == callback) {
+ return INVALID_OPERATION;
+ }
+ }
+ callbacks.add(callback);
+
+ mAudioDeviceCallbacks.replaceValueFor(audioIo, callbacks);
+ return NO_ERROR;
+}
+
+status_t AudioSystem::AudioFlingerClient::removeAudioDeviceCallback(
+ const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
+{
+ Mutex::Autolock _l(mLock);
+ ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(audioIo);
+ if (ioIndex < 0) {
+ return INVALID_OPERATION;
+ }
+ Vector < sp<AudioDeviceCallback> > callbacks = mAudioDeviceCallbacks.valueAt(ioIndex);
+
+ size_t cbIndex;
+ for (cbIndex = 0; cbIndex < callbacks.size(); cbIndex++) {
+ if (callbacks[cbIndex] == callback) {
+ break;
+ }
+ }
+ if (cbIndex == callbacks.size()) {
+ return INVALID_OPERATION;
+ }
+ callbacks.removeAt(cbIndex);
+ if (callbacks.size() != 0) {
+ mAudioDeviceCallbacks.replaceValueFor(audioIo, callbacks);
+ } else {
+ mAudioDeviceCallbacks.removeItem(audioIo);
+ }
+ return NO_ERROR;
+}
+
+/* static */ void AudioSystem::setErrorCallback(audio_error_callback cb)
{
Mutex::Autolock _l(gLock);
gAudioErrorCallback = cb;
@@ -864,11 +957,11 @@
{
// called by restoreTrack_l(), which needs new IAudioFlinger and IAudioPolicyService instances
ALOGV("clearAudioConfigCache()");
- if (gAudioFlingerClient != 0) {
- gAudioFlingerClient->clearIoCache();
- }
{
Mutex::Autolock _l(gLock);
+ if (gAudioFlingerClient != 0) {
+ gAudioFlingerClient->clearIoCache();
+ }
gAudioFlinger.clear();
}
{
@@ -934,7 +1027,7 @@
return aps->setAudioPortConfig(config);
}
-status_t AudioSystem::addAudioPortCallback(const sp<AudioPortCallback>& callBack)
+status_t AudioSystem::addAudioPortCallback(const sp<AudioPortCallback>& callback)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
@@ -943,11 +1036,11 @@
if (gAudioPolicyServiceClient == 0) {
return NO_INIT;
}
- return gAudioPolicyServiceClient->addAudioPortCallback(callBack);
+ return gAudioPolicyServiceClient->addAudioPortCallback(callback);
}
/*static*/
-status_t AudioSystem::removeAudioPortCallback(const sp<AudioPortCallback>& callBack)
+status_t AudioSystem::removeAudioPortCallback(const sp<AudioPortCallback>& callback)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
@@ -956,7 +1049,38 @@
if (gAudioPolicyServiceClient == 0) {
return NO_INIT;
}
- return gAudioPolicyServiceClient->removeAudioPortCallback(callBack);
+ return gAudioPolicyServiceClient->removeAudioPortCallback(callback);
+}
+
+status_t AudioSystem::addAudioDeviceCallback(
+ const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
+{
+ const sp<AudioFlingerClient> afc = getAudioFlingerClient();
+ if (afc == 0) {
+ return NO_INIT;
+ }
+ return afc->addAudioDeviceCallback(callback, audioIo);
+}
+
+status_t AudioSystem::removeAudioDeviceCallback(
+ const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
+{
+ const sp<AudioFlingerClient> afc = getAudioFlingerClient();
+ if (afc == 0) {
+ return NO_INIT;
+ }
+ return afc->removeAudioDeviceCallback(callback, audioIo);
+}
+
+audio_port_handle_t AudioSystem::getDeviceIdForIo(audio_io_handle_t audioIo)
+{
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ const sp<AudioIoDescriptor> desc = getIoDescriptor(audioIo);
+ if (desc == 0) {
+ return AUDIO_PORT_HANDLE_NONE;
+ }
+ return desc->getDeviceId();
}
status_t AudioSystem::acquireSoundTriggerSession(audio_session_t *session,
@@ -1008,25 +1132,25 @@
// ---------------------------------------------------------------------------
status_t AudioSystem::AudioPolicyServiceClient::addAudioPortCallback(
- const sp<AudioPortCallback>& callBack)
+ const sp<AudioPortCallback>& callback)
{
Mutex::Autolock _l(mLock);
for (size_t i = 0; i < mAudioPortCallbacks.size(); i++) {
- if (mAudioPortCallbacks[i] == callBack) {
+ if (mAudioPortCallbacks[i] == callback) {
return INVALID_OPERATION;
}
}
- mAudioPortCallbacks.add(callBack);
+ mAudioPortCallbacks.add(callback);
return NO_ERROR;
}
status_t AudioSystem::AudioPolicyServiceClient::removeAudioPortCallback(
- const sp<AudioPortCallback>& callBack)
+ const sp<AudioPortCallback>& callback)
{
Mutex::Autolock _l(mLock);
size_t i;
for (i = 0; i < mAudioPortCallbacks.size(); i++) {
- if (mAudioPortCallbacks[i] == callBack) {
+ if (mAudioPortCallbacks[i] == callback) {
break;
}
}
@@ -1037,6 +1161,7 @@
return NO_ERROR;
}
+
void AudioSystem::AudioPolicyServiceClient::onAudioPortListUpdate()
{
Mutex::Autolock _l(mLock);
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index bb47d3e..db316b0 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -234,6 +234,10 @@
mAudioTrackThread->requestExitAndWait();
mAudioTrackThread.clear();
}
+ // No lock here: worst case we remove a NULL callback which will be a nop
+ if (mDeviceCallback != 0 && mOutput != AUDIO_IO_HANDLE_NONE) {
+ AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput);
+ }
IInterface::asBinder(mAudioTrack)->unlinkToDeath(mDeathNotifier, this);
mAudioTrack.clear();
mCblkMemory.clear();
@@ -1042,6 +1046,14 @@
return mSelectedDeviceId;
}
+audio_port_handle_t AudioTrack::getRoutedDeviceId() {
+ AutoMutex lock(mLock);
+ if (mOutput == AUDIO_IO_HANDLE_NONE) {
+ return AUDIO_PORT_HANDLE_NONE;
+ }
+ return AudioSystem::getDeviceIdForIo(mOutput);
+}
+
status_t AudioTrack::attachAuxEffect(int effectId)
{
AutoMutex lock(mLock);
@@ -1071,6 +1083,9 @@
return NO_INIT;
}
+ if (mDeviceCallback != 0 && mOutput != AUDIO_IO_HANDLE_NONE) {
+ AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput);
+ }
audio_io_handle_t output;
audio_stream_type_t streamType = mStreamType;
audio_attributes_t *attr = (mStreamType == AUDIO_STREAM_DEFAULT) ? &mAttributes : NULL;
@@ -1375,6 +1390,10 @@
mDeathNotifier = new DeathNotifier(this);
IInterface::asBinder(mAudioTrack)->linkToDeath(mDeathNotifier, this);
+ if (mDeviceCallback != 0) {
+ AudioSystem::addAudioDeviceCallback(mDeviceCallback, mOutput);
+ }
+
return NO_ERROR;
}
@@ -2308,6 +2327,48 @@
return mProxy->getUnderrunFrames();
}
+status_t AudioTrack::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback)
+{
+ if (callback == 0) {
+ ALOGW("%s adding NULL callback!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ AutoMutex lock(mLock);
+ if (mDeviceCallback == callback) {
+ ALOGW("%s adding same callback!", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+ status_t status = NO_ERROR;
+ if (mOutput != AUDIO_IO_HANDLE_NONE) {
+ if (mDeviceCallback != 0) {
+ ALOGW("%s callback already present!", __FUNCTION__);
+ AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput);
+ }
+ status = AudioSystem::addAudioDeviceCallback(callback, mOutput);
+ }
+ mDeviceCallback = callback;
+ return status;
+}
+
+status_t AudioTrack::removeAudioDeviceCallback(
+ const sp<AudioSystem::AudioDeviceCallback>& callback)
+{
+ if (callback == 0) {
+ ALOGW("%s removing NULL callback!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ AutoMutex lock(mLock);
+ if (mDeviceCallback != callback) {
+ ALOGW("%s removing different callback!", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+ if (mOutput != AUDIO_IO_HANDLE_NONE) {
+ AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput);
+ }
+ mDeviceCallback = 0;
+ return NO_ERROR;
+}
+
// =========================================================================
void AudioTrack::DeathNotifier::binderDied(const wp<IBinder>& who __unused)
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index d48532e..d722fe9 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -178,6 +178,7 @@
size_t *pFrameCount,
track_flags_t *flags,
pid_t tid,
+ int clientUid,
int *sessionId,
size_t *notificationFrames,
sp<IMemory>& cblk,
@@ -197,6 +198,7 @@
track_flags_t lFlags = flags != NULL ? *flags : (track_flags_t) TRACK_DEFAULT;
data.writeInt32(lFlags);
data.writeInt32((int32_t) tid);
+ data.writeInt32((int32_t) clientUid);
int lSessionId = AUDIO_SESSION_ALLOCATE;
if (sessionId != NULL) {
lSessionId = *sessionId;
@@ -958,6 +960,7 @@
size_t frameCount = data.readInt64();
track_flags_t flags = (track_flags_t) data.readInt32();
pid_t tid = (pid_t) data.readInt32();
+ int clientUid = data.readInt32();
int sessionId = data.readInt32();
size_t notificationFrames = data.readInt64();
sp<IMemory> cblk;
@@ -965,7 +968,7 @@
status_t status;
sp<IAudioRecord> record = openRecord(input,
sampleRate, format, channelMask, opPackageName, &frameCount, &flags, tid,
- &sessionId, ¬ificationFrames, cblk, buffers, &status);
+ clientUid, &sessionId, ¬ificationFrames, cblk, buffers, &status);
LOG_ALWAYS_FATAL_IF((record != 0) != (status == NO_ERROR));
reply->writeInt64(frameCount);
reply->writeInt32(flags);
diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp
index a622241..3429d36 100644
--- a/media/libmedia/IAudioFlingerClient.cpp
+++ b/media/libmedia/IAudioFlingerClient.cpp
@@ -45,6 +45,7 @@
data.writeInterfaceToken(IAudioFlingerClient::getInterfaceDescriptor());
data.writeInt32(event);
data.writeInt32((int32_t)ioDesc->mIoHandle);
+ data.write(&ioDesc->mPatch, sizeof(struct audio_patch));
data.writeInt32(ioDesc->mSamplingRate);
data.writeInt32(ioDesc->mFormat);
data.writeInt32(ioDesc->mChannelMask);
@@ -67,6 +68,7 @@
audio_io_config_event event = (audio_io_config_event)data.readInt32();
sp<AudioIoDescriptor> ioDesc = new AudioIoDescriptor();
ioDesc->mIoHandle = (audio_io_handle_t) data.readInt32();
+ data.read(&ioDesc->mPatch, sizeof(struct audio_patch));
ioDesc->mSamplingRate = data.readInt32();
ioDesc->mFormat = (audio_format_t) data.readInt32();
ioDesc->mChannelMask = (audio_channel_mask_t) data.readInt32();
diff --git a/media/libmedia/ICrypto.cpp b/media/libmedia/ICrypto.cpp
index 9246a7c..2f440fe 100644
--- a/media/libmedia/ICrypto.cpp
+++ b/media/libmedia/ICrypto.cpp
@@ -142,7 +142,7 @@
ssize_t result = reply.readInt32();
- if (result >= ERROR_DRM_VENDOR_MIN && result <= ERROR_DRM_VENDOR_MAX) {
+ if (isCryptoError(result)) {
errorDetailMsg->setTo(reply.readCString());
}
@@ -319,8 +319,7 @@
reply->writeInt32(result);
- if (result >= ERROR_DRM_VENDOR_MIN
- && result <= ERROR_DRM_VENDOR_MAX) {
+ if (isCryptoError(result)) {
reply->writeCString(errorDetailMsg.c_str());
}
diff --git a/media/libmedia/IMediaHTTPConnection.cpp b/media/libmedia/IMediaHTTPConnection.cpp
index 2ff7658..09137ef 100644
--- a/media/libmedia/IMediaHTTPConnection.cpp
+++ b/media/libmedia/IMediaHTTPConnection.cpp
@@ -24,6 +24,7 @@
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaErrors.h>
namespace android {
@@ -106,11 +107,18 @@
return UNKNOWN_ERROR;
}
- int32_t len = reply.readInt32();
+ size_t len = reply.readInt32();
- if (len > 0) {
- memcpy(buffer, mMemory->pointer(), len);
+ if (len > size) {
+ ALOGE("requested %zu, got %zu", size, len);
+ return ERROR_OUT_OF_RANGE;
}
+ if (len > mMemory->size()) {
+ ALOGE("got %zu, but memory has %zu", len, mMemory->size());
+ return ERROR_OUT_OF_RANGE;
+ }
+
+ memcpy(buffer, mMemory->pointer(), len);
return len;
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 9963353..a118dec 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -423,7 +423,19 @@
CHECK(format->findInt32("type", &trackType));
AString mime;
- CHECK(format->findString("mime", &mime));
+ if (!format->findString("mime", &mime)) {
+ // Java MediaPlayer only uses mimetype for subtitle and timedtext tracks.
+ // If we can't find the mimetype here it means that we wouldn't be needing
+ // the mimetype on the Java end. We still write a placeholder mime to keep the
+ // (de)serialization logic simple.
+ if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
+ mime = "audio/";
+ } else if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
+ mime = "video/";
+ } else {
+ TRESPASS();
+ }
+ }
AString lang;
CHECK(format->findString("language", &lang));
@@ -704,9 +716,8 @@
}
if (mVideoDecoder != NULL) {
- sp<MetaData> meta = getFileMeta();
- int32_t rate;
- if (meta != NULL && meta->findInt32(kKeyFrameRate, &rate) && rate > 0) {
+ float rate = getFrameRate();
+ if (rate > 0) {
sp<AMessage> params = new AMessage();
params->setFloat("operating-rate", rate * mPlaybackSettings.mSpeed);
mVideoDecoder->setParameters(params);
@@ -1265,10 +1276,8 @@
return;
}
- sp<MetaData> meta = getFileMeta();
- int32_t rate;
- if (meta != NULL
- && meta->findInt32(kKeyFrameRate, &rate) && rate > 0) {
+ float rate = getFrameRate();
+ if (rate > 0) {
mRenderer->setVideoFrameRate(rate);
}
@@ -1426,9 +1435,8 @@
format->setInt32("protected", true);
}
- sp<MetaData> meta = getFileMeta();
- int32_t rate;
- if (meta != NULL && meta->findInt32(kKeyFrameRate, &rate) && rate > 0) {
+ float rate = getFrameRate();
+ if (rate > 0) {
format->setFloat("operating-rate", rate * mPlaybackSettings.mSpeed);
}
}
@@ -1702,6 +1710,28 @@
return mSource->getFileFormatMeta();
}
+float NuPlayer::getFrameRate() {
+ sp<MetaData> meta = mSource->getFormatMeta(false /* audio */);
+ if (meta == NULL) {
+ return 0;
+ }
+ int32_t rate;
+ if (!meta->findInt32(kKeyFrameRate, &rate)) {
+ // fall back to try file meta
+ sp<MetaData> fileMeta = getFileMeta();
+ if (fileMeta == NULL) {
+ ALOGW("source has video meta but not file meta");
+ return -1;
+ }
+ int32_t fileMetaRate;
+ if (!fileMeta->findInt32(kKeyFrameRate, &fileMetaRate)) {
+ return -1;
+ }
+ return fileMetaRate;
+ }
+ return rate;
+}
+
void NuPlayer::schedulePollDuration() {
sp<AMessage> msg = new AMessage(kWhatPollDuration, this);
msg->setInt32("generation", mPollDurationGeneration);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index fcf6841..6b7d71e 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -80,6 +80,7 @@
void getStats(int64_t *mNumFramesTotal, int64_t *mNumFramesDropped);
sp<MetaData> getFileMeta();
+ float getFrameRate();
protected:
virtual ~NuPlayer();
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index b7798d2..22395cc 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -4156,6 +4156,9 @@
goto error;
}
+ static_cast<Surface*>(mNativeWindow.get())
+ ->getIGraphicBufferProducer()->allowAllocation(true);
+
err = mNativeWindow->query(mNativeWindow.get(),
NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
if (err != NO_ERROR) {
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index beb12ec..3bc22f2 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -94,6 +94,7 @@
void addChunkOffset(off64_t offset);
int32_t getTrackId() const { return mTrackId; }
status_t dump(int fd, const Vector<String16>& args) const;
+ static const char *getFourCCForMime(const char *mime);
private:
enum {
@@ -426,6 +427,33 @@
return OK;
}
+// static
+const char *MPEG4Writer::Track::getFourCCForMime(const char *mime) {
+ if (mime == NULL) {
+ return NULL;
+ }
+ if (!strncasecmp(mime, "audio/", 6)) {
+ if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
+ return "samr";
+ } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
+ return "sawb";
+ } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
+ return "mp4a";
+ }
+ } else if (!strncasecmp(mime, "video/", 6)) {
+ if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
+ return "mp4v";
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
+ return "s263";
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
+ return "avc1";
+ }
+ } else {
+ ALOGE("Track (%s) other than video or audio is not supported", mime);
+ }
+ return NULL;
+}
+
status_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
Mutex::Autolock l(mLock);
if (mStarted) {
@@ -441,14 +469,11 @@
CHECK(source.get() != NULL);
- // A track of type other than video or audio is not supported.
const char *mime;
source->getFormat()->findCString(kKeyMIMEType, &mime);
bool isAudio = !strncasecmp(mime, "audio/", 6);
- bool isVideo = !strncasecmp(mime, "video/", 6);
- if (!isAudio && !isVideo) {
- ALOGE("Track (%s) other than video or audio is not supported",
- mime);
+ if (Track::getFourCCForMime(mime) == NULL) {
+ ALOGE("Unsupported mime '%s'", mime);
return ERROR_UNSUPPORTED;
}
@@ -2730,17 +2755,13 @@
const char *mime;
bool success = mMeta->findCString(kKeyMIMEType, &mime);
CHECK(success);
- if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
- mOwner->beginBox("mp4v");
- } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
- mOwner->beginBox("s263");
- } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
- mOwner->beginBox("avc1");
- } else {
+ const char *fourcc = getFourCCForMime(mime);
+ if (fourcc == NULL) {
ALOGE("Unknown mime type '%s'.", mime);
CHECK(!"should not be here, unknown mime type.");
}
+ mOwner->beginBox(fourcc); // video format
mOwner->writeInt32(0); // reserved
mOwner->writeInt16(0); // reserved
mOwner->writeInt16(1); // data ref index
@@ -2784,14 +2805,8 @@
const char *mime;
bool success = mMeta->findCString(kKeyMIMEType, &mime);
CHECK(success);
- const char *fourcc = NULL;
- if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
- fourcc = "samr";
- } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
- fourcc = "sawb";
- } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
- fourcc = "mp4a";
- } else {
+ const char *fourcc = getFourCCForMime(mime);
+ if (fourcc == NULL) {
ALOGE("Unknown mime type '%s'.", mime);
CHECK(!"should not be here, unknown mime type.");
}
diff --git a/media/libstagefright/MediaSync.cpp b/media/libstagefright/MediaSync.cpp
index ad4b7a3..97264fb 100644
--- a/media/libstagefright/MediaSync.cpp
+++ b/media/libstagefright/MediaSync.cpp
@@ -79,17 +79,17 @@
}
}
-status_t MediaSync::configureSurface(const sp<IGraphicBufferProducer> &output) {
+status_t MediaSync::setSurface(const sp<IGraphicBufferProducer> &output) {
Mutex::Autolock lock(mMutex);
// TODO: support suface change.
if (mOutput != NULL) {
- ALOGE("configureSurface: output surface has already been configured.");
+ ALOGE("setSurface: output surface has already been configured.");
return INVALID_OPERATION;
}
if (output == NULL && mSyncSettings.mSource == AVSYNC_SOURCE_VSYNC) {
- ALOGE("configureSurface: output surface is used as sync source and cannot be removed.");
+ ALOGE("setSurface: output surface is used as sync source and cannot be removed.");
return INVALID_OPERATION;
}
@@ -103,7 +103,7 @@
true /* producerControlledByApp */,
&queueBufferOutput);
if (status != NO_ERROR) {
- ALOGE("configureSurface: failed to connect (%d)", status);
+ ALOGE("setSurface: failed to connect (%d)", status);
return status;
}
@@ -114,17 +114,17 @@
}
// |audioTrack| is used only for querying information.
-status_t MediaSync::configureAudioTrack(const sp<AudioTrack> &audioTrack) {
+status_t MediaSync::setAudioTrack(const sp<AudioTrack> &audioTrack) {
Mutex::Autolock lock(mMutex);
// TODO: support audio track change.
if (mAudioTrack != NULL) {
- ALOGE("configureAudioTrack: audioTrack has already been configured.");
+ ALOGE("setAudioTrack: audioTrack has already been configured.");
return INVALID_OPERATION;
}
if (audioTrack == NULL && mSyncSettings.mSource == AVSYNC_SOURCE_AUDIO) {
- ALOGE("configureAudioTrack: audioTrack is used as sync source and cannot be removed.");
+ ALOGE("setAudioTrack: audioTrack is used as sync source and cannot be removed.");
return INVALID_OPERATION;
}
@@ -137,7 +137,7 @@
}
uint32_t nativeSampleRateInHz = audioTrack->getOriginalSampleRate();
if (nativeSampleRateInHz <= 0) {
- ALOGE("configureAudioTrack: native sample rate should be positive.");
+ ALOGE("setAudioTrack: native sample rate should be positive.");
return BAD_VALUE;
}
mAudioTrack = audioTrack;
diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp
index d577034..4297549 100644
--- a/media/libstagefright/OggExtractor.cpp
+++ b/media/libstagefright/OggExtractor.cpp
@@ -753,7 +753,9 @@
oggpack_buffer bits;
oggpack_readinit(&bits, &ref);
- CHECK_EQ(oggpack_read(&bits, 8), type);
+ if (oggpack_read(&bits, 8) != type) {
+ return ERROR_MALFORMED;
+ }
for (size_t i = 0; i < 6; ++i) {
oggpack_read(&bits, 8); // skip 'vorbis'
}
@@ -761,7 +763,9 @@
switch (type) {
case 1:
{
- CHECK_EQ(0, _vorbis_unpack_info(&mVi, &bits));
+ if (0 != _vorbis_unpack_info(&mVi, &bits)) {
+ return ERROR_MALFORMED;
+ }
mMeta->setData(kKeyVorbisInfo, 0, data, size);
mMeta->setInt32(kKeySampleRate, mVi.rate);
diff --git a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
old mode 100644
new mode 100755
index 06b2163..6afac74
--- a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
+++ b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
@@ -625,7 +625,7 @@
return errType;
}
- mStride = ALIGN16(mWidth);
+ mStride = mWidth;
if (mInputDataIsMeta) {
if (mConversionBuffer) {
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
index 970acf3..e654843 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
@@ -661,7 +661,8 @@
BufferInfo *outputBufferInfo = *outputBufferInfoQueue.begin();
OMX_BUFFERHEADERTYPE *outputBufferHeader = outputBufferInfo->mHeader;
- if (inputBufferHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+ if ((inputBufferHeader->nFlags & OMX_BUFFERFLAG_EOS) &&
+ inputBufferHeader->nFilledLen == 0) {
inputBufferInfoQueue.erase(inputBufferInfoQueue.begin());
inputBufferInfo->mOwnedByUs = false;
notifyEmptyBufferDone(inputBufferHeader);
@@ -762,6 +763,9 @@
encoded_packet->data.frame.sz);
outputBufferInfo->mOwnedByUs = false;
outputBufferInfoQueue.erase(outputBufferInfoQueue.begin());
+ if (inputBufferHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+ outputBufferHeader->nFlags |= OMX_BUFFERFLAG_EOS;
+ }
notifyFillBufferDone(outputBufferHeader);
}
}
diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
index 8f356b6..c559682 100644
--- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
@@ -364,7 +364,7 @@
} else {
numFrames = vorbis_dsp_pcmout(
mState, (int16_t *)outHeader->pBuffer,
- kMaxNumSamplesPerBuffer);
+ (kMaxNumSamplesPerBuffer / mVi->channels));
if (numFrames < 0) {
ALOGE("vorbis_dsp_pcmout returned %d", numFrames);
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index f31af7b..03c9a8a 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -29,6 +29,8 @@
struct OMXMaster;
class GraphicBufferSource;
+status_t StatusFromOMXError(OMX_ERRORTYPE err);
+
struct OMXNodeInstance {
OMXNodeInstance(
OMX *owner, const sp<IOMXObserver> &observer, const char *name);
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index b9e2f9c..876abb8 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -32,6 +32,7 @@
#include "OMXMaster.h"
+#include <OMX_AsString.h>
#include <OMX_Component.h>
namespace android {
@@ -233,11 +234,11 @@
instance, &handle);
if (err != OMX_ErrorNone) {
- ALOGE("FAILED to allocate omx component '%s'", name);
+ ALOGE("FAILED to allocate omx component '%s' err=%s(%#x)", name, asString(err), err);
instance->onGetHandleFailed();
- return UNKNOWN_ERROR;
+ return StatusFromOMXError(err);
}
*node = makeNodeID(instance);
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 5bc1972..04293d6 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -220,13 +220,15 @@
return mNodeID;
}
-static status_t StatusFromOMXError(OMX_ERRORTYPE err) {
+status_t StatusFromOMXError(OMX_ERRORTYPE err) {
switch (err) {
case OMX_ErrorNone:
return OK;
case OMX_ErrorUnsupportedSetting:
case OMX_ErrorUnsupportedIndex:
return ERROR_UNSUPPORTED;
+ case OMX_ErrorInsufficientResources:
+ return NO_MEMORY;
default:
return UNKNOWN_ERROR;
}
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index bd6889d..485e320 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1425,6 +1425,7 @@
size_t *frameCount,
IAudioFlinger::track_flags_t *flags,
pid_t tid,
+ int clientUid,
int *sessionId,
size_t *notificationFrames,
sp<IMemory>& cblk,
@@ -1494,8 +1495,7 @@
// TODO: the uid should be passed in as a parameter to openRecord
recordTrack = thread->createRecordTrack_l(client, sampleRate, format, channelMask,
frameCount, lSessionId, notificationFrames,
- IPCThreadState::self()->getCallingUid(),
- flags, tid, &lStatus);
+ clientUid, flags, tid, &lStatus);
LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (recordTrack == 0));
if (lStatus == NO_ERROR) {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 8085ec2..51b2610 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -124,6 +124,7 @@
size_t *pFrameCount,
IAudioFlinger::track_flags_t *flags,
pid_t tid,
+ int clientUid,
int *sessionId,
size_t *notificationFrames,
sp<IMemory>& cblk,
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 8b8dd78..2c4d801 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -500,6 +500,7 @@
// mName will be set by concrete (non-virtual) subclass
mDeathRecipient(new PMDeathRecipient(this))
{
+ memset(&mPatch, 0, sizeof(struct audio_patch));
}
AudioFlinger::ThreadBase::~ThreadBase()
@@ -1930,6 +1931,7 @@
switch (event) {
case AUDIO_OUTPUT_OPENED:
case AUDIO_OUTPUT_CONFIG_CHANGED:
+ desc->mPatch = mPatch;
desc->mChannelMask = mChannelMask;
desc->mSamplingRate = mSampleRate;
desc->mFormat = mFormat;
@@ -3002,6 +3004,7 @@
mEffectChains[i]->setDevice_l(type);
}
mOutDevice = type;
+ mPatch = *patch;
if (mOutput->audioHwDev->version() >= AUDIO_DEVICE_API_VERSION_3_0) {
audio_hw_device_t *hwDevice = mOutput->audioHwDev->hwDevice();
@@ -3028,6 +3031,7 @@
param.toString().string());
*handle = AUDIO_PATCH_HANDLE_NONE;
}
+ sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
return status;
}
@@ -6727,6 +6731,7 @@
switch (event) {
case AUDIO_INPUT_OPENED:
case AUDIO_INPUT_CONFIG_CHANGED:
+ desc->mPatch = mPatch;
desc->mChannelMask = mChannelMask;
desc->mSamplingRate = mSampleRate;
desc->mFormat = mFormat;
@@ -6884,6 +6889,7 @@
// store new device and send to effects
mInDevice = patch->sources[0].ext.device.type;
+ mPatch = *patch;
for (size_t i = 0; i < mEffectChains.size(); i++) {
mEffectChains[i]->setDevice_l(mInDevice);
}
@@ -6936,6 +6942,8 @@
*handle = AUDIO_PATCH_HANDLE_NONE;
}
+ sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
+
return status;
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 8167bd1..0a5597f 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -426,6 +426,7 @@
bool mStandby; // Whether thread is currently in standby.
audio_devices_t mOutDevice; // output device
audio_devices_t mInDevice; // input device
+ struct audio_patch mPatch;
audio_source_t mAudioSource;
const audio_io_handle_t mId;
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index a2327ee..e6a767f 100755
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -60,7 +60,7 @@
*
* @return true if the device is a virtual one, false otherwise.
*/
-static bool is_virtual_input_device(audio_devices_t device)
+static inline bool is_virtual_input_device(audio_devices_t device)
{
if ((device & AUDIO_DEVICE_BIT_IN) != 0) {
device &= ~AUDIO_DEVICE_BIT_IN;
@@ -78,7 +78,7 @@
*
* @return true if the device needs distinguish on address, false otherwise..
*/
-static bool device_distinguishes_on_address(audio_devices_t device)
+static inline bool device_distinguishes_on_address(audio_devices_t device)
{
return ((device & APM_AUDIO_DEVICE_MATCH_ADDRESS_ALL & ~AUDIO_DEVICE_BIT_IN) != 0);
}
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index aa37eec..d1a2f4f 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -29,7 +29,7 @@
class DeviceDescriptor : public AudioPort, public AudioPortConfig
{
public:
- DeviceDescriptor(const String8& name, audio_devices_t type);
+ DeviceDescriptor(audio_devices_t type);
virtual ~DeviceDescriptor() {}
@@ -50,10 +50,9 @@
status_t dump(int fd, int spaces, int index) const;
void log() const;
+ String8 mTag;
String8 mAddress;
- static String8 emptyNameStr;
-
private:
audio_devices_t mDeviceType;
audio_port_handle_t mId;
@@ -73,12 +72,12 @@
audio_devices_t types() const { return mDeviceTypes; }
void loadDevicesFromType(audio_devices_t types);
- void loadDevicesFromName(char *name, const DeviceVector& declaredDevices);
+ void loadDevicesFromTag(char *tag, const DeviceVector& declaredDevices);
sp<DeviceDescriptor> getDevice(audio_devices_t type, String8 address) const;
DeviceVector getDevicesFromType(audio_devices_t types) const;
sp<DeviceDescriptor> getDeviceFromId(audio_port_handle_t id) const;
- sp<DeviceDescriptor> getDeviceFromName(const String8& name) const;
+ sp<DeviceDescriptor> getDeviceFromTag(const String8& tag) const;
DeviceVector getDevicesFromTypeAddr(audio_devices_t type, String8 address) const;
audio_devices_t getDevicesFromHwModule(audio_module_handle_t moduleHandle) const;
diff --git a/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp b/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
index 9ab1d61..89ef045 100644
--- a/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
@@ -218,7 +218,7 @@
node = node->first_child;
while (node) {
if (strcmp(ATTACHED_OUTPUT_DEVICES_TAG, node->name) == 0) {
- availableOutputDevices.loadDevicesFromName((char *)node->value,
+ availableOutputDevices.loadDevicesFromTag((char *)node->value,
declaredDevices);
ALOGV("loadGlobalConfig() Attached Output Devices %08x",
availableOutputDevices.types());
@@ -228,13 +228,13 @@
ARRAY_SIZE(sDeviceTypeToEnumTable),
(char *)node->value);
if (device != AUDIO_DEVICE_NONE) {
- defaultOutputDevice = new DeviceDescriptor(String8("default-output"), device);
+ defaultOutputDevice = new DeviceDescriptor(device);
} else {
ALOGW("loadGlobalConfig() default device not specified");
}
ALOGV("loadGlobalConfig() mDefaultOutputDevice %08x", defaultOutputDevice->type());
} else if (strcmp(ATTACHED_INPUT_DEVICES_TAG, node->name) == 0) {
- availableInputDevices.loadDevicesFromName((char *)node->value,
+ availableInputDevices.loadDevicesFromTag((char *)node->value,
declaredDevices);
ALOGV("loadGlobalConfig() Available InputDevices %08x", availableInputDevices.types());
} else if (strcmp(SPEAKER_DRC_ENABLED_TAG, node->name) == 0) {
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index 0715eea..797077a 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -24,13 +24,11 @@
namespace android {
-String8 DeviceDescriptor::emptyNameStr = String8("");
-
-DeviceDescriptor::DeviceDescriptor(const String8& name, audio_devices_t type) :
- AudioPort(name, AUDIO_PORT_TYPE_DEVICE,
+DeviceDescriptor::DeviceDescriptor(audio_devices_t type) :
+ AudioPort(String8(""), AUDIO_PORT_TYPE_DEVICE,
audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
AUDIO_PORT_ROLE_SOURCE),
- mAddress(""), mDeviceType(type), mId(0)
+ mTag(""), mAddress(""), mDeviceType(type), mId(0)
{
}
@@ -142,24 +140,21 @@
uint32_t i = 31 - __builtin_clz(types);
uint32_t type = 1 << i;
types &= ~type;
- add(new DeviceDescriptor(String8("device_type"), type | role_bit));
+ add(new DeviceDescriptor(type | role_bit));
}
}
-void DeviceVector::loadDevicesFromName(char *name,
+void DeviceVector::loadDevicesFromTag(char *tag,
const DeviceVector& declaredDevices)
{
- char *devName = strtok(name, "|");
- while (devName != NULL) {
- if (strlen(devName) != 0) {
+ char *devTag = strtok(tag, "|");
+ while (devTag != NULL) {
+ if (strlen(devTag) != 0) {
audio_devices_t type = ConfigParsingUtils::stringToEnum(sDeviceTypeToEnumTable,
ARRAY_SIZE(sDeviceTypeToEnumTable),
- devName);
+ devTag);
if (type != AUDIO_DEVICE_NONE) {
- devName = (char *)ConfigParsingUtils::enumToString(sDeviceNameToEnumTable,
- ARRAY_SIZE(sDeviceNameToEnumTable),
- type);
- sp<DeviceDescriptor> dev = new DeviceDescriptor(String8(devName), type);
+ sp<DeviceDescriptor> dev = new DeviceDescriptor(type);
if (type == AUDIO_DEVICE_IN_REMOTE_SUBMIX ||
type == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ) {
dev->mAddress = String8("0");
@@ -167,13 +162,13 @@
add(dev);
} else {
sp<DeviceDescriptor> deviceDesc =
- declaredDevices.getDeviceFromName(String8(devName));
+ declaredDevices.getDeviceFromTag(String8(devTag));
if (deviceDesc != 0) {
add(deviceDesc);
}
}
}
- devName = strtok(NULL, "|");
+ devTag = strtok(NULL, "|");
}
}
@@ -239,11 +234,11 @@
return devices;
}
-sp<DeviceDescriptor> DeviceVector::getDeviceFromName(const String8& name) const
+sp<DeviceDescriptor> DeviceVector::getDeviceFromTag(const String8& tag) const
{
sp<DeviceDescriptor> device;
for (size_t i = 0; i < size(); i++) {
- if (itemAt(i)->mName == name) {
+ if (itemAt(i)->mTag == tag) {
device = itemAt(i);
break;
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index e955447..7e2050b 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -58,7 +58,7 @@
} else if (strcmp(node->name, CHANNELS_TAG) == 0) {
profile->loadInChannels((char *)node->value);
} else if (strcmp(node->name, DEVICES_TAG) == 0) {
- profile->mSupportedDevices.loadDevicesFromName((char *)node->value,
+ profile->mSupportedDevices.loadDevicesFromTag((char *)node->value,
mDeclaredDevices);
} else if (strcmp(node->name, FLAGS_TAG) == 0) {
profile->mFlags = ConfigParsingUtils::parseInputFlagNames((char *)node->value);
@@ -105,7 +105,7 @@
} else if (strcmp(node->name, CHANNELS_TAG) == 0) {
profile->loadOutChannels((char *)node->value);
} else if (strcmp(node->name, DEVICES_TAG) == 0) {
- profile->mSupportedDevices.loadDevicesFromName((char *)node->value,
+ profile->mSupportedDevices.loadDevicesFromTag((char *)node->value,
mDeclaredDevices);
} else if (strcmp(node->name, FLAGS_TAG) == 0) {
profile->mFlags = ConfigParsingUtils::parseOutputFlagNames((char *)node->value);
@@ -154,7 +154,8 @@
ALOGW("loadDevice() bad type %08x", type);
return BAD_VALUE;
}
- sp<DeviceDescriptor> deviceDesc = new DeviceDescriptor(String8(root->name), type);
+ sp<DeviceDescriptor> deviceDesc = new DeviceDescriptor(type);
+ deviceDesc->mTag = String8(root->name);
node = root->first_child;
while (node) {
@@ -172,8 +173,8 @@
node = node->next;
}
- ALOGV("loadDevice() adding device name %s type %08x address %s",
- deviceDesc->mName.string(), type, deviceDesc->mAddress.string());
+ ALOGV("loadDevice() adding device tag %s type %08x address %s",
+ deviceDesc->mTag.string(), type, deviceDesc->mAddress.string());
mDeclaredDevices.add(deviceDesc);
@@ -189,7 +190,7 @@
profile->mChannelMasks.add(config->channel_mask);
profile->mFormats.add(config->format);
- sp<DeviceDescriptor> devDesc = new DeviceDescriptor(name, device);
+ sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
devDesc->mAddress = address;
profile->mSupportedDevices.add(devDesc);
@@ -220,7 +221,7 @@
profile->mChannelMasks.add(config->channel_mask);
profile->mFormats.add(config->format);
- sp<DeviceDescriptor> devDesc = new DeviceDescriptor(name, device);
+ sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
devDesc->mAddress = address;
profile->mSupportedDevices.add(devDesc);
@@ -350,7 +351,8 @@
}
sp<DeviceDescriptor> devDesc =
- new DeviceDescriptor(String8(device_name != NULL ? device_name : ""), device);
+ new DeviceDescriptor(device);
+ devDesc->mName = device_name;
devDesc->mAddress = address;
return devDesc;
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index b7eed62..0c02d93 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2648,7 +2648,7 @@
mUidCached = getuid();
mpClientInterface = clientInterface;
- mDefaultOutputDevice = new DeviceDescriptor(String8("Speaker"), AUDIO_DEVICE_OUT_SPEAKER);
+ mDefaultOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER);
if (ConfigParsingUtils::loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE,
mHwModules, mAvailableInputDevices, mAvailableOutputDevices,
mDefaultOutputDevice, mSpeakerDrcEnabled) != NO_ERROR) {
@@ -4738,7 +4738,7 @@
sp<HwModule> module;
sp<IOProfile> profile;
sp<DeviceDescriptor> defaultInputDevice =
- new DeviceDescriptor(String8("builtin-mic"), AUDIO_DEVICE_IN_BUILTIN_MIC);
+ new DeviceDescriptor(AUDIO_DEVICE_IN_BUILTIN_MIC);
mAvailableOutputDevices.add(mDefaultOutputDevice);
mAvailableInputDevices.add(defaultInputDevice);
diff --git a/services/camera/libcameraservice/common/CameraModule.cpp b/services/camera/libcameraservice/common/CameraModule.cpp
index ac4d9a6..064ff71 100644
--- a/services/camera/libcameraservice/common/CameraModule.cpp
+++ b/services/camera/libcameraservice/common/CameraModule.cpp
@@ -36,12 +36,47 @@
chars.update(ANDROID_CONTROL_AE_LOCK_AVAILABLE, &data, /*count*/1);
data = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE;
chars.update(ANDROID_CONTROL_AWB_LOCK_AVAILABLE, &data, /*count*/1);
- controlModes.push(ANDROID_CONTROL_MODE_OFF);
controlModes.push(ANDROID_CONTROL_MODE_AUTO);
camera_metadata_entry entry = chars.find(ANDROID_CONTROL_AVAILABLE_SCENE_MODES);
if (entry.count > 1 || entry.data.u8[0] != ANDROID_CONTROL_SCENE_MODE_DISABLED) {
controlModes.push(ANDROID_CONTROL_MODE_USE_SCENE_MODE);
}
+
+ // Only advertise CONTROL_OFF mode if 3A manual controls are supported.
+ bool isManualAeSupported = false;
+ bool isManualAfSupported = false;
+ bool isManualAwbSupported = false;
+ entry = chars.find(ANDROID_CONTROL_AE_AVAILABLE_MODES);
+ if (entry.count > 0) {
+ for (size_t i = 0; i < entry.count; i++) {
+ if (entry.data.u8[i] == ANDROID_CONTROL_AE_MODE_OFF) {
+ isManualAeSupported = true;
+ break;
+ }
+ }
+ }
+ entry = chars.find(ANDROID_CONTROL_AF_AVAILABLE_MODES);
+ if (entry.count > 0) {
+ for (size_t i = 0; i < entry.count; i++) {
+ if (entry.data.u8[i] == ANDROID_CONTROL_AF_MODE_OFF) {
+ isManualAfSupported = true;
+ break;
+ }
+ }
+ }
+ entry = chars.find(ANDROID_CONTROL_AWB_AVAILABLE_MODES);
+ if (entry.count > 0) {
+ for (size_t i = 0; i < entry.count; i++) {
+ if (entry.data.u8[i] == ANDROID_CONTROL_AWB_MODE_OFF) {
+ isManualAwbSupported = true;
+ break;
+ }
+ }
+ }
+ if (isManualAeSupported && isManualAfSupported && isManualAwbSupported) {
+ controlModes.push(ANDROID_CONTROL_MODE_OFF);
+ }
+
chars.update(ANDROID_CONTROL_AVAILABLE_MODES, controlModes);
}
return;
@@ -86,7 +121,7 @@
if (ret != 0) {
return ret;
}
- int deviceVersion = cameraInfo.device_version;
+ int deviceVersion = rawInfo.device_version;
if (deviceVersion < CAMERA_DEVICE_API_VERSION_2_0) {
// static_camera_characteristics is invalid
*info = rawInfo;
diff --git a/soundtrigger/ISoundTriggerHwService.cpp b/soundtrigger/ISoundTriggerHwService.cpp
index 75f68b8..e14a771 100644
--- a/soundtrigger/ISoundTriggerHwService.cpp
+++ b/soundtrigger/ISoundTriggerHwService.cpp
@@ -40,6 +40,8 @@
SET_CAPTURE_STATE,
};
+#define MAX_ITEMS_PER_LIST 1024
+
class BpSoundTriggerHwService: public BpInterface<ISoundTriggerHwService>
{
public:
@@ -116,10 +118,18 @@
case LIST_MODULES: {
CHECK_INTERFACE(ISoundTriggerHwService, data, reply);
unsigned int numModulesReq = data.readInt32();
+ if (numModulesReq > MAX_ITEMS_PER_LIST) {
+ numModulesReq = MAX_ITEMS_PER_LIST;
+ }
unsigned int numModules = numModulesReq;
struct sound_trigger_module_descriptor *modules =
(struct sound_trigger_module_descriptor *)calloc(numModulesReq,
sizeof(struct sound_trigger_module_descriptor));
+ if (modules == NULL) {
+ reply->writeInt32(NO_MEMORY);
+ reply->writeInt32(0);
+ return NO_ERROR;
+ }
status_t status = listModules(modules, &numModules);
reply->writeInt32(status);
reply->writeInt32(numModules);