Merge "NuPlayerRenderer: Ensure cancelAudioOffloadPauseTimeout cancels timeout" into nyc-dev
diff --git a/include/media/AudioIoDescriptor.h b/include/media/AudioIoDescriptor.h
index a4907cc..fed86c9 100644
--- a/include/media/AudioIoDescriptor.h
+++ b/include/media/AudioIoDescriptor.h
@@ -35,7 +35,7 @@
AudioIoDescriptor() :
mIoHandle(AUDIO_IO_HANDLE_NONE),
mSamplingRate(0), mFormat(AUDIO_FORMAT_DEFAULT), mChannelMask(AUDIO_CHANNEL_NONE),
- mFrameCount(0), mLatency(0)
+ mFrameCount(0), mFrameCountHAL(0), mLatency(0)
{
memset(&mPatch, 0, sizeof(struct audio_patch));
}
@@ -62,6 +62,7 @@
audio_format_t mFormat;
audio_channel_mask_t mChannelMask;
size_t mFrameCount;
+ size_t mFrameCountHAL;
uint32_t mLatency; // only valid for output
};
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index c9eac2e..585ef59 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -43,6 +43,8 @@
{
public:
+ // FIXME Declare in binder opcode order, similarly to IAudioFlinger.h and IAudioFlinger.cpp
+
/* These are static methods to control the system-wide AudioFlinger
* only privileged processes can have access to them
*/
@@ -117,8 +119,8 @@
// returns the audio HAL sample rate
static status_t getSamplingRate(audio_io_handle_t ioHandle,
uint32_t* samplingRate);
- // returns the number of frames per audio HAL buffer. Corresponds to
- // audio_stream->get_buffer_size()/audio_stream_out/in_frame_size()
+ // For output threads with a fast mixer, returns the number of frames per normal mixer buffer.
+ // For output threads without a fast mixer, or for input, this is same as getFrameCountHAL().
static status_t getFrameCount(audio_io_handle_t ioHandle,
size_t* frameCount);
// returns the audio output latency in ms. Corresponds to
@@ -166,6 +168,12 @@
// Indicate JAVA services are ready (scheduling, power management ...)
static status_t systemReady();
+ // Returns the number of frames per audio HAL buffer.
+ // Corresponds to audio_stream->get_buffer_size()/audio_stream_in_frame_size() for input.
+ // See also getFrameCount().
+ static status_t getFrameCountHAL(audio_io_handle_t ioHandle,
+ size_t* frameCount);
+
// Events used to synchronize actions between audio sessions.
// For instance SYNC_EVENT_PRESENTATION_COMPLETE can be used to delay recording start until
// playback is complete on another audio session.
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index e48aa1c..1ade4ba 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -103,6 +103,9 @@
* and therefore can be cached.
*/
virtual uint32_t sampleRate(audio_io_handle_t ioHandle) const = 0;
+
+ // reserved; formerly channelCount()
+
virtual audio_format_t format(audio_io_handle_t output) const = 0;
virtual size_t frameCount(audio_io_handle_t ioHandle) const = 0;
@@ -247,6 +250,9 @@
/* Indicate JAVA services are ready (scheduling, power management ...) */
virtual status_t systemReady() = 0;
+
+ // Returns the number of frames per audio HAL buffer.
+ virtual size_t frameCountHAL(audio_io_handle_t ioHandle) const = 0;
};
diff --git a/include/media/ToneGenerator.h b/include/media/ToneGenerator.h
index 8406ed6..c41c686 100644
--- a/include/media/ToneGenerator.h
+++ b/include/media/ToneGenerator.h
@@ -193,12 +193,15 @@
TONE_JAPAN_DIAL, // Dial tone: 400Hz, continuous
TONE_JAPAN_BUSY, // Busy tone: 400Hz, 500ms ON, 500ms OFF...
TONE_JAPAN_RADIO_ACK, // Radio path acknowlegment: 400Hz, 1s ON, 2s OFF...
+ // UK Supervisory tones
+ TONE_UK_RINGTONE, // Ring Tone: A 400Hz + 450Hz tone repeated in a 0.4s on, 0.2s off, 0.4s on, 2.0s off pattern.
NUM_ALTERNATE_TONES
};
enum region {
ANSI,
JAPAN,
+ UK,
CEPT,
NUM_REGIONS
};
diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h
index c5df1f6..0254545 100644
--- a/include/media/stagefright/DataSource.h
+++ b/include/media/stagefright/DataSource.h
@@ -19,7 +19,7 @@
#define DATA_SOURCE_H_
#include <sys/types.h>
-
+#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaErrors.h>
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
@@ -71,6 +71,20 @@
bool getUInt32(off64_t offset, uint32_t *x);
bool getUInt64(off64_t offset, uint64_t *x);
+ // Reads in "count" entries of type T into vector *x.
+ // Returns true if "count" entries can be read.
+ // If fewer than "count" entries can be read, return false. In this case,
+ // the output vector *x will still have those entries that were read. Call
+ // x->size() to obtain the number of entries read.
+ // The optional parameter chunkSize specifies how many entries should be
+ // read from the data source at one time into a temporary buffer. Increasing
+ // chunkSize can improve the performance at the cost of extra memory usage.
+ // The default value for chunkSize is set to read at least 4k bytes at a
+ // time, depending on sizeof(T).
+ template <typename T>
+ bool getVector(off64_t offset, Vector<T>* x, size_t count,
+ size_t chunkSize = (4095 / sizeof(T)) + 1);
+
// May return ERROR_UNSUPPORTED.
virtual status_t getSize(off64_t *size);
@@ -127,6 +141,51 @@
DataSource &operator=(const DataSource &);
};
+template <typename T>
+bool DataSource::getVector(off64_t offset, Vector<T>* x, size_t count,
+ size_t chunkSize)
+{
+ x->clear();
+ if (chunkSize == 0) {
+ return false;
+ }
+ if (count == 0) {
+ return true;
+ }
+
+ T tmp[chunkSize];
+ ssize_t numBytesRead;
+ size_t numBytesPerChunk = chunkSize * sizeof(T);
+ size_t i;
+
+ for (i = 0; i + chunkSize < count; i += chunkSize) {
+ // This loops is executed when more than chunkSize records need to be
+ // read.
+ numBytesRead = this->readAt(offset, (void*)&tmp, numBytesPerChunk);
+ if (numBytesRead == -1) { // If readAt() returns -1, there is an error.
+ return false;
+ }
+ if (numBytesRead < numBytesPerChunk) {
+ // This case is triggered when the stream ends before the whole
+ // chunk is read.
+ x->appendArray(tmp, (size_t)numBytesRead / sizeof(T));
+ return false;
+ }
+ x->appendArray(tmp, chunkSize);
+ offset += numBytesPerChunk;
+ }
+
+ // There are (count - i) more records to read.
+ // Right now, (count - i) <= chunkSize.
+ // We do the same thing as above, but with chunkSize replaced by count - i.
+ numBytesRead = this->readAt(offset, (void*)&tmp, (count - i) * sizeof(T));
+ if (numBytesRead == -1) {
+ return false;
+ }
+ x->appendArray(tmp, (size_t)numBytesRead / sizeof(T));
+ return x->size() == count;
+}
+
} // namespace android
#endif // DATA_SOURCE_H_
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 3a5dee6..bbdf65e 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -104,6 +104,8 @@
return DEAD_OBJECT;
}
+// FIXME Declare in binder opcode order, similarly to IAudioFlinger.h and IAudioFlinger.cpp
+
status_t AudioSystem::muteMicrophone(bool state)
{
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
@@ -429,6 +431,27 @@
return af->systemReady();
}
+status_t AudioSystem::getFrameCountHAL(audio_io_handle_t ioHandle,
+ size_t* frameCount)
+{
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ sp<AudioIoDescriptor> desc = getIoDescriptor(ioHandle);
+ if (desc == 0) {
+ *frameCount = af->frameCountHAL(ioHandle);
+ } else {
+ *frameCount = desc->mFrameCountHAL;
+ }
+ if (*frameCount == 0) {
+ ALOGE("AudioSystem::getFrameCountHAL failed for ioHandle %d", ioHandle);
+ return BAD_VALUE;
+ }
+
+ ALOGV("getFrameCountHAL() ioHandle %d, frameCount %zu", ioHandle, *frameCount);
+
+ return NO_ERROR;
+}
+
// ---------------------------------------------------------------------------
@@ -528,10 +551,10 @@
}
}
ALOGV("ioConfigChanged() new config for %s %d samplingRate %u, format %#x "
- "channel mask %#x frameCount %zu deviceId %d",
+ "channel mask %#x frameCount %zu frameCountHAL %zu deviceId %d",
event == AUDIO_OUTPUT_CONFIG_CHANGED ? "output" : "input",
ioDesc->mIoHandle, ioDesc->mSamplingRate, ioDesc->mFormat,
- ioDesc->mChannelMask, ioDesc->mFrameCount, ioDesc->getDeviceId());
+ ioDesc->mChannelMask, ioDesc->mFrameCount, ioDesc->mFrameCountHAL, ioDesc->getDeviceId());
} break;
}
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 7543b60..aa75188 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -81,7 +81,8 @@
LIST_AUDIO_PATCHES,
SET_AUDIO_PORT_CONFIG,
GET_AUDIO_HW_SYNC,
- SYSTEM_READY
+ SYSTEM_READY,
+ FRAME_COUNT_HAL,
};
#define MAX_ITEMS_PER_LIST 1024
@@ -274,6 +275,8 @@
return reply.readInt32();
}
+ // RESERVED for channelCount()
+
virtual audio_format_t format(audio_io_handle_t output) const
{
Parcel data, reply;
@@ -911,6 +914,18 @@
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
return remote()->transact(SYSTEM_READY, data, &reply, IBinder::FLAG_ONEWAY);
}
+ virtual size_t frameCountHAL(audio_io_handle_t ioHandle) const
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32((int32_t) ioHandle);
+ status_t status = remote()->transact(FRAME_COUNT_HAL, data, &reply);
+ if (status != NO_ERROR) {
+ return 0;
+ }
+ return reply.readInt64();
+ }
+
};
IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger");
@@ -993,6 +1008,9 @@
reply->writeInt32( sampleRate((audio_io_handle_t) data.readInt32()) );
return NO_ERROR;
} break;
+
+ // RESERVED for channelCount()
+
case FORMAT: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
reply->writeInt32( format((audio_io_handle_t) data.readInt32()) );
@@ -1419,6 +1437,11 @@
systemReady();
return NO_ERROR;
} break;
+ case FRAME_COUNT_HAL: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ reply->writeInt64( frameCountHAL((audio_io_handle_t) data.readInt32()) );
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp
index 3429d36..8dca9e9 100644
--- a/media/libmedia/IAudioFlingerClient.cpp
+++ b/media/libmedia/IAudioFlingerClient.cpp
@@ -50,6 +50,7 @@
data.writeInt32(ioDesc->mFormat);
data.writeInt32(ioDesc->mChannelMask);
data.writeInt64(ioDesc->mFrameCount);
+ data.writeInt64(ioDesc->mFrameCountHAL);
data.writeInt32(ioDesc->mLatency);
remote()->transact(IO_CONFIG_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
}
@@ -73,6 +74,7 @@
ioDesc->mFormat = (audio_format_t) data.readInt32();
ioDesc->mChannelMask = (audio_channel_mask_t) data.readInt32();
ioDesc->mFrameCount = data.readInt64();
+ ioDesc->mFrameCountHAL = data.readInt64();
ioDesc->mLatency = data.readInt32();
ioConfigChanged(event, ioDesc);
return NO_ERROR;
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index 9f4b4de..411519d 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -740,6 +740,13 @@
{ .duration = 0 , .waveFreq = { 0 }, 0, 0}},
.repeatCnt = ToneGenerator::TONEGEN_INF,
.repeatSegment = 0 }, // TONE_JAPAN_RADIO_ACK
+ { .segments = { { .duration = 400, .waveFreq = { 400, 450, 0 }, 0, 0 },
+ { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+ { .duration = 400, .waveFreq = { 400, 450, 0 }, 0, 0 },
+ { .duration = 2000, .waveFreq = { 0 }, 0, 0},
+ { .duration = 0, .waveFreq = { 0 }, 0, 0}},
+ .repeatCnt = ToneGenerator::TONEGEN_INF,
+ .repeatSegment = 0 }, // TONE_UK_RINGTONE
@@ -767,7 +774,18 @@
TONE_SUP_ERROR, // TONE_SUP_ERROR
TONE_SUP_CALL_WAITING, // TONE_SUP_CALL_WAITING
TONE_SUP_RINGTONE // TONE_SUP_RINGTONE
+ },
+ { // UK
+ TONE_SUP_DIAL, // TONE_SUP_DIAL
+ TONE_SUP_BUSY, // TONE_SUP_BUSY
+ TONE_SUP_CONGESTION, // TONE_SUP_CONGESTION
+ TONE_SUP_RADIO_ACK, // TONE_SUP_RADIO_ACK
+ TONE_SUP_RADIO_NOTAVAIL, // TONE_SUP_RADIO_NOTAVAIL
+ TONE_SUP_ERROR, // TONE_SUP_ERROR
+ TONE_SUP_CALL_WAITING, // TONE_SUP_CALL_WAITING
+ TONE_UK_RINGTONE // TONE_SUP_RINGTONE
}
+
};
@@ -819,6 +837,9 @@
mRegion = ANSI;
} else if (strcmp(value,"jp") == 0) {
mRegion = JAPAN;
+ } else if (strcmp(value,"uk") == 0 ||
+ strcmp(value,"uk,uk") == 0) {
+ mRegion = UK;
} else {
mRegion = CEPT;
}
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index 1bdd812..542a06d 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -121,8 +121,9 @@
mSampleSizeFieldSize(0),
mDefaultSampleSize(0),
mNumSampleSizes(0),
+ mHasTimeToSample(false),
mTimeToSampleCount(0),
- mTimeToSample(NULL),
+ mTimeToSample(),
mSampleTimeEntries(NULL),
mCompositionTimeDeltaEntries(NULL),
mNumCompositionTimeDeltaEntries(0),
@@ -151,9 +152,6 @@
delete[] mSampleTimeEntries;
mSampleTimeEntries = NULL;
- delete[] mTimeToSample;
- mTimeToSample = NULL;
-
delete mSampleIterator;
mSampleIterator = NULL;
}
@@ -162,7 +160,7 @@
return mChunkOffsetOffset >= 0
&& mSampleToChunkOffset >= 0
&& mSampleSizeOffset >= 0
- && mTimeToSample != NULL;
+ && mHasTimeToSample;
}
status_t SampleTable::setChunkOffsetParams(
@@ -336,7 +334,7 @@
status_t SampleTable::setTimeToSampleParams(
off64_t data_offset, size_t data_size) {
- if (mTimeToSample != NULL || data_size < 8) {
+ if (mHasTimeToSample || data_size < 8) {
return ERROR_MALFORMED;
}
@@ -352,24 +350,31 @@
}
mTimeToSampleCount = U32_AT(&header[4]);
- uint64_t allocSize = (uint64_t)mTimeToSampleCount * 2 * sizeof(uint32_t);
- if (allocSize > UINT32_MAX) {
+ if ((uint64_t)mTimeToSampleCount >
+ (uint64_t)UINT32_MAX / (2 * sizeof(uint32_t))) {
+ // Choose this bound because
+ // 1) 2 * sizeof(uint32_t) is the amount of memory needed for one
+ // time-to-sample entry in the time-to-sample table.
+ // 2) mTimeToSampleCount is the number of entries of the time-to-sample
+ // table.
+ // 3) We hope that the table size does not exceed UINT32_MAX.
+ ALOGE(" Error: Time-to-sample table size too large.");
return ERROR_OUT_OF_RANGE;
}
- mTimeToSample = new (std::nothrow) uint32_t[mTimeToSampleCount * 2];
- if (!mTimeToSample)
- return ERROR_OUT_OF_RANGE;
- size_t size = sizeof(uint32_t) * mTimeToSampleCount * 2;
- if (mDataSource->readAt(
- data_offset + 8, mTimeToSample, size) < (ssize_t)size) {
+ // Note: At this point, we know that mTimeToSampleCount * 2 will not
+ // overflow because of the above condition.
+ if (!mDataSource->getVector(data_offset + 8, &mTimeToSample,
+ mTimeToSampleCount * 2)) {
+ ALOGE(" Error: Incomplete data read for time-to-sample table.");
return ERROR_IO;
}
- for (uint32_t i = 0; i < mTimeToSampleCount * 2; ++i) {
- mTimeToSample[i] = ntohl(mTimeToSample[i]);
+ for (size_t i = 0; i < mTimeToSample.size(); ++i) {
+ mTimeToSample.editItemAt(i) = ntohl(mTimeToSample[i]);
}
+ mHasTimeToSample = true;
return OK;
}
diff --git a/media/libstagefright/include/SampleTable.h b/media/libstagefright/include/SampleTable.h
index 738f864..54da497 100644
--- a/media/libstagefright/include/SampleTable.h
+++ b/media/libstagefright/include/SampleTable.h
@@ -24,6 +24,7 @@
#include <media/stagefright/MediaErrors.h>
#include <utils/RefBase.h>
#include <utils/threads.h>
+#include <utils/Vector.h>
namespace android {
@@ -110,8 +111,9 @@
uint32_t mDefaultSampleSize;
uint32_t mNumSampleSizes;
+ bool mHasTimeToSample;
uint32_t mTimeToSampleCount;
- uint32_t *mTimeToSample;
+ Vector<uint32_t> mTimeToSample;
struct SampleTimeEntry {
uint32_t mSampleIndex;
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 1b69f8c..ca1a0b7 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -176,7 +176,7 @@
mHardwareStatus(AUDIO_HW_IDLE),
mMasterVolume(1.0f),
mMasterMute(false),
- mNextUniqueId(AUDIO_UNIQUE_ID_USE_MAX), // zero has a special meaning, so unavailable
+ // mNextUniqueId(AUDIO_UNIQUE_ID_USE_MAX),
mMode(AUDIO_MODE_INVALID),
mBtNrecIsOff(false),
mIsLowRamDevice(true),
@@ -184,6 +184,12 @@
mGlobalEffectEnableTime(0),
mSystemReady(false)
{
+ // unsigned instead of audio_unique_id_use_t, because ++ operator is unavailable for enum
+ for (unsigned use = AUDIO_UNIQUE_ID_USE_UNSPECIFIED; use < AUDIO_UNIQUE_ID_USE_MAX; use++) {
+ // zero ID has a special meaning, so unavailable
+ mNextUniqueIds[use] = AUDIO_UNIQUE_ID_USE_MAX;
+ }
+
getpid_cached = getpid();
const bool doLog = property_get_bool("ro.test_harness", false);
if (doLog) {
@@ -740,6 +746,17 @@
return thread->frameCount();
}
+size_t AudioFlinger::frameCountHAL(audio_io_handle_t ioHandle) const
+{
+ Mutex::Autolock _l(mLock);
+ ThreadBase *thread = checkThread_l(ioHandle);
+ if (thread == NULL) {
+ ALOGW("frameCountHAL() unknown thread %d", ioHandle);
+ return 0;
+ }
+ return thread->frameCountHAL();
+}
+
uint32_t AudioFlinger::latency(audio_io_handle_t output) const
{
Mutex::Autolock _l(mLock);
@@ -2440,13 +2457,23 @@
audio_unique_id_t AudioFlinger::nextUniqueId(audio_unique_id_use_t use)
{
- int32_t base = android_atomic_add(AUDIO_UNIQUE_ID_USE_MAX, &mNextUniqueId);
- // We have no way of recovering from wraparound
- LOG_ALWAYS_FATAL_IF(base == 0, "unique ID overflow");
// This is the internal API, so it is OK to assert on bad parameter.
LOG_ALWAYS_FATAL_IF((unsigned) use >= (unsigned) AUDIO_UNIQUE_ID_USE_MAX);
- ALOG_ASSERT(audio_unique_id_get_use(base) == AUDIO_UNIQUE_ID_USE_UNSPECIFIED);
- return (audio_unique_id_t) (base | use);
+ const int maxRetries = use == AUDIO_UNIQUE_ID_USE_SESSION ? 3 : 1;
+ for (int retry = 0; retry < maxRetries; retry++) {
+ // The cast allows wraparound from max positive to min negative instead of abort
+ uint32_t base = (uint32_t) atomic_fetch_add_explicit(&mNextUniqueIds[use],
+ (uint_fast32_t) AUDIO_UNIQUE_ID_USE_MAX, memory_order_acq_rel);
+ ALOG_ASSERT(audio_unique_id_get_use(base) == AUDIO_UNIQUE_ID_USE_UNSPECIFIED);
+ // allow wrap by skipping 0 and -1 for session ids
+ if (!(base == 0 || base == (~0u & ~AUDIO_UNIQUE_ID_USE_MASK))) {
+ ALOGW_IF(retry != 0, "unique ID overflow for use %d", use);
+ return (audio_unique_id_t) (base | use);
+ }
+ }
+ // We have no way of recovering from wraparound
+ LOG_ALWAYS_FATAL("unique ID overflow for use %d", use);
+ // TODO Use a floor after wraparound. This may need a mutex.
}
AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l() const
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 498c33e..96d38d0 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -131,6 +131,7 @@
virtual uint32_t sampleRate(audio_io_handle_t ioHandle) const;
virtual audio_format_t format(audio_io_handle_t output) const;
virtual size_t frameCount(audio_io_handle_t ioHandle) const;
+ virtual size_t frameCountHAL(audio_io_handle_t ioHandle) const;
virtual uint32_t latency(audio_io_handle_t output) const;
virtual status_t setMasterVolume(float value);
@@ -679,9 +680,8 @@
// protected by mClientLock
DefaultKeyedVector< pid_t, sp<NotificationClient> > mNotificationClients;
- volatile int32_t mNextUniqueId; // updated by android_atomic_inc
- // nextUniqueId() returns uint32_t, but this is declared int32_t
- // because the atomic operations require an int32_t
+ // updated by atomic_fetch_add_explicit
+ volatile atomic_uint_fast32_t mNextUniqueIds[AUDIO_UNIQUE_ID_USE_MAX];
audio_mode_t mMode;
bool mBtNrecIsOff;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 21ce6b1..ff67fb2 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2153,6 +2153,7 @@
desc->mFormat = mFormat;
desc->mFrameCount = mNormalFrameCount; // FIXME see
// AudioFlinger::frameCount(audio_io_handle_t)
+ desc->mFrameCountHAL = mFrameCount;
desc->mLatency = latency_l();
break;
@@ -7117,6 +7118,7 @@
desc->mSamplingRate = mSampleRate;
desc->mFormat = mFormat;
desc->mFrameCount = mFrameCount;
+ desc->mFrameCountHAL = mFrameCount;
desc->mLatency = 0;
break;
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index cf896e0..e71840d 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -247,6 +247,10 @@
// Called by AudioFlinger::frameCount(audio_io_handle_t output) and effects,
// and returns the [normal mix] buffer's frame count.
virtual size_t frameCount() const = 0;
+
+ // Return's the HAL's frame count i.e. fast mixer buffer size.
+ size_t frameCountHAL() const { return mFrameCount; }
+
size_t frameSize() const { return mFrameSize; }
// Should be "virtual status_t requestExitAndWait()" and override same
@@ -606,9 +610,6 @@
virtual size_t frameCount() const { return mNormalFrameCount; }
- // Return's the HAL's frame count i.e. fast mixer buffer size.
- size_t frameCountHAL() const { return mFrameCount; }
-
status_t getTimestamp_l(AudioTimestamp& timestamp);
void addPatchTrack(const sp<PatchTrack>& track);
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index b1347f4..a215b95 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -158,14 +158,14 @@
int indexMax) = 0;
// sets the new stream volume at a level corresponding to the supplied index for the
- // supplied device. By convention, specifying AUDIO_DEVICE_OUT_DEFAULT means
+ // supplied device. By convention, specifying AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME means
// setting volume for all devices
virtual status_t setStreamVolumeIndex(audio_stream_type_t stream,
int index,
audio_devices_t device) = 0;
// retrieve current volume index for the specified stream and the
- // specified device. By convention, specifying AUDIO_DEVICE_OUT_DEFAULT means
+ // specified device. By convention, specifying AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME means
// querying the volume of the active device.
virtual status_t getStreamVolumeIndex(audio_stream_type_t stream,
int *index,
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index f73548d..55ee91f 100755
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -47,6 +47,23 @@
#define APM_AUDIO_DEVICE_IN_MATCH_ADDRESS_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX|AUDIO_DEVICE_IN_BUS)
/**
+ * Stub audio output device. Used in policy configuration file on platforms without audio outputs.
+ * This alias value to AUDIO_DEVICE_OUT_DEFAULT is only used in the audio policy context.
+ */
+#define AUDIO_DEVICE_OUT_STUB AUDIO_DEVICE_OUT_DEFAULT
+/**
+ * Stub audio input device. Used in policy configuration file on platforms without audio inputs.
+ * This alias value to AUDIO_DEVICE_IN_DEFAULT is only used in the audio policy context.
+ */
+#define AUDIO_DEVICE_IN_STUB AUDIO_DEVICE_IN_DEFAULT
+/**
+ * Alias to AUDIO_DEVICE_OUT_DEFAULT defined for clarification when this value is used by volume
+ * control APIs (e.g setStreamVolumeIndex().
+ */
+#define AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME AUDIO_DEVICE_OUT_DEFAULT
+
+
+/**
* Check if the state given correspond to an in call state.
* @TODO find a better name for widely call state
*
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index 54fcd0b..ed2450c 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -84,8 +84,6 @@
audio_devices_t getDevicesFromHwModule(audio_module_handle_t moduleHandle) const;
- audio_policy_dev_state_t getDeviceConnectionState(const sp<DeviceDescriptor> &devDesc) const;
-
status_t dump(int fd, const String8 &tag, int spaces = 0, bool verbose = true) const;
private:
diff --git a/services/audiopolicy/common/managerdefinitions/include/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
index 93d03e6..dd2993d 100644
--- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h
+++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
@@ -106,7 +106,8 @@
sp<DeviceDescriptor> getDeviceDescriptor(const audio_devices_t device,
const char *device_address,
- const char *device_name) const;
+ const char *device_name,
+ bool matchAdress = true) const;
status_t dump(int fd) const;
};
diff --git a/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h b/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
index 7c486c8..10f0766 100644
--- a/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
+++ b/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
@@ -74,7 +74,7 @@
public:
VolumeCurvesForStream() : mIndexMin(0), mIndexMax(1), mCanBeMuted(true)
{
- mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT, 0);
+ mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME, 0);
}
sp<VolumeCurve> getCurvesFor(device_category device) const
@@ -88,9 +88,9 @@
int getVolumeIndex(audio_devices_t device) const
{
device = Volume::getDeviceForVolume(device);
- // there is always a valid entry for AUDIO_DEVICE_OUT_DEFAULT
+ // there is always a valid entry for AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME
if (mIndexCur.indexOfKey(device) < 0) {
- device = AUDIO_DEVICE_OUT_DEFAULT;
+ device = AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME;
}
return mIndexCur.valueFor(device);
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
index b8c0550..f382dec 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
@@ -128,14 +128,35 @@
size_t patchesWritten = 0;
size_t patchesMax = *num_patches;
- for (size_t i = 0; i < size() && patchesWritten < patchesMax; i++) {
- const sp<AudioPatch> patch = valueAt(i);
- patches[patchesWritten] = patch->mPatch;
- patches[patchesWritten++].id = patch->mHandle;
+ *num_patches = 0;
+ for (size_t patchIndex = 0; patchIndex < size(); patchIndex++) {
+ // do not report patches with AUDIO_DEVICE_IN_STUB as source or
+ // AUDIO_DEVICE_OUT_STUB as sink as those devices are used by stub HALs by convention
+ const sp<AudioPatch> patch = valueAt(patchIndex);
+ bool skip = false;
+ for (size_t srcIndex = 0; srcIndex < patch->mPatch.num_sources && !skip; srcIndex++) {
+ if (patch->mPatch.sources[srcIndex].type == AUDIO_PORT_TYPE_DEVICE &&
+ patch->mPatch.sources[srcIndex].ext.device.type == AUDIO_DEVICE_IN_STUB) {
+ skip = true;
+ }
+ }
+ for (size_t sinkIndex = 0; sinkIndex < patch->mPatch.num_sinks && !skip; sinkIndex++) {
+ if (patch->mPatch.sinks[sinkIndex].type == AUDIO_PORT_TYPE_DEVICE &&
+ patch->mPatch.sinks[sinkIndex].ext.device.type == AUDIO_DEVICE_OUT_STUB) {
+ skip = true;
+ }
+ }
+ if (skip) {
+ continue; // to next audio patch
+ }
+ if (patchesWritten < patchesMax) {
+ patches[patchesWritten] = patch->mPatch;
+ patches[patchesWritten++].id = patch->mHandle;
+ }
+ (*num_patches)++;
ALOGV("listAudioPatches() patch %zu num_sources %d num_sinks %d",
- i, patch->mPatch.num_sources, patch->mPatch.num_sinks);
+ patchIndex, patch->mPatch.num_sources, patch->mPatch.num_sinks);
}
- *num_patches = size();
ALOGV("listAudioPatches() got %zu patches needed %d", patchesWritten, *num_patches);
return NO_ERROR;
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index 44f380a..35f078e 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -219,12 +219,6 @@
return NO_ERROR;
}
-audio_policy_dev_state_t DeviceVector::getDeviceConnectionState(const sp<DeviceDescriptor> &devDesc) const
-{
- ssize_t index = indexOf(devDesc);
- return index >= 0 ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE : AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
-}
-
void DeviceDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig) const
{
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 2d67bd2..a85c07f 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -292,7 +292,8 @@
sp<DeviceDescriptor> HwModuleCollection::getDeviceDescriptor(const audio_devices_t device,
const char *device_address,
- const char *device_name) const
+ const char *device_name,
+ bool matchAdress) const
{
String8 address = (device_address == NULL) ? String8("") : String8(device_address);
// handle legacy remote submix case where the address was not always specified
@@ -305,11 +306,17 @@
if (hwModule->mHandle == 0) {
continue;
}
- DeviceVector deviceList =
- hwModule->getDeclaredDevices().getDevicesFromTypeAddr(device, address);
+ DeviceVector declaredDevices = hwModule->getDeclaredDevices();
+ DeviceVector deviceList = declaredDevices.getDevicesFromTypeAddr(device, address);
if (!deviceList.isEmpty()) {
return deviceList.itemAt(0);
}
+ if (!matchAdress) {
+ deviceList = declaredDevices.getDevicesFromType(device);
+ if (!deviceList.isEmpty()) {
+ return deviceList.itemAt(0);
+ }
+ }
}
sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
diff --git a/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp
index 8388a50..b3019e1 100644
--- a/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp
@@ -26,6 +26,7 @@
#include "StreamDescriptor.h"
#include "Gains.h"
+#include "policy.h"
#include <utils/Log.h>
#include <utils/String8.h>
@@ -39,15 +40,15 @@
// Initialize the current stream's index to mIndexMax so volume isn't 0 in
// cases where the Java layer doesn't call into the audio policy service to
// set the default volume.
- mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT, mIndexMax);
+ mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME, mIndexMax);
}
int StreamDescriptor::getVolumeIndex(audio_devices_t device) const
{
device = Volume::getDeviceForVolume(device);
- // there is always a valid entry for AUDIO_DEVICE_OUT_DEFAULT
+ // there is always a valid entry for AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME
if (mIndexCur.indexOfKey(device) < 0) {
- device = AUDIO_DEVICE_OUT_DEFAULT;
+ device = AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME;
}
return mIndexCur.valueFor(device);
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
index c6ed53e..f639551 100644
--- a/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
@@ -51,6 +51,7 @@
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_AUX_LINE),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_IP),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BUS),
+ MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_STUB),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_AMBIENT),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
@@ -74,6 +75,7 @@
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_LOOPBACK),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_IP),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUS),
+ MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_STUB),
};
template<>
diff --git a/services/audiopolicy/config/audio_policy_configuration_stub.xml b/services/audiopolicy/config/audio_policy_configuration_stub.xml
new file mode 100644
index 0000000..a7747f8
--- /dev/null
+++ b/services/audiopolicy/config/audio_policy_configuration_stub.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- 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.
+-->
+
+<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <modules>
+ <module name="stub" halVersion="2.0">
+ <attachedDevices>
+ <item>Default Out</item>
+ <item>Default In</item>
+ </attachedDevices>
+ <defaultOutputDevice>Default Out</defaultOutputDevice>
+ <mixPorts>
+ <mixPort name="stub output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+
+ <mixPort name="stub input" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+ </mixPorts>
+ <devicePorts>
+ <devicePort tagName="Default Out" type="AUDIO_DEVICE_OUT_STUB" role="sink">
+ </devicePort>
+
+ <devicePort tagName="Default In" type="AUDIO_DEVICE_IN_STUB" role="source">
+ </devicePort>
+ </devicePorts>
+ <routes>
+ <route type="mix" sink="Default Out" sources="stub output"/>
+
+ <route type="mix" sink="stub input" sources="Default In"/>
+ </routes>
+
+ </module>
+
+ <!-- Remote Submix Audio HAL -->
+ <xi:include href="r_submix_audio_policy_configuration.xml"/>
+
+ </modules>
+
+ <xi:include href="audio_policy_volumes.xml"/>
+ <xi:include href="default_volume_tables.xml"/>
+
+</audioPolicyConfiguration>
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index f2224fd..d31429c 100755
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -254,10 +254,6 @@
case STRATEGY_TRANSMITTED_THROUGH_SPEAKER:
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
- if (!device) {
- ALOGE("getDeviceForStrategy() no device found for "\
- "STRATEGY_TRANSMITTED_THROUGH_SPEAKER");
- }
break;
case STRATEGY_SONIFICATION_RESPECTFUL:
@@ -373,11 +369,6 @@
if (device) break;
}
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_EARPIECE;
- if (device) break;
- device = mApmObserver->getDefaultOutputDevice()->type();
- if (device == AUDIO_DEVICE_NONE) {
- ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE");
- }
break;
case AUDIO_POLICY_FORCE_SPEAKER:
@@ -402,11 +393,6 @@
if (device) break;
}
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
- if (device) break;
- device = mApmObserver->getDefaultOutputDevice()->type();
- if (device == AUDIO_DEVICE_NONE) {
- ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE, FORCE_SPEAKER");
- }
break;
}
break;
@@ -431,9 +417,6 @@
if ((strategy == STRATEGY_SONIFICATION) ||
(mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)) {
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
- if (device == AUDIO_DEVICE_NONE) {
- ALOGE("getDeviceForStrategy() speaker device not found for STRATEGY_SONIFICATION");
- }
}
// The second device used for sonification is the same as the device used by media strategy
// FALL THROUGH
@@ -545,12 +528,6 @@
AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) {
device &= ~AUDIO_DEVICE_OUT_SPEAKER;
}
-
- if (device) break;
- device = mApmObserver->getDefaultOutputDevice()->type();
- if (device == AUDIO_DEVICE_NONE) {
- ALOGE("getDeviceForStrategy() no device found for STRATEGY_MEDIA");
- }
} break;
default:
@@ -558,6 +535,12 @@
break;
}
+ if (device == AUDIO_DEVICE_NONE) {
+ ALOGV("getDeviceForStrategy() no device found for strategy %d", strategy);
+ device = mApmObserver->getDefaultOutputDevice()->type();
+ ALOGE_IF(device == AUDIO_DEVICE_NONE,
+ "getDeviceForStrategy() no default device defined");
+ }
ALOGVV("getDeviceForStrategy() strategy %d, device %x", strategy, device);
return device;
}
@@ -677,6 +660,14 @@
ALOGW("getDeviceForInputSource() invalid input source %d", inputSource);
break;
}
+ if (device == AUDIO_DEVICE_NONE) {
+ ALOGV("getDeviceForInputSource() no device found for source %d", inputSource);
+ if (availableDeviceTypes & AUDIO_DEVICE_IN_STUB) {
+ device = AUDIO_DEVICE_IN_STUB;
+ }
+ ALOGE_IF(device == AUDIO_DEVICE_NONE,
+ "getDeviceForInputSource() no default device defined");
+ }
ALOGV("getDeviceForInputSource()input source %d, device %08x", inputSource, device);
return device;
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index bf18975..21ce8c9 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -291,7 +291,15 @@
audio_policy_dev_state_t AudioPolicyManager::getDeviceConnectionState(audio_devices_t device,
const char *device_address)
{
- sp<DeviceDescriptor> devDesc = mHwModules.getDeviceDescriptor(device, device_address, "");
+ sp<DeviceDescriptor> devDesc =
+ mHwModules.getDeviceDescriptor(device, device_address, "",
+ (strlen(device_address) != 0)/*matchAddress*/);
+
+ if (devDesc == 0) {
+ ALOGW("getDeviceConnectionState() undeclared device, type %08x, address: %s",
+ device, device_address);
+ return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
+ }
DeviceVector *deviceVector;
@@ -303,7 +311,9 @@
ALOGW("getDeviceConnectionState() invalid device type %08x", device);
return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
}
- return deviceVector->getDeviceConnectionState(devDesc);
+
+ return (deviceVector->getDevice(device, String8(device_address)) != 0) ?
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE : AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
}
void AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, int delayMs)
@@ -1847,8 +1857,8 @@
// the requested device
// - For non default requested device, currently selected device on the output is either the
// requested device or one of the devices selected by the strategy
- // - For default requested device (AUDIO_DEVICE_OUT_DEFAULT), apply volume only if no specific
- // device volume value exists for currently selected device.
+ // - For default requested device (AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME), apply volume only if
+ // no specific device volume value exists for currently selected device.
status_t status = NO_ERROR;
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
@@ -1867,7 +1877,7 @@
continue;
}
bool applyDefault = false;
- if (device != AUDIO_DEVICE_OUT_DEFAULT) {
+ if (device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
curStreamDevice |= device;
} else if (!mVolumeCurves->hasVolumeIndexForDevice(
stream, Volume::getDeviceForVolume(curStreamDevice))) {
@@ -1896,9 +1906,9 @@
if (!audio_is_output_device(device)) {
return BAD_VALUE;
}
- // if device is AUDIO_DEVICE_OUT_DEFAULT, return volume for device corresponding to
+ // if device is AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME, return volume for device corresponding to
// the strategy the stream belongs to.
- if (device == AUDIO_DEVICE_OUT_DEFAULT) {
+ if (device == AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
device = getDeviceForStrategy(getStrategy(stream), true /*fromCache*/);
}
device = Volume::getDeviceForVolume(device);
@@ -2332,19 +2342,29 @@
size_t portsMax = *num_ports;
*num_ports = 0;
if (type == AUDIO_PORT_TYPE_NONE || type == AUDIO_PORT_TYPE_DEVICE) {
+ // do not report devices with type AUDIO_DEVICE_IN_STUB or AUDIO_DEVICE_OUT_STUB
+ // as they are used by stub HALs by convention
if (role == AUDIO_PORT_ROLE_SINK || role == AUDIO_PORT_ROLE_NONE) {
- for (size_t i = 0;
- i < mAvailableOutputDevices.size() && portsWritten < portsMax; i++) {
- mAvailableOutputDevices[i]->toAudioPort(&ports[portsWritten++]);
+ for (size_t i = 0; i < mAvailableOutputDevices.size(); i++) {
+ if (mAvailableOutputDevices[i]->type() == AUDIO_DEVICE_OUT_STUB) {
+ continue;
+ }
+ if (portsWritten < portsMax) {
+ mAvailableOutputDevices[i]->toAudioPort(&ports[portsWritten++]);
+ }
+ (*num_ports)++;
}
- *num_ports += mAvailableOutputDevices.size();
}
if (role == AUDIO_PORT_ROLE_SOURCE || role == AUDIO_PORT_ROLE_NONE) {
- for (size_t i = 0;
- i < mAvailableInputDevices.size() && portsWritten < portsMax; i++) {
- mAvailableInputDevices[i]->toAudioPort(&ports[portsWritten++]);
+ for (size_t i = 0; i < mAvailableInputDevices.size(); i++) {
+ if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_STUB) {
+ continue;
+ }
+ if (portsWritten < portsMax) {
+ mAvailableInputDevices[i]->toAudioPort(&ports[portsWritten++]);
+ }
+ (*num_ports)++;
}
- *num_ports += mAvailableInputDevices.size();
}
}
if (type == AUDIO_PORT_TYPE_NONE || type == AUDIO_PORT_TYPE_MIX) {
@@ -4881,7 +4901,9 @@
float volumeDb = mVolumeCurves->volIndexToDb(stream, Volume::getDeviceCategory(device), index);
// if a headset is connected, apply the following rules to ring tones and notifications
// to avoid sound level bursts in user's ears:
- // - always attenuate ring tones and notifications volume by 6dB
+ // - always attenuate notifications volume by 6dB
+ // - attenuate ring tones volume by 6dB unless music is not playing and
+ // speaker is part of the select devices
// - if music is playing, always limit the volume to current music volume,
// with a minimum threshold at -36dB so that notification is always perceived.
const routing_strategy stream_strategy = getStrategy(stream);
@@ -4895,12 +4917,12 @@
|| ((stream_strategy == STRATEGY_ENFORCED_AUDIBLE) &&
(mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_NONE))) &&
mVolumeCurves->canBeMuted(stream)) {
- volumeDb += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
// when the phone is ringing we must consider that music could have been paused just before
// by the music application and behave as if music was active if the last music track was
// just stopped
if (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY) ||
mLimitRingtoneVolume) {
+ volumeDb += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
audio_devices_t musicDevice = getDeviceForStrategy(STRATEGY_MEDIA, true /*fromCache*/);
float musicVolDB = computeVolume(AUDIO_STREAM_MUSIC,
mVolumeCurves->getVolumeIndex(AUDIO_STREAM_MUSIC,
@@ -4912,6 +4934,9 @@
volumeDb = minVolDB;
ALOGV("computeVolume limiting volume to %f musicVol %f", minVolDB, musicVolDB);
}
+ } else if ((Volume::getDeviceForVolume(device) != AUDIO_DEVICE_OUT_SPEAKER) ||
+ stream_strategy != STRATEGY_SONIFICATION) {
+ volumeDb += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
}
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 94357b9..2d6a873 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -49,10 +49,8 @@
// ----------------------------------------------------------------------------
// Attenuation applied to STRATEGY_SONIFICATION streams when a headset is connected: 6dB
-#define SONIFICATION_HEADSET_VOLUME_FACTOR 0.5
#define SONIFICATION_HEADSET_VOLUME_FACTOR_DB (-6)
// Min volume for STRATEGY_SONIFICATION streams when limited by music volume: -36dB
-#define SONIFICATION_HEADSET_VOLUME_MIN 0.016
#define SONIFICATION_HEADSET_VOLUME_MIN_DB (-36)
// Time in milliseconds during which we consider that music is still active after a music
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index c011613..ebe65e4 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -66,7 +66,8 @@
libhardware \
libsync \
libcamera_metadata \
- libjpeg
+ libjpeg \
+ libmemunreachable
LOCAL_C_INCLUDES += \
system/media/private/camera/include \
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 0c88dad..fcb72e8 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -41,6 +41,7 @@
#include <cutils/properties.h>
#include <gui/Surface.h>
#include <hardware/hardware.h>
+#include <memunreachable/memunreachable.h>
#include <media/AudioSystem.h>
#include <media/IMediaHTTPService.h>
#include <media/mediaplayer.h>
@@ -2595,16 +2596,32 @@
write(fd, "\n", 1);
camera3::CameraTraces::dump(fd, args);
- // change logging level
+ // Process dump arguments, if any
int n = args.size();
- for (int i = 0; i + 1 < n; i++) {
- String16 verboseOption("-v");
+ String16 verboseOption("-v");
+ String16 unreachableOption("--unreachable");
+ for (int i = 0; i < n; i++) {
if (args[i] == verboseOption) {
+ // change logging level
+ if (i + 1 >= n) continue;
String8 levelStr(args[i+1]);
int level = atoi(levelStr.string());
result = String8::format("\nSetting log level to %d.\n", level);
setLogLevel(level);
write(fd, result.string(), result.size());
+ } else if (args[i] == unreachableOption) {
+ // Dump memory analysis
+ // TODO - should limit be an argument parameter?
+ UnreachableMemoryInfo info;
+ bool success = GetUnreachableMemory(info, /*limit*/ 10000);
+ if (!success) {
+ dprintf(fd, "\nUnable to dump unreachable memory. "
+ "Try disabling SELinux enforcement.\n");
+ } else {
+ dprintf(fd, "\nDumping unreachable memory:\n");
+ std::string s = info.ToString(/*log_contents*/ true);
+ write(fd, s.c_str(), s.size());
+ }
}
}
}