diff options
Diffstat (limited to 'services')
24 files changed, 535 insertions, 244 deletions
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 45e17f8..9bd0e9b 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -143,7 +143,7 @@ static int load_audio_interface(const char *if_name, audio_hw_device_t **dev) if (rc) { goto out; } - if ((*dev)->common.version != AUDIO_DEVICE_API_VERSION_CURRENT) { + if ((*dev)->common.version < AUDIO_DEVICE_API_VERSION_MIN) { ALOGE("%s wrong audio hw device version %04x", __func__, (*dev)->common.version); rc = BAD_VALUE; goto out; @@ -427,7 +427,7 @@ status_t AudioFlinger::dump(int fd, const Vector<String16>& args) if (mLogMemoryDealer != 0) { sp<IBinder> binder = defaultServiceManager()->getService(String16("media.log")); if (binder != 0) { - fdprintf(fd, "\nmedia.log:\n"); + dprintf(fd, "\nmedia.log:\n"); Vector<String16> args; binder->dump(fd, args); } @@ -635,8 +635,12 @@ sp<IAudioTrack> AudioFlinger::createTrack( if (lStatus != NO_ERROR) { // remove local strong reference to Client before deleting the Track so that the // Client destructor is called by the TrackBase destructor with mClientLock held - Mutex::Autolock _cl(mClientLock); - client.clear(); + // Don't hold mClientLock when releasing the reference on the track as the + // destructor will acquire it. + { + Mutex::Autolock _cl(mClientLock); + client.clear(); + } track.clear(); goto Exit; } @@ -1173,7 +1177,7 @@ void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client) } // mClientLock should not be held here because ThreadBase::sendIoConfigEvent() will lock the - // ThreadBase mutex and teh locknig order is ThreadBase::mLock then AudioFlinger::mClientLock. + // ThreadBase mutex and the locking order is ThreadBase::mLock then AudioFlinger::mClientLock. if (clientAdded) { // the config change is always sent from playback or record threads to avoid deadlock // with AudioSystem::gLock @@ -1419,8 +1423,12 @@ sp<IAudioRecord> AudioFlinger::openRecord( if (lStatus != NO_ERROR) { // remove local strong reference to Client before deleting the RecordTrack so that the // Client destructor is called by the TrackBase destructor with mClientLock held - Mutex::Autolock _cl(mClientLock); - client.clear(); + // Don't hold mClientLock when releasing the reference on the track as the + // destructor will acquire it. + { + Mutex::Autolock _cl(mClientLock); + client.clear(); + } recordTrack.clear(); goto Exit; } @@ -2380,6 +2388,11 @@ sp<IEffect> AudioFlinger::createEffect( if (handle != 0 && id != NULL) { *id = handle->id(); } + if (handle == 0) { + // remove local strong reference to Client with mClientLock held + Mutex::Autolock _cl(mClientLock); + client.clear(); + } } Exit: @@ -2590,7 +2603,7 @@ void AudioFlinger::dumpTee(int fd, const sp<NBAIO_Source>& source, audio_io_hand } } else { if (fd >= 0) { - fdprintf(fd, "unable to rotate tees in %s: %s\n", teePath, strerror(errno)); + dprintf(fd, "unable to rotate tees in %s: %s\n", teePath, strerror(errno)); } } char teeTime[16]; @@ -2644,11 +2657,11 @@ void AudioFlinger::dumpTee(int fd, const sp<NBAIO_Source>& source, audio_io_hand write(teeFd, &temp, sizeof(temp)); close(teeFd); if (fd >= 0) { - fdprintf(fd, "tee copied to %s\n", teePath); + dprintf(fd, "tee copied to %s\n", teePath); } } else { if (fd >= 0) { - fdprintf(fd, "unable to create tee %s: %s\n", teePath, strerror(errno)); + dprintf(fd, "unable to create tee %s: %s\n", teePath, strerror(errno)); } } } diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index d69d6a2..d2ded9a 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -82,9 +82,6 @@ class ServerProxy; static const nsecs_t kDefaultStandbyTimeInNsecs = seconds(3); -#define MAX_GAIN 4096.0f -#define MAX_GAIN_INT 0x1000 - #define INCLUDING_FROM_AUDIOFLINGER_H class AudioFlinger : diff --git a/services/audioflinger/AudioMixer.h b/services/audioflinger/AudioMixer.h index eca9848..573ba96 100644 --- a/services/audioflinger/AudioMixer.h +++ b/services/audioflinger/AudioMixer.h @@ -30,6 +30,9 @@ #include <system/audio.h> #include <media/nbaio/NBLog.h> +// FIXME This is actually unity gain, which might not be max in future, expressed in U.12 +#define MAX_GAIN_INT AudioMixer::UNITY_GAIN + namespace android { // ---------------------------------------------------------------------------- @@ -91,6 +94,7 @@ public: REMOVE = 0x4102, // Remove the sample rate converter on this track name; // the track is restored to the mix sample rate. // for target RAMP_VOLUME and VOLUME (8 channels max) + // FIXME use float for these 3 to improve the dynamic range VOLUME0 = 0x4200, VOLUME1 = 0x4201, AUXLEVEL = 0x4210, diff --git a/services/audioflinger/AudioWatchdog.cpp b/services/audioflinger/AudioWatchdog.cpp index 93d185e..877e776 100644 --- a/services/audioflinger/AudioWatchdog.cpp +++ b/services/audioflinger/AudioWatchdog.cpp @@ -34,7 +34,7 @@ void AudioWatchdogDump::dump(int fd) } else { strcpy(buf, "N/A\n"); } - fdprintf(fd, "Watchdog: underruns=%u, logs=%u, most recent underrun log at %s", + dprintf(fd, "Watchdog: underruns=%u, logs=%u, most recent underrun log at %s", mUnderruns, mLogs, buf); } diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h index ccc4825..4170fd4 100644 --- a/services/audioflinger/Effects.h +++ b/services/audioflinger/Effects.h @@ -270,6 +270,7 @@ public: sp<EffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor); sp<EffectModule> getEffectFromId_l(int id); sp<EffectModule> getEffectFromType_l(const effect_uuid_t *type); + // FIXME use float to improve the dynamic range bool setVolume_l(uint32_t *left, uint32_t *right); void setDevice_l(audio_devices_t device); void setMode_l(audio_mode_t mode); diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp index c1c7dd8f..c840418 100644 --- a/services/audioflinger/FastMixer.cpp +++ b/services/audioflinger/FastMixer.cpp @@ -26,7 +26,6 @@ #define ATRACE_TAG ATRACE_TAG_AUDIO #include "Configuration.h" -#include <sys/atomics.h> #include <time.h> #include <utils/Log.h> #include <utils/Trace.h> @@ -256,9 +255,9 @@ void FastMixer::onStateChange() mixer->setBufferProvider(name, bufferProvider); if (fastTrack->mVolumeProvider == NULL) { mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, - (void *)0x1000); + (void *) MAX_GAIN_INT); mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, - (void *)0x1000); + (void *) MAX_GAIN_INT); } mixer->setParameter(name, AudioMixer::RESAMPLE, AudioMixer::REMOVE, NULL); @@ -313,11 +312,13 @@ void FastMixer::onWork() int name = fastTrackNames[i]; ALOG_ASSERT(name >= 0); if (fastTrack->mVolumeProvider != NULL) { - uint32_t vlr = fastTrack->mVolumeProvider->getVolumeLR(); + gain_minifloat_packed_t vlr = fastTrack->mVolumeProvider->getVolumeLR(); mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, - (void *)(uintptr_t)(vlr & 0xFFFF)); + (void *) (uintptr_t) + (float_from_gain(gain_minifloat_unpack_left(vlr)) * MAX_GAIN_INT)); mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, - (void *)(uintptr_t)(vlr >> 16)); + (void *) (uintptr_t) + (float_from_gain(gain_minifloat_unpack_right(vlr)) * MAX_GAIN_INT)); } // FIXME The current implementation of framesReady() for fast tracks // takes a tryLock, which can block @@ -464,7 +465,7 @@ static int compare_uint32_t(const void *pa, const void *pb) void FastMixerDumpState::dump(int fd) const { if (mCommand == FastMixerState::INITIAL) { - fdprintf(fd, " FastMixer not initialized\n"); + dprintf(fd, " FastMixer not initialized\n"); return; } #define COMMAND_MAX 32 @@ -498,10 +499,10 @@ void FastMixerDumpState::dump(int fd) const double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) + (mMeasuredWarmupTs.tv_nsec / 1000000.0); double mixPeriodSec = (double) mFrameCount / (double) mSampleRate; - fdprintf(fd, " FastMixer command=%s writeSequence=%u framesWritten=%u\n" - " numTracks=%u writeErrors=%u underruns=%u overruns=%u\n" - " sampleRate=%u frameCount=%zu measuredWarmup=%.3g ms, warmupCycles=%u\n" - " mixPeriod=%.2f ms\n", + dprintf(fd, " FastMixer command=%s writeSequence=%u framesWritten=%u\n" + " numTracks=%u writeErrors=%u underruns=%u overruns=%u\n" + " sampleRate=%u frameCount=%zu measuredWarmup=%.3g ms, warmupCycles=%u\n" + " mixPeriod=%.2f ms\n", string, mWriteSequence, mFramesWritten, mNumTracks, mWriteErrors, mUnderruns, mOverruns, mSampleRate, mFrameCount, measuredWarmupMs, mWarmupCycles, @@ -553,26 +554,26 @@ void FastMixerDumpState::dump(int fd) const #endif } if (n) { - fdprintf(fd, " Simple moving statistics over last %.1f seconds:\n", - wall.n() * mixPeriodSec); - fdprintf(fd, " wall clock time in ms per mix cycle:\n" - " mean=%.2f min=%.2f max=%.2f stddev=%.2f\n", - wall.mean()*1e-6, wall.minimum()*1e-6, wall.maximum()*1e-6, - wall.stddev()*1e-6); - fdprintf(fd, " raw CPU load in us per mix cycle:\n" - " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n", - loadNs.mean()*1e-3, loadNs.minimum()*1e-3, loadNs.maximum()*1e-3, - loadNs.stddev()*1e-3); + dprintf(fd, " Simple moving statistics over last %.1f seconds:\n", + wall.n() * mixPeriodSec); + dprintf(fd, " wall clock time in ms per mix cycle:\n" + " mean=%.2f min=%.2f max=%.2f stddev=%.2f\n", + wall.mean()*1e-6, wall.minimum()*1e-6, wall.maximum()*1e-6, + wall.stddev()*1e-6); + dprintf(fd, " raw CPU load in us per mix cycle:\n" + " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n", + loadNs.mean()*1e-3, loadNs.minimum()*1e-3, loadNs.maximum()*1e-3, + loadNs.stddev()*1e-3); } else { - fdprintf(fd, " No FastMixer statistics available currently\n"); + dprintf(fd, " No FastMixer statistics available currently\n"); } #ifdef CPU_FREQUENCY_STATISTICS - fdprintf(fd, " CPU clock frequency in MHz:\n" - " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n", - kHz.mean()*1e-3, kHz.minimum()*1e-3, kHz.maximum()*1e-3, kHz.stddev()*1e-3); - fdprintf(fd, " adjusted CPU load in MHz (i.e. normalized for CPU clock frequency):\n" - " mean=%.1f min=%.1f max=%.1f stddev=%.1f\n", - loadMHz.mean(), loadMHz.minimum(), loadMHz.maximum(), loadMHz.stddev()); + dprintf(fd, " CPU clock frequency in MHz:\n" + " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n", + kHz.mean()*1e-3, kHz.minimum()*1e-3, kHz.maximum()*1e-3, kHz.stddev()*1e-3); + dprintf(fd, " adjusted CPU load in MHz (i.e. normalized for CPU clock frequency):\n" + " mean=%.1f min=%.1f max=%.1f stddev=%.1f\n", + loadMHz.mean(), loadMHz.minimum(), loadMHz.maximum(), loadMHz.stddev()); #endif if (tail != NULL) { qsort(tail, n, sizeof(uint32_t), compare_uint32_t); @@ -583,12 +584,12 @@ void FastMixerDumpState::dump(int fd) const left.sample(tail[i]); right.sample(tail[n - (i + 1)]); } - fdprintf(fd, " Distribution of mix cycle times in ms for the tails (> ~3 stddev outliers):\n" - " left tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n" - " right tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n", - left.mean()*1e-6, left.minimum()*1e-6, left.maximum()*1e-6, left.stddev()*1e-6, - right.mean()*1e-6, right.minimum()*1e-6, right.maximum()*1e-6, - right.stddev()*1e-6); + dprintf(fd, " Distribution of mix cycle times in ms for the tails (> ~3 stddev outliers):\n" + " left tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n" + " right tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n", + left.mean()*1e-6, left.minimum()*1e-6, left.maximum()*1e-6, left.stddev()*1e-6, + right.mean()*1e-6, right.minimum()*1e-6, right.maximum()*1e-6, + right.stddev()*1e-6); delete[] tail; } #endif @@ -598,9 +599,9 @@ void FastMixerDumpState::dump(int fd) const // Instead we always display all tracks, with an indication // of whether we think the track is active. uint32_t trackMask = mTrackMask; - fdprintf(fd, " Fast tracks: kMaxFastTracks=%u activeMask=%#x\n", + dprintf(fd, " Fast tracks: kMaxFastTracks=%u activeMask=%#x\n", FastMixerState::kMaxFastTracks, trackMask); - fdprintf(fd, " Index Active Full Partial Empty Recent Ready\n"); + dprintf(fd, " Index Active Full Partial Empty Recent Ready\n"); for (uint32_t i = 0; i < FastMixerState::kMaxFastTracks; ++i, trackMask >>= 1) { bool isActive = trackMask & 1; const FastTrackDump *ftDump = &mTracks[i]; @@ -620,7 +621,7 @@ void FastMixerDumpState::dump(int fd) const mostRecent = "?"; break; } - fdprintf(fd, " %5u %6s %4u %7u %5u %7s %5zu\n", i, isActive ? "yes" : "no", + dprintf(fd, " %5u %6s %4u %7u %5u %7s %5zu\n", i, isActive ? "yes" : "no", (underruns.mBitFields.mFull) & UNDERRUN_MASK, (underruns.mBitFields.mPartial) & UNDERRUN_MASK, (underruns.mBitFields.mEmpty) & UNDERRUN_MASK, diff --git a/services/audioflinger/FastMixer.h b/services/audioflinger/FastMixer.h index 7be004a..db3e2c9 100644 --- a/services/audioflinger/FastMixer.h +++ b/services/audioflinger/FastMixer.h @@ -17,13 +17,11 @@ #ifndef ANDROID_AUDIO_FAST_MIXER_H #define ANDROID_AUDIO_FAST_MIXER_H +#include <linux/futex.h> +#include <sys/syscall.h> #include <utils/Debug.h> -#if 1 // FIXME move to where used -extern "C" { -#include "../private/bionic_futex.h" -} -#endif #include "FastThread.h" +#include <utils/Thread.h> #include "StateQueue.h" #include "FastMixerState.h" #include "FastMixerDumpState.h" diff --git a/services/audioflinger/FastMixerState.h b/services/audioflinger/FastMixerState.h index cb54ff1..661c9ca 100644 --- a/services/audioflinger/FastMixerState.h +++ b/services/audioflinger/FastMixerState.h @@ -17,6 +17,7 @@ #ifndef ANDROID_AUDIO_FAST_MIXER_STATE_H #define ANDROID_AUDIO_FAST_MIXER_STATE_H +#include <audio_utils/minifloat.h> #include <system/audio.h> #include <media/ExtendedAudioBufferProvider.h> #include <media/nbaio/NBAIO.h> @@ -29,9 +30,8 @@ struct FastMixerDumpState; class VolumeProvider { public: - // Return the track volume in U4_12 format: left in lower half, right in upper half. The - // provider implementation is responsible for validating that the return value is in range. - virtual uint32_t getVolumeLR() = 0; + // The provider implementation is responsible for validating that the return value is in range. + virtual gain_minifloat_packed_t getVolumeLR() = 0; protected: VolumeProvider() { } virtual ~VolumeProvider() { } diff --git a/services/audioflinger/FastThread.cpp b/services/audioflinger/FastThread.cpp index 8a216b3..216dace 100644 --- a/services/audioflinger/FastThread.cpp +++ b/services/audioflinger/FastThread.cpp @@ -20,10 +20,9 @@ #define ATRACE_TAG ATRACE_TAG_AUDIO #include "Configuration.h" +#include <linux/futex.h> +#include <sys/syscall.h> #include <utils/Log.h> -extern "C" { -#include "../private/bionic_futex.h" -} #include <utils/Trace.h> #include "FastThread.h" @@ -157,7 +156,7 @@ bool FastThread::threadLoop() ALOG_ASSERT(coldFutexAddr != NULL); int32_t old = android_atomic_dec(coldFutexAddr); if (old <= 0) { - __futex_syscall4(coldFutexAddr, FUTEX_WAIT_PRIVATE, old - 1, NULL); + syscall(__NR_futex, coldFutexAddr, FUTEX_WAIT_PRIVATE, old - 1, NULL); } int policy = sched_getscheduler(0); if (!(policy == SCHED_FIFO || policy == SCHED_RR)) { diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h index 08b1728..6f1f293 100644 --- a/services/audioflinger/PlaybackTracks.h +++ b/services/audioflinger/PlaybackTracks.h @@ -65,7 +65,7 @@ public: void signal(); // implement FastMixerState::VolumeProvider interface - virtual uint32_t getVolumeLR(); + virtual gain_minifloat_packed_t getVolumeLR(); virtual status_t setSyncEvent(const sp<SyncEvent>& event); diff --git a/services/audioflinger/StateQueue.cpp b/services/audioflinger/StateQueue.cpp index 48399c0..7e01c9f 100644 --- a/services/audioflinger/StateQueue.cpp +++ b/services/audioflinger/StateQueue.cpp @@ -28,12 +28,12 @@ namespace android { #ifdef STATE_QUEUE_DUMP void StateQueueObserverDump::dump(int fd) { - fdprintf(fd, "State queue observer: stateChanges=%u\n", mStateChanges); + dprintf(fd, "State queue observer: stateChanges=%u\n", mStateChanges); } void StateQueueMutatorDump::dump(int fd) { - fdprintf(fd, "State queue mutator: pushDirty=%u pushAck=%u blockedSequence=%u\n", + dprintf(fd, "State queue mutator: pushDirty=%u pushAck=%u blockedSequence=%u\n", mPushDirty, mPushAck, mBlockedSequence); } #endif diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 0a18433..7843387 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -35,6 +35,7 @@ #include <audio_effects/effect_aec.h> #include <audio_utils/primitives.h> #include <audio_utils/format.h> +#include <audio_utils/minifloat.h> // NBAIO implementations #include <media/nbaio/AudioStreamOutSink.h> @@ -504,30 +505,30 @@ void AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args __u bool locked = AudioFlinger::dumpTryLock(mLock); if (!locked) { - fdprintf(fd, "thread %p maybe dead locked\n", this); + dprintf(fd, "thread %p maybe dead locked\n", this); } - fdprintf(fd, " I/O handle: %d\n", mId); - fdprintf(fd, " TID: %d\n", getTid()); - fdprintf(fd, " Standby: %s\n", mStandby ? "yes" : "no"); - fdprintf(fd, " Sample rate: %u\n", mSampleRate); - fdprintf(fd, " HAL frame count: %zu\n", mFrameCount); - fdprintf(fd, " HAL buffer size: %u bytes\n", mBufferSize); - fdprintf(fd, " Channel Count: %u\n", mChannelCount); - fdprintf(fd, " Channel Mask: 0x%08x (%s)\n", mChannelMask, + dprintf(fd, " I/O handle: %d\n", mId); + dprintf(fd, " TID: %d\n", getTid()); + dprintf(fd, " Standby: %s\n", mStandby ? "yes" : "no"); + dprintf(fd, " Sample rate: %u\n", mSampleRate); + dprintf(fd, " HAL frame count: %zu\n", mFrameCount); + dprintf(fd, " HAL buffer size: %u bytes\n", mBufferSize); + dprintf(fd, " Channel Count: %u\n", mChannelCount); + dprintf(fd, " Channel Mask: 0x%08x (%s)\n", mChannelMask, channelMaskToString(mChannelMask, mType != RECORD).string()); - fdprintf(fd, " Format: 0x%x (%s)\n", mFormat, formatToString(mFormat)); - fdprintf(fd, " Frame size: %zu\n", mFrameSize); - fdprintf(fd, " Pending config events:"); + dprintf(fd, " Format: 0x%x (%s)\n", mFormat, formatToString(mFormat)); + dprintf(fd, " Frame size: %zu\n", mFrameSize); + dprintf(fd, " Pending config events:"); size_t numConfig = mConfigEvents.size(); if (numConfig) { for (size_t i = 0; i < numConfig; i++) { mConfigEvents[i]->dump(buffer, SIZE); - fdprintf(fd, "\n %s", buffer); + dprintf(fd, "\n %s", buffer); } - fdprintf(fd, "\n"); + dprintf(fd, "\n"); } else { - fdprintf(fd, " none\n"); + dprintf(fd, " none\n"); } if (locked) { @@ -1190,15 +1191,15 @@ void AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& ar // These values are "raw"; they will wrap around. See prepareTracks_l() for a better way. FastTrackUnderruns underruns = getFastTrackUnderruns(0); - fdprintf(fd, " Normal mixer raw underrun counters: partial=%u empty=%u\n", + dprintf(fd, " Normal mixer raw underrun counters: partial=%u empty=%u\n", underruns.mBitFields.mPartial, underruns.mBitFields.mEmpty); size_t numtracks = mTracks.size(); size_t numactive = mActiveTracks.size(); - fdprintf(fd, " %d Tracks", numtracks); + dprintf(fd, " %d Tracks", numtracks); size_t numactiveseen = 0; if (numtracks) { - fdprintf(fd, " of which %d are active\n", numactive); + dprintf(fd, " of which %d are active\n", numactive); Track::appendDumpHeader(result); for (size_t i = 0; i < numtracks; ++i) { sp<Track> track = mTracks[i]; @@ -1230,22 +1231,21 @@ void AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& ar } write(fd, result.string(), result.size()); - } void AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args) { - fdprintf(fd, "\nOutput thread %p:\n", this); - fdprintf(fd, " Normal frame count: %zu\n", mNormalFrameCount); - fdprintf(fd, " Last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime)); - fdprintf(fd, " Total writes: %d\n", mNumWrites); - fdprintf(fd, " Delayed writes: %d\n", mNumDelayedWrites); - fdprintf(fd, " Blocked in write: %s\n", mInWrite ? "yes" : "no"); - fdprintf(fd, " Suspend count: %d\n", mSuspended); - fdprintf(fd, " Sink buffer : %p\n", mSinkBuffer); - fdprintf(fd, " Mixer buffer: %p\n", mMixerBuffer); - fdprintf(fd, " Effect buffer: %p\n", mEffectBuffer); - fdprintf(fd, " Fast track availMask=%#x\n", mFastTrackAvailMask); + dprintf(fd, "\nOutput thread %p:\n", this); + dprintf(fd, " Normal frame count: %zu\n", mNormalFrameCount); + dprintf(fd, " Last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime)); + dprintf(fd, " Total writes: %d\n", mNumWrites); + dprintf(fd, " Delayed writes: %d\n", mNumDelayedWrites); + dprintf(fd, " Blocked in write: %s\n", mInWrite ? "yes" : "no"); + dprintf(fd, " Suspend count: %d\n", mSuspended); + dprintf(fd, " Sink buffer : %p\n", mSinkBuffer); + dprintf(fd, " Mixer buffer: %p\n", mMixerBuffer); + dprintf(fd, " Effect buffer: %p\n", mEffectBuffer); + dprintf(fd, " Fast track availMask=%#x\n", mFastTrackAvailMask); dumpBase(fd, args); } @@ -2753,7 +2753,7 @@ AudioFlinger::MixerThread::~MixerThread() if (state->mCommand == FastMixerState::COLD_IDLE) { int32_t old = android_atomic_inc(&mFastMixerFutex); if (old == -1) { - (void) __futex_syscall3(&mFastMixerFutex, FUTEX_WAKE_PRIVATE, 1); + (void) syscall(__NR_futex, &mFastMixerFutex, FUTEX_WAKE_PRIVATE, 1); } } state->mCommand = FastMixerState::EXIT; @@ -2810,7 +2810,7 @@ ssize_t AudioFlinger::MixerThread::threadLoop_write() if (state->mCommand == FastMixerState::COLD_IDLE) { int32_t old = android_atomic_inc(&mFastMixerFutex); if (old == -1) { - (void) __futex_syscall3(&mFastMixerFutex, FUTEX_WAKE_PRIVATE, 1); + (void) syscall(__NR_futex, &mFastMixerFutex, FUTEX_WAKE_PRIVATE, 1); } #ifdef AUDIO_WATCHDOG if (mAudioWatchdog != 0) { @@ -3258,21 +3258,23 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac float typeVolume = mStreamTypes[track->streamType()].volume; float v = masterVolume * typeVolume; AudioTrackServerProxy *proxy = track->mAudioTrackServerProxy; - uint32_t vlr = proxy->getVolumeLR(); - vl = vlr & 0xFFFF; - vr = vlr >> 16; + gain_minifloat_packed_t vlr = proxy->getVolumeLR(); + float vlf = float_from_gain(gain_minifloat_unpack_left(vlr)); + float vrf = float_from_gain(gain_minifloat_unpack_right(vlr)); // track volumes come from shared memory, so can't be trusted and must be clamped - if (vl > MAX_GAIN_INT) { - ALOGV("Track left volume out of range: %04X", vl); - vl = MAX_GAIN_INT; + if (vlf > GAIN_FLOAT_UNITY) { + ALOGV("Track left volume out of range: %.3g", vlf); + vlf = GAIN_FLOAT_UNITY; } - if (vr > MAX_GAIN_INT) { - ALOGV("Track right volume out of range: %04X", vr); - vr = MAX_GAIN_INT; + if (vrf > GAIN_FLOAT_UNITY) { + ALOGV("Track right volume out of range: %.3g", vrf); + vrf = GAIN_FLOAT_UNITY; } // now apply the master volume and stream type volume - vl = (uint32_t)(v * vl) << 12; - vr = (uint32_t)(v * vr) << 12; + // FIXME we're losing the wonderful dynamic range in the minifloat representation + float v8_24 = v * (MAX_GAIN_INT * MAX_GAIN_INT); + vl = (uint32_t) (v8_24 * vlf); + vr = (uint32_t) (v8_24 * vrf); // assuming master volume and stream type volume each go up to 1.0, // vl and vr are now in 8.24 format @@ -3299,6 +3301,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac track->mHasVolumeController = false; } + // FIXME Use float // Convert volumes from 8.24 to 4.12 format // This additional clamping is needed in case chain->setVolume_l() overshot vl = (vl + (1 << 11)) >> 12; @@ -3674,7 +3677,7 @@ void AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& ar PlaybackThread::dumpInternals(fd, args); - fdprintf(fd, " AudioMixer tracks: 0x%08x\n", mAudioMixer->trackNames()); + dprintf(fd, " AudioMixer tracks: 0x%08x\n", mAudioMixer->trackNames()); // Make a non-atomic copy of fast mixer dump state so it won't change underneath us const FastMixerDumpState copy(mFastMixerDumpState); @@ -3755,13 +3758,17 @@ void AudioFlinger::DirectOutputThread::processVolume_l(Track *track, bool lastTr float typeVolume = mStreamTypes[track->streamType()].volume; float v = mMasterVolume * typeVolume; AudioTrackServerProxy *proxy = track->mAudioTrackServerProxy; - uint32_t vlr = proxy->getVolumeLR(); - float v_clamped = v * (vlr & 0xFFFF); - if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN; - left = v_clamped/MAX_GAIN; - v_clamped = v * (vlr >> 16); - if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN; - right = v_clamped/MAX_GAIN; + gain_minifloat_packed_t vlr = proxy->getVolumeLR(); + left = float_from_gain(gain_minifloat_unpack_left(vlr)); + if (left > GAIN_FLOAT_UNITY) { + left = GAIN_FLOAT_UNITY; + } + left *= v; + right = float_from_gain(gain_minifloat_unpack_right(vlr)); + if (right > GAIN_FLOAT_UNITY) { + right = GAIN_FLOAT_UNITY; + } + right *= v; } if (lastTrack) { @@ -4157,7 +4164,10 @@ void AudioFlinger::OffloadThread::threadLoop_exit() mMixerStatus = MIXER_DRAIN_ALL; threadLoop_drain(); } - mCallbackThread->exit(); + if (mUseAsyncWrite) { + ALOG_ASSERT(mCallbackThread != 0); + mCallbackThread->exit(); + } PlaybackThread::threadLoop_exit(); } @@ -5122,6 +5132,7 @@ sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRe // to be at least 2 x the record thread frame count and cover audio hardware latency. // This is probably too conservative, but legacy application code may depend on it. // If you change this calculation, also review the start threshold which is related. + // FIXME It's not clear how input latency actually matters. Perhaps this should be 0. uint32_t latencyMs = 50; // FIXME mInput->stream->get_latency(mInput->stream); size_t mNormalFrameCount = 2048; // FIXME uint32_t minBufCount = latencyMs / ((1000 * mNormalFrameCount) / mSampleRate); @@ -5354,12 +5365,12 @@ void AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args) void AudioFlinger::RecordThread::dumpInternals(int fd, const Vector<String16>& args) { - fdprintf(fd, "\nInput thread %p:\n", this); + dprintf(fd, "\nInput thread %p:\n", this); if (mActiveTracks.size() > 0) { - fdprintf(fd, " Buffer size: %zu bytes\n", mBufferSize); + dprintf(fd, " Buffer size: %zu bytes\n", mBufferSize); } else { - fdprintf(fd, " No active record clients\n"); + dprintf(fd, " No active record clients\n"); } dumpBase(fd, args); @@ -5374,9 +5385,9 @@ void AudioFlinger::RecordThread::dumpTracks(int fd, const Vector<String16>& args size_t numtracks = mTracks.size(); size_t numactive = mActiveTracks.size(); size_t numactiveseen = 0; - fdprintf(fd, " %d Tracks", numtracks); + dprintf(fd, " %d Tracks", numtracks); if (numtracks) { - fdprintf(fd, " of which %d are active\n", numactive); + dprintf(fd, " of which %d are active\n", numactive); RecordTrack::appendDumpHeader(result); for (size_t i = 0; i < numtracks ; ++i) { sp<RecordTrack> track = mTracks[i]; @@ -5390,7 +5401,7 @@ void AudioFlinger::RecordThread::dumpTracks(int fd, const Vector<String16>& args } } } else { - fdprintf(fd, "\n"); + dprintf(fd, "\n"); } if (numactiveseen != numactive) { diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h index 1b01512..44008e5 100644 --- a/services/audioflinger/Threads.h +++ b/services/audioflinger/Threads.h @@ -301,6 +301,8 @@ public: // If a thread does not have such a heap, this method returns 0. virtual sp<MemoryDealer> readOnlyHeap() const { return 0; } + virtual sp<IMemory> pipeMemory() const { return 0; } + mutable Mutex mLock; protected: diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h index 5f13be3..4cba3fd 100644 --- a/services/audioflinger/TrackBase.h +++ b/services/audioflinger/TrackBase.h @@ -39,6 +39,13 @@ public: STARTING_2, // for RecordTrack only }; + // where to allocate the data buffer + enum alloc_type { + ALLOC_CBLK, // allocate immediately after control block + ALLOC_READONLY, // allocate from a separate read-only heap per thread + ALLOC_PIPE, // do not allocate; use the pipe buffer + }; + TrackBase(ThreadBase *thread, const sp<Client>& client, uint32_t sampleRate, @@ -50,7 +57,7 @@ public: int uid, IAudioFlinger::track_flags_t flags, bool isOut, - bool useReadOnlyHeap = false); + alloc_type alloc = ALLOC_CBLK); virtual ~TrackBase(); virtual status_t initCheck() const { return getCblk() != 0 ? NO_ERROR : NO_MEMORY; } diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index 222ec53..7ddc71c 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -21,6 +21,7 @@ #include "Configuration.h" #include <math.h> +#include <sys/syscall.h> #include <utils/Log.h> #include <private/media/AudioTrackShared.h> @@ -34,6 +35,7 @@ #include <media/nbaio/Pipe.h> #include <media/nbaio/PipeReader.h> +#include <audio_utils/minifloat.h> // ---------------------------------------------------------------------------- @@ -71,7 +73,7 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( int clientUid, IAudioFlinger::track_flags_t flags, bool isOut, - bool useReadOnlyHeap) + alloc_type alloc) : RefBase(), mThread(thread), mClient(client), @@ -115,7 +117,7 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize); size_t size = sizeof(audio_track_cblk_t); size_t bufferSize = (sharedBuffer == 0 ? roundup(frameCount) : frameCount) * mFrameSize; - if (sharedBuffer == 0 && !useReadOnlyHeap) { + if (sharedBuffer == 0 && alloc == ALLOC_CBLK) { size += bufferSize; } @@ -137,7 +139,8 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( // construct the shared structure in-place. if (mCblk != NULL) { new(mCblk) audio_track_cblk_t(); - if (useReadOnlyHeap) { + switch (alloc) { + case ALLOC_READONLY: { const sp<MemoryDealer> roHeap(thread->readOnlyHeap()); if (roHeap == 0 || (mBufferMemory = roHeap->allocate(bufferSize)) == 0 || @@ -151,7 +154,17 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( return; } memset(mBuffer, 0, bufferSize); - } else { + } break; + case ALLOC_PIPE: + mBufferMemory = thread->pipeMemory(); + // mBuffer is the virtual address as seen from current process (mediaserver), + // and should normally be coming from mBufferMemory->pointer(). + // However in this case the TrackBase does not reference the buffer directly. + // It should references the buffer via the pipe. + // Therefore, to detect incorrect usage of the buffer, we set mBuffer to NULL. + mBuffer = NULL; + break; + case ALLOC_CBLK: // clear all buffers if (sharedBuffer == 0) { mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t); @@ -162,6 +175,7 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( mCblk->mFlags = CBLK_FORCEREADY; // FIXME hack, need to fix the track ready logic #endif } + break; } #ifdef TEE_SINK @@ -461,7 +475,7 @@ void AudioFlinger::PlaybackThread::Track::destroy() void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size, bool active) { - uint32_t vlr = mAudioTrackServerProxy->getVolumeLR(); + gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR(); if (isFastTrack()) { sprintf(buffer, " F %2d", mFastIndex); } else if (mName >= AudioMixer::TRACK0) { @@ -534,8 +548,8 @@ void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size, bool a stateChar, mFillingUpStatus, mAudioTrackServerProxy->getSampleRate(), - 20.0 * log10((vlr & 0xFFFF) / 4096.0), - 20.0 * log10((vlr >> 16) / 4096.0), + 20.0 * log10(float_from_gain(gain_minifloat_unpack_left(vlr))), + 20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))), mCblk->mServer, mMainBuffer, mAuxBuffer, @@ -961,27 +975,27 @@ void AudioFlinger::PlaybackThread::Track::triggerEvents(AudioSystem::sync_event_ // implement VolumeBufferProvider interface -uint32_t AudioFlinger::PlaybackThread::Track::getVolumeLR() +gain_minifloat_packed_t AudioFlinger::PlaybackThread::Track::getVolumeLR() { // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs ALOG_ASSERT(isFastTrack() && (mCblk != NULL)); - uint32_t vlr = mAudioTrackServerProxy->getVolumeLR(); - uint32_t vl = vlr & 0xFFFF; - uint32_t vr = vlr >> 16; + gain_minifloat_packed_t vlr = mAudioTrackServerProxy->getVolumeLR(); + float vl = float_from_gain(gain_minifloat_unpack_left(vlr)); + float vr = float_from_gain(gain_minifloat_unpack_right(vlr)); // track volumes come from shared memory, so can't be trusted and must be clamped - if (vl > MAX_GAIN_INT) { - vl = MAX_GAIN_INT; + if (vl > GAIN_FLOAT_UNITY) { + vl = GAIN_FLOAT_UNITY; } - if (vr > MAX_GAIN_INT) { - vr = MAX_GAIN_INT; + if (vr > GAIN_FLOAT_UNITY) { + vr = GAIN_FLOAT_UNITY; } // now apply the cached master volume and stream type volume; // this is trusted but lacks any synchronization or barrier so may be stale float v = mCachedVolume; vl *= v; vr *= v; - // re-combine into U4.16 - vlr = (vr << 16) | (vl & 0xFFFF); + // re-combine into packed minifloat + vlr = gain_minifloat_pack(gain_from_float(vl), gain_from_float(vr)); // FIXME look at mute, pause, and stop flags return vlr; } @@ -1007,7 +1021,7 @@ void AudioFlinger::PlaybackThread::Track::invalidate() android_atomic_or(CBLK_INVALID, &cblk->mFlags); android_atomic_release_store(0x40000000, &cblk->mFutex); // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE - (void) __futex_syscall3(&cblk->mFutex, FUTEX_WAKE, INT_MAX); + (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX); mIsInvalid = true; } @@ -1592,7 +1606,7 @@ AudioFlinger::PlaybackThread::OutputTrack::OutputTrack( // since client and server are in the same process, // the buffer has the same virtual address on both sides mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize); - mClientProxy->setVolumeLR((uint32_t(uint16_t(0x1000)) << 16) | uint16_t(0x1000)); + mClientProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY); mClientProxy->setSendLevel(0.0); mClientProxy->setSampleRate(sampleRate); mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize, @@ -1840,7 +1854,7 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack( : TrackBase(thread, client, sampleRate, format, channelMask, frameCount, 0 /*sharedBuffer*/, sessionId, uid, flags, false /*isOut*/, - (flags & IAudioFlinger::TRACK_FAST) != 0 /*useReadOnlyHeap*/), + (flags & IAudioFlinger::TRACK_FAST) != 0 ? ALLOC_READONLY : ALLOC_CBLK), mOverflow(false), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpOutFrameCount(0), // See real initialization of mRsmpInFront at RecordThread::start() mRsmpInUnrel(0), mRsmpInFront(0), mFramesToDrop(0), mResamplerBufferProvider(NULL) @@ -1936,7 +1950,7 @@ void AudioFlinger::RecordThread::RecordTrack::invalidate() android_atomic_or(CBLK_INVALID, &cblk->mFlags); android_atomic_release_store(0x40000000, &cblk->mFutex); // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE - (void) __futex_syscall3(&cblk->mFutex, FUTEX_WAKE, INT_MAX); + (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX); } diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk index f270bfc..a22ad9d 100644 --- a/services/audiopolicy/Android.mk +++ b/services/audiopolicy/Android.mk @@ -5,7 +5,6 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ AudioPolicyService.cpp -USE_LEGACY_AUDIO_POLICY = 1 ifeq ($(USE_LEGACY_AUDIO_POLICY), 1) LOCAL_SRC_FILES += \ AudioPolicyInterfaceImplLegacy.cpp \ @@ -15,8 +14,7 @@ LOCAL_SRC_FILES += \ else LOCAL_SRC_FILES += \ AudioPolicyInterfaceImpl.cpp \ - AudioPolicyClientImpl.cpp \ - AudioPolicyManager.cpp + AudioPolicyClientImpl.cpp endif LOCAL_C_INCLUDES := \ @@ -31,14 +29,42 @@ LOCAL_SHARED_LIBRARIES := \ libbinder \ libmedia \ libhardware \ - libhardware_legacy + libhardware_legacy \ + +ifneq ($(USE_LEGACY_AUDIO_POLICY), 1) +LOCAL_SHARED_LIBRARIES += \ + libaudiopolicymanager +endif LOCAL_STATIC_LIBRARIES := \ libmedia_helper \ libserviceutility -LOCAL_MODULE:= libaudiopolicy +LOCAL_MODULE:= libaudiopolicyservice LOCAL_CFLAGS += -fvisibility=hidden include $(BUILD_SHARED_LIBRARY) + +ifneq ($(USE_LEGACY_AUDIO_POLICY), 1) +ifneq ($(USE_CUSTOM_AUDIO_POLICY), 1) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + AudioPolicyManager.cpp + +LOCAL_SHARED_LIBRARIES := \ + libcutils \ + libutils \ + liblog + +LOCAL_STATIC_LIBRARIES := \ + libmedia_helper + +LOCAL_MODULE:= libaudiopolicymanager + +include $(BUILD_SHARED_LIBRARY) + +endif +endif diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp index 62a44ee..bd9b15a 100644 --- a/services/audiopolicy/AudioPolicyManager.cpp +++ b/services/audiopolicy/AudioPolicyManager.cpp @@ -70,24 +70,36 @@ const StringToEnum sDeviceNameToEnumTable[] = { STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER), STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_A2DP), STRING_TO_ENUM(AUDIO_DEVICE_OUT_AUX_DIGITAL), + STRING_TO_ENUM(AUDIO_DEVICE_OUT_HDMI), STRING_TO_ENUM(AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET), STRING_TO_ENUM(AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET), STRING_TO_ENUM(AUDIO_DEVICE_OUT_USB_ACCESSORY), STRING_TO_ENUM(AUDIO_DEVICE_OUT_USB_DEVICE), STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_USB), STRING_TO_ENUM(AUDIO_DEVICE_OUT_REMOTE_SUBMIX), + STRING_TO_ENUM(AUDIO_DEVICE_OUT_TELEPHONY_TX), + STRING_TO_ENUM(AUDIO_DEVICE_OUT_LINE), + STRING_TO_ENUM(AUDIO_DEVICE_OUT_HDMI_ARC), + STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPDIF), + STRING_TO_ENUM(AUDIO_DEVICE_OUT_FM), STRING_TO_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC), STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET), STRING_TO_ENUM(AUDIO_DEVICE_IN_ALL_SCO), STRING_TO_ENUM(AUDIO_DEVICE_IN_WIRED_HEADSET), STRING_TO_ENUM(AUDIO_DEVICE_IN_AUX_DIGITAL), + STRING_TO_ENUM(AUDIO_DEVICE_IN_HDMI), STRING_TO_ENUM(AUDIO_DEVICE_IN_VOICE_CALL), + STRING_TO_ENUM(AUDIO_DEVICE_IN_TELEPHONY_RX), STRING_TO_ENUM(AUDIO_DEVICE_IN_BACK_MIC), STRING_TO_ENUM(AUDIO_DEVICE_IN_REMOTE_SUBMIX), STRING_TO_ENUM(AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET), STRING_TO_ENUM(AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET), STRING_TO_ENUM(AUDIO_DEVICE_IN_USB_ACCESSORY), STRING_TO_ENUM(AUDIO_DEVICE_IN_USB_DEVICE), + STRING_TO_ENUM(AUDIO_DEVICE_IN_FM_TUNER), + STRING_TO_ENUM(AUDIO_DEVICE_IN_TV_TUNER), + STRING_TO_ENUM(AUDIO_DEVICE_IN_LINE), + STRING_TO_ENUM(AUDIO_DEVICE_IN_SPDIF), }; const StringToEnum sFlagNameToEnumTable[] = { diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index fe1e707..9fd35e1 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -39,6 +39,8 @@ #include <utils/String16.h> #include <utils/Trace.h> #include <system/camera_vendor_tags.h> +#include <system/camera_metadata.h> +#include <system/camera.h> #include "CameraService.h" #include "api1/CameraClient.h" @@ -178,6 +180,9 @@ void CameraService::onDeviceStatusChanged(int cameraId, { Mutex::Autolock al(mServiceLock); + /* Remove cached parameters from shim cache */ + mShimParams.removeItem(cameraId); + /* Find all clients that we need to disconnect */ sp<BasicClient> client = mClient[cameraId].promote(); if (client.get() != NULL) { @@ -236,6 +241,96 @@ status_t CameraService::getCameraInfo(int cameraId, return rc; } + +status_t CameraService::generateShimMetadata(int cameraId, /*out*/CameraMetadata* cameraInfo) { + status_t ret = OK; + struct CameraInfo info; + if ((ret = getCameraInfo(cameraId, &info)) != OK) { + return ret; + } + + CameraMetadata shimInfo; + int32_t orientation = static_cast<int32_t>(info.orientation); + if ((ret = shimInfo.update(ANDROID_SENSOR_ORIENTATION, &orientation, 1)) != OK) { + return ret; + } + + uint8_t facing = (info.facing == CAMERA_FACING_FRONT) ? + ANDROID_LENS_FACING_FRONT : ANDROID_LENS_FACING_BACK; + if ((ret = shimInfo.update(ANDROID_LENS_FACING, &facing, 1)) != OK) { + return ret; + } + + ssize_t index = -1; + { // Scope for service lock + Mutex::Autolock lock(mServiceLock); + index = mShimParams.indexOfKey(cameraId); + // Release service lock so initializeShimMetadata can be called correctly. + } + + if (index < 0) { + int64_t token = IPCThreadState::self()->clearCallingIdentity(); + ret = initializeShimMetadata(cameraId); + IPCThreadState::self()->restoreCallingIdentity(token); + if (ret != OK) { + return ret; + } + } + + Vector<Size> sizes; + Vector<int32_t> formats; + const char* supportedPreviewFormats; + { // Scope for service lock + Mutex::Autolock lock(mServiceLock); + index = mShimParams.indexOfKey(cameraId); + + mShimParams[index].getSupportedPreviewSizes(/*out*/sizes); + + mShimParams[index].getSupportedPreviewFormats(/*out*/formats); + } + + // Always include IMPLEMENTATION_DEFINED + formats.add(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED); + + const size_t INTS_PER_CONFIG = 4; + + // Build available stream configurations metadata + size_t streamConfigSize = sizes.size() * formats.size() * INTS_PER_CONFIG; + int32_t streamConfigs[streamConfigSize]; + size_t configIndex = 0; + for (size_t i = 0; i < formats.size(); ++i) { + for (size_t j = 0; j < sizes.size(); ++j) { + streamConfigs[configIndex++] = formats[i]; + streamConfigs[configIndex++] = sizes[j].width; + streamConfigs[configIndex++] = sizes[j].height; + streamConfigs[configIndex++] = + ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT; + } + } + + if ((ret = shimInfo.update(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, + streamConfigs, streamConfigSize)) != OK) { + return ret; + } + + int64_t fakeMinFrames[0]; + // TODO: Fixme, don't fake min frame durations. + if ((ret = shimInfo.update(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS, + fakeMinFrames, 0)) != OK) { + return ret; + } + + int64_t fakeStalls[0]; + // TODO: Fixme, don't fake stall durations. + if ((ret = shimInfo.update(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS, + fakeStalls, 0)) != OK) { + return ret; + } + + *cameraInfo = shimInfo; + return OK; +} + status_t CameraService::getCameraCharacteristics(int cameraId, CameraMetadata* cameraInfo) { if (!cameraInfo) { @@ -248,34 +343,38 @@ status_t CameraService::getCameraCharacteristics(int cameraId, return -ENODEV; } - if (mModule->common.module_api_version < CAMERA_MODULE_API_VERSION_2_0) { - // TODO: Remove this check once HAL1 shim is in place. - ALOGE("%s: Only HAL module version V2 or higher supports static metadata", __FUNCTION__); - return BAD_VALUE; - } - if (cameraId < 0 || cameraId >= mNumberOfCameras) { ALOGE("%s: Invalid camera id: %d", __FUNCTION__, cameraId); return BAD_VALUE; } int facing; - if (getDeviceVersion(cameraId, &facing) == CAMERA_DEVICE_API_VERSION_1_0) { - // TODO: Remove this check once HAL1 shim is in place. - ALOGE("%s: HAL1 doesn't support static metadata yet", __FUNCTION__); - return BAD_VALUE; - } + status_t ret = OK; + if (mModule->common.module_api_version < CAMERA_MODULE_API_VERSION_2_0 || + getDeviceVersion(cameraId, &facing) <= CAMERA_DEVICE_API_VERSION_2_1 ) { + /** + * Backwards compatibility mode for old HALs: + * - Convert CameraInfo into static CameraMetadata properties. + * - Retrieve cached CameraParameters for this camera. If none exist, + * attempt to open CameraClient and retrieve the CameraParameters. + * - Convert cached CameraParameters into static CameraMetadata + * properties. + */ + ALOGI("%s: Switching to HAL1 shim implementation...", __FUNCTION__); + + if ((ret = generateShimMetadata(cameraId, cameraInfo)) != OK) { + return ret; + } - if (getDeviceVersion(cameraId, &facing) <= CAMERA_DEVICE_API_VERSION_2_1) { - // Disable HAL2.x support for camera2 API for now. - ALOGW("%s: HAL2.x doesn't support getCameraCharacteristics for now", __FUNCTION__); - return BAD_VALUE; + } else { + /** + * Normal HAL 2.1+ codepath. + */ + struct camera_info info; + ret = mModule->get_camera_info(cameraId, &info); + *cameraInfo = info.static_camera_characteristics; } - struct camera_info info; - status_t ret = mModule->get_camera_info(cameraId, &info); - *cameraInfo = info.static_camera_characteristics; - return ret; } @@ -285,12 +384,6 @@ status_t CameraService::getCameraVendorTagDescriptor(/*out*/sp<VendorTagDescript return -ENODEV; } - if (mModule->common.module_api_version < CAMERA_MODULE_API_VERSION_2_2) { - // TODO: Remove this check once HAL1 shim is in place. - ALOGW("%s: Only HAL module version V2.2 or higher supports vendor tags", __FUNCTION__); - return -EOPNOTSUPP; - } - desc = VendorTagDescriptor::getGlobalVendorTagDescriptor(); return OK; } @@ -372,6 +465,54 @@ bool CameraService::setUpVendorTags() { return true; } +status_t CameraService::initializeShimMetadata(int cameraId) { + int pid = getCallingPid(); + int uid = getCallingUid(); + status_t ret = validateConnect(cameraId, uid); + if (ret != OK) { + return ret; + } + + bool needsNewClient = false; + sp<Client> client; + + String16 internalPackageName("media"); + { // Scope for service lock + Mutex::Autolock lock(mServiceLock); + if (mClient[cameraId] != NULL) { + client = static_cast<Client*>(mClient[cameraId].promote().get()); + } + if (client == NULL) { + needsNewClient = true; + ret = connectHelperLocked(/*cameraClient*/NULL, // Empty binder callbacks + cameraId, + internalPackageName, + uid, + pid, + client); + + if (ret != OK) { + return ret; + } + } + + if (client == NULL) { + ALOGE("%s: Could not connect to client camera device.", __FUNCTION__); + return BAD_VALUE; + } + + String8 rawParams = client->getParameters(); + CameraParameters params(rawParams); + mShimParams.add(cameraId, params); + } + + // Close client if one was opened solely for this call + if (needsNewClient) { + client->disconnect(); + } + return OK; +} + status_t CameraService::validateConnect(int cameraId, /*inout*/ int& clientUid) const { @@ -468,6 +609,64 @@ bool CameraService::canConnectUnsafe(int cameraId, return true; } +status_t CameraService::connectHelperLocked(const sp<ICameraClient>& cameraClient, + int cameraId, + const String16& clientPackageName, + int clientUid, + int callingPid, + /*out*/ + sp<Client>& client) { + + int facing = -1; + int deviceVersion = getDeviceVersion(cameraId, &facing); + + // If there are other non-exclusive users of the camera, + // this will tear them down before we can reuse the camera + if (isValidCameraId(cameraId)) { + // transition from PRESENT -> NOT_AVAILABLE + updateStatus(ICameraServiceListener::STATUS_NOT_AVAILABLE, + cameraId); + } + + switch(deviceVersion) { + case CAMERA_DEVICE_API_VERSION_1_0: + client = new CameraClient(this, cameraClient, + clientPackageName, cameraId, + facing, callingPid, clientUid, getpid()); + break; + case CAMERA_DEVICE_API_VERSION_2_0: + case CAMERA_DEVICE_API_VERSION_2_1: + case CAMERA_DEVICE_API_VERSION_3_0: + case CAMERA_DEVICE_API_VERSION_3_1: + case CAMERA_DEVICE_API_VERSION_3_2: + client = new Camera2Client(this, cameraClient, + clientPackageName, cameraId, + facing, callingPid, clientUid, getpid(), + deviceVersion); + break; + case -1: + ALOGE("Invalid camera id %d", cameraId); + return BAD_VALUE; + default: + ALOGE("Unknown camera device HAL version: %d", deviceVersion); + return INVALID_OPERATION; + } + + status_t status = connectFinishUnsafe(client, client->getRemote()); + if (status != OK) { + // this is probably not recoverable.. maybe the client can try again + // OK: we can only get here if we were originally in PRESENT state + updateStatus(ICameraServiceListener::STATUS_PRESENT, cameraId); + return status; + } + + mClient[cameraId] = client; + LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId, + getpid()); + + return OK; +} + status_t CameraService::connect( const sp<ICameraClient>& cameraClient, int cameraId, @@ -501,52 +700,16 @@ status_t CameraService::connect( return OK; } - int facing = -1; - int deviceVersion = getDeviceVersion(cameraId, &facing); - - // If there are other non-exclusive users of the camera, - // this will tear them down before we can reuse the camera - if (isValidCameraId(cameraId)) { - // transition from PRESENT -> NOT_AVAILABLE - updateStatus(ICameraServiceListener::STATUS_NOT_AVAILABLE, - cameraId); - } - - switch(deviceVersion) { - case CAMERA_DEVICE_API_VERSION_1_0: - client = new CameraClient(this, cameraClient, - clientPackageName, cameraId, - facing, callingPid, clientUid, getpid()); - break; - case CAMERA_DEVICE_API_VERSION_2_0: - case CAMERA_DEVICE_API_VERSION_2_1: - case CAMERA_DEVICE_API_VERSION_3_0: - case CAMERA_DEVICE_API_VERSION_3_1: - case CAMERA_DEVICE_API_VERSION_3_2: - client = new Camera2Client(this, cameraClient, - clientPackageName, cameraId, - facing, callingPid, clientUid, getpid(), - deviceVersion); - break; - case -1: - ALOGE("Invalid camera id %d", cameraId); - return BAD_VALUE; - default: - ALOGE("Unknown camera device HAL version: %d", deviceVersion); - return INVALID_OPERATION; - } - - status_t status = connectFinishUnsafe(client, client->getRemote()); + status = connectHelperLocked(cameraClient, + cameraId, + clientPackageName, + clientUid, + callingPid, + client); if (status != OK) { - // this is probably not recoverable.. maybe the client can try again - // OK: we can only get here if we were originally in PRESENT state - updateStatus(ICameraServiceListener::STATUS_PRESENT, cameraId); return status; } - mClient[cameraId] = client; - LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId, - getpid()); } // important: release the mutex here so the client can call back // into the service from its destructor (can be at the end of the call) @@ -561,8 +724,9 @@ status_t CameraService::connectFinishUnsafe(const sp<BasicClient>& client, if (status != OK) { return status; } - - remoteCallback->linkToDeath(this); + if (remoteCallback != NULL) { + remoteCallback->linkToDeath(this); + } return OK; } @@ -800,9 +964,13 @@ void CameraService::removeClientByRemote(const wp<IBinder>& remoteBinder) { if (client != 0) { // Found our camera, clear and leave. LOG1("removeClient: clear camera %d", outIndex); - mClient[outIndex].clear(); - client->getRemote()->unlinkToDeath(this); + sp<IBinder> remote = client->getRemote(); + if (remote != NULL) { + remote->unlinkToDeath(this); + } + + mClient[outIndex].clear(); } else { sp<ProClient> clientPro = findProClientUnsafe(remoteBinder); diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index 76ea7be..ee39d52 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -18,6 +18,7 @@ #define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H #include <utils/Vector.h> +#include <utils/KeyedVector.h> #include <binder/AppOpsManager.h> #include <binder/BinderService.h> #include <binder/IAppOpsCallback.h> @@ -32,6 +33,7 @@ #include <camera/camera2/ICameraDeviceCallbacks.h> #include <camera/VendorTagDescriptor.h> #include <camera/CaptureResult.h> +#include <camera/CameraParameters.h> #include <camera/ICameraServiceListener.h> @@ -395,6 +397,43 @@ private: bool isValidCameraId(int cameraId); bool setUpVendorTags(); + + /** + * A mapping of camera ids to CameraParameters returned by that camera device. + * + * This cache is used to generate CameraCharacteristic metadata when using + * the HAL1 shim. + */ + KeyedVector<int, CameraParameters> mShimParams; + + /** + * Initialize and cache the metadata used by the HAL1 shim for a given cameraId. + * + * Returns OK on success, or a negative error code. + */ + status_t initializeShimMetadata(int cameraId); + + /** + * Generate the CameraCharacteristics metadata required by the Camera2 API + * from the available HAL1 CameraParameters and CameraInfo. + * + * Returns OK on success, or a negative error code. + */ + status_t generateShimMetadata(int cameraId, /*out*/CameraMetadata* cameraInfo); + + /** + * Connect a new camera client. This should only be used while holding the + * mutex for mServiceLock. + * + * Returns OK on success, or a negative error code. + */ + status_t connectHelperLocked(const sp<ICameraClient>& cameraClient, + int cameraId, + const String16& clientPackageName, + int clientUid, + int callingPid, + /*out*/ + sp<Client>& client); }; } // namespace android diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp index 65592d3..dece764 100644 --- a/services/camera/libcameraservice/api1/client2/Parameters.cpp +++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp @@ -2028,24 +2028,7 @@ const char* Parameters::getStateName(State state) { } int Parameters::formatStringToEnum(const char *format) { - return - !format ? - HAL_PIXEL_FORMAT_YCrCb_420_SP : - !strcmp(format, CameraParameters::PIXEL_FORMAT_YUV422SP) ? - HAL_PIXEL_FORMAT_YCbCr_422_SP : // NV16 - !strcmp(format, CameraParameters::PIXEL_FORMAT_YUV420SP) ? - HAL_PIXEL_FORMAT_YCrCb_420_SP : // NV21 - !strcmp(format, CameraParameters::PIXEL_FORMAT_YUV422I) ? - HAL_PIXEL_FORMAT_YCbCr_422_I : // YUY2 - !strcmp(format, CameraParameters::PIXEL_FORMAT_YUV420P) ? - HAL_PIXEL_FORMAT_YV12 : // YV12 - !strcmp(format, CameraParameters::PIXEL_FORMAT_RGB565) ? - HAL_PIXEL_FORMAT_RGB_565 : // RGB565 - !strcmp(format, CameraParameters::PIXEL_FORMAT_RGBA8888) ? - HAL_PIXEL_FORMAT_RGBA_8888 : // RGB8888 - !strcmp(format, CameraParameters::PIXEL_FORMAT_BAYER_RGGB) ? - HAL_PIXEL_FORMAT_RAW_SENSOR : // Raw sensor data - -1; + return CameraParameters::previewFormatToEnum(format); } const char* Parameters::formatEnumToString(int format) { diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp index 5a48a62..4fce1b3 100644 --- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp +++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp @@ -246,6 +246,18 @@ status_t CameraDeviceClient::cancelRequest(int requestId, int64_t* lastFrameNumb return res; } +status_t CameraDeviceClient::beginConfigure() { + // TODO: Implement this. + ALOGE("%s: Not implemented yet.", __FUNCTION__); + return OK; +} + +status_t CameraDeviceClient::endConfigure() { + // TODO: Implement this. + ALOGE("%s: Not implemented yet.", __FUNCTION__); + return OK; +} + status_t CameraDeviceClient::deleteStream(int streamId) { ATRACE_CALL(); ALOGV("%s (streamId = 0x%x)", __FUNCTION__, streamId); diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h index 0b37784..9981dfe 100644 --- a/services/camera/libcameraservice/api2/CameraDeviceClient.h +++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h @@ -76,6 +76,10 @@ public: /*out*/ int64_t* lastFrameNumber = NULL); + virtual status_t beginConfigure(); + + virtual status_t endConfigure(); + // Returns -EBUSY if device is not idle virtual status_t deleteStream(int streamId); diff --git a/services/camera/libcameraservice/utils/CameraTraces.cpp b/services/camera/libcameraservice/utils/CameraTraces.cpp index 346e15f..374dc5e 100644 --- a/services/camera/libcameraservice/utils/CameraTraces.cpp +++ b/services/camera/libcameraservice/utils/CameraTraces.cpp @@ -74,10 +74,10 @@ status_t CameraTraces::dump(int fd, const Vector<String16> &args __attribute__(( return BAD_VALUE; } - fdprintf(fd, "Camera traces (%zu):\n", pcsList.size()); + dprintf(fd, "Camera traces (%zu):\n", pcsList.size()); if (pcsList.empty()) { - fdprintf(fd, " No camera traces collected.\n"); + dprintf(fd, " No camera traces collected.\n"); } // Print newest items first diff --git a/services/medialog/MediaLogService.cpp b/services/medialog/MediaLogService.cpp index 0c7fbbd..41dab1f 100644 --- a/services/medialog/MediaLogService.cpp +++ b/services/medialog/MediaLogService.cpp @@ -60,7 +60,7 @@ status_t MediaLogService::dump(int fd, const Vector<String16>& args __unused) static const String16 sDump("android.permission.DUMP"); if (!(IPCThreadState::self()->getCallingUid() == AID_MEDIA || PermissionCache::checkCallingPermission(sDump))) { - fdprintf(fd, "Permission Denial: can't dump media.log from pid=%d, uid=%d\n", + dprintf(fd, "Permission Denial: can't dump media.log from pid=%d, uid=%d\n", IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid()); return NO_ERROR; @@ -74,7 +74,7 @@ status_t MediaLogService::dump(int fd, const Vector<String16>& args __unused) for (size_t i = 0; i < namedReaders.size(); i++) { const NamedReader& namedReader = namedReaders[i]; if (fd >= 0) { - fdprintf(fd, "\n%s:\n", namedReader.name()); + dprintf(fd, "\n%s:\n", namedReader.name()); } else { ALOGI("%s:", namedReader.name()); } |