Merge "Blur media.metrics timestamps for privacy" into oc-mr1-dev
diff --git a/media/libaaudio/Doxyfile b/media/libaaudio/Doxyfile
index e2c4960..7298d11 100644
--- a/media/libaaudio/Doxyfile
+++ b/media/libaaudio/Doxyfile
@@ -744,12 +744,12 @@
# Note: If this tag is empty the current directory is searched.
INPUT = include/aaudio/AAudio.h \
+ src/binding/AAudioCommon.h \
src/legacy/AudioStreamTrack.h \
src/legacy/AudioStreamRecord.h \
src/legacy/AAudioLegacy.h \
src/core/AudioStreamBuilder.h \
src/core/AudioStream.h \
- src/utility/HandleTracker.h \
src/utility/MonotonicCounter.h \
src/utility/AudioClock.h \
src/utility/AAudioUtilities.h
diff --git a/media/libaaudio/src/Android.mk b/media/libaaudio/src/Android.mk
index cfcf27a..6861248 100644
--- a/media/libaaudio/src/Android.mk
+++ b/media/libaaudio/src/Android.mk
@@ -36,7 +36,6 @@
legacy/AudioStreamLegacy.cpp \
legacy/AudioStreamRecord.cpp \
legacy/AudioStreamTrack.cpp \
- utility/HandleTracker.cpp \
utility/AAudioUtilities.cpp \
utility/FixedBlockAdapter.cpp \
utility/FixedBlockReader.cpp \
@@ -95,7 +94,6 @@
legacy/AudioStreamLegacy.cpp \
legacy/AudioStreamRecord.cpp \
legacy/AudioStreamTrack.cpp \
- utility/HandleTracker.cpp \
utility/AAudioUtilities.cpp \
utility/FixedBlockAdapter.cpp \
utility/FixedBlockReader.cpp \
diff --git a/media/libaaudio/src/binding/AAudioCommon.h b/media/libaaudio/src/binding/AAudioCommon.h
new file mode 100644
index 0000000..e3e9e82
--- /dev/null
+++ b/media/libaaudio/src/binding/AAudioCommon.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AAUDIO_COMMON_H
+#define ANDROID_AAUDIO_COMMON_H
+
+#include <stdint.h>
+
+/*
+ * Internal header that is common to both client and server.
+ *
+ */
+namespace aaudio {
+
+typedef int32_t aaudio_handle_t;
+
+} /* namespace aaudio */
+
+#endif // ANDROID_AAUDIO_COMMON_H
diff --git a/media/libaaudio/src/binding/IAAudioClient.h b/media/libaaudio/src/binding/IAAudioClient.h
index 21cc33b..f21fd93 100644
--- a/media/libaaudio/src/binding/IAAudioClient.h
+++ b/media/libaaudio/src/binding/IAAudioClient.h
@@ -22,7 +22,7 @@
#include <aaudio/AAudio.h>
-#include "utility/HandleTracker.h"
+#include "binding/AAudioCommon.h"
namespace android {
@@ -33,7 +33,7 @@
DECLARE_META_INTERFACE(AAudioClient);
- virtual void onStreamChange(aaudio_handle_t handle, int32_t opcode, int32_t value) = 0;
+ virtual void onStreamChange(aaudio::aaudio_handle_t handle, int32_t opcode, int32_t value) = 0;
};
diff --git a/media/libaaudio/src/binding/IAAudioService.h b/media/libaaudio/src/binding/IAAudioService.h
index 30b3ead..6bdb826 100644
--- a/media/libaaudio/src/binding/IAAudioService.h
+++ b/media/libaaudio/src/binding/IAAudioService.h
@@ -24,12 +24,12 @@
#include <aaudio/AAudio.h>
+#include "binding/AAudioCommon.h"
#include "binding/AAudioServiceDefinitions.h"
-#include "binding/AudioEndpointParcelable.h"
-#include "binding/AAudioStreamRequest.h"
#include "binding/AAudioStreamConfiguration.h"
+#include "binding/AAudioStreamRequest.h"
+#include "binding/AudioEndpointParcelable.h"
#include "binding/IAAudioClient.h"
-#include "utility/HandleTracker.h"
namespace android {
@@ -51,7 +51,7 @@
* @param configuration contains information about the created stream
* @return handle to the stream or a negative error
*/
- virtual aaudio_handle_t openStream(const aaudio::AAudioStreamRequest &request,
+ virtual aaudio::aaudio_handle_t openStream(const aaudio::AAudioStreamRequest &request,
aaudio::AAudioStreamConfiguration &configurationOutput) = 0;
virtual aaudio_result_t closeStream(aaudio::aaudio_handle_t streamHandle) = 0;
@@ -89,11 +89,11 @@
/**
* Manage the specified thread as a low latency audio thread.
*/
- virtual aaudio_result_t registerAudioThread(aaudio_handle_t streamHandle,
+ virtual aaudio_result_t registerAudioThread(aaudio::aaudio_handle_t streamHandle,
pid_t clientThreadId,
int64_t periodNanoseconds) = 0;
- virtual aaudio_result_t unregisterAudioThread(aaudio_handle_t streamHandle,
+ virtual aaudio_result_t unregisterAudioThread(aaudio::aaudio_handle_t streamHandle,
pid_t clientThreadId) = 0;
};
diff --git a/media/libaaudio/src/client/AudioStreamInternalPlay.h b/media/libaaudio/src/client/AudioStreamInternalPlay.h
index 98783de..d5c1b1e 100644
--- a/media/libaaudio/src/client/AudioStreamInternalPlay.h
+++ b/media/libaaudio/src/client/AudioStreamInternalPlay.h
@@ -50,9 +50,6 @@
return AAUDIO_DIRECTION_OUTPUT;
}
- // Only register client side streams.
- bool needsSystemRegistration() override { return !mInService; }
-
protected:
aaudio_result_t requestPauseInternal();
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index 63569ad..1eaee81 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -24,15 +24,14 @@
#include <aaudio/AAudio.h>
#include <aaudio/AAudioTesting.h>
+#include "AudioClock.h"
#include "AudioStreamBuilder.h"
#include "AudioStream.h"
-#include "AudioClock.h"
+#include "binding/AAudioCommon.h"
#include "client/AudioStreamInternal.h"
-#include "HandleTracker.h"
using namespace aaudio;
-
// Macros for common code that includes a return.
// TODO Consider using do{}while(0) construct. I tried but it hung AndroidStudio
#define CONVERT_BUILDER_HANDLE_OR_RETURN() \
@@ -219,7 +218,7 @@
ALOGD("AAudioStreamBuilder_openStream() returns %d = %s for (%p) ----------------",
result, AAudio_convertResultToText(result), audioStream);
if (result == AAUDIO_OK) {
- audioStream->systemRegister();
+ audioStream->registerPlayerBase();
*streamPtr = (AAudioStream*) audioStream;
} else {
*streamPtr = nullptr;
@@ -243,7 +242,7 @@
ALOGD("AAudioStream_close(%p)", stream);
if (audioStream != nullptr) {
audioStream->close();
- audioStream->systemUnRegister();
+ audioStream->unregisterPlayerBase();
delete audioStream;
return AAUDIO_OK;
}
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 35a1c6a..8dcc37a 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -45,6 +45,8 @@
|| getState() == AAUDIO_STREAM_STATE_DISCONNECTED),
"aaudio stream still in use, state = %s",
AAudio_convertStreamStateToText(getState()));
+
+ mPlayerBase->clearParentReference(); // remove reference to this AudioStream
}
static const char *AudioStream_convertSharingModeToShortText(aaudio_sharing_mode_t sharingMode) {
@@ -197,3 +199,38 @@
return err ? AAudioConvert_androidToAAudioResult(-errno) : mThreadRegistrationResult;
}
+
+#if AAUDIO_USE_VOLUME_SHAPER
+android::media::VolumeShaper::Status AudioStream::applyVolumeShaper(
+ const android::media::VolumeShaper::Configuration& configuration __unused,
+ const android::media::VolumeShaper::Operation& operation __unused) {
+ ALOGW("applyVolumeShaper() is not supported");
+ return android::media::VolumeShaper::Status::ok();
+}
+#endif
+
+AudioStream::MyPlayerBase::MyPlayerBase(AudioStream *parent) : mParent(parent) {
+}
+
+AudioStream::MyPlayerBase::~MyPlayerBase() {
+ ALOGV("MyPlayerBase::~MyPlayerBase(%p) deleted", this);
+}
+
+void AudioStream::MyPlayerBase::registerWithAudioManager() {
+ if (!mRegistered) {
+ init(android::PLAYER_TYPE_AAUDIO, AUDIO_USAGE_MEDIA);
+ mRegistered = true;
+ }
+}
+
+void AudioStream::MyPlayerBase::unregisterWithAudioManager() {
+ if (mRegistered) {
+ baseDestroy();
+ mRegistered = false;
+ }
+}
+
+
+void AudioStream::MyPlayerBase::destroy() {
+ unregisterWithAudioManager();
+}
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index 5800fa2..34202d2 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -256,29 +256,29 @@
virtual android::status_t doSetVolume() { return android::NO_ERROR; }
#if AAUDIO_USE_VOLUME_SHAPER
- virtual android::binder::Status applyVolumeShaper(
+ virtual ::android::binder::Status applyVolumeShaper(
const ::android::media::VolumeShaper::Configuration& configuration __unused,
- const ::android::media::VolumeShaper::Operation& operation __unused) {
- ALOGW("applyVolumeShaper() is not supported");
- return android::binder::Status::ok();
- }
+ const ::android::media::VolumeShaper::Operation& operation __unused);
#endif
- // Should this object be registered with the AudioManager?
- virtual bool needsSystemRegistration() { return false; }
-
- // Register this stream's PlayerBase with the AudioManager
- void systemRegister() {
- if (needsSystemRegistration()) {
+ /**
+ * Register this stream's PlayerBase with the AudioManager if needed.
+ * Only register output streams.
+ * This should only be called for client streams and not for streams
+ * that run in the service.
+ */
+ void registerPlayerBase() {
+ if (getDirection() == AAUDIO_DIRECTION_OUTPUT) {
mPlayerBase->registerWithAudioManager();
}
}
- // UnRegister this stream's PlayerBase with the AudioManager
- void systemUnRegister() {
- if (needsSystemRegistration()) {
- mPlayerBase->destroy();
- }
+ /**
+ * Unregister this stream's PlayerBase with the AudioManager.
+ * This will only unregister if already registered.
+ */
+ void unregisterPlayerBase() {
+ mPlayerBase->unregisterWithAudioManager();
}
// Pass start request through PlayerBase for tracking.
@@ -308,43 +308,53 @@
// ------ AudioManager -------
class MyPlayerBase : public android::PlayerBase {
public:
- MyPlayerBase(AudioStream *parent) : mParent(parent) {}
- virtual ~MyPlayerBase() {}
+ explicit MyPlayerBase(AudioStream *parent);
- void registerWithAudioManager() {
- init(android::PLAYER_TYPE_AAUDIO, AUDIO_USAGE_MEDIA);
- }
+ virtual ~MyPlayerBase();
- void destroy() override {
- // FIXME what else should this do? close()? disconnect()?
- baseDestroy();
- }
+ /**
+ * Register for volume changes and remote control.
+ */
+ void registerWithAudioManager();
- virtual android::status_t playerStart() {
+ /**
+ * UnRegister.
+ */
+ void unregisterWithAudioManager();
+
+ /**
+ * Just calls unregisterWithAudioManager().
+ */
+ void destroy() override;
+
+ void clearParentReference() { mParent = nullptr; }
+
+ android::status_t playerStart() override {
+ // mParent should NOT be null. So go ahead and crash if it is.
mResult = mParent->requestStart();
return AAudioConvert_aaudioToAndroidStatus(mResult);
}
- virtual android::status_t playerPause() {
+ android::status_t playerPause() override {
mResult = mParent->requestPause();
return AAudioConvert_aaudioToAndroidStatus(mResult);
}
- virtual android::status_t playerStop() {
+ android::status_t playerStop() override {
mResult = mParent->requestStop();
return AAudioConvert_aaudioToAndroidStatus(mResult);
}
- virtual android::status_t playerSetVolume() {
+ android::status_t playerSetVolume() override {
// No pan and only left volume is taken into account from IPLayer interface
mParent->setDuckAndMuteVolume(mVolumeMultiplierL /* * mPanMultiplierL */);
return android::NO_ERROR;
}
#if AAUDIO_USE_VOLUME_SHAPER
- android::binder::Status applyVolumeShaper(
- const android::media::VolumeShaper::Configuration& configuration,
- const android::media::VolumeShaper::Operation& operation) {
+ ::android::binder::Status applyVolumeShaper(
+ const ::android::media::VolumeShaper::Configuration& configuration,
+ const ::android::media::VolumeShaper::Operation& operation) {
return mParent->applyVolumeShaper(configuration, operation);
}
#endif
@@ -353,12 +363,12 @@
return mResult;
}
- AudioStream *mParent;
+ private:
+ AudioStream *mParent;
aaudio_result_t mResult = AAUDIO_OK;
+ bool mRegistered = false;
};
-
-
/**
* This should not be called after the open() call.
*/
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
index a59fc6f..ee2504d 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
@@ -31,7 +31,8 @@
using namespace aaudio;
AudioStreamLegacy::AudioStreamLegacy()
- : AudioStream(), mDeviceCallback(new StreamDeviceCallback(this)) {
+ : AudioStream()
+ , mDeviceCallback(new StreamDeviceCallback(this)) {
}
AudioStreamLegacy::~AudioStreamLegacy() {
@@ -78,18 +79,20 @@
void AudioStreamLegacy::processCallbackCommon(aaudio_callback_operation_t opcode, void *info) {
aaudio_data_callback_result_t callbackResult;
- if (!mCallbackEnabled.load()) {
- return;
- }
-
switch (opcode) {
case AAUDIO_CALLBACK_OPERATION_PROCESS_DATA: {
- if (getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
- // Note that this code assumes an AudioTrack::Buffer is the same as
- // AudioRecord::Buffer
- // TODO define our own AudioBuffer and pass it from the subclasses.
- AudioTrack::Buffer *audioBuffer = static_cast<AudioTrack::Buffer *>(info);
- if (audioBuffer->frameCount == 0) return;
+ checkForDisconnectRequest();
+
+ // Note that this code assumes an AudioTrack::Buffer is the same as
+ // AudioRecord::Buffer
+ // TODO define our own AudioBuffer and pass it from the subclasses.
+ AudioTrack::Buffer *audioBuffer = static_cast<AudioTrack::Buffer *>(info);
+ if (getState() == AAUDIO_STREAM_STATE_DISCONNECTED || !mCallbackEnabled.load()) {
+ audioBuffer->size = 0; // silence the buffer
+ } else {
+ if (audioBuffer->frameCount == 0) {
+ return;
+ }
// If the caller specified an exact size then use a block size adapter.
if (mBlockAdapter != nullptr) {
@@ -107,26 +110,19 @@
audioBuffer->size = 0;
}
- if (updateStateMachine() == AAUDIO_OK) {
- break; // don't fall through
+ if (updateStateMachine() != AAUDIO_OK) {
+ forceDisconnect();
+ mCallbackEnabled.store(false);
}
}
}
- /// FALL THROUGH
+ break;
// Stream got rerouted so we disconnect.
- case AAUDIO_CALLBACK_OPERATION_DISCONNECTED: {
- setState(AAUDIO_STREAM_STATE_DISCONNECTED);
+ case AAUDIO_CALLBACK_OPERATION_DISCONNECTED:
ALOGD("processCallbackCommon() stream disconnected");
- if (getErrorCallbackProc() != nullptr) {
- (*getErrorCallbackProc())(
- (AAudioStream *) this,
- getErrorCallbackUserData(),
- AAUDIO_ERROR_DISCONNECTED
- );
- }
+ forceDisconnect();
mCallbackEnabled.store(false);
- }
break;
default:
@@ -134,6 +130,30 @@
}
}
+
+
+void AudioStreamLegacy::checkForDisconnectRequest() {
+ if (mRequestDisconnect.isRequested()) {
+ ALOGD("checkForDisconnectRequest() mRequestDisconnect acknowledged");
+ forceDisconnect();
+ mRequestDisconnect.acknowledge();
+ mCallbackEnabled.store(false);
+ }
+}
+
+void AudioStreamLegacy::forceDisconnect() {
+ if (getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
+ setState(AAUDIO_STREAM_STATE_DISCONNECTED);
+ if (getErrorCallbackProc() != nullptr) {
+ (*getErrorCallbackProc())(
+ (AAudioStream *) this,
+ getErrorCallbackUserData(),
+ AAUDIO_ERROR_DISCONNECTED
+ );
+ }
+ }
+}
+
aaudio_result_t AudioStreamLegacy::getBestTimestamp(clockid_t clockId,
int64_t *framePosition,
int64_t *timeNanoseconds,
@@ -175,15 +195,18 @@
ALOGD("onAudioDeviceUpdate() deviceId %d", (int)deviceId);
if (getDeviceId() != AAUDIO_UNSPECIFIED && getDeviceId() != deviceId &&
getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
- setState(AAUDIO_STREAM_STATE_DISCONNECTED);
- // if we have a data callback and the stream is active, send the error callback from
- // data callback thread when it sees the DISCONNECTED state
- if (!isDataCallbackActive() && getErrorCallbackProc() != nullptr) {
- (*getErrorCallbackProc())(
- (AAudioStream *) this,
- getErrorCallbackUserData(),
- AAUDIO_ERROR_DISCONNECTED
- );
+ // Note that isDataCallbackActive() is affected by state so call it before DISCONNECTING.
+ // If we have a data callback and the stream is active, then ask the data callback
+ // to DISCONNECT and call the error callback.
+ if (isDataCallbackActive()) {
+ ALOGD("onAudioDeviceUpdate() request DISCONNECT in data callback due to device change");
+ // If the stream is stopped before the data callback has a chance to handle the
+ // request then the requestStop() and requestPause() methods will handle it after
+ // the callback has stopped.
+ mRequestDisconnect.request();
+ } else {
+ ALOGD("onAudioDeviceUpdate() DISCONNECT the stream now");
+ forceDisconnect();
}
}
setDeviceId(deviceId);
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.h b/media/libaaudio/src/legacy/AudioStreamLegacy.h
index 66c216c..7e28579 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.h
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.h
@@ -24,6 +24,7 @@
#include "AudioStream.h"
#include "AAudioLegacy.h"
+#include "utility/AAudioUtilities.h"
#include "utility/FixedBlockAdapter.h"
namespace aaudio {
@@ -111,6 +112,10 @@
void onAudioDeviceUpdate(audio_port_handle_t deviceId);
+ void checkForDisconnectRequest();
+
+ void forceDisconnect();
+
void onStart() { mCallbackEnabled.store(true); }
void onStop() { mCallbackEnabled.store(false); }
@@ -130,6 +135,8 @@
aaudio_wrapping_frames_t mPositionWhenStarting = 0;
int32_t mCallbackBufferSize = 0;
const android::sp<StreamDeviceCallback> mDeviceCallback;
+
+ AtomicRequestor mRequestDisconnect;
};
} /* namespace aaudio */
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index 4d6fb2a..bc6e60c 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -238,6 +238,7 @@
mAudioRecord->stop();
mFramesRead.reset32();
mTimestampPosition.reset32();
+ checkForDisconnectRequest();
return AAUDIO_OK;
}
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index 09c078c..0e9aaef 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -261,6 +261,7 @@
onStop();
setState(AAUDIO_STREAM_STATE_PAUSING);
mAudioTrack->pause();
+ checkForDisconnectRequest();
status_t err = mAudioTrack->getPosition(&mPositionWhenPausing);
if (err != OK) {
return AAudioConvert_androidToAAudioResult(err);
@@ -300,6 +301,7 @@
mFramesWritten.reset32();
mTimestampPosition.reset32();
mAudioTrack->stop();
+ checkForDisconnectRequest();
return AAUDIO_OK;
}
@@ -476,6 +478,9 @@
}
#if AAUDIO_USE_VOLUME_SHAPER
+
+using namespace android::media::VolumeShaper;
+
binder::Status AudioStreamTrack::applyVolumeShaper(
const VolumeShaper::Configuration& configuration,
const VolumeShaper::Operation& operation) {
@@ -485,7 +490,7 @@
if (mAudioTrack.get() != nullptr) {
ALOGD("applyVolumeShaper() from IPlayer");
- VolumeShaper::Status status = mAudioTrack->applyVolumeShaper(spConfiguration, spOperation);
+ binder::Status status = mAudioTrack->applyVolumeShaper(spConfiguration, spOperation);
if (status < 0) { // a non-negative value is the volume shaper id.
ALOGE("applyVolumeShaper() failed with status %d", status);
}
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.h b/media/libaaudio/src/legacy/AudioStreamTrack.h
index dbcb94e..a871db4 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.h
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.h
@@ -77,8 +77,6 @@
return incrementFramesWritten(frames);
}
- bool needsSystemRegistration() override { return true; }
-
android::status_t doSetVolume() override;
#if AAUDIO_USE_VOLUME_SHAPER
diff --git a/media/libaaudio/src/utility/AAudioUtilities.h b/media/libaaudio/src/utility/AAudioUtilities.h
index f56be32..3afa976 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.h
+++ b/media/libaaudio/src/utility/AAudioUtilities.h
@@ -346,15 +346,18 @@
*/
class AtomicRequestor {
public:
+
+ __attribute__((no_sanitize("integer")))
void request() {
- // TODO handle overflows, very unlikely
mRequested++;
}
+ __attribute__((no_sanitize("integer")))
bool isRequested() {
- return mRequested.load() > mAcknowledged.load();
+ return (mRequested.load() - mAcknowledged.load()) > 0;
}
+ __attribute__((no_sanitize("integer")))
void acknowledge() {
mAcknowledged++;
}
diff --git a/media/libaaudio/src/utility/HandleTracker.cpp b/media/libaaudio/src/utility/HandleTracker.cpp
deleted file mode 100644
index 35ce95a..0000000
--- a/media/libaaudio/src/utility/HandleTracker.cpp
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#define LOG_TAG "AAudio"
-//#define LOG_NDEBUG 0
-#include <utils/Log.h>
-
-#include <assert.h>
-#include <functional>
-#include <iomanip>
-#include <new>
-#include <sstream>
-#include <stdint.h>
-#include <utils/Mutex.h>
-
-#include <aaudio/AAudio.h>
-#include "AAudioUtilities.h"
-#include "HandleTracker.h"
-
-using android::Mutex;
-
-// Handle format is: tgggiiii
-// where each letter is 4 bits, t=type, g=generation, i=index
-
-#define TYPE_SIZE 4
-#define GENERATION_SIZE 12
-#define INDEX_SIZE 16
-
-#define GENERATION_INVALID 0
-#define GENERATION_SHIFT INDEX_SIZE
-
-#define TYPE_MASK ((1 << TYPE_SIZE) - 1)
-#define GENERATION_MASK ((1 << GENERATION_SIZE) - 1)
-#define INDEX_MASK ((1 << INDEX_SIZE) - 1)
-
-#define SLOT_UNAVAILABLE (-1)
-
-// Error if handle is negative so type is limited to bottom half.
-#define HANDLE_INVALID_TYPE TYPE_MASK
-
-static_assert(HANDLE_TRACKER_MAX_TYPES == (1 << (TYPE_SIZE - 1)),
- "Mismatch between header and cpp.");
-static_assert(HANDLE_TRACKER_MAX_HANDLES == (1 << (INDEX_SIZE)),
- "Mismatch between header and cpp.");
-
-HandleTracker::HandleTracker(uint32_t maxHandles)
- : mMaxHandleCount(maxHandles)
- , mHandleHeaders(nullptr)
-{
- assert(maxHandles <= HANDLE_TRACKER_MAX_HANDLES);
- // Allocate arrays to hold addresses and validation info.
- mHandleAddresses = (handle_tracker_address_t *)
- new(std::nothrow) handle_tracker_address_t[maxHandles];
- if (mHandleAddresses != nullptr) {
- mHandleHeaders = new(std::nothrow) handle_tracker_header_t[maxHandles];
-
- if (mHandleHeaders != nullptr) {
- handle_tracker_header_t initialHeader = buildHeader(0, 1);
- // Initialize linked list of free nodes. nullptr terminated.
- for (uint32_t i = 0; i < (maxHandles - 1); i++) {
- mHandleAddresses[i] = &mHandleAddresses[i + 1]; // point to next node
- mHandleHeaders[i] = initialHeader;
- }
- mNextFreeAddress = &mHandleAddresses[0];
- mHandleAddresses[maxHandles - 1] = nullptr;
- mHandleHeaders[maxHandles - 1] = 0;
- } else {
- delete[] mHandleAddresses; // so the class appears uninitialized
- mHandleAddresses = nullptr;
- }
- }
-}
-
-HandleTracker::~HandleTracker()
-{
- Mutex::Autolock _l(mLock);
- delete[] mHandleAddresses;
- delete[] mHandleHeaders;
- mHandleAddresses = nullptr;
-}
-
-bool HandleTracker::isInitialized() const {
- return mHandleAddresses != nullptr;
-}
-
-
-
-std::string HandleTracker::dump() const {
- if (!isInitialized()) {
- return "HandleTracker is not initialized\n";
- }
-
- std::stringstream result;
- const bool isLocked = AAudio_tryUntilTrue(
- [this]()->bool { return mLock.tryLock(); } /* f */,
- 50 /* times */,
- 20 /* sleepMs */);
- if (!isLocked) {
- result << "HandleTracker may be deadlocked\n";
- }
-
- result << "HandleTracker:\n";
- result << " HandleHeaders:\n";
- // atLineStart() can be changed to support an arbitrary line breaking algorithm;
- // it should return true when a new line starts.
- // For simplicity, we will use a constant 16 items per line.
- const auto atLineStart = [](int index) -> bool {
- // Magic constant of 0xf used for mask to detect start every 16 items.
- return (index & 0xf) == 0; };
- const auto atLineEnd = [this, &atLineStart](int index) -> bool {
- return atLineStart(index + 1) || index == mMaxHandleCount - 1; };
-
- for (int i = 0; i < mMaxHandleCount; ++i) {
- if (atLineStart(i)) {
- result << " ";
- }
- result << std::hex << std::setw(4) << std::setfill('0') << mHandleHeaders[i]
- << (atLineEnd(i) ? "\n" : " ");
- }
-
- if (isLocked) {
- mLock.unlock();
- }
- return result.str();
-}
-
-handle_tracker_slot_t HandleTracker::allocateSlot_l() {
- void **allocated = mNextFreeAddress;
- if (allocated == nullptr) {
- return SLOT_UNAVAILABLE;
- }
- // Remove this slot from the head of the linked list.
- mNextFreeAddress = (void **) *allocated;
- return (allocated - mHandleAddresses);
-}
-
-handle_tracker_generation_t HandleTracker::nextGeneration_l(handle_tracker_slot_t index) {
- handle_tracker_generation_t generation = (mHandleHeaders[index] + 1) & GENERATION_MASK;
- // Avoid generation zero so that 0x0 is not a valid handle.
- if (generation == GENERATION_INVALID) {
- generation++;
- }
- return generation;
-}
-
-aaudio_handle_t HandleTracker::put(handle_tracker_type_t type, void *address)
-{
- if (type < 0 || type >= HANDLE_TRACKER_MAX_TYPES) {
- return static_cast<aaudio_handle_t>(AAUDIO_ERROR_OUT_OF_RANGE);
- }
- if (!isInitialized()) {
- return static_cast<aaudio_handle_t>(AAUDIO_ERROR_NO_MEMORY);
- }
-
- Mutex::Autolock _l(mLock);
-
- // Find an empty slot.
- handle_tracker_slot_t index = allocateSlot_l();
- if (index == SLOT_UNAVAILABLE) {
- ALOGE("HandleTracker::put() no room for more handles");
- return static_cast<aaudio_handle_t>(AAUDIO_ERROR_NO_FREE_HANDLES);
- }
-
- // Cycle the generation counter so stale handles can be detected.
- handle_tracker_generation_t generation = nextGeneration_l(index); // reads header table
- handle_tracker_header_t inputHeader = buildHeader(type, generation);
-
- // These two writes may need to be observed by other threads or cores during get().
- mHandleHeaders[index] = inputHeader;
- mHandleAddresses[index] = address;
- // TODO use store release to enforce memory order with get()
-
- // Generate a handle.
- aaudio_handle_t handle = buildHandle(inputHeader, index);
-
- ALOGV("HandleTracker::put(%p) returns 0x%08x", address, handle);
- return handle;
-}
-
-handle_tracker_slot_t HandleTracker::handleToIndex(handle_tracker_type_t type,
- aaudio_handle_t handle) const
-{
- // Validate the handle.
- handle_tracker_slot_t index = extractIndex(handle);
- if (index >= mMaxHandleCount) {
- ALOGE("HandleTracker::handleToIndex() invalid handle = 0x%08X", handle);
- return static_cast<aaudio_handle_t>(AAUDIO_ERROR_INVALID_HANDLE);
- }
- handle_tracker_generation_t handleGeneration = extractGeneration(handle);
- handle_tracker_header_t inputHeader = buildHeader(type, handleGeneration);
- // We do not need to synchronize this access to mHandleHeaders because it is constant for
- // the lifetime of the handle.
- if (inputHeader != mHandleHeaders[index]) {
- ALOGE("HandleTracker::handleToIndex() inputHeader = 0x%08x != mHandleHeaders[%d] = 0x%08x",
- inputHeader, index, mHandleHeaders[index]);
- return static_cast<aaudio_handle_t>(AAUDIO_ERROR_INVALID_HANDLE);
- }
- return index;
-}
-
-handle_tracker_address_t HandleTracker::get(handle_tracker_type_t type, aaudio_handle_t handle) const
-{
- if (!isInitialized()) {
- return nullptr;
- }
- handle_tracker_slot_t index = handleToIndex(type, handle);
- if (index >= 0) {
- // We do not need to synchronize this access to mHandleHeaders because this slot
- // is allocated and, therefore, not part of the linked list of free slots.
- return mHandleAddresses[index];
- } else {
- return nullptr;
- }
-}
-
-handle_tracker_address_t HandleTracker::remove(handle_tracker_type_t type, aaudio_handle_t handle) {
- if (!isInitialized()) {
- return nullptr;
- }
-
- Mutex::Autolock _l(mLock);
-
- handle_tracker_slot_t index = handleToIndex(type,handle);
- if (index >= 0) {
- handle_tracker_address_t address = mHandleAddresses[index];
-
- // Invalidate the header type but preserve the generation count.
- handle_tracker_generation_t generation = mHandleHeaders[index] & GENERATION_MASK;
- handle_tracker_header_t inputHeader = buildHeader(
- (handle_tracker_type_t) HANDLE_INVALID_TYPE, generation);
- mHandleHeaders[index] = inputHeader;
-
- // Add this slot to the head of the linked list.
- mHandleAddresses[index] = mNextFreeAddress;
- mNextFreeAddress = (handle_tracker_address_t *) &mHandleAddresses[index];
- return address;
- } else {
- return nullptr;
- }
-}
-
-aaudio_handle_t HandleTracker::buildHandle(handle_tracker_header_t typeGeneration,
- handle_tracker_slot_t index) {
- return (aaudio_handle_t)((typeGeneration << GENERATION_SHIFT) | (index & INDEX_MASK));
-}
-
-handle_tracker_header_t HandleTracker::buildHeader(handle_tracker_type_t type,
- handle_tracker_generation_t generation)
-{
- return (handle_tracker_header_t) (((type & TYPE_MASK) << GENERATION_SIZE)
- | (generation & GENERATION_MASK));
-}
-
-handle_tracker_slot_t HandleTracker::extractIndex(aaudio_handle_t handle)
-{
- return handle & INDEX_MASK;
-}
-
-handle_tracker_generation_t HandleTracker::extractGeneration(aaudio_handle_t handle)
-{
- return (handle >> GENERATION_SHIFT) & GENERATION_MASK;
-}
diff --git a/media/libaaudio/src/utility/HandleTracker.h b/media/libaaudio/src/utility/HandleTracker.h
deleted file mode 100644
index a4c51c0..0000000
--- a/media/libaaudio/src/utility/HandleTracker.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef UTILITY_HANDLE_TRACKER_H
-#define UTILITY_HANDLE_TRACKER_H
-
-#include <stdint.h>
-#include <string>
-#include <utils/Mutex.h>
-
-typedef int32_t aaudio_handle_t;
-typedef int32_t handle_tracker_type_t; // what kind of handle
-typedef int32_t handle_tracker_slot_t; // index in allocation table
-typedef int32_t handle_tracker_generation_t; // incremented when slot used
-typedef uint16_t handle_tracker_header_t; // combines type and generation
-typedef void *handle_tracker_address_t; // address of something that is stored here
-
-#define HANDLE_TRACKER_MAX_TYPES (1 << 3)
-#define HANDLE_TRACKER_MAX_HANDLES (1 << 16)
-
-/**
- * Represent Objects using an integer handle that can be used with Java.
- * This also makes the 'C' ABI more robust.
- *
- * Note that this should only be called from a single thread.
- * If you call it from more than one thread then you need to use your own mutex.
- */
-class HandleTracker {
-
-public:
- /**
- * @param maxHandles cannot exceed HANDLE_TRACKER_MAX_HANDLES
- */
- HandleTracker(uint32_t maxHandles = 256);
- virtual ~HandleTracker();
-
- /**
- * Don't use if this returns false;
- * @return true if the internal allocation succeeded
- */
- bool isInitialized() const;
-
- /**
- * Returns HandleTracker information.
- *
- * Will attempt to get the object lock, but will proceed
- * even if it cannot.
- *
- * Each line of information ends with a newline.
- *
- * @return a string representing the HandleTracker info.
- */
- std::string dump() const;
-
- /**
- * Store a pointer and return a handle that can be used to retrieve the pointer.
- *
- * It is safe to call put() or remove() from multiple threads.
- *
- * @param expectedType the type of the object to be tracked
- * @param address pointer to be converted to a handle
- * @return a valid handle or a negative error
- */
- aaudio_handle_t put(handle_tracker_type_t expectedType, handle_tracker_address_t address);
-
- /**
- * Get the original pointer associated with the handle.
- * The handle will be validated to prevent stale handles from being reused.
- * Note that the validation is designed to prevent common coding errors and not
- * to prevent deliberate hacking.
- *
- * @param expectedType shouldmatch the type we passed to put()
- * @param handle to be converted to a pointer
- * @return address associated with handle or nullptr
- */
- handle_tracker_address_t get(handle_tracker_type_t expectedType, aaudio_handle_t handle) const;
-
- /**
- * Free up the storage associated with the handle.
- * Subsequent attempts to use the handle will fail.
- *
- * Do NOT remove() a handle while get() is being called for the same handle from another thread.
- *
- * @param expectedType shouldmatch the type we passed to put()
- * @param handle to be removed from tracking
- * @return address associated with handle or nullptr if not found
- */
- handle_tracker_address_t remove(handle_tracker_type_t expectedType, aaudio_handle_t handle);
-
-private:
- const int32_t mMaxHandleCount; // size of array
- // This address is const after initialization.
- handle_tracker_address_t * mHandleAddresses; // address of objects or a free linked list node
- // This address is const after initialization.
- handle_tracker_header_t * mHandleHeaders; // combination of type and generation
- // head of the linked list of free nodes in mHandleAddresses
- handle_tracker_address_t * mNextFreeAddress;
-
- // This Mutex protects the linked list of free nodes.
- // The list is managed using mHandleAddresses and mNextFreeAddress.
- // The data in mHandleHeaders is only changed by put() and remove().
- mutable android::Mutex mLock;
-
- /**
- * Pull slot off of a list of empty slots.
- * @return index or a negative error
- */
- handle_tracker_slot_t allocateSlot_l();
-
- /**
- * Increment the generation for the slot, avoiding zero.
- */
- handle_tracker_generation_t nextGeneration_l(handle_tracker_slot_t index);
-
- /**
- * Validate the handle and return the corresponding index.
- * @return slot index or a negative error
- */
- handle_tracker_slot_t handleToIndex(aaudio_handle_t handle, handle_tracker_type_t type) const;
-
- /**
- * Construct a handle from a header and an index.
- * @param header combination of a type and a generation
- * @param index slot index returned from allocateSlot
- * @return handle or a negative error
- */
- static aaudio_handle_t buildHandle(handle_tracker_header_t header, handle_tracker_slot_t index);
-
- /**
- * Combine a type and a generation field into a header.
- */
- static handle_tracker_header_t buildHeader(handle_tracker_type_t type,
- handle_tracker_generation_t generation);
-
- /**
- * Extract the index from a handle.
- * Does not validate the handle.
- * @return index associated with a handle
- */
- static handle_tracker_slot_t extractIndex(aaudio_handle_t handle);
-
- /**
- * Extract the generation from a handle.
- * Does not validate the handle.
- * @return generation associated with a handle
- */
- static handle_tracker_generation_t extractGeneration(aaudio_handle_t handle);
-
-};
-
-#endif //UTILITY_HANDLE_TRACKER_H
diff --git a/media/libaaudio/tests/Android.mk b/media/libaaudio/tests/Android.mk
index 4402919..37b010d 100644
--- a/media/libaaudio/tests/Android.mk
+++ b/media/libaaudio/tests/Android.mk
@@ -5,16 +5,6 @@
$(call include-path-for, audio-utils) \
frameworks/av/media/libaaudio/include \
frameworks/av/media/libaaudio/src
-LOCAL_SRC_FILES:= test_handle_tracker.cpp
-LOCAL_SHARED_LIBRARIES := libaaudio
-LOCAL_MODULE := test_handle_tracker
-include $(BUILD_NATIVE_TEST)
-
-include $(CLEAR_VARS)
-LOCAL_C_INCLUDES := \
- $(call include-path-for, audio-utils) \
- frameworks/av/media/libaaudio/include \
- frameworks/av/media/libaaudio/src
LOCAL_SRC_FILES:= test_marshalling.cpp
LOCAL_SHARED_LIBRARIES := libaaudio libbinder libcutils libutils
LOCAL_MODULE := test_aaudio_marshalling
diff --git a/media/libaaudio/tests/test_handle_tracker.cpp b/media/libaaudio/tests/test_handle_tracker.cpp
deleted file mode 100644
index c4db47a..0000000
--- a/media/libaaudio/tests/test_handle_tracker.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// Unit tests for AAudio Handle Tracker
-
-#include <stdlib.h>
-#include <math.h>
-
-#include <gtest/gtest.h>
-
-#include <aaudio/AAudio.h>
-#include "utility/HandleTracker.h"
-
-// Test adding one address.
-TEST(test_handle_tracker, aaudio_handle_tracker) {
- const int MAX_HANDLES = 4;
- HandleTracker tracker(MAX_HANDLES);
- handle_tracker_type_t type = 3; // arbitrary generic type
- int data; // something that has an address we can use
- handle_tracker_address_t found;
-
- // repeat the test several times to see if it breaks
- const int SEVERAL = 5; // arbitrary
- for (int i = 0; i < SEVERAL; i++) {
- // should fail to find a bogus handle
- found = tracker.get(type, 0); // bad handle
- EXPECT_EQ(nullptr, found);
-
- // create a valid handle and use it to lookup the object again
- aaudio_handle_t dataHandle = tracker.put(type, &data);
- ASSERT_TRUE(dataHandle > 0);
- found = tracker.get(type, dataHandle);
- EXPECT_EQ(&data, found);
- found = tracker.get(type, 0); // bad handle
- EXPECT_EQ(nullptr, found);
-
- // wrong type
- found = tracker.get(type+1, dataHandle);
- EXPECT_EQ(nullptr, found);
-
- // remove from storage
- found = tracker.remove(type, dataHandle);
- EXPECT_EQ(&data, found);
- // should fail the second time
- found = tracker.remove(type, dataHandle);
- EXPECT_EQ(nullptr, found);
- }
-}
-
-// Test filling the tracker.
-TEST(test_handle_tracker, aaudio_full_up) {
- const int MAX_HANDLES = 5;
- HandleTracker tracker(MAX_HANDLES);
- handle_tracker_type_t type = 4; // arbitrary generic type
- int data[MAX_HANDLES];
- aaudio_handle_t handles[MAX_HANDLES];
- handle_tracker_address_t found;
-
- // repeat the test several times to see if it breaks
- const int SEVERAL = 5; // arbitrary
- for (int i = 0; i < SEVERAL; i++) {
- for (int i = 0; i < MAX_HANDLES; i++) {
- // add a handle
- handles[i] = tracker.put(type, &data[i]);
- ASSERT_TRUE(handles[i] > 0);
- found = tracker.get(type, handles[i]);
- EXPECT_EQ(&data[i], found);
- }
-
- // Now that it is full, try to add one more.
- aaudio_handle_t handle = tracker.put(type, &data[0]);
- EXPECT_TRUE(handle < 0);
-
- for (int i = 0; i < MAX_HANDLES; i++) {
- // look up each handle
- found = tracker.get(type, handles[i]);
- EXPECT_EQ(&data[i], found);
- }
-
- // remove one from storage
- found = tracker.remove(type, handles[2]);
- EXPECT_EQ(&data[2], found);
- // now try to look up the same handle and fail
- found = tracker.get(type, handles[2]);
- EXPECT_EQ(nullptr, found);
-
- // add that same one back
- handle = tracker.put(type, &data[2]);
- ASSERT_TRUE(handle > 0);
- found = tracker.get(type, handle);
- EXPECT_EQ(&data[2], found);
- // now use a stale handle again with a valid index and fail
- found = tracker.get(type, handles[2]);
- EXPECT_EQ(nullptr, found);
-
- // remove them all
- handles[2] = handle;
- for (int i = 0; i < MAX_HANDLES; i++) {
- // look up each handle
- found = tracker.remove(type, handles[i]);
- EXPECT_EQ(&data[i], found);
- }
- }
-}
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 611cde7..ba4acc6 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -120,7 +120,7 @@
}
// 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);
+ AudioSystem::removeAudioDeviceCallback(this, mInput);
}
IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this);
mAudioRecord.clear();
@@ -274,7 +274,7 @@
mStatus = NO_ERROR;
mUserData = user;
// TODO: add audio hardware input latency here
- mLatency = (1000 * mFrameCount) / mSampleRate;
+ mLatency = (1000LL * mFrameCount) / mSampleRate;
mMarkerPosition = 0;
mMarkerReached = false;
mNewPosition = 0;
@@ -499,19 +499,26 @@
return mSelectedDeviceId;
}
+// must be called with mLock held
+void AudioRecord::updateRoutedDeviceId_l()
+{
+ // if the record is inactive, do not update actual device as the input stream maybe routed
+ // from a device not relevant to this client because of other active use cases.
+ if (!mActive) {
+ return;
+ }
+ if (mInput != AUDIO_IO_HANDLE_NONE) {
+ audio_port_handle_t deviceId = AudioSystem::getDeviceIdForIo(mInput);
+ if (deviceId != AUDIO_PORT_HANDLE_NONE) {
+ mRoutedDeviceId = deviceId;
+ }
+ }
+}
+
audio_port_handle_t AudioRecord::getRoutedDeviceId() {
AutoMutex lock(mLock);
- if (mInput == AUDIO_IO_HANDLE_NONE) {
- return AUDIO_PORT_HANDLE_NONE;
- }
- // if the input stream does not have an active audio patch, use either the device initially
- // selected by audio policy manager or the last routed device
- audio_port_handle_t deviceId = AudioSystem::getDeviceIdForIo(mInput);
- if (deviceId == AUDIO_PORT_HANDLE_NONE) {
- deviceId = mRoutedDeviceId;
- }
- mRoutedDeviceId = deviceId;
- return deviceId;
+ updateRoutedDeviceId_l();
+ return mRoutedDeviceId;
}
// -------------------------------------------------------------------------
@@ -537,9 +544,6 @@
return NO_INIT;
}
- if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) {
- AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput);
- }
audio_io_handle_t input;
// mFlags (not mOrigFlags) is modified depending on whether fast request is accepted.
@@ -744,6 +748,15 @@
}
mNotificationFramesAct = (uint32_t) notificationFrames;
+
+ //mInput != input includes the case where mInput == AUDIO_IO_HANDLE_NONE for first creation
+ if (mDeviceCallback != 0 && mInput != input) {
+ if (mInput != AUDIO_IO_HANDLE_NONE) {
+ AudioSystem::removeAudioDeviceCallback(this, mInput);
+ }
+ AudioSystem::addAudioDeviceCallback(this, input);
+ }
+
// We retain a copy of the I/O handle, but don't own the reference
mInput = input;
mRefreshRemaining = true;
@@ -763,10 +776,6 @@
mDeathNotifier = new DeathNotifier(this);
IInterface::asBinder(mAudioRecord)->linkToDeath(mDeathNotifier, this);
- if (mDeviceCallback != 0) {
- AudioSystem::addAudioDeviceCallback(mDeviceCallback, mInput);
- }
-
return NO_ERROR;
// End of retry loop.
@@ -1238,7 +1247,7 @@
return BAD_VALUE;
}
AutoMutex lock(mLock);
- if (mDeviceCallback == callback) {
+ if (mDeviceCallback.unsafe_get() == callback.get()) {
ALOGW("%s adding same callback!", __FUNCTION__);
return INVALID_OPERATION;
}
@@ -1246,9 +1255,9 @@
if (mInput != AUDIO_IO_HANDLE_NONE) {
if (mDeviceCallback != 0) {
ALOGW("%s callback already present!", __FUNCTION__);
- AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput);
+ AudioSystem::removeAudioDeviceCallback(this, mInput);
}
- status = AudioSystem::addAudioDeviceCallback(callback, mInput);
+ status = AudioSystem::addAudioDeviceCallback(this, mInput);
}
mDeviceCallback = callback;
return status;
@@ -1262,17 +1271,38 @@
return BAD_VALUE;
}
AutoMutex lock(mLock);
- if (mDeviceCallback != callback) {
+ if (mDeviceCallback.unsafe_get() != callback.get()) {
ALOGW("%s removing different callback!", __FUNCTION__);
return INVALID_OPERATION;
}
+ mDeviceCallback.clear();
if (mInput != AUDIO_IO_HANDLE_NONE) {
- AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput);
+ AudioSystem::removeAudioDeviceCallback(this, mInput);
}
- mDeviceCallback = 0;
return NO_ERROR;
}
+void AudioRecord::onAudioDeviceUpdate(audio_io_handle_t audioIo,
+ audio_port_handle_t deviceId)
+{
+ sp<AudioSystem::AudioDeviceCallback> callback;
+ {
+ AutoMutex lock(mLock);
+ if (audioIo != mInput) {
+ return;
+ }
+ callback = mDeviceCallback.promote();
+ // only update device if the record is active as route changes due to other use cases are
+ // irrelevant for this client
+ if (mActive) {
+ mRoutedDeviceId = deviceId;
+ }
+ }
+ if (callback.get() != nullptr) {
+ callback->onAudioDeviceUpdate(mInput, mRoutedDeviceId);
+ }
+}
+
// =========================================================================
void AudioRecord::DeathNotifier::binderDied(const wp<IBinder>& who __unused)
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 211bd7d..cdc75ac 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -493,14 +493,16 @@
if (ioDesc == 0 || ioDesc->mIoHandle == AUDIO_IO_HANDLE_NONE) return;
audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE;
- Vector < sp<AudioDeviceCallback> > callbacks;
+ Vector < wp<AudioDeviceCallback> > callbacks;
{
Mutex::Autolock _l(mLock);
switch (event) {
case AUDIO_OUTPUT_OPENED:
- case AUDIO_INPUT_OPENED: {
+ case AUDIO_OUTPUT_REGISTERED:
+ case AUDIO_INPUT_OPENED:
+ case AUDIO_INPUT_REGISTERED: {
sp<AudioIoDescriptor> oldDesc = getIoDescriptor_l(ioDesc->mIoHandle);
if (oldDesc == 0) {
mIoDescriptors.add(ioDesc->mIoHandle, ioDesc);
@@ -511,13 +513,19 @@
if (ioDesc->getDeviceId() != AUDIO_PORT_HANDLE_NONE) {
deviceId = ioDesc->getDeviceId();
- ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(ioDesc->mIoHandle);
- if (ioIndex >= 0) {
- callbacks = mAudioDeviceCallbacks.valueAt(ioIndex);
+ if (event == AUDIO_OUTPUT_OPENED || event == AUDIO_INPUT_OPENED) {
+ 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",
+ ALOGV("ioConfigChanged() new %s %s %d samplingRate %u, format %#x channel mask %#x "
+ "frameCount %zu deviceId %d",
+ event == AUDIO_OUTPUT_OPENED || event == AUDIO_OUTPUT_REGISTERED ?
+ "output" : "input",
+ event == AUDIO_OUTPUT_OPENED || event == AUDIO_INPUT_OPENED ?
+ "opened" : "registered",
ioDesc->mIoHandle, ioDesc->mSamplingRate, ioDesc->mFormat, ioDesc->mChannelMask,
ioDesc->mFrameCount, ioDesc->getDeviceId());
} break;
@@ -563,9 +571,23 @@
} break;
}
}
+ bool callbackRemoved = false;
// callbacks.size() != 0 => ioDesc->mIoHandle and deviceId are valid
- for (size_t i = 0; i < callbacks.size(); i++) {
- callbacks[i]->onAudioDeviceUpdate(ioDesc->mIoHandle, deviceId);
+ for (size_t i = 0; i < callbacks.size(); ) {
+ sp<AudioDeviceCallback> callback = callbacks[i].promote();
+ if (callback.get() != nullptr) {
+ callback->onAudioDeviceUpdate(ioDesc->mIoHandle, deviceId);
+ i++;
+ } else {
+ callbacks.removeAt(i);
+ callbackRemoved = true;
+ }
+ }
+ // clean up callback list while we are here if some clients have disappeared without
+ // unregistering their callback
+ if (callbackRemoved) {
+ Mutex::Autolock _l(mLock);
+ mAudioDeviceCallbacks.replaceValueFor(ioDesc->mIoHandle, callbacks);
}
}
@@ -618,17 +640,17 @@
}
status_t AudioSystem::AudioFlingerClient::addAudioDeviceCallback(
- const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
+ const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
{
Mutex::Autolock _l(mLock);
- Vector < sp<AudioDeviceCallback> > callbacks;
+ Vector < wp<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) {
+ if (callbacks[cbIndex].unsafe_get() == callback.unsafe_get()) {
return INVALID_OPERATION;
}
}
@@ -639,18 +661,18 @@
}
status_t AudioSystem::AudioFlingerClient::removeAudioDeviceCallback(
- const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
+ const wp<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);
+ Vector < wp<AudioDeviceCallback> > callbacks = mAudioDeviceCallbacks.valueAt(ioIndex);
size_t cbIndex;
for (cbIndex = 0; cbIndex < callbacks.size(); cbIndex++) {
- if (callbacks[cbIndex] == callback) {
+ if (callbacks[cbIndex].unsafe_get() == callback.unsafe_get()) {
break;
}
}
@@ -1128,7 +1150,7 @@
}
status_t AudioSystem::addAudioDeviceCallback(
- const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
+ const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
{
const sp<AudioFlingerClient> afc = getAudioFlingerClient();
if (afc == 0) {
@@ -1145,7 +1167,7 @@
}
status_t AudioSystem::removeAudioDeviceCallback(
- const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
+ const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
{
const sp<AudioFlingerClient> afc = getAudioFlingerClient();
if (afc == 0) {
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index b99eaff..3529d2c 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -276,7 +276,7 @@
}
// 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);
+ AudioSystem::removeAudioDeviceCallback(this, mOutput);
}
IInterface::asBinder(mAudioTrack)->unlinkToDeath(mDeathNotifier, this);
mAudioTrack.clear();
@@ -1229,19 +1229,26 @@
return mSelectedDeviceId;
}
+// must be called with mLock held
+void AudioTrack::updateRoutedDeviceId_l()
+{
+ // if the track is inactive, do not update actual device as the output stream maybe routed
+ // to a device not relevant to this client because of other active use cases.
+ if (mState != STATE_ACTIVE) {
+ return;
+ }
+ if (mOutput != AUDIO_IO_HANDLE_NONE) {
+ audio_port_handle_t deviceId = AudioSystem::getDeviceIdForIo(mOutput);
+ if (deviceId != AUDIO_PORT_HANDLE_NONE) {
+ mRoutedDeviceId = deviceId;
+ }
+ }
+}
+
audio_port_handle_t AudioTrack::getRoutedDeviceId() {
AutoMutex lock(mLock);
- if (mOutput == AUDIO_IO_HANDLE_NONE) {
- return AUDIO_PORT_HANDLE_NONE;
- }
- // if the output stream does not have an active audio patch, use either the device initially
- // selected by audio policy manager or the last routed device
- audio_port_handle_t deviceId = AudioSystem::getDeviceIdForIo(mOutput);
- if (deviceId == AUDIO_PORT_HANDLE_NONE) {
- deviceId = mRoutedDeviceId;
- }
- mRoutedDeviceId = deviceId;
- return deviceId;
+ updateRoutedDeviceId_l();
+ return mRoutedDeviceId;
}
status_t AudioTrack::attachAuxEffect(int effectId)
@@ -1279,7 +1286,7 @@
ALOGW("getLatency(%d) failed status %d", mOutput, status);
} else {
// FIXME don't believe this lie
- mLatency = mAfLatency + (1000 * mFrameCount) / mSampleRate;
+ mLatency = mAfLatency + (1000LL * mFrameCount) / mSampleRate;
}
}
@@ -1305,12 +1312,10 @@
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;
+ bool callbackAdded = false;
// mFlags (not mOrigFlags) is modified depending on whether fast request is accepted.
// After fast request is denied, we will request again if IAudioTrack is re-created.
@@ -1515,12 +1520,14 @@
sp<IMemory> iMem = track->getCblk();
if (iMem == 0) {
ALOGE("Could not get control block");
- return NO_INIT;
+ status = NO_INIT;
+ goto release;
}
void *iMemPointer = iMem->pointer();
if (iMemPointer == NULL) {
ALOGE("Could not get control block pointer");
- return NO_INIT;
+ status = NO_INIT;
+ goto release;
}
// invariant that mAudioTrack != 0 is true only after set() returns successfully
if (mAudioTrack != 0) {
@@ -1582,6 +1589,15 @@
}
}
+ //mOutput != output includes the case where mOutput == AUDIO_IO_HANDLE_NONE for first creation
+ if (mDeviceCallback != 0 && mOutput != output) {
+ if (mOutput != AUDIO_IO_HANDLE_NONE) {
+ AudioSystem::removeAudioDeviceCallback(this, mOutput);
+ }
+ AudioSystem::addAudioDeviceCallback(this, output);
+ callbackAdded = true;
+ }
+
// We retain a copy of the I/O handle, but don't own the reference
mOutput = output;
mRefreshRemaining = true;
@@ -1597,7 +1613,8 @@
buffers = mSharedBuffer->pointer();
if (buffers == NULL) {
ALOGE("Could not get buffer pointer");
- return NO_INIT;
+ status = NO_INIT;
+ goto release;
}
}
@@ -1642,15 +1659,15 @@
mDeathNotifier = new DeathNotifier(this);
IInterface::asBinder(mAudioTrack)->linkToDeath(mDeathNotifier, this);
- if (mDeviceCallback != 0) {
- AudioSystem::addAudioDeviceCallback(mDeviceCallback, mOutput);
- }
-
return NO_ERROR;
}
release:
AudioSystem::releaseOutput(output, streamType, mSessionId);
+ if (callbackAdded) {
+ // note: mOutput is always valid is callbackAdded is true
+ AudioSystem::removeAudioDeviceCallback(this, mOutput);
+ }
if (status == NO_ERROR) {
status = NO_INIT;
}
@@ -2851,7 +2868,7 @@
return BAD_VALUE;
}
AutoMutex lock(mLock);
- if (mDeviceCallback == callback) {
+ if (mDeviceCallback.unsafe_get() == callback.get()) {
ALOGW("%s adding same callback!", __FUNCTION__);
return INVALID_OPERATION;
}
@@ -2859,9 +2876,9 @@
if (mOutput != AUDIO_IO_HANDLE_NONE) {
if (mDeviceCallback != 0) {
ALOGW("%s callback already present!", __FUNCTION__);
- AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput);
+ AudioSystem::removeAudioDeviceCallback(this, mOutput);
}
- status = AudioSystem::addAudioDeviceCallback(callback, mOutput);
+ status = AudioSystem::addAudioDeviceCallback(this, mOutput);
}
mDeviceCallback = callback;
return status;
@@ -2875,17 +2892,39 @@
return BAD_VALUE;
}
AutoMutex lock(mLock);
- if (mDeviceCallback != callback) {
+ if (mDeviceCallback.unsafe_get() != callback.get()) {
ALOGW("%s removing different callback!", __FUNCTION__);
return INVALID_OPERATION;
}
+ mDeviceCallback.clear();
if (mOutput != AUDIO_IO_HANDLE_NONE) {
- AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput);
+ AudioSystem::removeAudioDeviceCallback(this, mOutput);
}
- mDeviceCallback = 0;
return NO_ERROR;
}
+
+void AudioTrack::onAudioDeviceUpdate(audio_io_handle_t audioIo,
+ audio_port_handle_t deviceId)
+{
+ sp<AudioSystem::AudioDeviceCallback> callback;
+ {
+ AutoMutex lock(mLock);
+ if (audioIo != mOutput) {
+ return;
+ }
+ callback = mDeviceCallback.promote();
+ // only update device if the track is active as route changes due to other use cases are
+ // irrelevant for this client
+ if (mState == STATE_ACTIVE) {
+ mRoutedDeviceId = deviceId;
+ }
+ }
+ if (callback.get() != nullptr) {
+ callback->onAudioDeviceUpdate(mOutput, mRoutedDeviceId);
+ }
+}
+
status_t AudioTrack::pendingDuration(int32_t *msec, ExtendedTimestamp::Location location)
{
if (msec == nullptr ||
diff --git a/media/libaudioclient/include/media/AudioIoDescriptor.h b/media/libaudioclient/include/media/AudioIoDescriptor.h
index fed86c9..859f1a9 100644
--- a/media/libaudioclient/include/media/AudioIoDescriptor.h
+++ b/media/libaudioclient/include/media/AudioIoDescriptor.h
@@ -20,9 +20,11 @@
namespace android {
enum audio_io_config_event {
+ AUDIO_OUTPUT_REGISTERED,
AUDIO_OUTPUT_OPENED,
AUDIO_OUTPUT_CLOSED,
AUDIO_OUTPUT_CONFIG_CHANGED,
+ AUDIO_INPUT_REGISTERED,
AUDIO_INPUT_OPENED,
AUDIO_INPUT_CLOSED,
AUDIO_INPUT_CONFIG_CHANGED,
diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h
index e6a5efb..dd72170 100644
--- a/media/libaudioclient/include/media/AudioRecord.h
+++ b/media/libaudioclient/include/media/AudioRecord.h
@@ -33,7 +33,7 @@
// ----------------------------------------------------------------------------
-class AudioRecord : public RefBase
+class AudioRecord : public AudioSystem::AudioDeviceCallback
{
public:
@@ -424,7 +424,12 @@
/* 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.
+ * The device ID is relevant only if the AudioRecord is active.
+ * When the AudioRecord is inactive, the device ID returned can be either:
+ * - AUDIO_PORT_HANDLE_NONE if the AudioRecord is not attached to any output.
+ * - The device ID used before paused or stopped.
+ * - The device ID selected by audio policy manager of setOutputDevice() if the AudioRecord
+ * has not been started yet.
*
* Parameters:
* none.
@@ -454,6 +459,10 @@
status_t removeAudioDeviceCallback(
const sp<AudioSystem::AudioDeviceCallback>& callback);
+ // AudioSystem::AudioDeviceCallback> virtuals
+ virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo,
+ audio_port_handle_t deviceId);
+
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,
@@ -561,6 +570,8 @@
// FIXME enum is faster than strcmp() for parameter 'from'
status_t restoreRecord_l(const char *from);
+ void updateRoutedDeviceId_l();
+
sp<AudioRecordThread> mAudioRecordThread;
mutable Mutex mLock;
@@ -665,7 +676,7 @@
audio_port_handle_t mRoutedDeviceId; // Device actually selected by audio policy manager:
// May not match the app selection depending on other
// activity and connected devices
- sp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
+ wp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
audio_port_handle_t mPortId; // unique ID allocated by audio policy
};
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 4d5b317..5a81d83 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -370,9 +370,9 @@
audio_port_handle_t deviceId) = 0;
};
- static status_t addAudioDeviceCallback(const sp<AudioDeviceCallback>& callback,
+ static status_t addAudioDeviceCallback(const wp<AudioDeviceCallback>& callback,
audio_io_handle_t audioIo);
- static status_t removeAudioDeviceCallback(const sp<AudioDeviceCallback>& callback,
+ static status_t removeAudioDeviceCallback(const wp<AudioDeviceCallback>& callback,
audio_io_handle_t audioIo);
static audio_port_handle_t getDeviceIdForIo(audio_io_handle_t audioIo);
@@ -403,9 +403,9 @@
const sp<AudioIoDescriptor>& ioDesc);
- status_t addAudioDeviceCallback(const sp<AudioDeviceCallback>& callback,
+ status_t addAudioDeviceCallback(const wp<AudioDeviceCallback>& callback,
audio_io_handle_t audioIo);
- status_t removeAudioDeviceCallback(const sp<AudioDeviceCallback>& callback,
+ status_t removeAudioDeviceCallback(const wp<AudioDeviceCallback>& callback,
audio_io_handle_t audioIo);
audio_port_handle_t getDeviceIdForIo(audio_io_handle_t audioIo);
@@ -413,7 +413,7 @@
private:
Mutex mLock;
DefaultKeyedVector<audio_io_handle_t, sp<AudioIoDescriptor> > mIoDescriptors;
- DefaultKeyedVector<audio_io_handle_t, Vector < sp<AudioDeviceCallback> > >
+ DefaultKeyedVector<audio_io_handle_t, Vector < wp<AudioDeviceCallback> > >
mAudioDeviceCallbacks;
// cached values for recording getInputBufferSize() queries
size_t mInBuffSize; // zero indicates cache is invalid
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index 7ae8ec5..47d87e9 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -35,7 +35,7 @@
// ----------------------------------------------------------------------------
-class AudioTrack : public RefBase
+class AudioTrack : public AudioSystem::AudioDeviceCallback
{
public:
@@ -605,7 +605,11 @@
/* 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.
+ * When the AudioTrack is inactive, the device ID returned can be either:
+ * - AUDIO_PORT_HANDLE_NONE if the AudioTrack is not attached to any output.
+ * - The device ID used before paused or stopped.
+ * - The device ID selected by audio policy manager of setOutputDevice() if the AudioTrack
+ * has not been started yet.
*
* Parameters:
* none.
@@ -845,6 +849,12 @@
status_t removeAudioDeviceCallback(
const sp<AudioSystem::AudioDeviceCallback>& callback);
+ // AudioSystem::AudioDeviceCallback> virtuals
+ virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo,
+ audio_port_handle_t deviceId);
+
+
+
/* Obtain the pending duration in milliseconds for playback of pure PCM
* (mixable without embedded timing) data remaining in AudioTrack.
*
@@ -974,6 +984,8 @@
void restartIfDisabled();
+ void updateRoutedDeviceId_l();
+
// Next 4 fields may be changed if IAudioTrack is re-created, but always != 0
sp<IAudioTrack> mAudioTrack;
sp<IMemory> mCblkMemory;
@@ -1165,7 +1177,7 @@
uid_t mClientUid;
pid_t mClientPid;
- sp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
+ wp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
audio_port_handle_t mPortId; // unique ID allocated by audio policy
};
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 4f1fed5..aae80b6 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -35,6 +35,15 @@
// effect_handle_t interface implementation for bass boost
extern "C" const struct effect_interface_s gLvmEffectInterface;
+// Turn on VERY_VERY_VERBOSE_LOGGING to log parameter get and set for effects.
+
+//#define VERY_VERY_VERBOSE_LOGGING
+#ifdef VERY_VERY_VERBOSE_LOGGING
+#define ALOGVV ALOGV
+#else
+#define ALOGVV(a...) do { } while (false)
+#endif
+
#define LVM_ERROR_CHECK(LvmStatus, callingFunc, calledFunc){\
if ((LvmStatus) == LVM_NULLADDRESS){\
ALOGV("\tLVM_ERROR : Parameter error - "\
@@ -140,26 +149,43 @@
void LvmEffect_free (EffectContext *pContext);
int Effect_setConfig (EffectContext *pContext, effect_config_t *pConfig);
void Effect_getConfig (EffectContext *pContext, effect_config_t *pConfig);
-int BassBoost_setParameter (EffectContext *pContext, void *pParam, void *pValue);
+int BassBoost_setParameter (EffectContext *pContext,
+ uint32_t paramSize,
+ void *pParam,
+ uint32_t valueSize,
+ void *pValue);
int BassBoost_getParameter (EffectContext *pContext,
- void *pParam,
- uint32_t *pValueSize,
- void *pValue);
-int Virtualizer_setParameter (EffectContext *pContext, void *pParam, void *pValue);
-int Virtualizer_getParameter (EffectContext *pContext,
- void *pParam,
- uint32_t *pValueSize,
- void *pValue);
-int Equalizer_setParameter (EffectContext *pContext,
- void *pParam,
- uint32_t valueSize,
- void *pValue);
-int Equalizer_getParameter (EffectContext *pContext,
+ uint32_t paramSize,
void *pParam,
uint32_t *pValueSize,
void *pValue);
-int Volume_setParameter (EffectContext *pContext, void *pParam, void *pValue);
+int Virtualizer_setParameter (EffectContext *pContext,
+ uint32_t paramSize,
+ void *pParam,
+ uint32_t valueSize,
+ void *pValue);
+int Virtualizer_getParameter (EffectContext *pContext,
+ uint32_t paramSize,
+ void *pParam,
+ uint32_t *pValueSize,
+ void *pValue);
+int Equalizer_setParameter (EffectContext *pContext,
+ uint32_t paramSize,
+ void *pParam,
+ uint32_t valueSize,
+ void *pValue);
+int Equalizer_getParameter (EffectContext *pContext,
+ uint32_t paramSize,
+ void *pParam,
+ uint32_t *pValueSize,
+ void *pValue);
+int Volume_setParameter (EffectContext *pContext,
+ uint32_t paramSize,
+ void *pParam,
+ uint32_t valueSize,
+ void *pValue);
int Volume_getParameter (EffectContext *pContext,
+ uint32_t paramSize,
void *pParam,
uint32_t *pValueSize,
void *pValue);
@@ -985,8 +1011,12 @@
float energyBassBoost = 0;
float crossCorrection = 0;
+ bool eqEnabled = pContext->pBundledContext->bEqualizerEnabled == LVM_TRUE;
+ bool bbEnabled = pContext->pBundledContext->bBassEnabled == LVM_TRUE;
+ bool viEnabled = pContext->pBundledContext->bVirtualizerEnabled == LVM_TRUE;
+
//EQ contribution
- if (pContext->pBundledContext->bEqualizerEnabled == LVM_TRUE) {
+ if (eqEnabled) {
for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
float bandFactor = pContext->pBundledContext->bandGaindB[i]/15.0;
float bandCoefficient = LimitLevel_bandEnergyCoefficient[i];
@@ -1012,35 +1042,37 @@
}
bandFactorSum -= 1.0;
if (bandFactorSum > 0)
- crossCorrection = bandFactorSum * 0.7;
+ crossCorrection = bandFactorSum * 0.7;
}
//BassBoost contribution
- if (pContext->pBundledContext->bBassEnabled == LVM_TRUE) {
+ if (bbEnabled) {
float boostFactor = (pContext->pBundledContext->BassStrengthSaved)/1000.0;
float boostCoefficient = LimitLevel_bassBoostEnergyCoefficient;
energyContribution += boostFactor * boostCoefficient * boostCoefficient;
- for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
- float bandFactor = pContext->pBundledContext->bandGaindB[i]/15.0;
- float bandCrossCoefficient = LimitLevel_bassBoostEnergyCrossCoefficient[i];
- float bandEnergy = boostFactor * bandFactor *
+ if (eqEnabled) {
+ for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
+ float bandFactor = pContext->pBundledContext->bandGaindB[i]/15.0;
+ float bandCrossCoefficient = LimitLevel_bassBoostEnergyCrossCoefficient[i];
+ float bandEnergy = boostFactor * bandFactor *
bandCrossCoefficient;
- if (bandEnergy > 0)
- energyBassBoost += bandEnergy;
+ if (bandEnergy > 0)
+ energyBassBoost += bandEnergy;
+ }
}
}
//Virtualizer contribution
- if (pContext->pBundledContext->bVirtualizerEnabled == LVM_TRUE) {
+ if (viEnabled) {
energyContribution += LimitLevel_virtualizerContribution *
LimitLevel_virtualizerContribution;
}
double totalEnergyEstimation = sqrt(energyContribution + energyCross + energyBassBoost) -
crossCorrection;
- ALOGV(" TOTAL energy estimation: %0.2f", totalEnergyEstimation);
+ ALOGV(" TOTAL energy estimation: %0.2f dB", totalEnergyEstimation);
//roundoff
int maxLevelRound = (int)(totalEnergyEstimation + 0.99);
@@ -1058,6 +1090,8 @@
/* Activate the initial settings */
LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "LvmEffect_limitLevel")
+
+ ALOGV("LVM_SetControlParameters return:%d", (int)LvmStatus);
//ALOGV("\tLvmEffect_limitLevel just Set -> %d\n",
// ActiveParams.pEQNB_BandDefinition[band].Gain);
@@ -1308,6 +1342,8 @@
ALOGV("\tEffect_setConfig Succesfully called LVM_SetControlParameters\n");
pContext->pBundledContext->SampleRate = SampleRate;
+ LvmEffect_limitLevel(pContext);
+
}else{
//ALOGV("\tEffect_setConfig keep sampling rate at %d", SampleRate);
}
@@ -2165,59 +2201,54 @@
//
//----------------------------------------------------------------------------
-int BassBoost_getParameter(EffectContext *pContext,
- void *pParam,
- uint32_t *pValueSize,
- void *pValue){
+int BassBoost_getParameter(EffectContext *pContext,
+ uint32_t paramSize,
+ void *pParam,
+ uint32_t *pValueSize,
+ void *pValue) {
int status = 0;
- int32_t *pParamTemp = (int32_t *)pParam;
- int32_t param = *pParamTemp++;
+ int32_t *params = (int32_t *)pParam;
- //ALOGV("\tBassBoost_getParameter start");
+ ALOGVV("%s start", __func__);
- switch (param){
- case BASSBOOST_PARAM_STRENGTH_SUPPORTED:
- if (*pValueSize != sizeof(uint32_t)){
- ALOGV("\tLVM_ERROR : BassBoost_getParameter() invalid pValueSize1 %d", *pValueSize);
- return -EINVAL;
- }
- *pValueSize = sizeof(uint32_t);
- break;
- case BASSBOOST_PARAM_STRENGTH:
- if (*pValueSize != sizeof(int16_t)){
- ALOGV("\tLVM_ERROR : BassBoost_getParameter() invalid pValueSize2 %d", *pValueSize);
- return -EINVAL;
- }
- *pValueSize = sizeof(int16_t);
- break;
-
- default:
- ALOGV("\tLVM_ERROR : BassBoost_getParameter() invalid param %d", param);
- return -EINVAL;
+ if (paramSize < sizeof(int32_t)) {
+ ALOGV("%s invalid paramSize: %u", __func__, paramSize);
+ return -EINVAL;
}
-
- switch (param){
+ switch (params[0]) {
case BASSBOOST_PARAM_STRENGTH_SUPPORTED:
- *(uint32_t *)pValue = 1;
+ if (*pValueSize != sizeof(uint32_t)) { // legacy: check equality here.
+ ALOGV("%s BASSBOOST_PARAM_STRENGTH_SUPPORTED invalid *pValueSize %u",
+ __func__, *pValueSize);
+ status = -EINVAL;
+ break;
+ }
+ // no need to set *pValueSize
- //ALOGV("\tBassBoost_getParameter() BASSBOOST_PARAM_STRENGTH_SUPPORTED Value is %d",
- // *(uint32_t *)pValue);
+ *(uint32_t *)pValue = 1;
+ ALOGVV("%s BASSBOOST_PARAM_STRENGTH_SUPPORTED %u", __func__, *(uint32_t *)pValue);
break;
case BASSBOOST_PARAM_STRENGTH:
- *(int16_t *)pValue = BassGetStrength(pContext);
+ if (*pValueSize != sizeof(int16_t)) { // legacy: check equality here.
+ ALOGV("%s BASSBOOST_PARAM_STRENGTH invalid *pValueSize %u",
+ __func__, *pValueSize);
+ status = -EINVAL;
+ break;
+ }
+ // no need to set *pValueSize
- //ALOGV("\tBassBoost_getParameter() BASSBOOST_PARAM_STRENGTH Value is %d",
- // *(int16_t *)pValue);
+ *(int16_t *)pValue = BassGetStrength(pContext);
+ ALOGVV("%s BASSBOOST_PARAM_STRENGTH %d", __func__, *(int16_t *)pValue);
break;
default:
- ALOGV("\tLVM_ERROR : BassBoost_getParameter() invalid param %d", param);
+ ALOGV("%s invalid param %d", __func__, params[0]);
status = -EINVAL;
break;
}
- //ALOGV("\tBassBoost_getParameter end");
+ ALOGVV("%s end param: %d, status: %d", __func__, params[0], status);
return status;
} /* end BassBoost_getParameter */
@@ -2236,27 +2267,42 @@
//
//----------------------------------------------------------------------------
-int BassBoost_setParameter (EffectContext *pContext, void *pParam, void *pValue){
+int BassBoost_setParameter(EffectContext *pContext,
+ uint32_t paramSize,
+ void *pParam,
+ uint32_t valueSize,
+ void *pValue) {
int status = 0;
- int16_t strength;
- int32_t *pParamTemp = (int32_t *)pParam;
+ int32_t *params = (int32_t *)pParam;
- //ALOGV("\tBassBoost_setParameter start");
+ ALOGVV("%s start", __func__);
- switch (*pParamTemp){
- case BASSBOOST_PARAM_STRENGTH:
- strength = *(int16_t *)pValue;
- //ALOGV("\tBassBoost_setParameter() BASSBOOST_PARAM_STRENGTH value is %d", strength);
- //ALOGV("\tBassBoost_setParameter() Calling pBassBoost->BassSetStrength");
+ if (paramSize != sizeof(int32_t)) { // legacy: check equality here.
+ ALOGV("%s invalid paramSize: %u", __func__, paramSize);
+ return -EINVAL;
+ }
+ switch (params[0]) {
+ case BASSBOOST_PARAM_STRENGTH: {
+ if (valueSize < sizeof(int16_t)) {
+ ALOGV("%s BASSBOOST_PARAM_STRENGTH invalid valueSize: %u", __func__, valueSize);
+ status = -EINVAL;
+ break;
+ }
+
+ const int16_t strength = *(int16_t *)pValue;
+ ALOGVV("%s BASSBOOST_PARAM_STRENGTH %d", __func__, strength);
+ ALOGVV("%s BASSBOOST_PARAM_STRENGTH Calling BassSetStrength", __func__);
BassSetStrength(pContext, (int32_t)strength);
- //ALOGV("\tBassBoost_setParameter() Called pBassBoost->BassSetStrength");
- break;
+ ALOGVV("%s BASSBOOST_PARAM_STRENGTH Called BassSetStrength", __func__);
+ } break;
+
default:
- ALOGV("\tLVM_ERROR : BassBoost_setParameter() invalid param %d", *pParamTemp);
+ ALOGV("%s invalid param %d", __func__, params[0]);
+ status = -EINVAL;
break;
}
- //ALOGV("\tBassBoost_setParameter end");
+ ALOGVV("%s end param: %d, status: %d", __func__, params[0], status);
return status;
} /* end BassBoost_setParameter */
@@ -2281,92 +2327,97 @@
//
//----------------------------------------------------------------------------
-int Virtualizer_getParameter(EffectContext *pContext,
- void *pParam,
- uint32_t *pValueSize,
- void *pValue){
+int Virtualizer_getParameter(EffectContext *pContext,
+ uint32_t paramSize,
+ void *pParam,
+ uint32_t *pValueSize,
+ void *pValue) {
int status = 0;
- int32_t *pParamTemp = (int32_t *)pParam;
- int32_t param = *pParamTemp++;
+ int32_t *params = (int32_t *)pParam;
- //ALOGV("\tVirtualizer_getParameter start");
+ ALOGVV("%s start", __func__);
- switch (param){
- case VIRTUALIZER_PARAM_STRENGTH_SUPPORTED:
- if (*pValueSize != sizeof(uint32_t)){
- ALOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid pValueSize %d",*pValueSize);
- return -EINVAL;
- }
- *pValueSize = sizeof(uint32_t);
- break;
- case VIRTUALIZER_PARAM_STRENGTH:
- if (*pValueSize != sizeof(int16_t)){
- ALOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid pValueSize2 %d",*pValueSize);
- return -EINVAL;
- }
- *pValueSize = sizeof(int16_t);
- break;
- case VIRTUALIZER_PARAM_VIRTUAL_SPEAKER_ANGLES:
- // return value size can only be interpreted as relative to input value,
- // deferring validity check to below
- break;
- case VIRTUALIZER_PARAM_VIRTUALIZATION_MODE:
- if (*pValueSize != sizeof(uint32_t)){
- ALOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid pValueSize %d",*pValueSize);
- return -EINVAL;
- }
- *pValueSize = sizeof(uint32_t);
- break;
- default:
- ALOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid param %d", param);
- return -EINVAL;
+ if (paramSize < sizeof(int32_t)) {
+ ALOGV("%s invalid paramSize: %u", __func__, paramSize);
+ return -EINVAL;
}
-
- switch (param){
+ switch (params[0]) {
case VIRTUALIZER_PARAM_STRENGTH_SUPPORTED:
- *(uint32_t *)pValue = 1;
+ if (*pValueSize != sizeof(uint32_t)) { // legacy: check equality here.
+ ALOGV("%s VIRTUALIZER_PARAM_STRENGTH_SUPPORTED invalid *pValueSize %u",
+ __func__, *pValueSize);
+ status = -EINVAL;
+ break;
+ }
+ // no need to set *pValueSize
- //ALOGV("\tVirtualizer_getParameter() VIRTUALIZER_PARAM_STRENGTH_SUPPORTED Value is %d",
- // *(uint32_t *)pValue);
+ *(uint32_t *)pValue = 1;
+ ALOGVV("%s VIRTUALIZER_PARAM_STRENGTH_SUPPORTED %d", __func__, *(uint32_t *)pValue);
break;
case VIRTUALIZER_PARAM_STRENGTH:
+ if (*pValueSize != sizeof(int16_t)) { // legacy: check equality here.
+ ALOGV("%s VIRTUALIZER_PARAM_STRENGTH invalid *pValueSize %u",
+ __func__, *pValueSize);
+ status = -EINVAL;
+ break;
+ }
+ // no need to set *pValueSize
+
*(int16_t *)pValue = VirtualizerGetStrength(pContext);
- //ALOGV("\tVirtualizer_getParameter() VIRTUALIZER_PARAM_STRENGTH Value is %d",
- // *(int16_t *)pValue);
+ ALOGVV("%s VIRTUALIZER_PARAM_STRENGTH %d", __func__, *(int16_t *)pValue);
break;
case VIRTUALIZER_PARAM_VIRTUAL_SPEAKER_ANGLES: {
- const audio_channel_mask_t channelMask = (audio_channel_mask_t) *pParamTemp++;
- const audio_devices_t deviceType = (audio_devices_t) *pParamTemp;
- uint32_t nbChannels = audio_channel_count_from_out_mask(channelMask);
- if (*pValueSize < 3 * nbChannels * sizeof(int32_t)){
- ALOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid pValueSize %d",*pValueSize);
- return -EINVAL;
+ if (paramSize < 3 * sizeof(int32_t)) {
+ ALOGV("%s VIRTUALIZER_PARAM_SPEAKER_ANGLES invalid paramSize: %u",
+ __func__, paramSize);
+ status = -EINVAL;
+ break;
}
+
+ const audio_channel_mask_t channelMask = (audio_channel_mask_t) params[1];
+ const audio_devices_t deviceType = (audio_devices_t) params[2];
+ const uint32_t nbChannels = audio_channel_count_from_out_mask(channelMask);
+ const uint32_t valueSizeRequired = 3 * nbChannels * sizeof(int32_t);
+ if (*pValueSize < valueSizeRequired) {
+ ALOGV("%s VIRTUALIZER_PARAM_SPEAKER_ANGLES invalid *pValueSize %u",
+ __func__, *pValueSize);
+ status = -EINVAL;
+ break;
+ }
+ *pValueSize = valueSizeRequired;
+
// verify the configuration is supported
status = VirtualizerIsConfigurationSupported(channelMask, deviceType);
if (status == 0) {
- ALOGV("VIRTUALIZER_PARAM_VIRTUAL_SPEAKER_ANGLES supports mask=0x%x device=0x%x",
- channelMask, deviceType);
+ ALOGV("%s VIRTUALIZER_PARAM_VIRTUAL_SPEAKER_ANGLES mask=0x%x device=0x%x",
+ __func__, channelMask, deviceType);
// configuration is supported, get the angles
VirtualizerGetSpeakerAngles(channelMask, deviceType, (int32_t *)pValue);
}
- }
- break;
+ } break;
case VIRTUALIZER_PARAM_VIRTUALIZATION_MODE:
- *(uint32_t *)pValue = (uint32_t) VirtualizerGetVirtualizationMode(pContext);
+ if (*pValueSize != sizeof(uint32_t)) { // legacy: check equality here.
+ ALOGV("%s VIRTUALIZER_PARAM_VIRTUALIZATION_MODE invalid *pValueSize %u",
+ __func__, *pValueSize);
+ status = -EINVAL;
+ break;
+ }
+ // no need to set *pValueSize
+
+ *(uint32_t *)pValue = (uint32_t) VirtualizerGetVirtualizationMode(pContext);
break;
default:
- ALOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid param %d", param);
+ ALOGV("%s invalid param %d", __func__, params[0]);
status = -EINVAL;
break;
}
- ALOGV("\tVirtualizer_getParameter end returning status=%d", status);
+ ALOGVV("%s end param: %d, status: %d", __func__, params[0], status);
return status;
} /* end Virtualizer_getParameter */
@@ -2385,37 +2436,57 @@
//
//----------------------------------------------------------------------------
-int Virtualizer_setParameter (EffectContext *pContext, void *pParam, void *pValue){
+int Virtualizer_setParameter(EffectContext *pContext,
+ uint32_t paramSize,
+ void *pParam,
+ uint32_t valueSize,
+ void *pValue) {
int status = 0;
- int16_t strength;
- int32_t *pParamTemp = (int32_t *)pParam;
- int32_t param = *pParamTemp++;
+ int32_t *params = (int32_t *)pParam;
- //ALOGV("\tVirtualizer_setParameter start");
+ ALOGVV("%s start", __func__);
- switch (param){
- case VIRTUALIZER_PARAM_STRENGTH:
- strength = *(int16_t *)pValue;
- //ALOGV("\tVirtualizer_setParameter() VIRTUALIZER_PARAM_STRENGTH value is %d", strength);
- //ALOGV("\tVirtualizer_setParameter() Calling pVirtualizer->setStrength");
+ if (paramSize != sizeof(int32_t)) { // legacy: check equality here.
+ ALOGV("%s invalid paramSize: %u", __func__, paramSize);
+ return -EINVAL;
+ }
+ switch (params[0]) {
+ case VIRTUALIZER_PARAM_STRENGTH: {
+ if (valueSize < sizeof(int16_t)) {
+ ALOGV("%s VIRTUALIZER_PARAM_STRENGTH invalid valueSize: %u", __func__, valueSize);
+ status = -EINVAL;
+ break;
+ }
+
+ const int16_t strength = *(int16_t *)pValue;
+ ALOGVV("%s VIRTUALIZER_PARAM_STRENGTH %d", __func__, strength);
+ ALOGVV("%s VIRTUALIZER_PARAM_STRENGTH Calling VirtualizerSetStrength", __func__);
VirtualizerSetStrength(pContext, (int32_t)strength);
- //ALOGV("\tVirtualizer_setParameter() Called pVirtualizer->setStrength");
- break;
+ ALOGVV("%s VIRTUALIZER_PARAM_STRENGTH Called VirtualizerSetStrength", __func__);
+ } break;
case VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE: {
- const audio_devices_t deviceType = *(audio_devices_t *) pValue;
- status = VirtualizerForceVirtualizationMode(pContext, deviceType);
- //ALOGV("VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE device=0x%x result=%d",
- // deviceType, status);
+ if (valueSize < sizeof(int32_t)) {
+ ALOGV("%s VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE invalid valueSize: %u",
+ __func__, valueSize);
+ android_errorWriteLog(0x534e4554, "64478003");
+ status = -EINVAL;
+ break;
}
- break;
+
+ const audio_devices_t deviceType = (audio_devices_t)*(int32_t *)pValue;
+ status = VirtualizerForceVirtualizationMode(pContext, deviceType);
+ ALOGVV("%s VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE device=%#x result=%d",
+ __func__, deviceType, status);
+ } break;
default:
- ALOGV("\tLVM_ERROR : Virtualizer_setParameter() invalid param %d", param);
+ ALOGV("%s invalid param %d", __func__, params[0]);
+ status = -EINVAL;
break;
}
- //ALOGV("\tVirtualizer_setParameter end");
+ ALOGVV("%s end param: %d, status: %d", __func__, params[0], status);
return status;
} /* end Virtualizer_setParameter */
@@ -2439,174 +2510,215 @@
// Side Effects:
//
//----------------------------------------------------------------------------
-int Equalizer_getParameter(EffectContext *pContext,
- void *pParam,
- uint32_t *pValueSize,
- void *pValue){
+int Equalizer_getParameter(EffectContext *pContext,
+ uint32_t paramSize,
+ void *pParam,
+ uint32_t *pValueSize,
+ void *pValue) {
int status = 0;
- int32_t *pParamTemp = (int32_t *)pParam;
- int32_t param = *pParamTemp++;
- int32_t param2;
- char *name;
+ int32_t *params = (int32_t *)pParam;
- //ALOGV("\tEqualizer_getParameter start");
+ ALOGVV("%s start", __func__);
- switch (param) {
+ if (paramSize < sizeof(int32_t)) {
+ ALOGV("%s invalid paramSize: %u", __func__, paramSize);
+ return -EINVAL;
+ }
+ switch (params[0]) {
case EQ_PARAM_NUM_BANDS:
+ if (*pValueSize < sizeof(uint16_t)) {
+ ALOGV("%s EQ_PARAM_NUM_BANDS invalid *pValueSize %u", __func__, *pValueSize);
+ status = -EINVAL;
+ break;
+ }
+ *pValueSize = sizeof(uint16_t);
+
+ *(uint16_t *)pValue = (uint16_t)FIVEBAND_NUMBANDS;
+ ALOGVV("%s EQ_PARAM_NUM_BANDS %u", __func__, *(uint16_t *)pValue);
+ break;
+
case EQ_PARAM_CUR_PRESET:
+ if (*pValueSize < sizeof(uint16_t)) {
+ ALOGV("%s EQ_PARAM_CUR_PRESET invalid *pValueSize %u", __func__, *pValueSize);
+ status = -EINVAL;
+ break;
+ }
+ *pValueSize = sizeof(uint16_t);
+
+ *(uint16_t *)pValue = (uint16_t)EqualizerGetPreset(pContext);
+ ALOGVV("%s EQ_PARAM_CUR_PRESET %u", __func__, *(uint16_t *)pValue);
+ break;
+
case EQ_PARAM_GET_NUM_OF_PRESETS:
- case EQ_PARAM_BAND_LEVEL:
- case EQ_PARAM_GET_BAND:
+ if (*pValueSize < sizeof(uint16_t)) {
+ ALOGV("%s EQ_PARAM_GET_NUM_OF_PRESETS invalid *pValueSize %u", __func__, *pValueSize);
+ status = -EINVAL;
+ break;
+ }
+ *pValueSize = sizeof(uint16_t);
+
+ *(uint16_t *)pValue = (uint16_t)EqualizerGetNumPresets();
+ ALOGVV("%s EQ_PARAM_GET_NUM_OF_PRESETS %u", __func__, *(uint16_t *)pValue);
+ break;
+
+ case EQ_PARAM_GET_BAND: {
+ if (paramSize < 2 * sizeof(int32_t)) {
+ ALOGV("%s EQ_PARAM_GET_BAND invalid paramSize: %u", __func__, paramSize);
+ status = -EINVAL;
+ break;
+ }
+ if (*pValueSize < sizeof(uint16_t)) {
+ ALOGV("%s EQ_PARAM_GET_BAND invalid *pValueSize %u", __func__, *pValueSize);
+ status = -EINVAL;
+ break;
+ }
+ *pValueSize = sizeof(uint16_t);
+
+ const int32_t frequency = params[1];
+ *(uint16_t *)pValue = (uint16_t)EqualizerGetBand(pContext, frequency);
+ ALOGVV("%s EQ_PARAM_GET_BAND frequency %d, band %u",
+ __func__, frequency, *(uint16_t *)pValue);
+ } break;
+
+ case EQ_PARAM_BAND_LEVEL: {
+ if (paramSize < 2 * sizeof(int32_t)) {
+ ALOGV("%s EQ_PARAM_BAND_LEVEL invalid paramSize %u", __func__, paramSize);
+ status = -EINVAL;
+ break;
+ }
if (*pValueSize < sizeof(int16_t)) {
- ALOGV("\tLVM_ERROR : Equalizer_getParameter() invalid pValueSize 1 %d", *pValueSize);
- return -EINVAL;
+ ALOGV("%s EQ_PARAM_BAND_LEVEL invalid *pValueSize %u", __func__, *pValueSize);
+ status = -EINVAL;
+ break;
}
*pValueSize = sizeof(int16_t);
- break;
+
+ const int32_t band = params[1];
+ if (band < 0 || band >= FIVEBAND_NUMBANDS) {
+ if (band < 0) {
+ android_errorWriteLog(0x534e4554, "32438598");
+ ALOGW("%s EQ_PARAM_BAND_LEVEL invalid band %d", __func__, band);
+ }
+ status = -EINVAL;
+ break;
+ }
+ *(int16_t *)pValue = (int16_t)EqualizerGetBandLevel(pContext, band);
+ ALOGVV("%s EQ_PARAM_BAND_LEVEL band %d, level %d",
+ __func__, band, *(int16_t *)pValue);
+ } break;
case EQ_PARAM_LEVEL_RANGE:
if (*pValueSize < 2 * sizeof(int16_t)) {
- ALOGV("\tLVM_ERROR : Equalizer_getParameter() invalid pValueSize 2 %d", *pValueSize);
- return -EINVAL;
+ ALOGV("%s EQ_PARAM_LEVEL_RANGE invalid *pValueSize %u", __func__, *pValueSize);
+ status = -EINVAL;
+ break;
}
*pValueSize = 2 * sizeof(int16_t);
- break;
- case EQ_PARAM_BAND_FREQ_RANGE:
- if (*pValueSize < 2 * sizeof(int32_t)) {
- ALOGV("\tLVM_ERROR : Equalizer_getParameter() invalid pValueSize 3 %d", *pValueSize);
- return -EINVAL;
- }
- *pValueSize = 2 * sizeof(int32_t);
- break;
- case EQ_PARAM_CENTER_FREQ:
- if (*pValueSize < sizeof(int32_t)) {
- ALOGV("\tLVM_ERROR : Equalizer_getParameter() invalid pValueSize 5 %d", *pValueSize);
- return -EINVAL;
- }
- *pValueSize = sizeof(int32_t);
- break;
-
- case EQ_PARAM_GET_PRESET_NAME:
- break;
-
- case EQ_PARAM_PROPERTIES:
- if (*pValueSize < (2 + FIVEBAND_NUMBANDS) * sizeof(uint16_t)) {
- ALOGV("\tLVM_ERROR : Equalizer_getParameter() invalid pValueSize 1 %d", *pValueSize);
- return -EINVAL;
- }
- *pValueSize = (2 + FIVEBAND_NUMBANDS) * sizeof(uint16_t);
- break;
-
- default:
- ALOGV("\tLVM_ERROR : Equalizer_getParameter unknown param %d", param);
- return -EINVAL;
- }
-
- switch (param) {
- case EQ_PARAM_NUM_BANDS:
- *(uint16_t *)pValue = (uint16_t)FIVEBAND_NUMBANDS;
- //ALOGV("\tEqualizer_getParameter() EQ_PARAM_NUM_BANDS %d", *(int16_t *)pValue);
- break;
-
- case EQ_PARAM_LEVEL_RANGE:
*(int16_t *)pValue = -1500;
*((int16_t *)pValue + 1) = 1500;
- //ALOGV("\tEqualizer_getParameter() EQ_PARAM_LEVEL_RANGE min %d, max %d",
- // *(int16_t *)pValue, *((int16_t *)pValue + 1));
+ ALOGVV("%s EQ_PARAM_LEVEL_RANGE min %d, max %d",
+ __func__, *(int16_t *)pValue, *((int16_t *)pValue + 1));
break;
- case EQ_PARAM_BAND_LEVEL:
- param2 = *pParamTemp;
- if (param2 < 0 || param2 >= FIVEBAND_NUMBANDS) {
+ case EQ_PARAM_BAND_FREQ_RANGE: {
+ if (paramSize < 2 * sizeof(int32_t)) {
+ ALOGV("%s EQ_PARAM_BAND_FREQ_RANGE invalid paramSize: %u", __func__, paramSize);
status = -EINVAL;
- if (param2 < 0) {
- android_errorWriteLog(0x534e4554, "32438598");
- ALOGW("\tERROR Equalizer_getParameter() EQ_PARAM_BAND_LEVEL band %d", param2);
- }
break;
}
- *(int16_t *)pValue = (int16_t)EqualizerGetBandLevel(pContext, param2);
- //ALOGV("\tEqualizer_getParameter() EQ_PARAM_BAND_LEVEL band %d, level %d",
- // param2, *(int32_t *)pValue);
- break;
-
- case EQ_PARAM_CENTER_FREQ:
- param2 = *pParamTemp;
- if (param2 < 0 || param2 >= FIVEBAND_NUMBANDS) {
+ if (*pValueSize < 2 * sizeof(int32_t)) {
+ ALOGV("%s EQ_PARAM_BAND_FREQ_RANGE invalid *pValueSize %u", __func__, *pValueSize);
status = -EINVAL;
- if (param2 < 0) {
- android_errorWriteLog(0x534e4554, "32436341");
- ALOGW("\tERROR Equalizer_getParameter() EQ_PARAM_CENTER_FREQ band %d", param2);
- }
break;
}
- *(int32_t *)pValue = EqualizerGetCentreFrequency(pContext, param2);
- //ALOGV("\tEqualizer_getParameter() EQ_PARAM_CENTER_FREQ band %d, frequency %d",
- // param2, *(int32_t *)pValue);
- break;
+ *pValueSize = 2 * sizeof(int32_t);
- case EQ_PARAM_BAND_FREQ_RANGE:
- param2 = *pParamTemp;
- if (param2 < 0 || param2 >= FIVEBAND_NUMBANDS) {
- status = -EINVAL;
- if (param2 < 0) {
+ const int32_t band = params[1];
+ if (band < 0 || band >= FIVEBAND_NUMBANDS) {
+ if (band < 0) {
android_errorWriteLog(0x534e4554, "32247948");
- ALOGW("\tERROR Equalizer_getParameter() EQ_PARAM_BAND_FREQ_RANGE band %d", param2);
+ ALOGW("%s EQ_PARAM_BAND_FREQ_RANGE invalid band %d",
+ __func__, band);
}
- break;
- }
- EqualizerGetBandFreqRange(pContext, param2, (uint32_t *)pValue, ((uint32_t *)pValue + 1));
- //ALOGV("\tEqualizer_getParameter() EQ_PARAM_BAND_FREQ_RANGE band %d, min %d, max %d",
- // param2, *(int32_t *)pValue, *((int32_t *)pValue + 1));
- break;
-
- case EQ_PARAM_GET_BAND:
- param2 = *pParamTemp;
- *(uint16_t *)pValue = (uint16_t)EqualizerGetBand(pContext, param2);
- //ALOGV("\tEqualizer_getParameter() EQ_PARAM_GET_BAND frequency %d, band %d",
- // param2, *(uint16_t *)pValue);
- break;
-
- case EQ_PARAM_CUR_PRESET:
- *(uint16_t *)pValue = (uint16_t)EqualizerGetPreset(pContext);
- //ALOGV("\tEqualizer_getParameter() EQ_PARAM_CUR_PRESET %d", *(int32_t *)pValue);
- break;
-
- case EQ_PARAM_GET_NUM_OF_PRESETS:
- *(uint16_t *)pValue = (uint16_t)EqualizerGetNumPresets();
- //ALOGV("\tEqualizer_getParameter() EQ_PARAM_GET_NUM_OF_PRESETS %d", *(int16_t *)pValue);
- break;
-
- case EQ_PARAM_GET_PRESET_NAME:
- param2 = *pParamTemp;
- if ((param2 < 0 && param2 != PRESET_CUSTOM) || param2 >= EqualizerGetNumPresets()) {
status = -EINVAL;
- if (param2 < 0) {
- android_errorWriteLog(0x534e4554, "32448258");
- ALOGE("\tERROR Equalizer_getParameter() EQ_PARAM_GET_PRESET_NAME preset %d",
- param2);
+ break;
+ }
+ EqualizerGetBandFreqRange(pContext, band, (uint32_t *)pValue, ((uint32_t *)pValue + 1));
+ ALOGVV("%s EQ_PARAM_BAND_FREQ_RANGE band %d, min %d, max %d",
+ __func__, band, *(int32_t *)pValue, *((int32_t *)pValue + 1));
+
+ } break;
+
+ case EQ_PARAM_CENTER_FREQ: {
+ if (paramSize < 2 * sizeof(int32_t)) {
+ ALOGV("%s EQ_PARAM_CENTER_FREQ invalid paramSize: %u", __func__, paramSize);
+ status = -EINVAL;
+ break;
+ }
+ if (*pValueSize < sizeof(int32_t)) {
+ ALOGV("%s EQ_PARAM_CENTER_FREQ invalid *pValueSize %u", __func__, *pValueSize);
+ status = -EINVAL;
+ break;
+ }
+ *pValueSize = sizeof(int32_t);
+
+ const int32_t band = params[1];
+ if (band < 0 || band >= FIVEBAND_NUMBANDS) {
+ status = -EINVAL;
+ if (band < 0) {
+ android_errorWriteLog(0x534e4554, "32436341");
+ ALOGW("%s EQ_PARAM_CENTER_FREQ invalid band %d", __func__, band);
}
break;
}
+ *(int32_t *)pValue = EqualizerGetCentreFrequency(pContext, band);
+ ALOGVV("%s EQ_PARAM_CENTER_FREQ band %d, frequency %d",
+ __func__, band, *(int32_t *)pValue);
+ } break;
+ case EQ_PARAM_GET_PRESET_NAME: {
+ if (paramSize < 2 * sizeof(int32_t)) {
+ ALOGV("%s EQ_PARAM_PRESET_NAME invalid paramSize: %u", __func__, paramSize);
+ status = -EINVAL;
+ break;
+ }
if (*pValueSize < 1) {
- status = -EINVAL;
android_errorWriteLog(0x534e4554, "37536407");
+ status = -EINVAL;
break;
}
- name = (char *)pValue;
- strncpy(name, EqualizerGetPresetName(param2), *pValueSize - 1);
+ const int32_t preset = params[1];
+ if ((preset < 0 && preset != PRESET_CUSTOM) || preset >= EqualizerGetNumPresets()) {
+ if (preset < 0) {
+ android_errorWriteLog(0x534e4554, "32448258");
+ ALOGE("%s EQ_PARAM_GET_PRESET_NAME preset %d", __func__, preset);
+ }
+ status = -EINVAL;
+ break;
+ }
+
+ char * const name = (char *)pValue;
+ strncpy(name, EqualizerGetPresetName(preset), *pValueSize - 1);
name[*pValueSize - 1] = 0;
*pValueSize = strlen(name) + 1;
- //ALOGV("\tEqualizer_getParameter() EQ_PARAM_GET_PRESET_NAME preset %d, name %s len %d",
- // param2, gEqualizerPresets[param2].name, *pValueSize);
- break;
+ ALOGVV("%s EQ_PARAM_GET_PRESET_NAME preset %d, name %s len %d",
+ __func__, preset, gEqualizerPresets[preset].name, *pValueSize);
+
+ } break;
case EQ_PARAM_PROPERTIES: {
+ constexpr uint32_t requiredValueSize = (2 + FIVEBAND_NUMBANDS) * sizeof(uint16_t);
+ if (*pValueSize < requiredValueSize) {
+ ALOGV("%s EQ_PARAM_PROPERTIES invalid *pValueSize %u", __func__, *pValueSize);
+ status = -EINVAL;
+ break;
+ }
+ *pValueSize = requiredValueSize;
+
int16_t *p = (int16_t *)pValue;
- ALOGV("\tEqualizer_getParameter() EQ_PARAM_PROPERTIES");
+ ALOGV("%s EQ_PARAM_PROPERTIES", __func__);
p[0] = (int16_t)EqualizerGetPreset(pContext);
p[1] = (int16_t)FIVEBAND_NUMBANDS;
for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
@@ -2615,12 +2727,12 @@
} break;
default:
- ALOGV("\tLVM_ERROR : Equalizer_getParameter() invalid param %d", param);
+ ALOGV("%s invalid param %d", __func__, params[0]);
status = -EINVAL;
break;
}
- //GV("\tEqualizer_getParameter end\n");
+ ALOGVV("%s end param: %d, status: %d", __func__, params[0], status);
return status;
} /* end Equalizer_getParameter */
@@ -2640,74 +2752,89 @@
// Outputs:
//
//----------------------------------------------------------------------------
-int Equalizer_setParameter (EffectContext *pContext,
- void *pParam,
- uint32_t valueSize,
- void *pValue) {
+int Equalizer_setParameter(EffectContext *pContext,
+ uint32_t paramSize,
+ void *pParam,
+ uint32_t valueSize,
+ void *pValue) {
int status = 0;
- int32_t preset;
- int32_t band;
- int32_t level;
- int32_t *pParamTemp = (int32_t *)pParam;
- int32_t param = *pParamTemp++;
+ int32_t *params = (int32_t *)pParam;
+ ALOGVV("%s start", __func__);
- //ALOGV("\tEqualizer_setParameter start");
- switch (param) {
- case EQ_PARAM_CUR_PRESET:
+ if (paramSize < sizeof(int32_t)) {
+ ALOGV("%s invalid paramSize: %u", __func__, paramSize);
+ return -EINVAL;
+ }
+ switch (params[0]) {
+ case EQ_PARAM_CUR_PRESET: {
if (valueSize < sizeof(int16_t)) {
- status = -EINVAL;
- break;
+ ALOGV("%s EQ_PARAM_CUR_PRESET invalid valueSize %u", __func__, valueSize);
+ status = -EINVAL;
+ break;
}
- preset = (int32_t)(*(uint16_t *)pValue);
+ const int32_t preset = (int32_t)*(uint16_t *)pValue;
- //ALOGV("\tEqualizer_setParameter() EQ_PARAM_CUR_PRESET %d", preset);
- if ((preset >= EqualizerGetNumPresets())||(preset < 0)) {
+ ALOGVV("%s EQ_PARAM_CUR_PRESET %d", __func__, preset);
+ if (preset >= EqualizerGetNumPresets() || preset < 0) {
+ ALOGV("%s EQ_PARAM_CUR_PRESET invalid preset %d", __func__, preset);
status = -EINVAL;
break;
}
EqualizerSetPreset(pContext, preset);
- break;
- case EQ_PARAM_BAND_LEVEL:
- if (valueSize < sizeof(int16_t)) {
- status = -EINVAL;
- break;
- }
- band = *pParamTemp;
- level = (int32_t)(*(int16_t *)pValue);
- //ALOGV("\tEqualizer_setParameter() EQ_PARAM_BAND_LEVEL band %d, level %d", band, level);
- if (band < 0 || band >= FIVEBAND_NUMBANDS) {
+ } break;
+
+ case EQ_PARAM_BAND_LEVEL: {
+ if (paramSize < 2 * sizeof(int32_t)) {
+ ALOGV("%s EQ_PARAM_BAND_LEVEL invalid paramSize: %u", __func__, paramSize);
status = -EINVAL;
+ break;
+ }
+ if (valueSize < sizeof(int16_t)) {
+ ALOGV("%s EQ_PARAM_BAND_LEVEL invalid valueSize %u", __func__, valueSize);
+ status = -EINVAL;
+ break;
+ }
+ const int32_t band = params[1];
+ const int32_t level = (int32_t)*(int16_t *)pValue;
+ ALOGVV("%s EQ_PARAM_BAND_LEVEL band %d, level %d", __func__, band, level);
+ if (band < 0 || band >= FIVEBAND_NUMBANDS) {
if (band < 0) {
android_errorWriteLog(0x534e4554, "32095626");
- ALOGE("\tERROR Equalizer_setParameter() EQ_PARAM_BAND_LEVEL band %d", band);
+ ALOGE("%s EQ_PARAM_BAND_LEVEL invalid band %d", __func__, band);
}
+ status = -EINVAL;
break;
}
EqualizerSetBandLevel(pContext, band, level);
- break;
+ } break;
+
case EQ_PARAM_PROPERTIES: {
- //ALOGV("\tEqualizer_setParameter() EQ_PARAM_PROPERTIES");
+ ALOGVV("%s EQ_PARAM_PROPERTIES", __func__);
if (valueSize < sizeof(int16_t)) {
- status = -EINVAL;
- break;
+ ALOGV("%s EQ_PARAM_PROPERTIES invalid valueSize %u", __func__, valueSize);
+ status = -EINVAL;
+ break;
}
int16_t *p = (int16_t *)pValue;
if ((int)p[0] >= EqualizerGetNumPresets()) {
+ ALOGV("%s EQ_PARAM_PROPERTIES invalid preset %d", __func__, (int)p[0]);
status = -EINVAL;
break;
}
if (p[0] >= 0) {
EqualizerSetPreset(pContext, (int)p[0]);
} else {
- if (valueSize < (2 + FIVEBAND_NUMBANDS) * sizeof(int16_t)) {
+ constexpr uint32_t valueSizeRequired = (2 + FIVEBAND_NUMBANDS) * sizeof(int16_t);
+ if (valueSize < valueSizeRequired) {
android_errorWriteLog(0x534e4554, "37563371");
- ALOGE("\tERROR Equalizer_setParameter() EQ_PARAM_PROPERTIES valueSize %d < %d",
- (int)valueSize, (int)((2 + FIVEBAND_NUMBANDS) * sizeof(int16_t)));
+ ALOGE("%s EQ_PARAM_PROPERTIES invalid valueSize %u < %u",
+ __func__, valueSize, valueSizeRequired);
status = -EINVAL;
break;
}
if ((int)p[1] != FIVEBAND_NUMBANDS) {
+ ALOGV("%s EQ_PARAM_PROPERTIES invalid bands %d", __func__, (int)p[1]);
status = -EINVAL;
break;
}
@@ -2716,13 +2843,14 @@
}
}
} break;
+
default:
- ALOGV("\tLVM_ERROR : Equalizer_setParameter() invalid param %d", param);
+ ALOGV("%s invalid param %d", __func__, params[0]);
status = -EINVAL;
break;
}
- //ALOGV("\tEqualizer_setParameter end");
+ ALOGVV("%s end param: %d, status: %d", __func__, params[0], status);
return status;
} /* end Equalizer_setParameter */
@@ -2747,79 +2875,92 @@
//
//----------------------------------------------------------------------------
-int Volume_getParameter(EffectContext *pContext,
- void *pParam,
- uint32_t *pValueSize,
- void *pValue){
+int Volume_getParameter(EffectContext *pContext,
+ uint32_t paramSize,
+ void *pParam,
+ uint32_t *pValueSize,
+ void *pValue) {
int status = 0;
- int32_t *pParamTemp = (int32_t *)pParam;
- int32_t param = *pParamTemp++;;
+ int32_t *params = (int32_t *)pParam;
- //ALOGV("\tVolume_getParameter start");
+ ALOGVV("%s start", __func__);
- switch (param){
+ if (paramSize < sizeof(int32_t)) {
+ ALOGV("%s invalid paramSize: %u", __func__, paramSize);
+ return -EINVAL;
+ }
+ switch (params[0]) {
case VOLUME_PARAM_LEVEL:
- case VOLUME_PARAM_MAXLEVEL:
- case VOLUME_PARAM_STEREOPOSITION:
- if (*pValueSize != sizeof(int16_t)){
- ALOGV("\tLVM_ERROR : Volume_getParameter() invalid pValueSize 1 %d", *pValueSize);
- return -EINVAL;
+ if (*pValueSize != sizeof(int16_t)) { // legacy: check equality here.
+ ALOGV("%s VOLUME_PARAM_LEVEL invalid *pValueSize %u", __func__, *pValueSize);
+ status = -EINVAL;
+ break;
}
- *pValueSize = sizeof(int16_t);
+ // no need to set *pValueSize
+
+ status = VolumeGetVolumeLevel(pContext, (int16_t *)(pValue));
+ ALOGVV("%s VOLUME_PARAM_LEVEL %d", __func__, *(int16_t *)pValue);
+ break;
+
+ case VOLUME_PARAM_MAXLEVEL:
+ if (*pValueSize != sizeof(int16_t)) { // legacy: check equality here.
+ ALOGV("%s VOLUME_PARAM_MAXLEVEL invalid *pValueSize %u", __func__, *pValueSize);
+ status = -EINVAL;
+ break;
+ }
+ // no need to set *pValueSize
+
+ // in millibel
+ *(int16_t *)pValue = 0;
+ ALOGVV("%s VOLUME_PARAM_MAXLEVEL %d", __func__, *(int16_t *)pValue);
+ break;
+
+ case VOLUME_PARAM_STEREOPOSITION:
+ if (*pValueSize != sizeof(int16_t)) { // legacy: check equality here.
+ ALOGV("%s VOLUME_PARAM_STEREOPOSITION invalid *pValueSize %u",
+ __func__, *pValueSize);
+ status = -EINVAL;
+ break;
+ }
+ // no need to set *pValueSize
+
+ VolumeGetStereoPosition(pContext, (int16_t *)pValue);
+ ALOGVV("%s VOLUME_PARAM_STEREOPOSITION %d", __func__, *(int16_t *)pValue);
break;
case VOLUME_PARAM_MUTE:
+ if (*pValueSize < sizeof(uint32_t)) {
+ ALOGV("%s VOLUME_PARAM_MUTE invalid *pValueSize %u", __func__, *pValueSize);
+ status = -EINVAL;
+ break;
+ }
+ *pValueSize = sizeof(uint32_t);
+
+ status = VolumeGetMute(pContext, (uint32_t *)pValue);
+ ALOGV("%s VOLUME_PARAM_MUTE %u", __func__, *(uint32_t *)pValue);
+ break;
+
case VOLUME_PARAM_ENABLESTEREOPOSITION:
- if (*pValueSize < sizeof(int32_t)){
- ALOGV("\tLVM_ERROR : Volume_getParameter() invalid pValueSize 2 %d", *pValueSize);
- return -EINVAL;
+ if (*pValueSize < sizeof(int32_t)) {
+ ALOGV("%s VOLUME_PARAM_ENABLESTEREOPOSITION invalid *pValueSize %u",
+ __func__, *pValueSize);
+ status = -EINVAL;
+ break;
}
*pValueSize = sizeof(int32_t);
- break;
- default:
- ALOGV("\tLVM_ERROR : Volume_getParameter unknown param %d", param);
- return -EINVAL;
- }
-
- switch (param){
- case VOLUME_PARAM_LEVEL:
- status = VolumeGetVolumeLevel(pContext, (int16_t *)(pValue));
- //ALOGV("\tVolume_getParameter() VOLUME_PARAM_LEVEL Value is %d",
- // *(int16_t *)pValue);
- break;
-
- case VOLUME_PARAM_MAXLEVEL:
- *(int16_t *)pValue = 0;
- //ALOGV("\tVolume_getParameter() VOLUME_PARAM_MAXLEVEL Value is %d",
- // *(int16_t *)pValue);
- break;
-
- case VOLUME_PARAM_STEREOPOSITION:
- VolumeGetStereoPosition(pContext, (int16_t *)pValue);
- //ALOGV("\tVolume_getParameter() VOLUME_PARAM_STEREOPOSITION Value is %d",
- // *(int16_t *)pValue);
- break;
-
- case VOLUME_PARAM_MUTE:
- status = VolumeGetMute(pContext, (uint32_t *)pValue);
- ALOGV("\tVolume_getParameter() VOLUME_PARAM_MUTE Value is %d",
- *(uint32_t *)pValue);
- break;
-
- case VOLUME_PARAM_ENABLESTEREOPOSITION:
*(int32_t *)pValue = pContext->pBundledContext->bStereoPositionEnabled;
- //ALOGV("\tVolume_getParameter() VOLUME_PARAM_ENABLESTEREOPOSITION Value is %d",
- // *(uint32_t *)pValue);
+ ALOGVV("%s VOLUME_PARAM_ENABLESTEREOPOSITION %d", __func__, *(int32_t *)pValue);
+
break;
default:
- ALOGV("\tLVM_ERROR : Volume_getParameter() invalid param %d", param);
+ ALOGV("%s invalid param %d", __func__, params[0]);
status = -EINVAL;
break;
}
- //ALOGV("\tVolume_getParameter end");
+ ALOGVV("%s end param: %d, status: %d", __func__, params[0], status);
return status;
} /* end Volume_getParameter */
@@ -2839,55 +2980,87 @@
//
//----------------------------------------------------------------------------
-int Volume_setParameter (EffectContext *pContext, void *pParam, void *pValue){
- int status = 0;
- int16_t level;
- int16_t position;
- uint32_t mute;
- uint32_t positionEnabled;
- int32_t *pParamTemp = (int32_t *)pParam;
- int32_t param = *pParamTemp++;
+int Volume_setParameter(EffectContext *pContext,
+ uint32_t paramSize,
+ void *pParam,
+ uint32_t valueSize,
+ void *pValue) {
+ int status = 0;
+ int32_t *params = (int32_t *)pParam;
- //ALOGV("\tVolume_setParameter start");
+ ALOGVV("%s start", __func__);
- switch (param){
- case VOLUME_PARAM_LEVEL:
- level = *(int16_t *)pValue;
- //ALOGV("\tVolume_setParameter() VOLUME_PARAM_LEVEL value is %d", level);
- //ALOGV("\tVolume_setParameter() Calling pVolume->setVolumeLevel");
- status = VolumeSetVolumeLevel(pContext, (int16_t)level);
- //ALOGV("\tVolume_setParameter() Called pVolume->setVolumeLevel");
- break;
+ if (paramSize < sizeof(int32_t)) {
+ ALOGV("%s invalid paramSize: %u", __func__, paramSize);
+ return -EINVAL;
+ }
+ switch (params[0]) {
+ case VOLUME_PARAM_LEVEL: {
+ if (valueSize < sizeof(int16_t)) {
+ ALOGV("%s VOLUME_PARAM_LEVEL invalid valueSize %u", __func__, valueSize);
+ status = -EINVAL;
+ break;
+ }
- case VOLUME_PARAM_MUTE:
- mute = *(uint32_t *)pValue;
- //ALOGV("\tVolume_setParameter() Calling pVolume->setMute, mute is %d", mute);
- //ALOGV("\tVolume_setParameter() Calling pVolume->setMute");
+ const int16_t level = *(int16_t *)pValue;
+ ALOGVV("%s VOLUME_PARAM_LEVEL %d", __func__, level);
+ ALOGVV("%s VOLUME_PARAM_LEVEL Calling VolumeSetVolumeLevel", __func__);
+ status = VolumeSetVolumeLevel(pContext, level);
+ ALOGVV("%s VOLUME_PARAM_LEVEL Called VolumeSetVolumeLevel", __func__);
+ } break;
+
+ case VOLUME_PARAM_MUTE: {
+ if (valueSize < sizeof(uint32_t)) {
+ ALOGV("%s VOLUME_PARAM_MUTE invalid valueSize %u", __func__, valueSize);
+ android_errorWriteLog(0x534e4554, "64477217");
+ status = -EINVAL;
+ break;
+ }
+
+ const uint32_t mute = *(uint32_t *)pValue;
+ ALOGVV("%s VOLUME_PARAM_MUTE %d", __func__, mute);
+ ALOGVV("%s VOLUME_PARAM_MUTE Calling VolumeSetMute", __func__);
status = VolumeSetMute(pContext, mute);
- //ALOGV("\tVolume_setParameter() Called pVolume->setMute");
- break;
+ ALOGVV("%s VOLUME_PARAM_MUTE Called VolumeSetMute", __func__);
+ } break;
- case VOLUME_PARAM_ENABLESTEREOPOSITION:
- positionEnabled = *(uint32_t *)pValue;
- (void) VolumeEnableStereoPosition(pContext, positionEnabled);
- (void) VolumeSetStereoPosition(pContext, pContext->pBundledContext->positionSaved);
- //ALOGV("\tVolume_setParameter() VOLUME_PARAM_ENABLESTEREOPOSITION called");
- break;
+ case VOLUME_PARAM_ENABLESTEREOPOSITION: {
+ if (valueSize < sizeof(uint32_t)) {
+ ALOGV("%s VOLUME_PARAM_ENABLESTEREOPOSITION invalid valueSize %u",
+ __func__, valueSize);
+ status = -EINVAL;
+ break;
+ }
- case VOLUME_PARAM_STEREOPOSITION:
- position = *(int16_t *)pValue;
- //ALOGV("\tVolume_setParameter() VOLUME_PARAM_STEREOPOSITION value is %d", position);
- //ALOGV("\tVolume_setParameter() Calling pVolume->VolumeSetStereoPosition");
- status = VolumeSetStereoPosition(pContext, (int16_t)position);
- //ALOGV("\tVolume_setParameter() Called pVolume->VolumeSetStereoPosition");
- break;
+ const uint32_t positionEnabled = *(uint32_t *)pValue;
+ status = VolumeEnableStereoPosition(pContext, positionEnabled)
+ ?: VolumeSetStereoPosition(pContext, pContext->pBundledContext->positionSaved);
+ ALOGVV("%s VOLUME_PARAM_ENABLESTEREOPOSITION called", __func__);
+ } break;
+
+ case VOLUME_PARAM_STEREOPOSITION: {
+ if (valueSize < sizeof(int16_t)) {
+ ALOGV("%s VOLUME_PARAM_STEREOPOSITION invalid valueSize %u", __func__, valueSize);
+ status = -EINVAL;
+ break;
+ }
+
+ const int16_t position = *(int16_t *)pValue;
+ ALOGVV("%s VOLUME_PARAM_STEREOPOSITION %d", __func__, position);
+ ALOGVV("%s VOLUME_PARAM_STEREOPOSITION Calling VolumeSetStereoPosition",
+ __func__);
+ status = VolumeSetStereoPosition(pContext, position);
+ ALOGVV("%s VOLUME_PARAM_STEREOPOSITION Called VolumeSetStereoPosition",
+ __func__);
+ } break;
default:
- ALOGV("\tLVM_ERROR : Volume_setParameter() invalid param %d", param);
+ ALOGV("%s invalid param %d", __func__, params[0]);
+ status = -EINVAL;
break;
}
- //ALOGV("\tVolume_setParameter end");
+ ALOGVV("%s end param: %d, status: %d", __func__, params[0], status);
return status;
} /* end Volume_setParameter */
@@ -3205,6 +3378,13 @@
return status;
} /* end Effect_process */
+// The value offset of an effect parameter is computed by rounding up
+// the parameter size to the next 32 bit alignment.
+static inline uint32_t computeParamVOffset(const effect_param_t *p) {
+ return ((p->psize + sizeof(int32_t) - 1) / sizeof(int32_t)) *
+ sizeof(int32_t);
+}
+
/* Effect Control Interface Implementation: Command */
int Effect_command(effect_handle_t self,
uint32_t cmdCode,
@@ -3315,8 +3495,7 @@
ALOGV("\tLVM_ERROR : EFFECT_CMD_GET_PARAM: psize too big");
return -EINVAL;
}
- uint32_t paddedParamSize = ((p->psize + sizeof(int32_t) - 1) / sizeof(int32_t)) *
- sizeof(int32_t);
+ const uint32_t paddedParamSize = computeParamVOffset(p);
if ((EFFECT_PARAM_SIZE_MAX - sizeof(effect_param_t) < paddedParamSize) ||
(EFFECT_PARAM_SIZE_MAX - sizeof(effect_param_t) - paddedParamSize <
p->vsize)) {
@@ -3338,6 +3517,7 @@
uint32_t voffset = paddedParamSize;
if(pContext->EffectType == LVM_BASS_BOOST){
p->status = android::BassBoost_getParameter(pContext,
+ p->psize,
p->data,
&p->vsize,
p->data + voffset);
@@ -3350,6 +3530,7 @@
if(pContext->EffectType == LVM_VIRTUALIZER){
p->status = android::Virtualizer_getParameter(pContext,
+ p->psize,
(void *)p->data,
&p->vsize,
p->data + voffset);
@@ -3364,6 +3545,7 @@
//ALOGV("\tEqualizer_command cmdCode Case: "
// "EFFECT_CMD_GET_PARAM start");
p->status = android::Equalizer_getParameter(pContext,
+ p->psize,
p->data,
&p->vsize,
p->data + voffset);
@@ -3378,6 +3560,7 @@
if(pContext->EffectType == LVM_VOLUME){
//ALOGV("\tVolume_command cmdCode Case: EFFECT_CMD_GET_PARAM start");
p->status = android::Volume_getParameter(pContext,
+ p->psize,
(void *)p->data,
&p->vsize,
p->data + voffset);
@@ -3407,13 +3590,9 @@
"EFFECT_CMD_SET_PARAM: ERROR");
return -EINVAL;
}
- effect_param_t *p = (effect_param_t *) pCmdData;
- if (p->psize != sizeof(int32_t)){
- ALOGV("\tLVM_ERROR : BassBoost_command cmdCode Case: "
- "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
- return -EINVAL;
- }
+ effect_param_t * const p = (effect_param_t *) pCmdData;
+ const uint32_t voffset = computeParamVOffset(p);
//ALOGV("\tnBassBoost_command cmdSize is %d\n"
// "\tsizeof(effect_param_t) is %d\n"
@@ -3423,8 +3602,10 @@
// cmdSize, sizeof(effect_param_t), p->psize, p->vsize );
*(int *)pReplyData = android::BassBoost_setParameter(pContext,
- (void *)p->data,
- p->data + p->psize);
+ p->psize,
+ (void *)p->data,
+ p->vsize,
+ p->data + voffset);
}
if(pContext->EffectType == LVM_VIRTUALIZER){
// Warning this log will fail to properly read an int32_t value, assumes int16_t
@@ -3442,13 +3623,9 @@
"EFFECT_CMD_SET_PARAM: ERROR");
return -EINVAL;
}
- effect_param_t *p = (effect_param_t *) pCmdData;
- if (p->psize != sizeof(int32_t)){
- ALOGV("\tLVM_ERROR : Virtualizer_command cmdCode Case: "
- "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
- return -EINVAL;
- }
+ effect_param_t * const p = (effect_param_t *) pCmdData;
+ const uint32_t voffset = computeParamVOffset(p);
//ALOGV("\tnVirtualizer_command cmdSize is %d\n"
// "\tsizeof(effect_param_t) is %d\n"
@@ -3458,8 +3635,10 @@
// cmdSize, sizeof(effect_param_t), p->psize, p->vsize );
*(int *)pReplyData = android::Virtualizer_setParameter(pContext,
- (void *)p->data,
- p->data + p->psize);
+ p->psize,
+ (void *)p->data,
+ p->vsize,
+ p->data + voffset);
}
if(pContext->EffectType == LVM_EQUALIZER){
//ALOGV("\tEqualizer_command cmdCode Case: "
@@ -3475,12 +3654,15 @@
"EFFECT_CMD_SET_PARAM: ERROR");
return -EINVAL;
}
- effect_param_t *p = (effect_param_t *) pCmdData;
+
+ effect_param_t * const p = (effect_param_t *) pCmdData;
+ const uint32_t voffset = computeParamVOffset(p);
*(int *)pReplyData = android::Equalizer_setParameter(pContext,
- (void *)p->data,
- p->vsize,
- p->data + p->psize);
+ p->psize,
+ (void *)p->data,
+ p->vsize,
+ p->data + voffset);
}
if(pContext->EffectType == LVM_VOLUME){
//ALOGV("\tVolume_command cmdCode Case: EFFECT_CMD_SET_PARAM start");
@@ -3497,11 +3679,15 @@
"EFFECT_CMD_SET_PARAM: ERROR");
return -EINVAL;
}
- effect_param_t *p = (effect_param_t *) pCmdData;
+
+ effect_param_t * const p = (effect_param_t *) pCmdData;
+ const uint32_t voffset = computeParamVOffset(p);
*(int *)pReplyData = android::Volume_setParameter(pContext,
- (void *)p->data,
- p->data + p->psize);
+ p->psize,
+ (void *)p->data,
+ p->vsize,
+ p->data + voffset);
}
//ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_SET_PARAM end");
} break;
@@ -3648,10 +3834,10 @@
if(rightdB > maxdB){
maxdB = rightdB;
}
- //ALOGV("\tEFFECT_CMD_SET_VOLUME Session: %d, SessionID: %d VOLUME is %d dB (%d), "
+ //ALOGV("\tEFFECT_CMD_SET_VOLUME Session: %d, SessionID: %d VOLUME is %d dB, "
// "effect is %d",
//pContext->pBundledContext->SessionNo, pContext->pBundledContext->SessionId,
- //(int32_t)maxdB, maxVol<<7, pContext->EffectType);
+ //(int32_t)maxdB, pContext->EffectType);
//ALOGV("\tEFFECT_CMD_SET_VOLUME: Left is %d, Right is %d", leftVolume, rightVolume);
//ALOGV("\tEFFECT_CMD_SET_VOLUME: Left %ddB, Right %ddB, Position %ddB",
// leftdB, rightdB, pandB);
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
index cad89fd..291383a 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
@@ -213,7 +213,7 @@
static const float LimitLevel_bassBoostEnergyCrossCoefficient[FIVEBAND_NUMBANDS] = {
221.21, 208.10, 28.16, 0.0, 0.0 };
-static const float LimitLevel_bassBoostEnergyCoefficient = 7.12;
+static const float LimitLevel_bassBoostEnergyCoefficient = 9.00;
static const float LimitLevel_virtualizerContribution = 1.9;
diff --git a/media/libmediametrics/MediaAnalyticsItem.cpp b/media/libmediametrics/MediaAnalyticsItem.cpp
index 47a147e..30a31e6 100644
--- a/media/libmediametrics/MediaAnalyticsItem.cpp
+++ b/media/libmediametrics/MediaAnalyticsItem.cpp
@@ -59,6 +59,7 @@
MediaAnalyticsItem::MediaAnalyticsItem()
: mPid(-1),
mUid(-1),
+ mPkgVersionCode(0),
mSessionID(MediaAnalyticsItem::SessionIDNone),
mTimestamp(0),
mFinalized(0),
@@ -70,6 +71,7 @@
MediaAnalyticsItem::MediaAnalyticsItem(MediaAnalyticsItem::Key key)
: mPid(-1),
mUid(-1),
+ mPkgVersionCode(0),
mSessionID(MediaAnalyticsItem::SessionIDNone),
mTimestamp(0),
mFinalized(0),
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index c9394bb..c44e868 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -6356,12 +6356,14 @@
ALOGE("Unable to obtain MediaCodecList while "
"attempting to create codec \"%s\"",
componentName.c_str());
+ mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
return false;
}
ssize_t index = list->findCodecByName(componentName.c_str());
if (index < 0) {
ALOGE("Unable to find codec \"%s\"",
componentName.c_str());
+ mCodec->signalError(OMX_ErrorInvalidComponent, NAME_NOT_FOUND);
return false;
}
sp<MediaCodecInfo> info = list->getCodecInfo(index);
@@ -6369,6 +6371,7 @@
ALOGE("Unexpected error (index out-of-bound) while "
"retrieving information for codec \"%s\"",
componentName.c_str());
+ mCodec->signalError(OMX_ErrorUndefined, UNKNOWN_ERROR);
return false;
}
matchingCodecs.add(info->getCodecName());
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 3cdb49e..abacf13 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -73,6 +73,11 @@
static const char *kCodecCrypto = "android.media.mediacodec.crypto"; /* 0,1 */
static const char *kCodecEncoder = "android.media.mediacodec.encoder"; /* 0,1 */
+static const char *kCodecBytesIn = "android.media.mediacodec.bytesin"; /* 0..n */
+static const char *kCodecProfile = "android.media.mediacodec.profile"; /* 0..n */
+static const char *kCodecLevel = "android.media.mediacodec.level"; /* 0..n */
+static const char *kCodecMaxWidth = "android.media.mediacodec.maxwidth"; /* 0..n */
+static const char *kCodecMaxHeight = "android.media.mediacodec.maxheight"; /* 0..n */
static int64_t getId(const sp<IResourceManagerClient> &client) {
@@ -684,10 +689,21 @@
uint32_t flags) {
sp<AMessage> msg = new AMessage(kWhatConfigure, this);
+ if (mAnalyticsItem != NULL) {
+ int32_t profile = 0;
+ if (format->findInt32("profile", &profile)) {
+ mAnalyticsItem->setInt32(kCodecProfile, profile);
+ }
+ int32_t level = 0;
+ if (format->findInt32("level", &level)) {
+ mAnalyticsItem->setInt32(kCodecLevel, level);
+ }
+ }
+
if (mIsVideo) {
format->findInt32("width", &mVideoWidth);
format->findInt32("height", &mVideoHeight);
- if (!format->findInt32(kCodecRotation, &mRotationDegrees)) {
+ if (!format->findInt32("rotation-degrees", &mRotationDegrees)) {
mRotationDegrees = 0;
}
@@ -695,6 +711,14 @@
mAnalyticsItem->setInt32(kCodecWidth, mVideoWidth);
mAnalyticsItem->setInt32(kCodecHeight, mVideoHeight);
mAnalyticsItem->setInt32(kCodecRotation, mRotationDegrees);
+ int32_t maxWidth = 0;
+ if (format->findInt32("max-width", &maxWidth)) {
+ mAnalyticsItem->setInt32(kCodecMaxWidth, maxWidth);
+ }
+ int32_t maxHeight = 0;
+ if (format->findInt32("max-height", &maxHeight)) {
+ mAnalyticsItem->setInt32(kCodecMaxHeight, maxHeight);
+ }
}
// Prevent possible integer overflow in downstream code.
@@ -1576,6 +1600,19 @@
}
setState(CONFIGURED);
(new AMessage)->postReply(mReplyID);
+
+ // augment our media metrics info, now that we know more things
+ if (mAnalyticsItem != NULL) {
+ sp<AMessage> format;
+ if (mConfigureMsg != NULL &&
+ mConfigureMsg->findMessage("format", &format)) {
+ // format includes: mime
+ AString mime;
+ if (format->findString("mime", &mime)) {
+ mAnalyticsItem->setCString(kCodecMime, mime.c_str());
+ }
+ }
+ }
break;
}
@@ -2801,6 +2838,9 @@
Mutex::Autolock al(mBufferLock);
info->mOwnedByClient = false;
info->mData.clear();
+ if (mAnalyticsItem != NULL) {
+ mAnalyticsItem->addInt64(kCodecBytesIn, size);
+ }
}
return err;
diff --git a/media/libstagefright/OmxInfoBuilder.cpp b/media/libstagefright/OmxInfoBuilder.cpp
index 686bcc8..8717a79 100644
--- a/media/libstagefright/OmxInfoBuilder.cpp
+++ b/media/libstagefright/OmxInfoBuilder.cpp
@@ -61,9 +61,9 @@
}
for (const auto& attribute : node.attributes) {
// All features have an int32 value except
- // "feature-bitrate-control", which has a string value.
+ // "feature-bitrate-modes", which has a string value.
if ((attribute.key.compare(0, 8, "feature-") == 0) &&
- (attribute.key.compare(8, 15, "bitrate-control")
+ (attribute.key.compare(8, 15, "bitrate-modes")
!= 0)) {
// If this attribute.key is a feature that is not a bitrate
// control, add an int32 value.
diff --git a/media/libstagefright/data/media_codecs_google_video.xml b/media/libstagefright/data/media_codecs_google_video.xml
index a127843..829f403 100644
--- a/media/libstagefright/data/media_codecs_google_video.xml
+++ b/media/libstagefright/data/media_codecs_google_video.xml
@@ -35,10 +35,10 @@
</MediaCodec>
<MediaCodec name="OMX.google.h264.decoder" type="video/avc">
<!-- profiles and levels: ProfileHigh : Level52 -->
- <Limit name="size" min="2x2" max="4096x4096" />
+ <Limit name="size" min="2x2" max="4080x4080" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
- <Limit name="block-count" range="1-32768" /> <!-- max 4096x2048 -->
+ <Limit name="block-count" range="1-32768" /> <!-- max 4096x2048 equivalent -->
<Limit name="blocks-per-second" range="1-1966080" />
<Limit name="bitrate" range="1-48000000" />
<Feature name="adaptive-playback" />
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index 109460d..1917d2a 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -956,28 +956,40 @@
Mutex::Autolock lock(mMutex);
uint64_t slotMask;
- if (mConsumer->getReleasedBuffers(&slotMask) != NO_ERROR) {
- ALOGW("onBuffersReleased: unable to get released buffer set");
+ uint64_t releaseMask;
+ if (mConsumer->getReleasedBuffers(&releaseMask) != NO_ERROR) {
slotMask = 0xffffffffffffffffULL;
+ ALOGW("onBuffersReleased: unable to get released buffer set");
+ } else {
+ slotMask = releaseMask;
+ ALOGV("onBuffersReleased: 0x%016" PRIx64, slotMask);
}
- ALOGV("onBuffersReleased: 0x%016" PRIx64, slotMask);
-
+ AString unpopulated;
for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
if ((slotMask & 0x01) != 0) {
- discardBufferInSlot_l(i);
+ if (!discardBufferInSlot_l(i)) {
+ if (!unpopulated.empty()) {
+ unpopulated.append(", ");
+ }
+ unpopulated.append(i);
+ }
}
slotMask >>= 1;
}
+ if (!unpopulated.empty()) {
+ ALOGW("released unpopulated slots: [%s]", unpopulated.c_str());
+ }
}
-void GraphicBufferSource::discardBufferInSlot_l(GraphicBufferSource::slot_id i) {
+bool GraphicBufferSource::discardBufferInSlot_l(GraphicBufferSource::slot_id i) {
ssize_t bsi = mBufferSlots.indexOfKey(i);
if (bsi < 0) {
- ALOGW("releasing an unpopulated slot: %d", i);
+ return false;
} else {
discardBufferAtSlotIndex_l(bsi);
mBufferSlots.removeItemsAt(bsi);
+ return true;
}
}
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index cc96172..015a148 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -372,6 +372,8 @@
mPortMode[1] = IOMX::kPortModePresetByteBuffer;
mSecureBufferType[0] = kSecureBufferTypeUnknown;
mSecureBufferType[1] = kSecureBufferTypeUnknown;
+ mGraphicBufferEnabled[0] = false;
+ mGraphicBufferEnabled[1] = false;
mIsSecure = AString(name).endsWith(".secure");
mLegacyAdaptiveExperiment = ADebug::isExperimentEnabled("legacy-adaptive");
}
@@ -677,6 +679,11 @@
return BAD_VALUE;
}
+ if (mSailed || mNumPortBuffers[portIndex] > 0) {
+ android_errorWriteLog(0x534e4554, "29422020");
+ return INVALID_OPERATION;
+ }
+
CLOG_CONFIG(setPortMode, "%s(%d), port %d", asString(mode), mode, portIndex);
switch (mode) {
@@ -808,6 +815,12 @@
} else if (mSecureBufferType[portIndex] == kSecureBufferTypeUnknown) {
mSecureBufferType[portIndex] = kSecureBufferTypeOpaque;
}
+ } else {
+ if (err == OMX_ErrorNone) {
+ mGraphicBufferEnabled[portIndex] = enable;
+ } else if (enable) {
+ mGraphicBufferEnabled[portIndex] = false;
+ }
}
} else {
CLOG_ERROR_IF(enable, getExtensionIndex, err, "%s", name);
@@ -1076,6 +1089,12 @@
OMX_ERRORTYPE err = OMX_ErrorNone;
bool isMetadata = mMetadataType[portIndex] != kMetadataBufferTypeInvalid;
+ if (!isMetadata && mGraphicBufferEnabled[portIndex]) {
+ ALOGE("b/62948670");
+ android_errorWriteLog(0x534e4554, "62948670");
+ return INVALID_OPERATION;
+ }
+
size_t paramsSize;
void* paramsPointer;
if (params != NULL && hParams != NULL) {
@@ -1261,6 +1280,13 @@
portIndex, graphicBuffer, buffer);
}
+ if (!mGraphicBufferEnabled[portIndex]) {
+ // Report error if this is not in graphic buffer mode.
+ ALOGE("b/62948670");
+ android_errorWriteLog(0x534e4554, "62948670");
+ return INVALID_OPERATION;
+ }
+
// See if the newer version of the extension is present.
OMX_INDEXTYPE index;
if (OMX_GetExtensionIndex(
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/include/media/stagefright/omx/GraphicBufferSource.h
index 0f2d9a6..84fee6f 100644
--- a/media/libstagefright/omx/include/media/stagefright/omx/GraphicBufferSource.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/GraphicBufferSource.h
@@ -264,8 +264,8 @@
void onBufferAcquired_l(const VideoBuffer &buffer);
// marks the buffer at the slot no longer cached, and accounts for the outstanding
- // acquire count
- void discardBufferInSlot_l(slot_id i);
+ // acquire count. Returns true if the slot was populated; otherwise, false.
+ bool discardBufferInSlot_l(slot_id i);
// marks the buffer at the slot index no longer cached, and accounts for the outstanding
// acquire count
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h b/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h
index 19114e2..1065ca5 100644
--- a/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h
@@ -152,7 +152,7 @@
bool mLegacyAdaptiveExperiment;
IOMX::PortMode mPortMode[2];
- // metadata and secure buffer type tracking
+ // metadata and secure buffer types and graphic buffer mode tracking
MetadataBufferType mMetadataType[2];
enum SecureBufferType {
kSecureBufferTypeUnknown,
@@ -160,6 +160,7 @@
kSecureBufferTypeNativeHandle,
};
SecureBufferType mSecureBufferType[2];
+ bool mGraphicBufferEnabled[2];
// Following are OMX parameters managed by us (instead of the component)
// OMX_IndexParamMaxFrameDurationForBitrateControl
diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp
index dbca53e..8d894c1 100644
--- a/media/mtp/MtpFfsHandle.cpp
+++ b/media/mtp/MtpFfsHandle.cpp
@@ -62,6 +62,8 @@
constexpr int USB_FFS_MAX_WRITE = MTP_BUFFER_SIZE;
constexpr int USB_FFS_MAX_READ = MTP_BUFFER_SIZE;
+constexpr unsigned FFS_NUM_EVENTS = 5;
+
static_assert(USB_FFS_MAX_WRITE > 0, "Max r/w values must be > 0!");
static_assert(USB_FFS_MAX_READ > 0, "Max r/w values must be > 0!");
@@ -315,6 +317,11 @@
.Reserved2 = {0},
};
+struct mtp_device_status {
+ uint16_t wLength;
+ uint16_t wCode;
+};
+
} // anonymous namespace
namespace android {
@@ -392,6 +399,88 @@
mControl.reset();
}
+void MtpFfsHandle::controlLoop() {
+ while (!handleEvent()) {}
+ LOG(DEBUG) << "Mtp server shutting down";
+}
+
+int MtpFfsHandle::handleEvent() {
+ std::vector<usb_functionfs_event> events(FFS_NUM_EVENTS);
+ usb_functionfs_event *event = events.data();
+ int nbytes = TEMP_FAILURE_RETRY(::read(mControl, event,
+ events.size() * sizeof(usb_functionfs_event)));
+ if (nbytes == -1) {
+ return -1;
+ }
+ int ret = 0;
+ for (size_t n = nbytes / sizeof *event; n; --n, ++event) {
+ switch (event->type) {
+ case FUNCTIONFS_BIND:
+ case FUNCTIONFS_ENABLE:
+ case FUNCTIONFS_RESUME:
+ ret = 0;
+ errno = 0;
+ break;
+ case FUNCTIONFS_SUSPEND:
+ case FUNCTIONFS_UNBIND:
+ case FUNCTIONFS_DISABLE:
+ errno = ESHUTDOWN;
+ ret = -1;
+ break;
+ case FUNCTIONFS_SETUP:
+ if (handleControlRequest(&event->u.setup) == -1)
+ ret = -1;
+ break;
+ default:
+ LOG(DEBUG) << "Mtp Event " << event->type << " (unknown)";
+ }
+ }
+ return ret;
+}
+
+int MtpFfsHandle::handleControlRequest(const struct usb_ctrlrequest *setup) {
+ uint8_t type = setup->bRequestType;
+ uint8_t code = setup->bRequest;
+ uint16_t length = setup->wLength;
+ uint16_t index = setup->wIndex;
+ uint16_t value = setup->wValue;
+ std::vector<char> buf;
+ buf.resize(length);
+
+ if (!(type & USB_DIR_IN)) {
+ if (::read(mControl, buf.data(), length) != length) {
+ PLOG(DEBUG) << "Mtp error ctrlreq read data";
+ }
+ }
+
+ if ((type & USB_TYPE_MASK) == USB_TYPE_CLASS && index == 0 && value == 0) {
+ switch(code) {
+ case MTP_REQ_GET_DEVICE_STATUS:
+ {
+ if (length < sizeof(struct mtp_device_status)) {
+ return -1;
+ }
+ struct mtp_device_status *st = reinterpret_cast<struct mtp_device_status*>(buf.data());
+ st->wLength = htole16(sizeof(st));
+ st->wCode = MTP_RESPONSE_OK;
+ length = st->wLength;
+ break;
+ }
+ default:
+ LOG(DEBUG) << "Unrecognized Mtp class request! " << code;
+ }
+ } else {
+ LOG(DEBUG) << "Unrecognized request type " << type;
+ }
+
+ if (type & USB_DIR_IN) {
+ if (::write(mControl, buf.data(), length) != length) {
+ PLOG(DEBUG) << "Mtp error ctrlreq write data";
+ }
+ }
+ return 0;
+}
+
int MtpFfsHandle::writeHandle(int fd, const void* data, int len) {
LOG(VERBOSE) << "MTP about to write fd = " << fd << ", len=" << len;
int ret = 0;
@@ -491,6 +580,10 @@
posix_madvise(mBuffer2.data(), MAX_FILE_CHUNK_SIZE,
POSIX_MADV_SEQUENTIAL | POSIX_MADV_WILLNEED);
+ // Handle control requests.
+ std::thread t([this]() { this->controlLoop(); });
+ t.detach();
+
// Get device specific r/w size
mMaxWrite = android::base::GetIntProperty("sys.usb.ffs.max_write", USB_FFS_MAX_WRITE);
mMaxRead = android::base::GetIntProperty("sys.usb.ffs.max_read", USB_FFS_MAX_READ);
diff --git a/media/mtp/MtpFfsHandle.h b/media/mtp/MtpFfsHandle.h
index b637d65..da0cd9f 100644
--- a/media/mtp/MtpFfsHandle.h
+++ b/media/mtp/MtpFfsHandle.h
@@ -35,6 +35,10 @@
void closeEndpoints();
void doSendEvent(mtp_event me);
+ void controlLoop();
+ int handleEvent();
+ int handleControlRequest(const struct usb_ctrlrequest *setup);
+
bool mPtp;
std::timed_mutex mLock;
diff --git a/media/mtp/mtp.h b/media/mtp/mtp.h
index 13cc859..1c7829d 100644
--- a/media/mtp/mtp.h
+++ b/media/mtp/mtp.h
@@ -494,4 +494,10 @@
#define MTP_ASSOCIATION_TYPE_UNDEFINED 0x0000
#define MTP_ASSOCIATION_TYPE_GENERIC_FOLDER 0x0001
+// MTP class reqeusts
+#define MTP_REQ_CANCEL 0x64
+#define MTP_REQ_GET_EXT_EVENT_DATA 0x65
+#define MTP_REQ_RESET 0x66
+#define MTP_REQ_GET_DEVICE_STATUS 0x67
+
#endif // _MTP_H
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 13522f5..39f04fb 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -329,6 +329,11 @@
thread->configure(attr, streamType, sessionId, callback, *deviceId, portId);
*handle = portId;
} else {
+ if (direction == MmapStreamInterface::DIRECTION_OUTPUT) {
+ AudioSystem::releaseOutput(io, streamType, sessionId);
+ } else {
+ AudioSystem::releaseInput(io, sessionId);
+ }
ret = NO_INIT;
}
@@ -1397,11 +1402,11 @@
// the config change is always sent from playback or record threads to avoid deadlock
// with AudioSystem::gLock
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- mPlaybackThreads.valueAt(i)->sendIoConfigEvent(AUDIO_OUTPUT_OPENED, pid);
+ mPlaybackThreads.valueAt(i)->sendIoConfigEvent(AUDIO_OUTPUT_REGISTERED, pid);
}
for (size_t i = 0; i < mRecordThreads.size(); i++) {
- mRecordThreads.valueAt(i)->sendIoConfigEvent(AUDIO_INPUT_OPENED, pid);
+ mRecordThreads.valueAt(i)->sendIoConfigEvent(AUDIO_INPUT_REGISTERED, pid);
}
}
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 297608c..49047af 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2253,6 +2253,7 @@
switch (event) {
case AUDIO_OUTPUT_OPENED:
+ case AUDIO_OUTPUT_REGISTERED:
case AUDIO_OUTPUT_CONFIG_CHANGED:
desc->mPatch = mPatch;
desc->mChannelMask = mChannelMask;
@@ -7242,6 +7243,7 @@
switch (event) {
case AUDIO_INPUT_OPENED:
+ case AUDIO_INPUT_REGISTERED:
case AUDIO_INPUT_CONFIG_CHANGED:
desc->mPatch = mPatch;
desc->mChannelMask = mChannelMask;
@@ -7913,8 +7915,10 @@
switch (event) {
case AUDIO_INPUT_OPENED:
+ case AUDIO_INPUT_REGISTERED:
case AUDIO_INPUT_CONFIG_CHANGED:
case AUDIO_OUTPUT_OPENED:
+ case AUDIO_OUTPUT_REGISTERED:
case AUDIO_OUTPUT_CONFIG_CHANGED:
desc->mPatch = mPatch;
desc->mChannelMask = mChannelMask;
diff --git a/services/audiopolicy/config/primary_audio_policy_configuration.xml b/services/audiopolicy/config/primary_audio_policy_configuration.xml
index bf508ac..5b7ae7f 100644
--- a/services/audiopolicy/config/primary_audio_policy_configuration.xml
+++ b/services/audiopolicy/config/primary_audio_policy_configuration.xml
@@ -13,7 +13,7 @@
</mixPort>
<mixPort name="primary input" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
- samplingRates="8000, 16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
</mixPort>
</mixPorts>
<devicePorts>
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index e6ee6c9..bdfaf2f 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1499,62 +1499,13 @@
"session %d, flags %#x",
attr->source, config->sample_rate, config->format, config->channel_mask, session, flags);
- // special case for mmap capture: if an input IO handle is specified, we reuse this input if
- // possible
- if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) == AUDIO_INPUT_FLAG_MMAP_NOIRQ &&
- *input != AUDIO_IO_HANDLE_NONE) {
- ssize_t index = mInputs.indexOfKey(*input);
- if (index < 0) {
- ALOGW("getInputForAttr() unknown MMAP input %d", *input);
- return BAD_VALUE;
- }
- sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(index);
- sp<AudioSession> audioSession = inputDesc->getAudioSession(session);
- if (audioSession == 0) {
- ALOGW("getInputForAttr() unknown session %d on input %d", session, *input);
- return BAD_VALUE;
- }
- // For MMAP mode, the first call to getInputForAttr() is made on behalf of audioflinger.
- // The second call is for the first active client and sets the UID. Any further call
- // corresponds to a new client and is only permitted from the same UId.
- if (audioSession->openCount() == 1) {
- audioSession->setUid(uid);
- } else if (audioSession->uid() != uid) {
- ALOGW("getInputForAttr() bad uid %d for session %d uid %d",
- uid, session, audioSession->uid());
- return INVALID_OPERATION;
- }
- audioSession->changeOpenCount(1);
- *inputType = API_INPUT_LEGACY;
- if (*portId == AUDIO_PORT_HANDLE_NONE) {
- *portId = AudioPort::getNextUniqueId();
- }
- DeviceVector inputDevices = mAvailableInputDevices.getDevicesFromType(inputDesc->mDevice);
- *selectedDeviceId = inputDevices.size() > 0 ? inputDevices.itemAt(0)->getId()
- : AUDIO_PORT_HANDLE_NONE;
- ALOGI("%s reusing MMAP input %d for session %d", __FUNCTION__, *input, session);
- return NO_ERROR;
- }
-
- *input = AUDIO_IO_HANDLE_NONE;
- *inputType = API_INPUT_INVALID;
-
- audio_devices_t device;
+ status_t status = NO_ERROR;
// handle legacy remote submix case where the address was not always specified
String8 address = String8("");
- audio_source_t inputSource = attr->source;
audio_source_t halInputSource;
+ audio_source_t inputSource = attr->source;
AudioMix *policyMix = NULL;
-
- if (inputSource == AUDIO_SOURCE_DEFAULT) {
- inputSource = AUDIO_SOURCE_MIC;
- }
- halInputSource = inputSource;
-
- // TODO: check for existing client for this port ID
- if (*portId == AUDIO_PORT_HANDLE_NONE) {
- *portId = AudioPort::getNextUniqueId();
- }
+ DeviceVector inputDevices;
// Explicit routing?
sp<DeviceDescriptor> deviceDesc;
@@ -1568,11 +1519,67 @@
}
mInputRoutes.addRoute(session, SessionRoute::STREAM_TYPE_NA, inputSource, deviceDesc, uid);
+ // special case for mmap capture: if an input IO handle is specified, we reuse this input if
+ // possible
+ if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) == AUDIO_INPUT_FLAG_MMAP_NOIRQ &&
+ *input != AUDIO_IO_HANDLE_NONE) {
+ ssize_t index = mInputs.indexOfKey(*input);
+ if (index < 0) {
+ ALOGW("getInputForAttr() unknown MMAP input %d", *input);
+ status = BAD_VALUE;
+ goto error;
+ }
+ sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(index);
+ sp<AudioSession> audioSession = inputDesc->getAudioSession(session);
+ if (audioSession == 0) {
+ ALOGW("getInputForAttr() unknown session %d on input %d", session, *input);
+ status = BAD_VALUE;
+ goto error;
+ }
+ // For MMAP mode, the first call to getInputForAttr() is made on behalf of audioflinger.
+ // The second call is for the first active client and sets the UID. Any further call
+ // corresponds to a new client and is only permitted from the same UId.
+ if (audioSession->openCount() == 1) {
+ audioSession->setUid(uid);
+ } else if (audioSession->uid() != uid) {
+ ALOGW("getInputForAttr() bad uid %d for session %d uid %d",
+ uid, session, audioSession->uid());
+ status = INVALID_OPERATION;
+ goto error;
+ }
+ audioSession->changeOpenCount(1);
+ *inputType = API_INPUT_LEGACY;
+ if (*portId == AUDIO_PORT_HANDLE_NONE) {
+ *portId = AudioPort::getNextUniqueId();
+ }
+ inputDevices = mAvailableInputDevices.getDevicesFromType(inputDesc->mDevice);
+ *selectedDeviceId = inputDevices.size() > 0 ? inputDevices.itemAt(0)->getId()
+ : AUDIO_PORT_HANDLE_NONE;
+ ALOGI("%s reusing MMAP input %d for session %d", __FUNCTION__, *input, session);
+
+ return NO_ERROR;
+ }
+
+ *input = AUDIO_IO_HANDLE_NONE;
+ *inputType = API_INPUT_INVALID;
+
+ if (inputSource == AUDIO_SOURCE_DEFAULT) {
+ inputSource = AUDIO_SOURCE_MIC;
+ }
+ halInputSource = inputSource;
+
+ // TODO: check for existing client for this port ID
+ if (*portId == AUDIO_PORT_HANDLE_NONE) {
+ *portId = AudioPort::getNextUniqueId();
+ }
+
+ audio_devices_t device;
+
if (inputSource == AUDIO_SOURCE_REMOTE_SUBMIX &&
strncmp(attr->tags, "addr=", strlen("addr=")) == 0) {
- status_t ret = mPolicyMixes.getInputMixForAttr(*attr, &policyMix);
- if (ret != NO_ERROR) {
- return ret;
+ status = mPolicyMixes.getInputMixForAttr(*attr, &policyMix);
+ if (status != NO_ERROR) {
+ goto error;
}
*inputType = API_INPUT_MIX_EXT_POLICY_REROUTE;
device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
@@ -1581,7 +1588,8 @@
device = getDeviceAndMixForInputSource(inputSource, &policyMix);
if (device == AUDIO_DEVICE_NONE) {
ALOGW("getInputForAttr() could not find device for source %d", inputSource);
- return BAD_VALUE;
+ status = BAD_VALUE;
+ goto error;
}
if (policyMix != NULL) {
address = policyMix->mDeviceAddress;
@@ -1610,11 +1618,11 @@
config->sample_rate, config->format, config->channel_mask, flags,
policyMix);
if (*input == AUDIO_IO_HANDLE_NONE) {
- mInputRoutes.removeRoute(session);
- return INVALID_OPERATION;
+ status = INVALID_OPERATION;
+ goto error;
}
- DeviceVector inputDevices = mAvailableInputDevices.getDevicesFromType(device);
+ inputDevices = mAvailableInputDevices.getDevicesFromType(device);
*selectedDeviceId = inputDevices.size() > 0 ? inputDevices.itemAt(0)->getId()
: AUDIO_PORT_HANDLE_NONE;
@@ -1622,6 +1630,10 @@
*input, *inputType, *selectedDeviceId);
return NO_ERROR;
+
+error:
+ mInputRoutes.removeRoute(session);
+ return status;
}
@@ -4926,12 +4938,13 @@
// scan the whole RouteMap, for each entry, convert the stream type to a strategy
// (getStrategy(stream)).
// if the strategy from the stream type in the RouteMap is the same as the argument above,
- // and activity count is non-zero
- // the device = the device from the descriptor in the RouteMap, and exit.
+ // and activity count is non-zero and the device in the route descriptor is available
+ // then select this device.
for (size_t routeIndex = 0; routeIndex < mOutputRoutes.size(); routeIndex++) {
sp<SessionRoute> route = mOutputRoutes.valueAt(routeIndex);
routing_strategy routeStrategy = getStrategy(route->mStreamType);
- if ((routeStrategy == strategy) && route->isActive()) {
+ if ((routeStrategy == strategy) && route->isActive() &&
+ (mAvailableOutputDevices.indexOf(route->mDeviceDescriptor) >= 0)) {
return route->mDeviceDescriptor->type();
}
}
@@ -5326,9 +5339,15 @@
audio_devices_t AudioPolicyManager::getDeviceForInputSource(audio_source_t inputSource)
{
+ // Routing
+ // Scan the whole RouteMap to see if we have an explicit route:
+ // if the input source in the RouteMap is the same as the argument above,
+ // and activity count is non-zero and the device in the route descriptor is available
+ // then select this device.
for (size_t routeIndex = 0; routeIndex < mInputRoutes.size(); routeIndex++) {
sp<SessionRoute> route = mInputRoutes.valueAt(routeIndex);
- if (inputSource == route->mSource && route->isActive()) {
+ if ((inputSource == route->mSource) && route->isActive() &&
+ (mAvailableInputDevices.indexOf(route->mDeviceDescriptor) >= 0)) {
return route->mDeviceDescriptor->type();
}
}
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 1d4386c..b7bce55 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -694,6 +694,7 @@
audio_io_handle_t *ioHandle,
audio_devices_t *device)
{
+ Mutex::Autolock _l(mLock);
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
@@ -703,6 +704,7 @@
status_t AudioPolicyService::releaseSoundTriggerSession(audio_session_t session)
{
+ Mutex::Autolock _l(mLock);
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index f1cdea3..7ec3ccb 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -77,7 +77,8 @@
android.hardware.camera.common@1.0 \
android.hardware.camera.provider@2.4 \
android.hardware.camera.device@1.0 \
- android.hardware.camera.device@3.2
+ android.hardware.camera.device@3.2 \
+ android.hardware.camera.device@3.3
LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := libbinder libcamera_client libfmq
diff --git a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
index b6f443a..73dca73 100644
--- a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
@@ -324,7 +324,7 @@
streamInfo.width != (uint32_t)params.videoWidth ||
streamInfo.height != (uint32_t)params.videoHeight ||
!streamInfo.matchFormat((uint32_t)params.videoFormat) ||
- streamInfo.dataSpace != params.videoDataSpace) {
+ !streamInfo.matchDataSpace(params.videoDataSpace)) {
*needsUpdate = true;
return res;
}
@@ -356,7 +356,7 @@
if (streamInfo.width != (uint32_t)params.videoWidth ||
streamInfo.height != (uint32_t)params.videoHeight ||
!streamInfo.matchFormat((uint32_t)params.videoFormat) ||
- streamInfo.dataSpace != params.videoDataSpace) {
+ !streamInfo.matchDataSpace(params.videoDataSpace)) {
// TODO: Should wait to be sure previous recording has finished
res = device->deleteStream(mRecordingStreamId);
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index fe4c8d7..3919bfa 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -145,23 +145,42 @@
struct StreamInfo {
uint32_t width;
uint32_t height;
+
uint32_t format;
bool formatOverridden;
uint32_t originalFormat;
+
android_dataspace dataSpace;
+ bool dataSpaceOverridden;
+ android_dataspace originalDataSpace;
+
StreamInfo() : width(0), height(0), format(0), formatOverridden(false), originalFormat(0),
- dataSpace(HAL_DATASPACE_UNKNOWN) {}
+ dataSpace(HAL_DATASPACE_UNKNOWN), dataSpaceOverridden(false),
+ originalDataSpace(HAL_DATASPACE_UNKNOWN) {}
/**
* Check whether the format matches the current or the original one in case
* it got overridden.
*/
- bool matchFormat(uint32_t clientFormat) {
+ bool matchFormat(uint32_t clientFormat) const {
if ((formatOverridden && (originalFormat == clientFormat)) ||
(format == clientFormat)) {
return true;
}
return false;
}
+
+ /**
+ * Check whether the dataspace matches the current or the original one in case
+ * it got overridden.
+ */
+ bool matchDataSpace(android_dataspace clientDataSpace) const {
+ if ((dataSpaceOverridden && (originalDataSpace == clientDataSpace)) ||
+ (dataSpace == clientDataSpace)) {
+ return true;
+ }
+ return false;
+ }
+
};
/**
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
index 991b50f..f539ac1 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
@@ -97,11 +97,13 @@
ALOGE("%s: CameraHeapMemory has FD %d (expect >= 0)", __FUNCTION__, memPoolId);
return 0;
}
+ std::lock_guard<std::mutex> lock(mHidlMemPoolMapLock);
mHidlMemPoolMap.insert(std::make_pair(memPoolId, mem));
return memPoolId;
}
hardware::Return<void> CameraHardwareInterface::unregisterMemory(uint32_t memId) {
+ std::lock_guard<std::mutex> lock(mHidlMemPoolMapLock);
if (mHidlMemPoolMap.count(memId) == 0) {
ALOGE("%s: memory pool ID %d not found", __FUNCTION__, memId);
return hardware::Void();
@@ -115,6 +117,7 @@
hardware::Return<void> CameraHardwareInterface::dataCallback(
DataCallbackMsg msgType, uint32_t data, uint32_t bufferIndex,
const hardware::camera::device::V1_0::CameraFrameMetadata& metadata) {
+ std::lock_guard<std::mutex> lock(mHidlMemPoolMapLock);
if (mHidlMemPoolMap.count(data) == 0) {
ALOGE("%s: memory pool ID %d not found", __FUNCTION__, data);
return hardware::Void();
@@ -129,6 +132,7 @@
hardware::Return<void> CameraHardwareInterface::dataCallbackTimestamp(
DataCallbackMsg msgType, uint32_t data,
uint32_t bufferIndex, int64_t timestamp) {
+ std::lock_guard<std::mutex> lock(mHidlMemPoolMapLock);
if (mHidlMemPoolMap.count(data) == 0) {
ALOGE("%s: memory pool ID %d not found", __FUNCTION__, data);
return hardware::Void();
@@ -140,6 +144,7 @@
hardware::Return<void> CameraHardwareInterface::handleCallbackTimestamp(
DataCallbackMsg msgType, const hidl_handle& frameData, uint32_t data,
uint32_t bufferIndex, int64_t timestamp) {
+ std::lock_guard<std::mutex> lock(mHidlMemPoolMapLock);
if (mHidlMemPoolMap.count(data) == 0) {
ALOGE("%s: memory pool ID %d not found", __FUNCTION__, data);
return hardware::Void();
@@ -158,6 +163,7 @@
std::vector<android::HandleTimestampMessage> msgs;
msgs.reserve(messages.size());
+ std::lock_guard<std::mutex> lock(mHidlMemPoolMapLock);
for (const auto& hidl_msg : messages) {
if (mHidlMemPoolMap.count(hidl_msg.data) == 0) {
ALOGE("%s: memory pool ID %d not found", __FUNCTION__, hidl_msg.data);
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.h b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
index 6a1b4fb..e519b04 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
@@ -479,6 +479,7 @@
uint64_t mNextBufferId = 1;
static const uint64_t BUFFER_ID_NO_BUFFER = 0;
+ std::mutex mHidlMemPoolMapLock; // protecting mHidlMemPoolMap
std::unordered_map<int, camera_memory_t*> mHidlMemPoolMap;
};
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 669f763..ced1d3a 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -154,6 +154,15 @@
resultQueueRet.description().c_str());
return DEAD_OBJECT;
}
+ IF_ALOGV() {
+ session->interfaceChain([](
+ ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
+ ALOGV("Session interface chain:");
+ for (auto iface : interfaceChain) {
+ ALOGV(" %s", iface.c_str());
+ }
+ });
+ }
mInterface = new HalInterface(session, queue);
std::string providerType;
@@ -460,6 +469,11 @@
return static_cast<uint32_t>(pixelFormat);
}
+android_dataspace Camera3Device::mapToFrameworkDataspace(
+ DataspaceFlags dataSpace) {
+ return static_cast<android_dataspace>(dataSpace);
+}
+
uint64_t Camera3Device::mapConsumerToFrameworkUsage(
BufferUsageFlags usage) {
return usage;
@@ -1382,6 +1396,8 @@
streamInfo->dataSpace = mOutputStreams[idx]->getDataSpace();
streamInfo->formatOverridden = mOutputStreams[idx]->isFormatOverridden();
streamInfo->originalFormat = mOutputStreams[idx]->getOriginalFormat();
+ streamInfo->dataSpaceOverridden = mOutputStreams[idx]->isDataSpaceOverridden();
+ streamInfo->originalDataSpace = mOutputStreams[idx]->getOriginalDataSpace();
return OK;
}
@@ -3196,17 +3212,51 @@
// Invoke configureStreams
- HalStreamConfiguration finalConfiguration;
+ device::V3_3::HalStreamConfiguration finalConfiguration;
common::V1_0::Status status;
- auto err = mHidlSession->configureStreams(requestedConfiguration,
+
+ // See if we have v3.3 HAL
+ sp<device::V3_3::ICameraDeviceSession> hidlSession_3_3;
+ auto castResult = device::V3_3::ICameraDeviceSession::castFrom(mHidlSession);
+ if (castResult.isOk()) {
+ hidlSession_3_3 = castResult;
+ } else {
+ ALOGE("%s: Transaction error when casting ICameraDeviceSession: %s", __FUNCTION__,
+ castResult.description().c_str());
+ }
+ if (hidlSession_3_3 != nullptr) {
+ // We do; use v3.3 for the call
+ ALOGV("%s: v3.3 device found", __FUNCTION__);
+ auto err = hidlSession_3_3->configureStreams_3_3(requestedConfiguration,
[&status, &finalConfiguration]
- (common::V1_0::Status s, const HalStreamConfiguration& halConfiguration) {
+ (common::V1_0::Status s, const device::V3_3::HalStreamConfiguration& halConfiguration) {
finalConfiguration = halConfiguration;
status = s;
});
- if (!err.isOk()) {
- ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
- return DEAD_OBJECT;
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ return DEAD_OBJECT;
+ }
+ } else {
+ // We don't; use v3.2 call and construct a v3.3 HalStreamConfiguration
+ ALOGV("%s: v3.2 device found", __FUNCTION__);
+ HalStreamConfiguration finalConfiguration_3_2;
+ auto err = mHidlSession->configureStreams(requestedConfiguration,
+ [&status, &finalConfiguration_3_2]
+ (common::V1_0::Status s, const HalStreamConfiguration& halConfiguration) {
+ finalConfiguration_3_2 = halConfiguration;
+ status = s;
+ });
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ return DEAD_OBJECT;
+ }
+ finalConfiguration.streams.resize(finalConfiguration_3_2.streams.size());
+ for (size_t i = 0; i < finalConfiguration_3_2.streams.size(); i++) {
+ finalConfiguration.streams[i].v3_2 = finalConfiguration_3_2.streams[i];
+ finalConfiguration.streams[i].overrideDataSpace =
+ requestedConfiguration.streams[i].dataSpace;
+ }
}
if (status != common::V1_0::Status::OK ) {
@@ -3223,7 +3273,7 @@
size_t realIdx = i;
bool found = false;
for (size_t idx = 0; idx < finalConfiguration.streams.size(); idx++) {
- if (finalConfiguration.streams[realIdx].id == streamId) {
+ if (finalConfiguration.streams[realIdx].v3_2.id == streamId) {
found = true;
break;
}
@@ -3234,42 +3284,51 @@
__FUNCTION__, streamId);
return INVALID_OPERATION;
}
- HalStream &src = finalConfiguration.streams[realIdx];
+ device::V3_3::HalStream &src = finalConfiguration.streams[realIdx];
Camera3Stream* dstStream = Camera3Stream::cast(dst);
dstStream->setFormatOverride(false);
- int overrideFormat = mapToFrameworkFormat(src.overrideFormat);
+ dstStream->setDataSpaceOverride(false);
+ int overrideFormat = mapToFrameworkFormat(src.v3_2.overrideFormat);
+ android_dataspace overrideDataSpace = mapToFrameworkDataspace(src.overrideDataSpace);
+
if (dst->format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
if (dst->format != overrideFormat) {
ALOGE("%s: Stream %d: Format override not allowed for format 0x%x", __FUNCTION__,
streamId, dst->format);
}
+ if (dst->data_space != overrideDataSpace) {
+ ALOGE("%s: Stream %d: DataSpace override not allowed for format 0x%x", __FUNCTION__,
+ streamId, dst->format);
+ }
} else {
dstStream->setFormatOverride((dst->format != overrideFormat) ? true : false);
- dstStream->setOriginalFormat(dst->format);
+ dstStream->setDataSpaceOverride((dst->data_space != overrideDataSpace) ? true : false);
+
// Override allowed with IMPLEMENTATION_DEFINED
dst->format = overrideFormat;
+ dst->data_space = overrideDataSpace;
}
if (dst->stream_type == CAMERA3_STREAM_INPUT) {
- if (src.producerUsage != 0) {
+ if (src.v3_2.producerUsage != 0) {
ALOGE("%s: Stream %d: INPUT streams must have 0 for producer usage",
__FUNCTION__, streamId);
return INVALID_OPERATION;
}
- Camera3Stream::cast(dst)->setUsage(
- mapConsumerToFrameworkUsage(src.consumerUsage));
+ dstStream->setUsage(
+ mapConsumerToFrameworkUsage(src.v3_2.consumerUsage));
} else {
// OUTPUT
- if (src.consumerUsage != 0) {
+ if (src.v3_2.consumerUsage != 0) {
ALOGE("%s: Stream %d: OUTPUT streams must have 0 for consumer usage",
__FUNCTION__, streamId);
return INVALID_OPERATION;
}
- Camera3Stream::cast(dst)->setUsage(
- mapProducerToFrameworkUsage(src.producerUsage));
+ dstStream->setUsage(
+ mapProducerToFrameworkUsage(src.v3_2.producerUsage));
}
- dst->max_buffers = src.maxBuffers;
+ dst->max_buffers = src.v3_2.maxBuffers;
}
return res;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 298a3d8..fbbbd08 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -30,6 +30,7 @@
#include <android/hardware/camera/device/3.2/ICameraDevice.h>
#include <android/hardware/camera/device/3.2/ICameraDeviceSession.h>
+#include <android/hardware/camera/device/3.3/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.2/ICameraDeviceCallback.h>
#include <fmq/MessageQueue.h>
#include <hardware/camera3.h>
@@ -595,6 +596,8 @@
/*out*/ hardware::camera::device::V3_2::StreamConfigurationMode *mode);
static camera3_buffer_status_t mapHidlBufferStatus(hardware::camera::device::V3_2::BufferStatus status);
static int mapToFrameworkFormat(hardware::graphics::common::V1_0::PixelFormat pixelFormat);
+ static android_dataspace mapToFrameworkDataspace(
+ hardware::camera::device::V3_2::DataspaceFlags);
static uint64_t mapConsumerToFrameworkUsage(
hardware::camera::device::V3_2::BufferUsageFlags usage);
static uint64_t mapProducerToFrameworkUsage(
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index c186208..fbe8f4f 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -116,18 +116,28 @@
void Camera3Stream::setFormatOverride(bool formatOverridden) {
mFormatOverridden = formatOverridden;
+ if (formatOverridden) mOriginalFormat = camera3_stream::format;
}
-bool Camera3Stream::isFormatOverridden() {
+bool Camera3Stream::isFormatOverridden() const {
return mFormatOverridden;
}
-void Camera3Stream::setOriginalFormat(int originalFormat) {
- mOriginalFormat = originalFormat;
+int Camera3Stream::getOriginalFormat() const {
+ return mOriginalFormat;
}
-int Camera3Stream::getOriginalFormat() {
- return mOriginalFormat;
+void Camera3Stream::setDataSpaceOverride(bool dataSpaceOverridden) {
+ mDataSpaceOverridden = dataSpaceOverridden;
+ if (dataSpaceOverridden) mOriginalDataSpace = camera3_stream::data_space;
+}
+
+bool Camera3Stream::isDataSpaceOverridden() const {
+ return mDataSpaceOverridden;
+}
+
+android_dataspace Camera3Stream::getOriginalDataSpace() const {
+ return mOriginalDataSpace;
}
camera3_stream* Camera3Stream::startConfiguration() {
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index 1843ae8..6e7912e 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -147,9 +147,11 @@
uint64_t getUsage() const;
void setUsage(uint64_t usage);
void setFormatOverride(bool formatOverriden);
- bool isFormatOverridden();
- void setOriginalFormat(int originalFormat);
- int getOriginalFormat();
+ bool isFormatOverridden() const;
+ int getOriginalFormat() const;
+ void setDataSpaceOverride(bool dataSpaceOverriden);
+ bool isDataSpaceOverridden() const;
+ android_dataspace getOriginalDataSpace() const;
camera3_stream* asHalStream() override {
return this;
@@ -522,6 +524,11 @@
//Keep track of original format in case it gets overridden
bool mFormatOverridden;
int mOriginalFormat;
+
+ //Keep track of original dataSpace in case it gets overridden
+ bool mDataSpaceOverridden;
+ android_dataspace mOriginalDataSpace;
+
}; // class Camera3Stream
}; // namespace camera3
diff --git a/services/camera/libcameraservice/device3/Camera3StreamInterface.h b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
index 63456c4..cc9bf8e 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
@@ -72,9 +72,11 @@
virtual int getFormat() const = 0;
virtual android_dataspace getDataSpace() const = 0;
virtual void setFormatOverride(bool formatOverriden) = 0;
- virtual bool isFormatOverridden() = 0;
- virtual void setOriginalFormat(int originalFormat) = 0;
- virtual int getOriginalFormat() = 0;
+ virtual bool isFormatOverridden() const = 0;
+ virtual int getOriginalFormat() const = 0;
+ virtual void setDataSpaceOverride(bool dataSpaceOverriden) = 0;
+ virtual bool isDataSpaceOverridden() const = 0;
+ virtual android_dataspace getOriginalDataSpace() const = 0;
/**
* Get a HAL3 handle for the stream, without starting stream configuration.
diff --git a/services/mediaanalytics/MediaAnalyticsService.cpp b/services/mediaanalytics/MediaAnalyticsService.cpp
index 763b937..c7f9270 100644
--- a/services/mediaanalytics/MediaAnalyticsService.cpp
+++ b/services/mediaanalytics/MediaAnalyticsService.cpp
@@ -259,14 +259,15 @@
break;
}
+
// Overwrite package name and version if the caller was untrusted.
if (!isTrusted) {
- item->setPkgName(getPkgName(item->getUid(), true));
- item->setPkgVersionCode(0);
+ setPkgInfo(item, item->getUid(), true, true);
} else if (item->getPkgName().empty()) {
- // Only overwrite the package name if it was empty. Trust whatever
- // version code was provided by the trusted caller.
- item->setPkgName(getPkgName(uid, true));
+ // empty, so fill out both parts
+ setPkgInfo(item, item->getUid(), true, true);
+ } else {
+ // trusted, provided a package, do nothing
}
ALOGV("given uid %d; sanitized uid: %d sanitized pkg: %s "
@@ -802,85 +803,155 @@
}
-// mapping uids to package names
+// how long we hold package info before we re-fetch it
+#define PKG_EXPIRATION_NS (30*60*1000000000ll) // 30 minutes, in nsecs
// give me the package name, perhaps going to find it
-AString MediaAnalyticsService::getPkgName(uid_t uid, bool addIfMissing) {
+void MediaAnalyticsService::setPkgInfo(MediaAnalyticsItem *item, uid_t uid, bool setName, bool setVersion) {
+ ALOGV("asking for packagename to go with uid=%d", uid);
+
+ if (!setName && !setVersion) {
+ // setting nothing? strange
+ return;
+ }
+
+ nsecs_t now = systemTime(SYSTEM_TIME_REALTIME);
+ struct UidToPkgMap mapping;
+ mapping.uid = (-1);
+
ssize_t i = mPkgMappings.indexOfKey(uid);
if (i >= 0) {
- AString pkg = mPkgMappings.valueAt(i);
- ALOGV("returning pkg '%s' for uid %d", pkg.c_str(), uid);
- return pkg;
- }
-
- AString pkg;
-
- if (addIfMissing == false) {
- return pkg;
- }
-
- struct passwd *pw = getpwuid(uid);
- if (pw) {
- pkg = pw->pw_name;
- } else {
- pkg = "-";
- }
-
- // find the proper value
-
- sp<IBinder> binder = NULL;
- sp<IServiceManager> sm = defaultServiceManager();
- if (sm == NULL) {
- ALOGE("defaultServiceManager failed");
- } else {
- binder = sm->getService(String16("package_native"));
- if (binder == NULL) {
- ALOGE("getService package_native failed");
+ mapping = mPkgMappings.valueAt(i);
+ ALOGV("Expiration? uid %d expiration %" PRId64 " now %" PRId64,
+ uid, mapping.expiration, now);
+ if (mapping.expiration < now) {
+ // purge our current entry and re-query
+ ALOGV("entry for uid %d expired, now= %" PRId64 "", uid, now);
+ mPkgMappings.removeItemsAt(i, 1);
+ // could cheat and use a goto back to the top of the routine.
+ // a good compiler should recognize the local tail recursion...
+ return setPkgInfo(item, uid, setName, setVersion);
}
- }
+ } else {
+ AString pkg;
+ std::string installer = "";
+ int32_t versionCode = 0;
- if (binder != NULL) {
- sp<IPackageManagerNative> package_mgr = interface_cast<IPackageManagerNative>(binder);
+ struct passwd *pw = getpwuid(uid);
+ if (pw) {
+ pkg = pw->pw_name;
+ }
- std::vector<int> uids;
- std::vector<std::string> names;
+ // find the proper value -- should we cache this binder??
- uids.push_back(uid);
-
- binder::Status status = package_mgr->getNamesForUids(uids, &names);
- if (!status.isOk()) {
- ALOGE("package_native::getNamesForUids failed: %s",
- status.exceptionMessage().c_str());
+ sp<IBinder> binder = NULL;
+ sp<IServiceManager> sm = defaultServiceManager();
+ if (sm == NULL) {
+ ALOGE("defaultServiceManager failed");
} else {
- if (!names[0].empty()) {
- pkg = names[0].c_str();
+ binder = sm->getService(String16("package_native"));
+ if (binder == NULL) {
+ ALOGE("getService package_native failed");
+ }
+ }
+
+ if (binder != NULL) {
+ sp<IPackageManagerNative> package_mgr = interface_cast<IPackageManagerNative>(binder);
+ binder::Status status;
+
+ std::vector<int> uids;
+ std::vector<std::string> names;
+
+ uids.push_back(uid);
+
+ status = package_mgr->getNamesForUids(uids, &names);
+ if (!status.isOk()) {
+ ALOGE("package_native::getNamesForUids failed: %s",
+ status.exceptionMessage().c_str());
+ } else {
+ if (!names[0].empty()) {
+ pkg = names[0].c_str();
+ }
+ }
+
+ // strip any leading "shared:" strings that came back
+ if (pkg.startsWith("shared:")) {
+ pkg.erase(0, 7);
+ }
+
+ // determine how pkg was installed and the versionCode
+ //
+ if (pkg.empty()) {
+ // no name for us to manage
+ } else if (strchr(pkg.c_str(), '.') == NULL) {
+ // not of form 'com.whatever...'; assume internal and ok
+ } else if (strncmp(pkg.c_str(), "android.", 8) == 0) {
+ // android.* packages are assumed fine
+ } else {
+ String16 pkgName16(pkg.c_str());
+ status = package_mgr->getInstallerForPackage(pkgName16, &installer);
+ if (!status.isOk()) {
+ ALOGE("package_native::getInstallerForPackage failed: %s",
+ status.exceptionMessage().c_str());
+ }
+
+ // skip if we didn't get an installer
+ if (status.isOk()) {
+ status = package_mgr->getVersionCodeForPackage(pkgName16, &versionCode);
+ if (!status.isOk()) {
+ ALOGE("package_native::getVersionCodeForPackage failed: %s",
+ status.exceptionMessage().c_str());
+ }
+ }
+
+
+ ALOGV("package '%s' installed by '%s' versioncode %d / %08x",
+ pkg.c_str(), installer.c_str(), versionCode, versionCode);
+
+ if (strncmp(installer.c_str(), "com.android.", 12) == 0) {
+ // from play store, we keep info
+ } else if (strncmp(installer.c_str(), "com.google.", 11) == 0) {
+ // some google source, we keep info
+ } else if (strcmp(installer.c_str(), "preload") == 0) {
+ // preloads, we keep the info
+ } else if (installer.c_str()[0] == '\0') {
+ // sideload (no installer); do not report
+ pkg = "";
+ versionCode = 0;
+ } else {
+ // unknown installer; do not report
+ pkg = "";
+ versionCode = 0;
+ }
+ }
+ }
+
+ // add it to the map, to save a subsequent lookup
+ if (!pkg.empty()) {
+ Mutex::Autolock _l(mLock_mappings);
+ ALOGV("Adding uid %d pkg '%s'", uid, pkg.c_str());
+ ssize_t i = mPkgMappings.indexOfKey(uid);
+ if (i < 0) {
+ mapping.uid = uid;
+ mapping.pkg = pkg;
+ mapping.installer = installer.c_str();
+ mapping.versionCode = versionCode;
+ mapping.expiration = now + PKG_EXPIRATION_NS;
+ ALOGV("expiration for uid %d set to %" PRId64 "", uid, mapping.expiration);
+
+ mPkgMappings.add(uid, mapping);
}
}
}
- // XXX determine whether package was side-loaded or from playstore.
- // for privacy, we only list apps loaded from playstore.
-
- // Sanitize the package name for ":"
- // as an example, we get "shared:android.uid.systemui"
- // replace : with something benign (I'm going to use !)
- if (!pkg.empty()) {
- int n = pkg.size();
- char *p = (char *) pkg.c_str();
- for (int i = 0 ; i < n; i++) {
- if (p[i] == ':') {
- p[i] = '!';
- }
+ if (mapping.uid != (uid_t)(-1)) {
+ if (setName) {
+ item->setPkgName(mapping.pkg);
+ }
+ if (setVersion) {
+ item->setPkgVersionCode(mapping.versionCode);
}
}
-
- // add it to the map, to save a subsequent lookup
- if (!pkg.empty()) {
- ALOGV("Adding uid %d pkg '%s'", uid, pkg.c_str());
- mPkgMappings.add(uid, pkg);
- }
-
- return pkg;
}
} // namespace android
diff --git a/services/mediaanalytics/MediaAnalyticsService.h b/services/mediaanalytics/MediaAnalyticsService.h
index 4fe2fb2..52e4631 100644
--- a/services/mediaanalytics/MediaAnalyticsService.h
+++ b/services/mediaanalytics/MediaAnalyticsService.h
@@ -62,6 +62,7 @@
// partitioned a bit so we don't over serialize
mutable Mutex mLock;
mutable Mutex mLock_ids;
+ mutable Mutex mLock_mappings;
// limit how many records we'll retain
// by count (in each queue (open, finalized))
@@ -135,10 +136,13 @@
struct UidToPkgMap {
uid_t uid;
AString pkg;
+ AString installer;
+ int32_t versionCode;
+ nsecs_t expiration;
};
- KeyedVector<uid_t,AString> mPkgMappings;
- AString getPkgName(uid_t uid, bool addIfMissing);
+ KeyedVector<uid_t,struct UidToPkgMap> mPkgMappings;
+ void setPkgInfo(MediaAnalyticsItem *item, uid_t uid, bool setName, bool setVersion);
};
diff --git a/services/mediaanalytics/MetricsSummarizerCodec.cpp b/services/mediaanalytics/MetricsSummarizerCodec.cpp
index 8c74782..921dd63 100644
--- a/services/mediaanalytics/MetricsSummarizerCodec.cpp
+++ b/services/mediaanalytics/MetricsSummarizerCodec.cpp
@@ -17,6 +17,8 @@
#define LOG_TAG "MetricsSummarizerCodec"
#include <utils/Log.h>
+#include <stdint.h>
+#include <inttypes.h>
#include <utils/threads.h>
#include <utils/Errors.h>
@@ -34,10 +36,30 @@
namespace android {
+static const char *codec_ignorable[] = {
+ "android.media.mediacodec.bytesin",
+ 0
+};
+
MetricsSummarizerCodec::MetricsSummarizerCodec(const char *key)
: MetricsSummarizer(key)
{
ALOGV("MetricsSummarizerCodec::MetricsSummarizerCodec");
+ setIgnorables(codec_ignorable);
+
+}
+
+void MetricsSummarizerCodec::mergeRecord(MediaAnalyticsItem &summation, MediaAnalyticsItem &item) {
+
+ ALOGV("MetricsSummarizerCodec::mergeRecord()");
+
+ int64_t bytesin = 0;
+ if (item.getInt64("android.media.mediacodec.bytesin", &bytesin)) {
+ ALOGV("found bytesin of %" PRId64, bytesin);
+ }
+ if (bytesin >= 0) {
+ minMaxVar64(summation,"android.media.mediacodec.bytesin", bytesin);
+ }
}
diff --git a/services/mediaanalytics/MetricsSummarizerCodec.h b/services/mediaanalytics/MetricsSummarizerCodec.h
index c01196f..872a16c 100644
--- a/services/mediaanalytics/MetricsSummarizerCodec.h
+++ b/services/mediaanalytics/MetricsSummarizerCodec.h
@@ -38,6 +38,8 @@
MetricsSummarizerCodec(const char *key);
virtual ~MetricsSummarizerCodec() {};
+ virtual void mergeRecord(MediaAnalyticsItem &have, MediaAnalyticsItem &incoming);
+
};
// ----------------------------------------------------------------------------
diff --git a/services/oboeservice/AAudioEndpointManager.cpp b/services/oboeservice/AAudioEndpointManager.cpp
index f41219e..f996f74 100644
--- a/services/oboeservice/AAudioEndpointManager.cpp
+++ b/services/oboeservice/AAudioEndpointManager.cpp
@@ -102,7 +102,7 @@
}
}
- ALOGD("AAudioEndpointManager.findExclusiveEndpoint_l(), found %p for device = %d",
+ ALOGV("AAudioEndpointManager.findExclusiveEndpoint_l(), found %p for device = %d",
endpoint.get(), configuration.getDeviceId());
return endpoint;
}
@@ -118,7 +118,7 @@
}
}
- ALOGD("AAudioEndpointManager.findSharedEndpoint_l(), found %p for device = %d",
+ ALOGV("AAudioEndpointManager.findSharedEndpoint_l(), found %p for device = %d",
endpoint.get(), configuration.getDeviceId());
return endpoint;
}
@@ -238,8 +238,6 @@
std::lock_guard<std::mutex> lock(mExclusiveLock);
int32_t newRefCount = serviceEndpoint->getOpenCount() - 1;
serviceEndpoint->setOpenCount(newRefCount);
- ALOGD("AAudioEndpointManager::closeExclusiveEndpoint(%p) newRefCount = %d",
- serviceEndpoint.get(), newRefCount);
// If no longer in use then close and delete it.
if (newRefCount <= 0) {
@@ -262,8 +260,6 @@
std::lock_guard<std::mutex> lock(mSharedLock);
int32_t newRefCount = serviceEndpoint->getOpenCount() - 1;
serviceEndpoint->setOpenCount(newRefCount);
- ALOGD("AAudioEndpointManager::closeSharedEndpoint(%p) newRefCount = %d",
- serviceEndpoint.get(), newRefCount);
// If no longer in use then close and delete it.
if (newRefCount <= 0) {
diff --git a/services/oboeservice/AAudioService.cpp b/services/oboeservice/AAudioService.cpp
index 5b34895..5a3488d 100644
--- a/services/oboeservice/AAudioService.cpp
+++ b/services/oboeservice/AAudioService.cpp
@@ -18,9 +18,9 @@
//#define LOG_NDEBUG 0
#include <utils/Log.h>
+#include <iomanip>
+#include <iostream>
#include <sstream>
-//#include <time.h>
-//#include <pthread.h>
#include <aaudio/AAudio.h>
#include <mediautils/SchedulingPolicyService.h>
@@ -35,18 +35,13 @@
#include "AAudioServiceStreamMMAP.h"
#include "binding/IAAudioService.h"
#include "ServiceUtilities.h"
-#include "utility/HandleTracker.h"
using namespace android;
using namespace aaudio;
#define MAX_STREAMS_PER_PROCESS 8
-typedef enum
-{
- AAUDIO_HANDLE_TYPE_STREAM
-} aaudio_service_handle_type_t;
-static_assert(AAUDIO_HANDLE_TYPE_STREAM < HANDLE_TRACKER_MAX_TYPES, "Too many handle types.");
+using android::AAudioService;
android::AAudioService::AAudioService()
: BnAAudioService() {
@@ -70,7 +65,8 @@
result = ss.str();
ALOGW("%s", result.c_str());
} else {
- result = mHandleTracker.dump()
+ result = "------------ AAudio Service ------------\n"
+ + mStreamTracker.dump()
+ AAudioClientTracker::getInstance().dump()
+ AAudioEndpointManager::getInstance().dump();
}
@@ -125,7 +121,7 @@
// if SHARED requested or if EXCLUSIVE failed
if (sharingMode == AAUDIO_SHARING_MODE_SHARED
- || (serviceStream == nullptr && !sharingModeMatchRequired)) {
+ || (serviceStream.get() == nullptr && !sharingModeMatchRequired)) {
serviceStream = new AAudioServiceStreamShared(*this);
result = serviceStream->open(request);
}
@@ -136,18 +132,12 @@
result, AAudio_convertResultToText(result));
return result;
} else {
- aaudio_handle_t handle = mHandleTracker.put(AAUDIO_HANDLE_TYPE_STREAM, serviceStream.get());
- if (handle < 0) {
- ALOGE("AAudioService::openStream(): handle table full");
- serviceStream->close();
- serviceStream.clear();
- } else {
- ALOGD("AAudioService::openStream(): handle = 0x%08X", handle);
- serviceStream->setHandle(handle);
- pid_t pid = request.getProcessId();
- AAudioClientTracker::getInstance().registerClientStream(pid, serviceStream);
- configurationOutput.copyFrom(*serviceStream);
- }
+ aaudio_handle_t handle = mStreamTracker.addStreamForHandle(serviceStream.get());
+ ALOGD("AAudioService::openStream(): handle = 0x%08X", handle);
+ serviceStream->setHandle(handle);
+ pid_t pid = request.getProcessId();
+ AAudioClientTracker::getInstance().registerClientStream(pid, serviceStream);
+ configurationOutput.copyFrom(*serviceStream);
return handle;
}
}
@@ -155,30 +145,32 @@
aaudio_result_t AAudioService::closeStream(aaudio_handle_t streamHandle) {
// Check permission and ownership first.
sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
- if (serviceStream == nullptr) {
- ALOGE("AAudioService::startStream(), illegal stream handle = 0x%0x", streamHandle);
+ if (serviceStream.get() == nullptr) {
+ ALOGE("AAudioService::closeStream(0x%0x), illegal stream handle", streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
}
ALOGD("AAudioService.closeStream(0x%08X)", streamHandle);
// Remove handle from tracker so that we cannot look up the raw address any more.
- serviceStream = (AAudioServiceStreamBase *)
- mHandleTracker.remove(AAUDIO_HANDLE_TYPE_STREAM,
- streamHandle);
- if (serviceStream != nullptr) {
+ // removeStreamByHandle() uses a lock so that if there are two simultaneous closes
+ // then only one will get the pointer and do the close.
+ serviceStream = mStreamTracker.removeStreamByHandle(streamHandle);
+ if (serviceStream.get() != nullptr) {
serviceStream->close();
pid_t pid = serviceStream->getOwnerProcessId();
AAudioClientTracker::getInstance().unregisterClientStream(pid, serviceStream);
return AAUDIO_OK;
+ } else {
+ ALOGW("AAudioService::closeStream(0x%0x) being handled by another thread", streamHandle);
+ return AAUDIO_ERROR_INVALID_HANDLE;
}
- return AAUDIO_ERROR_INVALID_HANDLE;
}
-AAudioServiceStreamBase *AAudioService::convertHandleToServiceStream(
- aaudio_handle_t streamHandle) const {
- AAudioServiceStreamBase *serviceStream = (AAudioServiceStreamBase *)
- mHandleTracker.get(AAUDIO_HANDLE_TYPE_STREAM, (aaudio_handle_t)streamHandle);
- if (serviceStream != nullptr) {
+
+sp<AAudioServiceStreamBase> AAudioService::convertHandleToServiceStream(
+ aaudio_handle_t streamHandle) {
+ sp<AAudioServiceStreamBase> serviceStream = mStreamTracker.getStreamByHandle(streamHandle);
+ if (serviceStream.get() != nullptr) {
// Only allow owner or the aaudio service to access the stream.
const uid_t callingUserId = IPCThreadState::self()->getCallingUid();
const uid_t ownerUserId = serviceStream->getOwnerUserId();
@@ -198,19 +190,20 @@
aaudio_result_t AAudioService::getStreamDescription(
aaudio_handle_t streamHandle,
aaudio::AudioEndpointParcelable &parcelable) {
- AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
- if (serviceStream == nullptr) {
+ sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+ if (serviceStream.get() == nullptr) {
ALOGE("AAudioService::getStreamDescription(), illegal stream handle = 0x%0x", streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
}
+
aaudio_result_t result = serviceStream->getDescription(parcelable);
// parcelable.dump();
return result;
}
aaudio_result_t AAudioService::startStream(aaudio_handle_t streamHandle) {
- AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
- if (serviceStream == nullptr) {
+ sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+ if (serviceStream.get() == nullptr) {
ALOGE("AAudioService::startStream(), illegal stream handle = 0x%0x", streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
}
@@ -219,8 +212,8 @@
}
aaudio_result_t AAudioService::pauseStream(aaudio_handle_t streamHandle) {
- AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
- if (serviceStream == nullptr) {
+ sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+ if (serviceStream.get() == nullptr) {
ALOGE("AAudioService::pauseStream(), illegal stream handle = 0x%0x", streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
}
@@ -229,9 +222,9 @@
}
aaudio_result_t AAudioService::stopStream(aaudio_handle_t streamHandle) {
- AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
- if (serviceStream == nullptr) {
- ALOGE("AAudioService::pauseStream(), illegal stream handle = 0x%0x", streamHandle);
+ sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+ if (serviceStream.get() == nullptr) {
+ ALOGE("AAudioService::stopStream(), illegal stream handle = 0x%0x", streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
}
aaudio_result_t result = serviceStream->stop();
@@ -239,8 +232,8 @@
}
aaudio_result_t AAudioService::flushStream(aaudio_handle_t streamHandle) {
- AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
- if (serviceStream == nullptr) {
+ sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+ if (serviceStream.get() == nullptr) {
ALOGE("AAudioService::flushStream(), illegal stream handle = 0x%0x", streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
}
@@ -250,8 +243,8 @@
aaudio_result_t AAudioService::registerAudioThread(aaudio_handle_t streamHandle,
pid_t clientThreadId,
int64_t periodNanoseconds) {
- AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
- if (serviceStream == nullptr) {
+ sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+ if (serviceStream.get() == nullptr) {
ALOGE("AAudioService::registerAudioThread(), illegal stream handle = 0x%0x", streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
}
@@ -275,8 +268,8 @@
aaudio_result_t AAudioService::unregisterAudioThread(aaudio_handle_t streamHandle,
pid_t clientThreadId) {
- AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
- if (serviceStream == nullptr) {
+ sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+ if (serviceStream.get() == nullptr) {
ALOGE("AAudioService::unregisterAudioThread(), illegal stream handle = 0x%0x",
streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
@@ -292,8 +285,8 @@
aaudio_result_t AAudioService::startClient(aaudio_handle_t streamHandle,
const android::AudioClient& client,
audio_port_handle_t *clientHandle) {
- AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
- if (serviceStream == nullptr) {
+ sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+ if (serviceStream.get() == nullptr) {
ALOGE("AAudioService::startClient(), illegal stream handle = 0x%0x",
streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
@@ -303,8 +296,8 @@
aaudio_result_t AAudioService::stopClient(aaudio_handle_t streamHandle,
audio_port_handle_t clientHandle) {
- AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
- if (serviceStream == nullptr) {
+ sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+ if (serviceStream.get() == nullptr) {
ALOGE("AAudioService::stopClient(), illegal stream handle = 0x%0x",
streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
diff --git a/services/oboeservice/AAudioService.h b/services/oboeservice/AAudioService.h
index ffaf538..eef0824 100644
--- a/services/oboeservice/AAudioService.h
+++ b/services/oboeservice/AAudioService.h
@@ -24,13 +24,13 @@
#include <media/AudioClient.h>
#include <aaudio/AAudio.h>
-#include "utility/HandleTracker.h"
-#include "binding/IAAudioService.h"
-#include "binding/AAudioServiceInterface.h"
-namespace aaudio {
- class AAudioServiceStreamBase;
-};
+#include "binding/AAudioCommon.h"
+#include "binding/AAudioServiceInterface.h"
+#include "binding/IAAudioService.h"
+
+#include "AAudioServiceStreamBase.h"
+#include "AAudioStreamTracker.h"
namespace android {
@@ -51,45 +51,53 @@
virtual void registerClient(const sp<IAAudioClient>& client);
- virtual aaudio_handle_t openStream(const aaudio::AAudioStreamRequest &request,
- aaudio::AAudioStreamConfiguration &configurationOutput);
+ aaudio::aaudio_handle_t openStream(const aaudio::AAudioStreamRequest &request,
+ aaudio::AAudioStreamConfiguration &configurationOutput)
+ override;
- virtual aaudio_result_t closeStream(aaudio_handle_t streamHandle);
+ aaudio_result_t closeStream(aaudio::aaudio_handle_t streamHandle) override;
- virtual aaudio_result_t getStreamDescription(
- aaudio_handle_t streamHandle,
- aaudio::AudioEndpointParcelable &parcelable);
+ aaudio_result_t getStreamDescription(
+ aaudio::aaudio_handle_t streamHandle,
+ aaudio::AudioEndpointParcelable &parcelable) override;
- virtual aaudio_result_t startStream(aaudio_handle_t streamHandle);
+ aaudio_result_t startStream(aaudio::aaudio_handle_t streamHandle) override;
- virtual aaudio_result_t pauseStream(aaudio_handle_t streamHandle);
+ aaudio_result_t pauseStream(aaudio::aaudio_handle_t streamHandle) override;
- virtual aaudio_result_t stopStream(aaudio_handle_t streamHandle);
+ aaudio_result_t stopStream(aaudio::aaudio_handle_t streamHandle) override;
- virtual aaudio_result_t flushStream(aaudio_handle_t streamHandle);
+ aaudio_result_t flushStream(aaudio::aaudio_handle_t streamHandle) override;
- virtual aaudio_result_t registerAudioThread(aaudio_handle_t streamHandle,
+ aaudio_result_t registerAudioThread(aaudio::aaudio_handle_t streamHandle,
pid_t tid,
- int64_t periodNanoseconds) ;
+ int64_t periodNanoseconds) override;
- virtual aaudio_result_t unregisterAudioThread(aaudio_handle_t streamHandle,
- pid_t tid);
+ aaudio_result_t unregisterAudioThread(aaudio::aaudio_handle_t streamHandle,
+ pid_t tid) override;
- virtual aaudio_result_t startClient(aaudio_handle_t streamHandle,
+ aaudio_result_t startClient(aaudio::aaudio_handle_t streamHandle,
const android::AudioClient& client,
- audio_port_handle_t *clientHandle);
+ audio_port_handle_t *clientHandle) override;
- virtual aaudio_result_t stopClient(aaudio_handle_t streamHandle,
- audio_port_handle_t clientHandle);
+ aaudio_result_t stopClient(aaudio::aaudio_handle_t streamHandle,
+ audio_port_handle_t clientHandle) override;
private:
- aaudio::AAudioServiceStreamBase *convertHandleToServiceStream(aaudio_handle_t streamHandle) const;
+ /**
+ * Lookup stream and then validate access to the stream.
+ * @param streamHandle
+ * @return
+ */
+ sp<aaudio::AAudioServiceStreamBase> convertHandleToServiceStream(
+ aaudio::aaudio_handle_t streamHandle);
- HandleTracker mHandleTracker;
android::AudioClient mAudioClient;
+ aaudio::AAudioStreamTracker mStreamTracker;
+
enum constants {
DEFAULT_AUDIO_PRIORITY = 2
};
diff --git a/services/oboeservice/AAudioServiceEndpoint.cpp b/services/oboeservice/AAudioServiceEndpoint.cpp
index cba5bc8..3095bc9 100644
--- a/services/oboeservice/AAudioServiceEndpoint.cpp
+++ b/services/oboeservice/AAudioServiceEndpoint.cpp
@@ -60,7 +60,7 @@
result << " Reference Count: " << mOpenCount << "\n";
result << " Requested Device Id: " << mRequestedDeviceId << "\n";
result << " Device Id: " << getDeviceId() << "\n";
- result << " Registered Streams: " << "\n";
+ result << " Registered Streams:" << "\n";
result << AAudioServiceStreamShared::dumpHeader() << "\n";
for (const auto stream : mRegisteredStreams) {
result << stream->dump() << "\n";
diff --git a/services/oboeservice/AAudioServiceEndpointCapture.cpp b/services/oboeservice/AAudioServiceEndpointCapture.cpp
index 97558ca..c7d9b8e 100644
--- a/services/oboeservice/AAudioServiceEndpointCapture.cpp
+++ b/services/oboeservice/AAudioServiceEndpointCapture.cpp
@@ -84,30 +84,42 @@
std::lock_guard <std::mutex> lock(mLockStreams);
for (const auto clientStream : mRegisteredStreams) {
if (clientStream->isRunning()) {
- AAudioServiceStreamShared *streamShared =
+ int64_t clientFramesWritten = 0;
+ sp<AAudioServiceStreamShared> streamShared =
static_cast<AAudioServiceStreamShared *>(clientStream.get());
- FifoBuffer *fifo = streamShared->getDataFifoBuffer();
+ {
+ // Lock the AudioFifo to protect against close.
+ std::lock_guard <std::mutex> lock(streamShared->getAudioDataQueueLock());
- // Determine offset between framePosition in client's stream vs the underlying
- // MMAP stream.
- int64_t clientFramesWritten = fifo->getWriteCounter();
- // There are two indices that refer to the same frame.
- int64_t positionOffset = mmapFramesRead - clientFramesWritten;
- streamShared->setTimestampPositionOffset(positionOffset);
+ FifoBuffer *fifo = streamShared->getAudioDataFifoBuffer_l();
+ if (fifo != nullptr) {
- if (fifo->getFifoControllerBase()->getEmptyFramesAvailable() <
- getFramesPerBurst()) {
- underflowCount++;
- } else {
- fifo->write(mDistributionBuffer, getFramesPerBurst());
+ // Determine offset between framePosition in client's stream
+ // vs the underlying MMAP stream.
+ clientFramesWritten = fifo->getWriteCounter();
+ // There are two indices that refer to the same frame.
+ int64_t positionOffset = mmapFramesRead - clientFramesWritten;
+ streamShared->setTimestampPositionOffset(positionOffset);
+
+ if (fifo->getFifoControllerBase()->getEmptyFramesAvailable() <
+ getFramesPerBurst()) {
+ underflowCount++;
+ } else {
+ fifo->write(mDistributionBuffer, getFramesPerBurst());
+ }
+ clientFramesWritten = fifo->getWriteCounter();
+ }
}
- // This timestamp represents the completion of data being written into the
- // client buffer. It is sent to the client and used in the timing model
- // to decide when data will be available to read.
- Timestamp timestamp(fifo->getWriteCounter(), AudioClock::getNanoseconds());
- streamShared->markTransferTime(timestamp);
+ if (clientFramesWritten > 0) {
+ // This timestamp represents the completion of data being written into the
+ // client buffer. It is sent to the client and used in the timing model
+ // to decide when data will be available to read.
+ Timestamp timestamp(clientFramesWritten, AudioClock::getNanoseconds());
+ streamShared->markTransferTime(timestamp);
+ }
+
}
}
}
diff --git a/services/oboeservice/AAudioServiceEndpointPlay.cpp b/services/oboeservice/AAudioServiceEndpointPlay.cpp
index c42a6e2..9b1833a 100644
--- a/services/oboeservice/AAudioServiceEndpointPlay.cpp
+++ b/services/oboeservice/AAudioServiceEndpointPlay.cpp
@@ -81,32 +81,44 @@
std::lock_guard <std::mutex> lock(mLockStreams);
for (const auto clientStream : mRegisteredStreams) {
+ int64_t clientFramesRead = 0;
+
if (!clientStream->isRunning()) {
continue;
}
- AAudioServiceStreamShared *streamShared =
+ sp<AAudioServiceStreamShared> streamShared =
static_cast<AAudioServiceStreamShared *>(clientStream.get());
- FifoBuffer *fifo = streamShared->getDataFifoBuffer();
- // Determine offset between framePosition in client's stream vs the underlying
- // MMAP stream.
- int64_t clientFramesRead = fifo->getReadCounter();
- // These two indices refer to the same frame.
- int64_t positionOffset = mmapFramesWritten - clientFramesRead;
- streamShared->setTimestampPositionOffset(positionOffset);
+ {
+ // Lock the AudioFifo to protect against close.
+ std::lock_guard <std::mutex> lock(streamShared->getAudioDataQueueLock());
- float volume = 1.0; // to match legacy volume
- bool underflowed = mMixer.mix(index, fifo, volume);
+ FifoBuffer *fifo = streamShared->getAudioDataFifoBuffer_l();
+ if (fifo != nullptr) {
- // This timestamp represents the completion of data being read out of the
- // client buffer. It is sent to the client and used in the timing model
- // to decide when the client has room to write more data.
- Timestamp timestamp(fifo->getReadCounter(), AudioClock::getNanoseconds());
- streamShared->markTransferTime(timestamp);
+ // Determine offset between framePosition in client's stream
+ // vs the underlying MMAP stream.
+ clientFramesRead = fifo->getReadCounter();
+ // These two indices refer to the same frame.
+ int64_t positionOffset = mmapFramesWritten - clientFramesRead;
+ streamShared->setTimestampPositionOffset(positionOffset);
- if (underflowed) {
- streamShared->incrementXRunCount();
+ float volume = 1.0; // to match legacy volume
+ bool underflowed = mMixer.mix(index, fifo, volume);
+ if (underflowed) {
+ streamShared->incrementXRunCount();
+ }
+ clientFramesRead = fifo->getReadCounter();
+ }
+ }
+
+ if (clientFramesRead > 0) {
+ // This timestamp represents the completion of data being read out of the
+ // client buffer. It is sent to the client and used in the timing model
+ // to decide when the client has room to write more data.
+ Timestamp timestamp(clientFramesRead, AudioClock::getNanoseconds());
+ streamShared->markTransferTime(timestamp);
}
index++; // just used for labelling tracks in systrace
diff --git a/services/oboeservice/AAudioServiceEndpointShared.cpp b/services/oboeservice/AAudioServiceEndpointShared.cpp
index 18dc12f..cd40066 100644
--- a/services/oboeservice/AAudioServiceEndpointShared.cpp
+++ b/services/oboeservice/AAudioServiceEndpointShared.cpp
@@ -115,15 +115,33 @@
aaudio_result_t AAudioServiceEndpointShared::startStream(sp<AAudioServiceStreamBase> sharedStream,
audio_port_handle_t *clientHandle) {
aaudio_result_t result = AAUDIO_OK;
- if (++mRunningStreamCount == 1) {
- // TODO use real-time technique to avoid mutex, eg. atomic command FIFO
+
+ {
std::lock_guard<std::mutex> lock(mLockStreams);
- result = getStreamInternal()->requestStart();
- startSharingThread_l();
+ if (++mRunningStreamCount == 1) { // atomic
+ result = getStreamInternal()->requestStart();
+ if (result != AAUDIO_OK) {
+ --mRunningStreamCount;
+ } else {
+ result = startSharingThread_l();
+ if (result != AAUDIO_OK) {
+ getStreamInternal()->requestStop();
+ --mRunningStreamCount;
+ }
+ }
+ }
}
+
if (result == AAUDIO_OK) {
result = getStreamInternal()->startClient(sharedStream->getAudioClient(), clientHandle);
+ if (result != AAUDIO_OK) {
+ if (--mRunningStreamCount == 0) { // atomic
+ stopSharingThread();
+ getStreamInternal()->requestStop();
+ }
+ }
}
+
return result;
}
@@ -141,7 +159,6 @@
return AAUDIO_OK;
}
-
// Get timestamp that was written by the real-time service thread, eg. mixer.
aaudio_result_t AAudioServiceEndpointShared::getFreeRunningPosition(int64_t *positionFrames,
int64_t *timeNanos) {
diff --git a/services/oboeservice/AAudioServiceStreamBase.cpp b/services/oboeservice/AAudioServiceStreamBase.cpp
index ca7b528..e670129 100644
--- a/services/oboeservice/AAudioServiceStreamBase.cpp
+++ b/services/oboeservice/AAudioServiceStreamBase.cpp
@@ -365,10 +365,17 @@
* used to communicate with the underlying HAL or Service.
*/
aaudio_result_t AAudioServiceStreamBase::getDescription(AudioEndpointParcelable &parcelable) {
- // Gather information on the message queue.
- mUpMessageQueue->fillParcelable(parcelable,
- parcelable.mUpMessageQueueParcelable);
- return getDownDataDescription(parcelable);
+ {
+ std::lock_guard<std::mutex> lock(mUpMessageQueueLock);
+ if (mUpMessageQueue == nullptr) {
+ ALOGE("getDescription(): mUpMessageQueue null! - stream not open");
+ return AAUDIO_ERROR_NULL;
+ }
+ // Gather information on the message queue.
+ mUpMessageQueue->fillParcelable(parcelable,
+ parcelable.mUpMessageQueueParcelable);
+ }
+ return getAudioDataDescription(parcelable);
}
void AAudioServiceStreamBase::onVolumeChanged(float volume) {
diff --git a/services/oboeservice/AAudioServiceStreamBase.h b/services/oboeservice/AAudioServiceStreamBase.h
index 6f61401..af435b4 100644
--- a/services/oboeservice/AAudioServiceStreamBase.h
+++ b/services/oboeservice/AAudioServiceStreamBase.h
@@ -32,7 +32,10 @@
#include "SharedRingBuffer.h"
#include "AAudioThread.h"
-#include "AAudioService.h"
+
+namespace android {
+ class AAudioService;
+}
namespace aaudio {
@@ -210,7 +213,7 @@
virtual aaudio_result_t getHardwareTimestamp(int64_t *positionFrames, int64_t *timeNanos) = 0;
- virtual aaudio_result_t getDownDataDescription(AudioEndpointParcelable &parcelable) = 0;
+ virtual aaudio_result_t getAudioDataDescription(AudioEndpointParcelable &parcelable) = 0;
aaudio_stream_state_t mState = AAUDIO_STREAM_STATE_UNINITIALIZED;
diff --git a/services/oboeservice/AAudioServiceStreamMMAP.cpp b/services/oboeservice/AAudioServiceStreamMMAP.cpp
index a629ed6..44ba1ca 100644
--- a/services/oboeservice/AAudioServiceStreamMMAP.cpp
+++ b/services/oboeservice/AAudioServiceStreamMMAP.cpp
@@ -168,7 +168,8 @@
/**
* Get an immutable description of the data queue from the HAL.
*/
-aaudio_result_t AAudioServiceStreamMMAP::getDownDataDescription(AudioEndpointParcelable &parcelable)
+aaudio_result_t AAudioServiceStreamMMAP::getAudioDataDescription(
+ AudioEndpointParcelable &parcelable)
{
sp<AAudioServiceEndpointMMAP> serviceEndpointMMAP{
static_cast<AAudioServiceEndpointMMAP *>(mServiceEndpoint.get())};
diff --git a/services/oboeservice/AAudioServiceStreamMMAP.h b/services/oboeservice/AAudioServiceStreamMMAP.h
index 83cd2ef..e2415d0 100644
--- a/services/oboeservice/AAudioServiceStreamMMAP.h
+++ b/services/oboeservice/AAudioServiceStreamMMAP.h
@@ -75,7 +75,7 @@
protected:
- aaudio_result_t getDownDataDescription(AudioEndpointParcelable &parcelable) override;
+ aaudio_result_t getAudioDataDescription(AudioEndpointParcelable &parcelable) override;
aaudio_result_t getFreeRunningPosition(int64_t *positionFrames, int64_t *timeNanos) override;
diff --git a/services/oboeservice/AAudioServiceStreamShared.cpp b/services/oboeservice/AAudioServiceStreamShared.cpp
index 348d407..084f996 100644
--- a/services/oboeservice/AAudioServiceStreamShared.cpp
+++ b/services/oboeservice/AAudioServiceStreamShared.cpp
@@ -167,14 +167,17 @@
goto error;
}
- // Create audio data shared memory buffer for client.
- mAudioDataQueue = new SharedRingBuffer();
- result = mAudioDataQueue->allocate(calculateBytesPerFrame(), getBufferCapacity());
- if (result != AAUDIO_OK) {
- ALOGE("AAudioServiceStreamShared::open() could not allocate FIFO with %d frames",
- getBufferCapacity());
- result = AAUDIO_ERROR_NO_MEMORY;
- goto error;
+ {
+ std::lock_guard<std::mutex> lock(mAudioDataQueueLock);
+ // Create audio data shared memory buffer for client.
+ mAudioDataQueue = new SharedRingBuffer();
+ result = mAudioDataQueue->allocate(calculateBytesPerFrame(), getBufferCapacity());
+ if (result != AAUDIO_OK) {
+ ALOGE("AAudioServiceStreamShared::open() could not allocate FIFO with %d frames",
+ getBufferCapacity());
+ result = AAUDIO_ERROR_NO_MEMORY;
+ goto error;
+ }
}
ALOGD("AAudioServiceStreamShared::open() actual rate = %d, channels = %d, deviceId = %d",
@@ -197,8 +200,11 @@
aaudio_result_t AAudioServiceStreamShared::close() {
aaudio_result_t result = AAudioServiceStreamBase::close();
- delete mAudioDataQueue;
- mAudioDataQueue = nullptr;
+ {
+ std::lock_guard<std::mutex> lock(mAudioDataQueueLock);
+ delete mAudioDataQueue;
+ mAudioDataQueue = nullptr;
+ }
return result;
}
@@ -206,8 +212,14 @@
/**
* Get an immutable description of the data queue created by this service.
*/
-aaudio_result_t AAudioServiceStreamShared::getDownDataDescription(AudioEndpointParcelable &parcelable)
+aaudio_result_t AAudioServiceStreamShared::getAudioDataDescription(
+ AudioEndpointParcelable &parcelable)
{
+ std::lock_guard<std::mutex> lock(mAudioDataQueueLock);
+ if (mAudioDataQueue == nullptr) {
+ ALOGE("getAudioDataDescription(): mUpMessageQueue null! - stream not open");
+ return AAUDIO_ERROR_NULL;
+ }
// Gather information on the data queue.
mAudioDataQueue->fillParcelable(parcelable,
parcelable.mDownDataQueueParcelable);
diff --git a/services/oboeservice/AAudioServiceStreamShared.h b/services/oboeservice/AAudioServiceStreamShared.h
index bc86dcc..8499ea5 100644
--- a/services/oboeservice/AAudioServiceStreamShared.h
+++ b/services/oboeservice/AAudioServiceStreamShared.h
@@ -54,7 +54,21 @@
aaudio_result_t close() override;
- android::FifoBuffer *getDataFifoBuffer() { return mAudioDataQueue->getFifoBuffer(); }
+ /**
+ * This must be locked when calling getAudioDataFifoBuffer_l() and while
+ * using the FifoBuffer it returns.
+ */
+ std::mutex &getAudioDataQueueLock() {
+ return mAudioDataQueueLock;
+ }
+
+ /**
+ * This must only be call under getAudioDataQueueLock().
+ * @return
+ */
+ android::FifoBuffer *getAudioDataFifoBuffer_l() { return (mAudioDataQueue == nullptr)
+ ? nullptr
+ : mAudioDataQueue->getFifoBuffer(); }
/* Keep a record of when a buffer transfer completed.
* This allows for a more accurate timing model.
@@ -75,7 +89,7 @@
protected:
- aaudio_result_t getDownDataDescription(AudioEndpointParcelable &parcelable) override;
+ aaudio_result_t getAudioDataDescription(AudioEndpointParcelable &parcelable) override;
aaudio_result_t getFreeRunningPosition(int64_t *positionFrames, int64_t *timeNanos) override;
@@ -90,7 +104,8 @@
int32_t framesPerBurst);
private:
- SharedRingBuffer *mAudioDataQueue = nullptr;
+ SharedRingBuffer *mAudioDataQueue = nullptr; // protected by mAudioDataQueueLock
+ std::mutex mAudioDataQueueLock;
std::atomic<int64_t> mTimestampPositionOffset;
std::atomic<int32_t> mXRunCount;
diff --git a/services/oboeservice/AAudioStreamTracker.cpp b/services/oboeservice/AAudioStreamTracker.cpp
new file mode 100644
index 0000000..ef88b34
--- /dev/null
+++ b/services/oboeservice/AAudioStreamTracker.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AAudioStreamTracker"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+
+#include <aaudio/AAudio.h>
+#include <utils/String16.h>
+
+#include "AAudioStreamTracker.h"
+
+using namespace android;
+using namespace aaudio;
+
+sp<AAudioServiceStreamBase> AAudioStreamTracker::removeStreamByHandle(
+ aaudio_handle_t streamHandle) {
+ std::lock_guard<std::mutex> lock(mHandleLock);
+ sp<AAudioServiceStreamBase> serviceStream;
+ auto it = mStreamsByHandle.find(streamHandle);
+ if (it != mStreamsByHandle.end()) {
+ serviceStream = it->second;
+ mStreamsByHandle.erase(it);
+ }
+ return serviceStream;
+}
+
+sp<AAudioServiceStreamBase> AAudioStreamTracker::getStreamByHandle(
+ aaudio_handle_t streamHandle) {
+ std::lock_guard<std::mutex> lock(mHandleLock);
+ sp<AAudioServiceStreamBase> serviceStream;
+ auto it = mStreamsByHandle.find(streamHandle);
+ if (it != mStreamsByHandle.end()) {
+ serviceStream = it->second;
+ }
+ return serviceStream;
+}
+
+// advance to next legal handle value
+__attribute__((no_sanitize("integer")))
+aaudio_handle_t AAudioStreamTracker::bumpHandle(aaudio_handle_t handle) {
+ handle++;
+ // Only use positive integers.
+ if (handle <= 0) {
+ handle = 1;
+ }
+ return handle;
+}
+
+aaudio_handle_t AAudioStreamTracker::addStreamForHandle(sp<AAudioServiceStreamBase> serviceStream) {
+ std::lock_guard<std::mutex> lock(mHandleLock);
+ aaudio_handle_t handle = mPreviousHandle.load();
+ // Assign a unique handle.
+ while (true) {
+ handle = bumpHandle(handle);
+ sp<AAudioServiceStreamBase> oldServiceStream = mStreamsByHandle[handle];
+ // Is this an unused handle? It would be extremely unlikely to wrap
+ // around and collide with a very old handle. But just in case.
+ if (oldServiceStream.get() == nullptr) {
+ mStreamsByHandle[handle] = serviceStream;
+ break;
+ }
+ }
+ mPreviousHandle.store(handle);
+ return handle;
+}
+
+std::string AAudioStreamTracker::dump() const {
+ std::stringstream result;
+ const bool isLocked = AAudio_tryUntilTrue(
+ [this]()->bool { return mHandleLock.try_lock(); } /* f */,
+ 50 /* times */,
+ 20 /* sleepMs */);
+ if (!isLocked) {
+ result << "AAudioStreamTracker may be deadlocked\n";
+ } else {
+ result << "Stream Handles:\n";
+ for (const auto& it : mStreamsByHandle) {
+ aaudio_handle_t handle = it.second->getHandle();
+ result << " 0x" << std::setfill('0') << std::setw(8) << std::hex << handle
+ << std::dec << std::setfill(' ') << "\n";
+ }
+
+ mHandleLock.unlock();
+ }
+ return result.str();
+}
diff --git a/services/oboeservice/AAudioStreamTracker.h b/services/oboeservice/AAudioStreamTracker.h
new file mode 100644
index 0000000..70d440d
--- /dev/null
+++ b/services/oboeservice/AAudioStreamTracker.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAUDIO_AAUDIO_STREAM_TRACKER_H
+#define AAUDIO_AAUDIO_STREAM_TRACKER_H
+
+#include <time.h>
+#include <pthread.h>
+
+#include <aaudio/AAudio.h>
+
+#include "binding/AAudioCommon.h"
+
+#include "AAudioServiceStreamBase.h"
+
+namespace aaudio {
+
+class AAudioStreamTracker {
+
+public:
+ /**
+ * Remove the stream associated with the handle.
+ * @param streamHandle
+ * @return strong pointer to the stream if found or to nullptr
+ */
+ android::sp<AAudioServiceStreamBase> removeStreamByHandle(aaudio_handle_t streamHandle);
+
+ /**
+ * Look up a stream based on the handle.
+ * @param streamHandle
+ * @return strong pointer to the stream if found or to nullptr
+ */
+ android::sp<aaudio::AAudioServiceStreamBase> getStreamByHandle(aaudio_handle_t streamHandle);
+
+ /**
+ * Store a strong pointer to the stream and return a unique handle for future reference.
+ * The handle is guaranteed not to collide with an existing stream.
+ * @param serviceStream
+ * @return handle for identifying the stream
+ */
+ aaudio_handle_t addStreamForHandle(android::sp<AAudioServiceStreamBase> serviceStream);
+
+ /**
+ * @return string that can be added to dumpsys
+ */
+ std::string dump() const;
+
+private:
+ static aaudio_handle_t bumpHandle(aaudio_handle_t handle);
+
+ // Track stream using a unique handle that wraps. Only use positive half.
+ mutable std::mutex mHandleLock;
+ std::atomic<aaudio_handle_t> mPreviousHandle{0};
+ std::map<aaudio_handle_t, android::sp<aaudio::AAudioServiceStreamBase>> mStreamsByHandle;
+};
+
+
+} /* namespace aaudio */
+
+#endif /* AAUDIO_AAUDIO_STREAM_TRACKER_H */
diff --git a/services/oboeservice/Android.mk b/services/oboeservice/Android.mk
index 1b74ad3..584b2ef 100644
--- a/services/oboeservice/Android.mk
+++ b/services/oboeservice/Android.mk
@@ -22,7 +22,6 @@
$(TOP)/frameworks/av/media/libaaudio/src
LOCAL_SRC_FILES += \
- $(LIBAAUDIO_SRC_DIR)/utility/HandleTracker.cpp \
SharedMemoryProxy.cpp \
SharedRingBuffer.cpp \
AAudioClientTracker.cpp \
@@ -37,6 +36,7 @@
AAudioServiceStreamBase.cpp \
AAudioServiceStreamMMAP.cpp \
AAudioServiceStreamShared.cpp \
+ AAudioStreamTracker.cpp \
TimestampScheduler.cpp \
AAudioThread.cpp