Merge "Adjust mediadrmserver uid" into nyc-dev
diff --git a/include/camera/ndk/NdkCameraMetadataTags.h b/include/camera/ndk/NdkCameraMetadataTags.h
index 0c398be..43f5193 100644
--- a/include/camera/ndk/NdkCameraMetadataTags.h
+++ b/include/camera/ndk/NdkCameraMetadataTags.h
@@ -836,6 +836,7 @@
ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED,
ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY,
+ ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_3,
} acamera_metadata_enum_android_info_supported_hardware_level_t;
diff --git a/include/media/AudioPolicy.h b/include/media/AudioPolicy.h
index a171493..c769a62 100644
--- a/include/media/AudioPolicy.h
+++ b/include/media/AudioPolicy.h
@@ -97,6 +97,7 @@
// definitions for audio recording configuration updates
// which update type is reported
+#define RECORD_CONFIG_EVENT_NONE -1
#define RECORD_CONFIG_EVENT_START 1
#define RECORD_CONFIG_EVENT_STOP 0
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 2f95b90..e3f2d60 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -31,7 +31,9 @@
typedef void (*audio_error_callback)(status_t err);
typedef void (*dynamic_policy_callback)(int event, String8 regId, int val);
-typedef void (*record_config_callback)(int event, int session, int source);
+typedef void (*record_config_callback)(int event, int session, int source,
+ const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
+ audio_patch_handle_t patchHandle);
class IAudioFlinger;
class IAudioPolicyService;
@@ -424,7 +426,8 @@
virtual void onAudioPatchListUpdate();
virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
virtual void onRecordingConfigurationUpdate(int event, audio_session_t session,
- audio_source_t source);
+ audio_source_t source, const audio_config_base_t *clientConfig,
+ const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle);
private:
Mutex mLock;
diff --git a/include/media/ExtendedAudioBufferProvider.h b/include/media/ExtendedAudioBufferProvider.h
index 2539ed3..168ceed 100644
--- a/include/media/ExtendedAudioBufferProvider.h
+++ b/include/media/ExtendedAudioBufferProvider.h
@@ -27,11 +27,11 @@
virtual size_t framesReady() const = 0; // see description at AudioFlinger.h
// Return the total number of frames that have been obtained and released
- virtual size_t framesReleased() const { return 0; }
+ virtual int64_t framesReleased() const { return 0; }
// Invoked by buffer consumer when a new timestamp is available.
// Default implementation ignores the timestamp.
- virtual void onTimestamp(const AudioTimestamp& timestamp) { }
+ virtual void onTimestamp(const ExtendedTimestamp& timestamp) { }
};
} // namespace android
diff --git a/include/media/IAudioPolicyServiceClient.h b/include/media/IAudioPolicyServiceClient.h
index e8fd39f..d94ad00 100644
--- a/include/media/IAudioPolicyServiceClient.h
+++ b/include/media/IAudioPolicyServiceClient.h
@@ -39,7 +39,10 @@
virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state) = 0;
// Notifies a change of audio recording configuration
virtual void onRecordingConfigurationUpdate(int event, audio_session_t session,
- audio_source_t source) = 0;
+ audio_source_t source,
+ const audio_config_base_t *clientConfig,
+ const audio_config_base_t *deviceConfig,
+ audio_patch_handle_t patchHandle) = 0;
};
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index d6db67a..3f211bf 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -59,6 +59,7 @@
virtual status_t allocateNode(
const char *name, const sp<IOMXObserver> &observer,
+ sp<IBinder> *nodeBinder,
node_id *node) = 0;
virtual status_t freeNode(node_id node) = 0;
diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h
index f655f35..8ed07ee 100644
--- a/include/media/mediametadataretriever.h
+++ b/include/media/mediametadataretriever.h
@@ -82,7 +82,7 @@
const char* extractMetadata(int keyCode);
private:
- static const sp<IMediaPlayerService>& getService();
+ static const sp<IMediaPlayerService> getService();
class DeathNotifier: public IBinder::DeathRecipient
{
diff --git a/include/media/nbaio/AudioStreamInSource.h b/include/media/nbaio/AudioStreamInSource.h
index eaea63c..a6e7992 100644
--- a/include/media/nbaio/AudioStreamInSource.h
+++ b/include/media/nbaio/AudioStreamInSource.h
@@ -38,8 +38,8 @@
// NBAIO_Sink interface
//virtual size_t framesRead() const;
- virtual size_t framesOverrun();
- virtual size_t overruns() { (void) framesOverrun(); return mOverruns; }
+ virtual int64_t framesOverrun();
+ virtual int64_t overruns() { (void) framesOverrun(); return mOverruns; }
// This is an over-estimate, and could dupe the caller into making a blocking read()
// FIXME Use an audio HAL API to query the buffer filling status when it's available.
@@ -56,8 +56,8 @@
private:
audio_stream_in * const mStream;
size_t mStreamBufferSizeBytes; // as reported by get_buffer_size()
- size_t mFramesOverrun;
- size_t mOverruns;
+ int64_t mFramesOverrun;
+ int64_t mOverruns;
};
} // namespace android
diff --git a/include/media/nbaio/AudioStreamOutSink.h b/include/media/nbaio/AudioStreamOutSink.h
index 0998d45..e86b018 100644
--- a/include/media/nbaio/AudioStreamOutSink.h
+++ b/include/media/nbaio/AudioStreamOutSink.h
@@ -47,7 +47,7 @@
virtual ssize_t write(const void *buffer, size_t count);
- virtual status_t getTimestamp(AudioTimestamp& timestamp);
+ virtual status_t getTimestamp(ExtendedTimestamp ×tamp);
// NBAIO_Sink end
diff --git a/include/media/nbaio/MonoPipe.h b/include/media/nbaio/MonoPipe.h
index df9cafe..d2cd218 100644
--- a/include/media/nbaio/MonoPipe.h
+++ b/include/media/nbaio/MonoPipe.h
@@ -23,7 +23,7 @@
namespace android {
-typedef SingleStateQueue<AudioTimestamp> AudioTimestampSingleStateQueue;
+typedef SingleStateQueue<ExtendedTimestamp> ExtendedTimestampSingleStateQueue;
// MonoPipe is similar to Pipe except:
// - supports only a single reader, called MonoPipeReader
@@ -51,9 +51,9 @@
// NBAIO_Sink interface
- //virtual size_t framesWritten() const;
- //virtual size_t framesUnderrun() const;
- //virtual size_t underruns() const;
+ //virtual int64_t framesWritten() const;
+ //virtual int64_t framesUnderrun() const;
+ //virtual int64_t underruns() const;
virtual ssize_t availableToWrite() const;
virtual ssize_t write(const void *buffer, size_t count);
@@ -77,7 +77,7 @@
bool isShutdown();
// Return NO_ERROR if there is a timestamp available
- status_t getTimestamp(AudioTimestamp& timestamp);
+ status_t getTimestamp(ExtendedTimestamp ×tamp);
private:
const size_t mReqFrames; // as requested in constructor, unrounded
@@ -97,9 +97,9 @@
bool mIsShutdown; // whether shutdown(true) was called, no barriers are needed
- AudioTimestampSingleStateQueue::Shared mTimestampShared;
- AudioTimestampSingleStateQueue::Mutator mTimestampMutator;
- AudioTimestampSingleStateQueue::Observer mTimestampObserver;
+ ExtendedTimestampSingleStateQueue::Shared mTimestampShared;
+ ExtendedTimestampSingleStateQueue::Mutator mTimestampMutator;
+ ExtendedTimestampSingleStateQueue::Observer mTimestampObserver;
};
} // namespace android
diff --git a/include/media/nbaio/MonoPipeReader.h b/include/media/nbaio/MonoPipeReader.h
index 4a7c3c5..b3c891d 100644
--- a/include/media/nbaio/MonoPipeReader.h
+++ b/include/media/nbaio/MonoPipeReader.h
@@ -49,7 +49,7 @@
virtual ssize_t read(void *buffer, size_t count);
- virtual void onTimestamp(const AudioTimestamp& timestamp);
+ virtual void onTimestamp(const ExtendedTimestamp ×tamp);
// NBAIO_Source end
diff --git a/include/media/nbaio/NBAIO.h b/include/media/nbaio/NBAIO.h
index 2f7e291..120de4f 100644
--- a/include/media/nbaio/NBAIO.h
+++ b/include/media/nbaio/NBAIO.h
@@ -145,13 +145,13 @@
// 32 bits rolls over after 27 hours at 44.1 kHz; if that concerns you then poll periodically.
// Return the number of frames written successfully since construction.
- virtual size_t framesWritten() const { return mFramesWritten; }
+ virtual int64_t framesWritten() const { return mFramesWritten; }
// Number of frames lost due to underrun since construction.
- virtual size_t framesUnderrun() const { return 0; }
+ virtual int64_t framesUnderrun() const { return 0; }
// Number of underruns since construction, where a set of contiguous lost frames is one event.
- virtual size_t underruns() const { return 0; }
+ virtual int64_t underruns() const { return 0; }
// Estimate of number of frames that could be written successfully now without blocking.
// When a write() is actually attempted, the implementation is permitted to return a smaller or
@@ -212,7 +212,7 @@
// Returns NO_ERROR if a timestamp is available. The timestamp includes the total number
// of frames presented to an external observer, together with the value of CLOCK_MONOTONIC
// as of this presentation count. The timestamp parameter is undefined if error is returned.
- virtual status_t getTimestamp(AudioTimestamp& timestamp) { return INVALID_OPERATION; }
+ virtual status_t getTimestamp(ExtendedTimestamp ×tamp) { return INVALID_OPERATION; }
protected:
NBAIO_Sink(const NBAIO_Format& format = Format_Invalid) : NBAIO_Port(format), mFramesWritten(0)
@@ -220,7 +220,7 @@
virtual ~NBAIO_Sink() { }
// Implementations are free to ignore these if they don't need them
- size_t mFramesWritten;
+ int64_t mFramesWritten;
};
// Abstract class (interface) representing a non-blocking data source, for use by a data consumer.
@@ -232,15 +232,15 @@
// 32 bits rolls over after 27 hours at 44.1 kHz; if that concerns you then poll periodically.
// Number of frames read successfully since construction.
- virtual size_t framesRead() const { return mFramesRead; }
+ virtual int64_t framesRead() const { return mFramesRead; }
// Number of frames lost due to overrun since construction.
// Not const because implementations may need to do I/O.
- virtual size_t framesOverrun() /*const*/ { return 0; }
+ virtual int64_t framesOverrun() /*const*/ { return 0; }
// Number of overruns since construction, where a set of contiguous lost frames is one event.
// Not const because implementations may need to do I/O.
- virtual size_t overruns() /*const*/ { return 0; }
+ virtual int64_t overruns() /*const*/ { return 0; }
// Estimate of number of frames that could be read successfully now.
// When a read() is actually attempted, the implementation is permitted to return a smaller or
@@ -299,7 +299,7 @@
// Invoked asynchronously by corresponding sink when a new timestamp is available.
// Default implementation ignores the timestamp.
- virtual void onTimestamp(const AudioTimestamp& timestamp) { }
+ virtual void onTimestamp(const ExtendedTimestamp& timestamp) { }
protected:
NBAIO_Source(const NBAIO_Format& format = Format_Invalid) : NBAIO_Port(format), mFramesRead(0)
@@ -307,7 +307,7 @@
virtual ~NBAIO_Source() { }
// Implementations are free to ignore these if they don't need them
- size_t mFramesRead;
+ int64_t mFramesRead;
};
} // namespace android
diff --git a/include/media/nbaio/Pipe.h b/include/media/nbaio/Pipe.h
index eba37bc..cc95ff7 100644
--- a/include/media/nbaio/Pipe.h
+++ b/include/media/nbaio/Pipe.h
@@ -45,9 +45,9 @@
// NBAIO_Sink interface
- //virtual size_t framesWritten() const;
- //virtual size_t framesUnderrun() const;
- //virtual size_t underruns() const;
+ //virtual int64_t framesWritten() const;
+ //virtual int64_t framesUnderrun() const;
+ //virtual int64_t underruns() const;
// The write side of a pipe permits overruns; flow control is the caller's responsibility.
// It doesn't return +infinity because that would guarantee an overrun.
diff --git a/include/media/nbaio/PipeReader.h b/include/media/nbaio/PipeReader.h
index 398353b..7c733ad 100644
--- a/include/media/nbaio/PipeReader.h
+++ b/include/media/nbaio/PipeReader.h
@@ -40,8 +40,8 @@
// NBAIO_Source interface
//virtual size_t framesRead() const;
- virtual size_t framesOverrun() { return mFramesOverrun; }
- virtual size_t overruns() { return mOverruns; }
+ virtual int64_t framesOverrun() { return mFramesOverrun; }
+ virtual int64_t overruns() { return mOverruns; }
virtual ssize_t availableToRead();
@@ -56,8 +56,8 @@
private:
Pipe& mPipe;
int32_t mFront; // follows behind mPipe.mRear
- size_t mFramesOverrun;
- size_t mOverruns;
+ int64_t mFramesOverrun;
+ int64_t mOverruns;
};
} // namespace android
diff --git a/include/media/nbaio/SourceAudioBufferProvider.h b/include/media/nbaio/SourceAudioBufferProvider.h
index 29172e1..ae49903 100644
--- a/include/media/nbaio/SourceAudioBufferProvider.h
+++ b/include/media/nbaio/SourceAudioBufferProvider.h
@@ -36,8 +36,8 @@
// ExtendedAudioBufferProvider interface
virtual size_t framesReady() const;
- virtual size_t framesReleased() const;
- virtual void onTimestamp(const AudioTimestamp& timestamp);
+ virtual int64_t framesReleased() const;
+ virtual void onTimestamp(const ExtendedTimestamp ×tamp);
private:
const sp<NBAIO_Source> mSource; // the wrapped source
@@ -47,7 +47,7 @@
size_t mOffset; // frame offset within mAllocated of valid data
size_t mRemaining; // frame count within mAllocated of valid data
size_t mGetCount; // buffer.frameCount of the most recent getNextBuffer
- uint32_t mFramesReleased; // counter of the total number of frames released
+ int64_t mFramesReleased; // counter of the total number of frames released
};
} // namespace android
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index cc5b486..4489d37 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -238,6 +238,7 @@
uint32_t mFlags;
uint32_t mQuirks;
sp<IOMX> mOMX;
+ sp<IBinder> mNodeBinder;
IOMX::node_id mNode;
sp<MemoryDealer> mDealer[2];
diff --git a/include/media/stagefright/CodecBase.h b/include/media/stagefright/CodecBase.h
index cbf9839..3131090 100644
--- a/include/media/stagefright/CodecBase.h
+++ b/include/media/stagefright/CodecBase.h
@@ -78,7 +78,7 @@
virtual size_t countBuffers() = 0;
virtual IOMX::buffer_id bufferIDAt(size_t index) const = 0;
virtual sp<ABuffer> bufferAt(size_t index) const = 0;
- virtual sp<NativeHandle> handleAt(size_t index) { return NULL; };
+ virtual sp<NativeHandle> handleAt(size_t index) const { return NULL; };
virtual sp<RefBase> memRefAt(size_t index) const { return NULL; }
protected:
diff --git a/include/media/stagefright/ProcessInfo.h b/include/media/stagefright/ProcessInfo.h
index ec0cdff..0be1a52 100644
--- a/include/media/stagefright/ProcessInfo.h
+++ b/include/media/stagefright/ProcessInfo.h
@@ -27,6 +27,7 @@
ProcessInfo();
virtual bool getPriority(int pid, int* priority);
+ virtual bool isValidPid(int pid);
protected:
virtual ~ProcessInfo();
diff --git a/include/media/stagefright/ProcessInfoInterface.h b/include/media/stagefright/ProcessInfoInterface.h
index 222f92d..b39112a 100644
--- a/include/media/stagefright/ProcessInfoInterface.h
+++ b/include/media/stagefright/ProcessInfoInterface.h
@@ -23,6 +23,7 @@
struct ProcessInfoInterface : public RefBase {
virtual bool getPriority(int pid, int* priority) = 0;
+ virtual bool isValidPid(int pid) = 0;
protected:
virtual ~ProcessInfoInterface() {}
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index aa9e98c..ea8a78e 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -176,6 +176,7 @@
// server write-only, client read
ExtendedTimestampQueue::Shared mExtendedTimestampQueue;
+
public:
volatile int32_t mFlags; // combinations of CBLK_*
@@ -532,7 +533,7 @@
size_t frameSize, bool clientInServer = false, uint32_t sampleRate = 0)
: ServerProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/, clientInServer),
mPlaybackRateObserver(&cblk->mPlaybackRateQueue),
- mUnderrunCount(0), mUnderrunning(false) {
+ mUnderrunCount(0), mUnderrunning(false), mDrained(true) {
mCblk->mSampleRate = sampleRate;
mPlaybackRate = AUDIO_PLAYBACK_RATE_DEFAULT;
}
@@ -569,6 +570,18 @@
// Return the playback speed and pitch read atomically. Not multi-thread safe on server side.
AudioPlaybackRate getPlaybackRate();
+ // Set the internal drain state of the track buffer from the timestamp received.
+ virtual void setDrained(bool drained) {
+ mDrained.store(drained);
+ }
+
+ // Check if the internal drain state of the track buffer.
+ // This is not a guarantee, but advisory for determining whether the track is
+ // fully played out.
+ virtual bool isDrained() const {
+ return mDrained.load();
+ }
+
private:
AudioPlaybackRate mPlaybackRate; // last observed playback rate
PlaybackRateQueue::Observer mPlaybackRateObserver;
@@ -576,6 +589,8 @@
// The server keeps a copy here where it is safe from the client.
uint32_t mUnderrunCount; // echoed to mCblk
bool mUnderrunning; // used to detect edge of underrun
+
+ std::atomic<bool> mDrained; // is the track buffer drained
};
class StaticAudioTrackServerProxy : public AudioTrackServerProxy {
diff --git a/media/audioserver/Android.mk b/media/audioserver/Android.mk
index 324ebbb..aa79bc1 100644
--- a/media/audioserver/Android.mk
+++ b/media/audioserver/Android.mk
@@ -9,11 +9,14 @@
libaudioflinger \
libaudiopolicyservice \
libbinder \
+ libcutils \
liblog \
libmedia \
+ libmedialogservice \
+ libnbaio \
libradioservice \
libsoundtriggerservice \
- libutils \
+ libutils
LOCAL_C_INCLUDES := \
frameworks/av/services/audioflinger \
@@ -22,6 +25,7 @@
frameworks/av/services/audiopolicy/common/include \
frameworks/av/services/audiopolicy/engine/interface \
frameworks/av/services/audiopolicy/service \
+ frameworks/av/services/medialog \
frameworks/av/services/radio \
frameworks/av/services/soundtrigger \
$(call include-path-for, audio-utils) \
diff --git a/media/audioserver/main_audioserver.cpp b/media/audioserver/main_audioserver.cpp
index a7123aa..698da1f 100644
--- a/media/audioserver/main_audioserver.cpp
+++ b/media/audioserver/main_audioserver.cpp
@@ -17,6 +17,11 @@
#define LOG_TAG "audioserver"
//#define LOG_NDEBUG 0
+#include <fcntl.h>
+#include <sys/prctl.h>
+#include <sys/wait.h>
+#include <cutils/properties.h>
+
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
@@ -25,24 +30,105 @@
// from LOCAL_C_INCLUDES
#include "AudioFlinger.h"
#include "AudioPolicyService.h"
+#include "MediaLogService.h"
#include "RadioService.h"
#include "SoundTriggerHwService.h"
using namespace android;
-int main(int argc __unused, char **argv __unused)
+int main(int argc __unused, char **argv)
{
signal(SIGPIPE, SIG_IGN);
- // TODO: add logging b/24511453#3
+ bool doLog = (bool) property_get_bool("ro.test_harness", 0);
- sp<ProcessState> proc(ProcessState::self());
- sp<IServiceManager> sm(defaultServiceManager());
- ALOGI("ServiceManager: %p", sm.get());
- AudioFlinger::instantiate();
- AudioPolicyService::instantiate();
- RadioService::instantiate();
- SoundTriggerHwService::instantiate();
- ProcessState::self()->startThreadPool();
- IPCThreadState::self()->joinThreadPool();
+ pid_t childPid;
+ // FIXME The advantage of making the process containing media.log service the parent process of
+ // the process that contains the other audio services, is that it allows us to collect more
+ // detailed information such as signal numbers, stop and continue, resource usage, etc.
+ // But it is also more complex. Consider replacing this by independent processes, and using
+ // binder on death notification instead.
+ if (doLog && (childPid = fork()) != 0) {
+ // media.log service
+ //prctl(PR_SET_NAME, (unsigned long) "media.log", 0, 0, 0);
+ // unfortunately ps ignores PR_SET_NAME for the main thread, so use this ugly hack
+ strcpy(argv[0], "media.log");
+ sp<ProcessState> proc(ProcessState::self());
+ MediaLogService::instantiate();
+ ProcessState::self()->startThreadPool();
+ for (;;) {
+ siginfo_t info;
+ int ret = waitid(P_PID, childPid, &info, WEXITED | WSTOPPED | WCONTINUED);
+ if (ret == EINTR) {
+ continue;
+ }
+ if (ret < 0) {
+ break;
+ }
+ char buffer[32];
+ const char *code;
+ switch (info.si_code) {
+ case CLD_EXITED:
+ code = "CLD_EXITED";
+ break;
+ case CLD_KILLED:
+ code = "CLD_KILLED";
+ break;
+ case CLD_DUMPED:
+ code = "CLD_DUMPED";
+ break;
+ case CLD_STOPPED:
+ code = "CLD_STOPPED";
+ break;
+ case CLD_TRAPPED:
+ code = "CLD_TRAPPED";
+ break;
+ case CLD_CONTINUED:
+ code = "CLD_CONTINUED";
+ break;
+ default:
+ snprintf(buffer, sizeof(buffer), "unknown (%d)", info.si_code);
+ code = buffer;
+ break;
+ }
+ struct rusage usage;
+ getrusage(RUSAGE_CHILDREN, &usage);
+ ALOG(LOG_ERROR, "media.log", "pid %d status %d code %s user %ld.%03lds sys %ld.%03lds",
+ info.si_pid, info.si_status, code,
+ usage.ru_utime.tv_sec, usage.ru_utime.tv_usec / 1000,
+ usage.ru_stime.tv_sec, usage.ru_stime.tv_usec / 1000);
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16("media.log"));
+ if (binder != 0) {
+ Vector<String16> args;
+ binder->dump(-1, args);
+ }
+ switch (info.si_code) {
+ case CLD_EXITED:
+ case CLD_KILLED:
+ case CLD_DUMPED: {
+ ALOG(LOG_INFO, "media.log", "exiting");
+ _exit(0);
+ // not reached
+ }
+ default:
+ break;
+ }
+ }
+ } else {
+ // all other services
+ if (doLog) {
+ prctl(PR_SET_PDEATHSIG, SIGKILL); // if parent media.log dies before me, kill me also
+ setpgid(0, 0); // but if I die first, don't kill my parent
+ }
+ sp<ProcessState> proc(ProcessState::self());
+ sp<IServiceManager> sm = defaultServiceManager();
+ ALOGI("ServiceManager: %p", sm.get());
+ AudioFlinger::instantiate();
+ AudioPolicyService::instantiate();
+ RadioService::instantiate();
+ SoundTriggerHwService::instantiate();
+ ProcessState::self()->startThreadPool();
+ IPCThreadState::self()->joinThreadPool();
+ }
}
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 1ea2003..56c600d 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -1245,7 +1245,9 @@
}
void AudioSystem::AudioPolicyServiceClient::onRecordingConfigurationUpdate(
- int event, audio_session_t session, audio_source_t source) {
+ int event, audio_session_t session, audio_source_t source,
+ const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
+ audio_patch_handle_t patchHandle) {
record_config_callback cb = NULL;
{
Mutex::Autolock _l(AudioSystem::gLock);
@@ -1253,7 +1255,7 @@
}
if (cb != NULL) {
- cb(event, session, source);
+ cb(event, session, source, clientConfig, deviceConfig, patchHandle);
}
}
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 33dcc57..f0074b6 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -2202,7 +2202,7 @@
// To avoid a race, read the presented frames first. This ensures that presented <= consumed.
status_t status;
- if (!(mFlags & AUDIO_OUTPUT_FLAG_FAST)) {
+ if (isOffloadedOrDirect_l()) {
// use Binder to get timestamp
status = mAudioTrack->getTimestamp(timestamp);
} else {
diff --git a/media/libmedia/IAudioPolicyServiceClient.cpp b/media/libmedia/IAudioPolicyServiceClient.cpp
index fe5df28..5f931e5 100644
--- a/media/libmedia/IAudioPolicyServiceClient.cpp
+++ b/media/libmedia/IAudioPolicyServiceClient.cpp
@@ -34,6 +34,21 @@
RECORDING_CONFIGURATION_UPDATE
};
+// ----------------------------------------------------------------------
+inline void readAudioConfigBaseFromParcel(const Parcel& data, audio_config_base_t *config) {
+ config->sample_rate = data.readUint32();
+ config->channel_mask = (audio_channel_mask_t) data.readInt32();
+ config->format = (audio_format_t) data.readInt32();
+}
+
+inline void writeAudioConfigBaseToParcel(Parcel& data, const audio_config_base_t *config)
+{
+ data.writeUint32(config->sample_rate);
+ data.writeInt32((int32_t) config->channel_mask);
+ data.writeInt32((int32_t) config->format);
+}
+
+// ----------------------------------------------------------------------
class BpAudioPolicyServiceClient : public BpInterface<IAudioPolicyServiceClient>
{
public:
@@ -66,12 +81,16 @@
}
void onRecordingConfigurationUpdate(int event, audio_session_t session,
- audio_source_t source) {
+ audio_source_t source, const audio_config_base_t *clientConfig,
+ const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle) {
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor());
data.writeInt32(event);
data.writeInt32(session);
data.writeInt32(source);
+ writeAudioConfigBaseToParcel(data, clientConfig);
+ writeAudioConfigBaseToParcel(data, deviceConfig);
+ data.writeInt32(patchHandle);
remote()->transact(RECORDING_CONFIGURATION_UPDATE, data, &reply, IBinder::FLAG_ONEWAY);
}
};
@@ -106,7 +125,13 @@
int event = (int) data.readInt32();
audio_session_t session = (audio_session_t) data.readInt32();
audio_source_t source = (audio_source_t) data.readInt32();
- onRecordingConfigurationUpdate(event, session, source);
+ audio_config_base_t clientConfig;
+ audio_config_base_t deviceConfig;
+ readAudioConfigBaseFromParcel(data, &clientConfig);
+ readAudioConfigBaseFromParcel(data, &deviceConfig);
+ audio_patch_handle_t patchHandle = (audio_patch_handle_t) data.readInt32();
+ onRecordingConfigurationUpdate(event, session, source, &clientConfig, &deviceConfig,
+ patchHandle);
return NO_ERROR;
} break;
default:
diff --git a/media/libmedia/IDrm.cpp b/media/libmedia/IDrm.cpp
index 5a4591c..7f131f4 100644
--- a/media/libmedia/IDrm.cpp
+++ b/media/libmedia/IDrm.cpp
@@ -645,7 +645,7 @@
Vector<uint8_t> request;
String8 defaultUrl;
- DrmPlugin::KeyRequestType keyRequestType;
+ DrmPlugin::KeyRequestType keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
status_t result = getKeyRequest(sessionId, initData, mimeType,
keyType, optionalParameters, request, defaultUrl,
diff --git a/media/libmedia/IMediaSource.cpp b/media/libmedia/IMediaSource.cpp
index b988c46..6cfbeaa 100644
--- a/media/libmedia/IMediaSource.cpp
+++ b/media/libmedia/IMediaSource.cpp
@@ -18,6 +18,8 @@
#define LOG_TAG "BpMediaSource"
#include <utils/Log.h>
+#include <utils/CallStack.h>
+
#include <inttypes.h>
#include <stdint.h>
#include <sys/types.h>
@@ -109,9 +111,16 @@
BpMediaSource(const sp<IBinder>& impl)
: BpInterface<IMediaSource>(impl)
{
+ mStarted = false;
}
virtual status_t start(MetaData *params) {
+ if (mStarted) {
+ ALOGD("Source was started previously from:");
+ mStartStack.log(LOG_TAG);
+ ALOGD("Now from:");
+ CallStack stack(LOG_TAG);
+ }
ALOGV("start");
Parcel data, reply;
data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
@@ -119,6 +128,10 @@
params->writeToParcel(data);
}
status_t ret = remote()->transact(START, data, &reply);
+ if (ret == NO_ERROR) {
+ mStarted = true;
+ mStartStack.update();
+ }
if (ret == NO_ERROR && params) {
ALOGW("ignoring potentially modified MetaData from start");
ALOGW("input:");
@@ -131,6 +144,7 @@
}
virtual status_t stop() {
+ mStarted = false;
ALOGV("stop");
Parcel data, reply;
data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
@@ -205,7 +219,8 @@
// NuPlayer passes pointers-to-metadata around, so we use this to keep the metadata alive
// XXX: could we use this for caching, or does metadata change on the fly?
sp<MetaData> mMetaData;
-
+ bool mStarted;
+ CallStack mStartStack;
};
IMPLEMENT_META_INTERFACE(MediaSource, "android.media.IMediaSource");
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index bd398aa..0ef6e3e 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -98,7 +98,9 @@
}
virtual status_t allocateNode(
- const char *name, const sp<IOMXObserver> &observer, node_id *node) {
+ const char *name, const sp<IOMXObserver> &observer,
+ sp<IBinder> *nodeBinder,
+ node_id *node) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
data.writeCString(name);
@@ -108,6 +110,9 @@
status_t err = reply.readInt32();
if (err == OK) {
*node = (node_id)reply.readInt32();
+ if (nodeBinder != NULL) {
+ *nodeBinder = remote();
+ }
} else {
*node = 0;
}
@@ -656,7 +661,8 @@
node_id node;
- status_t err = allocateNode(name, observer, &node);
+ status_t err = allocateNode(name, observer,
+ NULL /* nodeBinder */, &node);
reply->writeInt32(err);
if (err == OK) {
reply->writeInt32((int32_t)node);
@@ -704,34 +710,39 @@
size_t size = data.readInt64();
- void *params = malloc(size);
- data.read(params, size);
+ status_t err = NO_MEMORY;
+ void *params = calloc(size, 1);
+ if (params) {
+ err = data.read(params, size);
+ if (err != OK) {
+ android_errorWriteLog(0x534e4554, "26914474");
+ } else {
+ switch (code) {
+ case GET_PARAMETER:
+ err = getParameter(node, index, params, size);
+ break;
+ case SET_PARAMETER:
+ err = setParameter(node, index, params, size);
+ break;
+ case GET_CONFIG:
+ err = getConfig(node, index, params, size);
+ break;
+ case SET_CONFIG:
+ err = setConfig(node, index, params, size);
+ break;
+ case SET_INTERNAL_OPTION:
+ {
+ InternalOptionType type =
+ (InternalOptionType)data.readInt32();
- status_t err;
- switch (code) {
- case GET_PARAMETER:
- err = getParameter(node, index, params, size);
- break;
- case SET_PARAMETER:
- err = setParameter(node, index, params, size);
- break;
- case GET_CONFIG:
- err = getConfig(node, index, params, size);
- break;
- case SET_CONFIG:
- err = setConfig(node, index, params, size);
- break;
- case SET_INTERNAL_OPTION:
- {
- InternalOptionType type =
- (InternalOptionType)data.readInt32();
+ err = setInternalOption(node, index, type, params, size);
+ break;
+ }
- err = setInternalOption(node, index, type, params, size);
- break;
+ default:
+ TRESPASS();
+ }
}
-
- default:
- TRESPASS();
}
reply->writeInt32(err);
@@ -950,10 +961,6 @@
MetadataBufferType type = kMetadataBufferTypeInvalid;
status_t err = storeMetaDataInBuffers(node, port_index, enable, &type);
- if ((err != OK) && (type == kMetadataBufferTypeInvalid)) {
- android_errorWriteLog(0x534e4554, "26324358");
- }
-
reply->writeInt32(type);
reply->writeInt32(err);
diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp
index 9a76f58..08a9e6a 100644
--- a/media/libmedia/mediametadataretriever.cpp
+++ b/media/libmedia/mediametadataretriever.cpp
@@ -35,7 +35,7 @@
sp<IMediaPlayerService> MediaMetadataRetriever::sService;
sp<MediaMetadataRetriever::DeathNotifier> MediaMetadataRetriever::sDeathNotifier;
-const sp<IMediaPlayerService>& MediaMetadataRetriever::getService()
+const sp<IMediaPlayerService> MediaMetadataRetriever::getService()
{
Mutex::Autolock lock(sServiceLock);
if (sService == 0) {
@@ -62,7 +62,7 @@
MediaMetadataRetriever::MediaMetadataRetriever()
{
ALOGV("constructor");
- const sp<IMediaPlayerService>& service(getService());
+ const sp<IMediaPlayerService> service(getService());
if (service == 0) {
ALOGE("failed to obtain MediaMetadataRetrieverService");
return;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index d0e7aa9..6c54e3f 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -731,6 +731,29 @@
readFromAMessage(msg, &rate);
status_t err = OK;
if (mRenderer != NULL) {
+ // AudioSink allows only 1.f and 0.f for offload mode.
+ // For other speed, switch to non-offload mode.
+ if (mOffloadAudio && ((rate.mSpeed != 0.f && rate.mSpeed != 1.f)
+ || rate.mPitch != 1.f)) {
+ int64_t currentPositionUs;
+ if (getCurrentPosition(¤tPositionUs) != OK) {
+ currentPositionUs = mPreviousSeekTimeUs;
+ }
+
+ // Set mPlaybackSettings so that the new audio decoder can
+ // be created correctly.
+ mPlaybackSettings = rate;
+ if (!mPaused) {
+ mRenderer->pause();
+ }
+ restartAudio(
+ currentPositionUs, true /* forceNonOffload */,
+ true /* needsToCreateAudioDecoder */);
+ if (!mPaused) {
+ mRenderer->resume();
+ }
+ }
+
err = mRenderer->setPlaybackSettings(rate);
}
if (err == OK) {
@@ -1121,41 +1144,14 @@
int32_t reason;
CHECK(msg->findInt32("reason", &reason));
ALOGV("Tear down audio with reason %d.", reason);
- mAudioDecoder->pause();
- mAudioDecoder.clear();
- ++mAudioDecoderGeneration;
- bool needsToCreateAudioDecoder = true;
- if (mFlushingAudio == FLUSHING_DECODER) {
- mFlushComplete[1 /* audio */][1 /* isDecoder */] = true;
- mFlushingAudio = FLUSHED;
- finishFlushIfPossible();
- } else if (mFlushingAudio == FLUSHING_DECODER_SHUTDOWN
- || mFlushingAudio == SHUTTING_DOWN_DECODER) {
- mFlushComplete[1 /* audio */][1 /* isDecoder */] = true;
- mFlushingAudio = SHUT_DOWN;
- finishFlushIfPossible();
- needsToCreateAudioDecoder = false;
- }
- if (mRenderer == NULL) {
- break;
- }
- closeAudioSink();
- mRenderer->flush(
- true /* audio */, false /* notifyComplete */);
- if (mVideoDecoder != NULL) {
- mRenderer->flush(
- false /* audio */, false /* notifyComplete */);
- }
-
int64_t positionUs;
if (!msg->findInt64("positionUs", &positionUs)) {
positionUs = mPreviousSeekTimeUs;
}
- performSeek(positionUs);
- if (reason == Renderer::kDueToError && needsToCreateAudioDecoder) {
- instantiateDecoder(true /* audio */, &mAudioDecoder);
- }
+ restartAudio(
+ positionUs, false /* forceNonOffload */,
+ reason == Renderer::kDueToError /* needsToCreateAudioDecoder */);
}
break;
}
@@ -1339,7 +1335,8 @@
sp<AMessage> videoFormat = mSource->getFormat(false /* audio */);
mOffloadAudio =
- canOffloadStream(audioMeta, (videoFormat != NULL), mSource->isStreaming(), streamType);
+ canOffloadStream(audioMeta, (videoFormat != NULL), mSource->isStreaming(), streamType)
+ && (mPlaybackSettings.mSpeed == 1.f && mPlaybackSettings.mPitch == 1.f);
if (mOffloadAudio) {
flags |= Renderer::FLAG_OFFLOAD_AUDIO;
}
@@ -1491,6 +1488,42 @@
mRenderer->closeAudioSink();
}
+void NuPlayer::restartAudio(
+ int64_t currentPositionUs, bool forceNonOffload, bool needsToCreateAudioDecoder) {
+ mAudioDecoder->pause();
+ mAudioDecoder.clear();
+ ++mAudioDecoderGeneration;
+ if (mFlushingAudio == FLUSHING_DECODER) {
+ mFlushComplete[1 /* audio */][1 /* isDecoder */] = true;
+ mFlushingAudio = FLUSHED;
+ finishFlushIfPossible();
+ } else if (mFlushingAudio == FLUSHING_DECODER_SHUTDOWN
+ || mFlushingAudio == SHUTTING_DOWN_DECODER) {
+ mFlushComplete[1 /* audio */][1 /* isDecoder */] = true;
+ mFlushingAudio = SHUT_DOWN;
+ finishFlushIfPossible();
+ needsToCreateAudioDecoder = false;
+ }
+ if (mRenderer == NULL) {
+ return;
+ }
+ closeAudioSink();
+ mRenderer->flush(true /* audio */, false /* notifyComplete */);
+ if (mVideoDecoder != NULL) {
+ mRenderer->flush(false /* audio */, false /* notifyComplete */);
+ }
+
+ performSeek(currentPositionUs);
+
+ if (forceNonOffload) {
+ mRenderer->signalDisableOffloadAudio();
+ mOffloadAudio = false;
+ }
+ if (needsToCreateAudioDecoder) {
+ instantiateDecoder(true /* audio */, &mAudioDecoder);
+ }
+}
+
void NuPlayer::determineAudioModeChange() {
if (mSource == NULL || mAudioSink == NULL) {
return;
@@ -1507,7 +1540,8 @@
audio_stream_type_t streamType = mAudioSink->getAudioStreamType();
const bool hasVideo = (videoFormat != NULL);
const bool canOffload = canOffloadStream(
- audioMeta, hasVideo, mSource->isStreaming(), streamType);
+ audioMeta, hasVideo, mSource->isStreaming(), streamType)
+ && (mPlaybackSettings.mSpeed == 1.f && mPlaybackSettings.mPitch == 1.f);
if (canOffload) {
if (!mOffloadAudio) {
mRenderer->signalEnableOffloadAudio();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index cefbb19..a55aa5f 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -233,6 +233,8 @@
void tryOpenAudioSinkForOffload(const sp<AMessage> &format, bool hasVideo);
void closeAudioSink();
+ void restartAudio(
+ int64_t currentPositionUs, bool forceNonOffload, bool needsToCreateAudioDecoder);
void determineAudioModeChange();
status_t instantiateDecoder(bool audio, sp<DecoderBase> *decoder);
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index ec33478..ba40876 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -32,6 +32,12 @@
const int64_t kNearEOSTimeoutUs = 2000000ll; // 2 secs
+// Buffer Underflow/Prepare/StartServer/Overflow Marks
+const int64_t NuPlayer::RTSPSource::kUnderflowMarkUs = 1000000ll;
+const int64_t NuPlayer::RTSPSource::kPrepareMarkUs = 3000000ll;
+const int64_t NuPlayer::RTSPSource::kStartServerMarkUs = 5000000ll;
+const int64_t NuPlayer::RTSPSource::kOverflowMarkUs = 10000000ll;
+
NuPlayer::RTSPSource::RTSPSource(
const sp<AMessage> ¬ify,
const sp<IMediaHTTPService> &httpService,
@@ -51,6 +57,7 @@
mFinalResult(OK),
mDisconnectReplyID(0),
mBuffering(false),
+ mInPreparationPhase(true),
mSeekGeneration(0),
mEOSTimeoutAudio(0),
mEOSTimeoutVideo(0) {
@@ -127,29 +134,6 @@
msg->postAndAwaitResponse(&dummy);
}
-void NuPlayer::RTSPSource::pause() {
- int64_t mediaDurationUs = 0;
- getDuration(&mediaDurationUs);
- for (size_t index = 0; index < mTracks.size(); index++) {
- TrackInfo *info = &mTracks.editItemAt(index);
- sp<AnotherPacketSource> source = info->mSource;
-
- // Check if EOS or ERROR is received
- if (source != NULL && source->isFinished(mediaDurationUs)) {
- return;
- }
- }
- if (mHandler != NULL) {
- mHandler->pause();
- }
-}
-
-void NuPlayer::RTSPSource::resume() {
- if (mHandler != NULL) {
- mHandler->resume();
- }
-}
-
status_t NuPlayer::RTSPSource::feedMoreTSData() {
Mutex::Autolock _l(mBufferingLock);
return mFinalResult;
@@ -324,6 +308,73 @@
mHandler->seek(seekTimeUs);
}
+void NuPlayer::RTSPSource::schedulePollBuffering() {
+ sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
+ msg->post(1000000ll); // 1 second intervals
+}
+
+void NuPlayer::RTSPSource::checkBuffering(
+ bool *prepared, bool *underflow, bool *overflow, bool *startServer) {
+ size_t numTracks = mTracks.size();
+ size_t preparedCount, underflowCount, overflowCount, startCount;
+ preparedCount = underflowCount = overflowCount = startCount = 0;
+ for (size_t i = 0; i < numTracks; ++i) {
+ status_t finalResult;
+ TrackInfo *info = &mTracks.editItemAt(i);
+ sp<AnotherPacketSource> src = info->mSource;
+ int64_t bufferedDurationUs = src->getBufferedDurationUs(&finalResult);
+
+ // isFinished when duration is 0 checks for EOS result only
+ if (bufferedDurationUs > kPrepareMarkUs || src->isFinished(/* duration */ 0)) {
+ ++preparedCount;
+ }
+
+ if (src->isFinished(/* duration */ 0)) {
+ ++overflowCount;
+ } else {
+ if (bufferedDurationUs < kUnderflowMarkUs) {
+ ++underflowCount;
+ }
+ if (bufferedDurationUs > kOverflowMarkUs) {
+ ++overflowCount;
+ }
+ if (bufferedDurationUs < kStartServerMarkUs) {
+ ++startCount;
+ }
+ }
+ }
+
+ *prepared = (preparedCount == numTracks);
+ *underflow = (underflowCount > 0);
+ *overflow = (overflowCount == numTracks);
+ *startServer = (startCount > 0);
+}
+
+void NuPlayer::RTSPSource::onPollBuffering() {
+ bool prepared, underflow, overflow, startServer;
+ checkBuffering(&prepared, &underflow, &overflow, &startServer);
+
+ if (prepared && mInPreparationPhase) {
+ mInPreparationPhase = false;
+ notifyPrepared();
+ }
+
+ if (!mInPreparationPhase && underflow) {
+ startBufferingIfNecessary();
+ }
+
+ if (overflow && mHandler != NULL) {
+ stopBufferingIfNecessary();
+ mHandler->pause();
+ }
+
+ if (startServer && mHandler != NULL) {
+ mHandler->resume();
+ }
+
+ schedulePollBuffering();
+}
+
void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
if (msg->what() == kWhatDisconnect) {
sp<AReplyToken> replyID;
@@ -348,6 +399,9 @@
performSeek(seekTimeUs);
return;
+ } else if (msg->what() == kWhatPollBuffering) {
+ onPollBuffering();
+ return;
}
CHECK_EQ(msg->what(), (int)kWhatNotify);
@@ -372,7 +426,7 @@
}
notifyFlagsChanged(flags);
- notifyPrepared();
+ schedulePollBuffering();
break;
}
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.h b/media/libmediaplayerservice/nuplayer/RTSPSource.h
index 6438a1e..a6a7644 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.h
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.h
@@ -43,8 +43,6 @@
virtual void prepareAsync();
virtual void start();
virtual void stop();
- virtual void pause();
- virtual void resume();
virtual status_t feedMoreTSData();
@@ -65,6 +63,7 @@
kWhatNotify = 'noti',
kWhatDisconnect = 'disc',
kWhatPerformSeek = 'seek',
+ kWhatPollBuffering = 'poll',
};
enum State {
@@ -79,6 +78,12 @@
kFlagIncognito = 1,
};
+ // Buffer Prepare/Underflow/Overflow/Resume Marks
+ static const int64_t kPrepareMarkUs;
+ static const int64_t kUnderflowMarkUs;
+ static const int64_t kOverflowMarkUs;
+ static const int64_t kStartServerMarkUs;
+
struct TrackInfo {
sp<AnotherPacketSource> mSource;
@@ -100,6 +105,7 @@
sp<AReplyToken> mDisconnectReplyID;
Mutex mBufferingLock;
bool mBuffering;
+ bool mInPreparationPhase;
sp<ALooper> mLooper;
sp<MyHandler> mHandler;
@@ -126,6 +132,9 @@
void finishDisconnectIfPossible();
void performSeek(int64_t seekTimeUs);
+ void schedulePollBuffering();
+ void checkBuffering(bool *prepared, bool *underflow, bool *overflow, bool *startServer);
+ void onPollBuffering();
bool haveSufficientDataOnAllTracks();
diff --git a/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp b/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
index de350a1..ef4c833 100644
--- a/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
+++ b/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
@@ -39,6 +39,10 @@
return true;
}
+ virtual bool isValidPid(int /* pid */) {
+ return true;
+ }
+
private:
DISALLOW_EVIL_CONSTRUCTORS(FakeProcessInfo);
};
diff --git a/media/libnbaio/AudioStreamInSource.cpp b/media/libnbaio/AudioStreamInSource.cpp
index 286e0eb..2dc3050 100644
--- a/media/libnbaio/AudioStreamInSource.cpp
+++ b/media/libnbaio/AudioStreamInSource.cpp
@@ -53,7 +53,7 @@
return NBAIO_Source::negotiate(offers, numOffers, counterOffers, numCounterOffers);
}
-size_t AudioStreamInSource::framesOverrun()
+int64_t AudioStreamInSource::framesOverrun()
{
uint32_t framesOverrun = mStream->get_input_frames_lost(mStream);
if (framesOverrun > 0) {
diff --git a/media/libnbaio/AudioStreamOutSink.cpp b/media/libnbaio/AudioStreamOutSink.cpp
index 3f4e0bb..ee44678 100644
--- a/media/libnbaio/AudioStreamOutSink.cpp
+++ b/media/libnbaio/AudioStreamOutSink.cpp
@@ -66,18 +66,20 @@
return ret;
}
-status_t AudioStreamOutSink::getTimestamp(AudioTimestamp& timestamp)
+status_t AudioStreamOutSink::getTimestamp(ExtendedTimestamp ×tamp)
{
if (mStream->get_presentation_position == NULL) {
return INVALID_OPERATION;
}
- // FIXME position64 won't be needed after AudioTimestamp.mPosition is changed to uint64_t
+
uint64_t position64;
- int ok = mStream->get_presentation_position(mStream, &position64, ×tamp.mTime);
- if (ok != 0) {
+ struct timespec time;
+ if (mStream->get_presentation_position(mStream, &position64, &time) != OK) {
return INVALID_OPERATION;
}
- timestamp.mPosition = position64;
+ timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] = position64;
+ timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] =
+ time.tv_sec * 1000000000LL + time.tv_nsec;
return OK;
}
diff --git a/media/libnbaio/MonoPipe.cpp b/media/libnbaio/MonoPipe.cpp
index aef9834..8d1cb0f 100644
--- a/media/libnbaio/MonoPipe.cpp
+++ b/media/libnbaio/MonoPipe.cpp
@@ -183,9 +183,14 @@
return mIsShutdown;
}
-status_t MonoPipe::getTimestamp(AudioTimestamp& timestamp)
+status_t MonoPipe::getTimestamp(ExtendedTimestamp ×tamp)
{
- if (mTimestampObserver.poll(timestamp)) {
+ ExtendedTimestamp ets;
+ if (mTimestampObserver.poll(ets)) {
+ timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] =
+ ets.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
+ timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] =
+ ets.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL];
return OK;
}
return INVALID_OPERATION;
diff --git a/media/libnbaio/MonoPipeReader.cpp b/media/libnbaio/MonoPipeReader.cpp
index 7e09544..01dc524 100644
--- a/media/libnbaio/MonoPipeReader.cpp
+++ b/media/libnbaio/MonoPipeReader.cpp
@@ -72,7 +72,7 @@
return red;
}
-void MonoPipeReader::onTimestamp(const AudioTimestamp& timestamp)
+void MonoPipeReader::onTimestamp(const ExtendedTimestamp ×tamp)
{
mPipe->mTimestampMutator.push(timestamp);
}
diff --git a/media/libnbaio/SourceAudioBufferProvider.cpp b/media/libnbaio/SourceAudioBufferProvider.cpp
index dc01c0e..d58619f 100644
--- a/media/libnbaio/SourceAudioBufferProvider.cpp
+++ b/media/libnbaio/SourceAudioBufferProvider.cpp
@@ -112,12 +112,12 @@
return avail < 0 ? 0 : (size_t) avail;
}
-size_t SourceAudioBufferProvider::framesReleased() const
+int64_t SourceAudioBufferProvider::framesReleased() const
{
return mFramesReleased;
}
-void SourceAudioBufferProvider::onTimestamp(const AudioTimestamp& timestamp)
+void SourceAudioBufferProvider::onTimestamp(const ExtendedTimestamp ×tamp)
{
mSource->onTimestamp(timestamp);
}
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 0dc5d4c..ee573f0 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -5541,7 +5541,7 @@
ALOGV("Now uninitialized");
if (mDeathNotifier != NULL) {
- IInterface::asBinder(mCodec->mOMX)->unlinkToDeath(mDeathNotifier);
+ mCodec->mNodeBinder->unlinkToDeath(mDeathNotifier);
mDeathNotifier.clear();
}
@@ -5638,13 +5638,6 @@
sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec);
- mDeathNotifier = new DeathNotifier(notify);
- if (IInterface::asBinder(omx)->linkToDeath(mDeathNotifier) != OK) {
- // This was a local binder, if it dies so do we, we won't care
- // about any notifications in the afterlife.
- mDeathNotifier.clear();
- }
-
Vector<AString> matchingCodecs;
AString mime;
@@ -5683,7 +5676,7 @@
pid_t tid = gettid();
int prevPriority = androidGetThreadPriority(tid);
androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
- err = omx->allocateNode(componentName.c_str(), observer, &node);
+ err = omx->allocateNode(componentName.c_str(), observer, &mCodec->mNodeBinder, &node);
androidSetThreadPriority(tid, prevPriority);
if (err == OK) {
@@ -5707,6 +5700,14 @@
return false;
}
+ mDeathNotifier = new DeathNotifier(notify);
+ if (mCodec->mNodeBinder == NULL ||
+ mCodec->mNodeBinder->linkToDeath(mDeathNotifier) != OK) {
+ // This was a local binder, if it dies so do we, we won't care
+ // about any notifications in the afterlife.
+ mDeathNotifier.clear();
+ }
+
notify = new AMessage(kWhatOMXMessageList, mCodec);
observer->setNotificationMessage(notify);
@@ -7078,7 +7079,7 @@
sp<CodecObserver> observer = new CodecObserver;
IOMX::node_id node = 0;
- err = omx->allocateNode(name.c_str(), observer, &node);
+ err = omx->allocateNode(name.c_str(), observer, NULL, &node);
if (err != OK) {
client.disconnect();
return err;
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 6f4a65b..d5a869d 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -4279,7 +4279,15 @@
continue;
}
- CHECK(dstOffset + 4 <= mBuffer->size());
+ if (dstOffset > SIZE_MAX - 4 ||
+ dstOffset + 4 > SIZE_MAX - nalLength ||
+ dstOffset + 4 + nalLength > mBuffer->size()) {
+ ALOGE("b/27208621 : %zu %zu", dstOffset, mBuffer->size());
+ android_errorWriteLog(0x534e4554, "27208621");
+ mBuffer->release();
+ mBuffer = NULL;
+ return ERROR_MALFORMED;
+ }
dstData[dstOffset++] = 0;
dstData[dstOffset++] = 0;
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index a5d9484..d520cb3 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -2536,6 +2536,7 @@
ALOGE("timestampUs %" PRId64 " < lastTimestampUs %" PRId64 " for %s track",
timestampUs, lastTimestampUs, trackName);
copy->release();
+ mSource->stop();
return UNKNOWN_ERROR;
}
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index fb1f401..fbdf56f 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -2498,7 +2498,7 @@
ICrypto::DestinationType dst_type = ICrypto::kDestinationTypeOpaqueHandle;
if (info->mNativeHandle != NULL) {
- dst_pointer = (void *)info->mNativeHandle.get();
+ dst_pointer = (void *)info->mNativeHandle->handle();
dst_type = ICrypto::kDestinationTypeNativeHandle;
} else if ((mFlags & kFlagIsSecure) == 0) {
dst_type = ICrypto::kDestinationTypeVmPointer;
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 3a3a538..bdfddc7 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -48,6 +48,7 @@
struct MediaCodecSource::Puller : public AHandler {
Puller(const sp<MediaSource> &source);
+ void interruptSource();
status_t start(const sp<MetaData> &meta, const sp<AMessage> ¬ify);
void stop();
void stopSource();
@@ -84,9 +85,9 @@
void flush();
// if queue is empty, return false and set *|buffer| to NULL . Otherwise, pop
- // buffer from front of the queue, place it into *|buffer| and return true.
+ // buffer from front of the queue, place it into *|buffer| and return true.
bool readBuffer(MediaBuffer **buffer);
- // add a buffer to the back of the queue
+ // add a buffer to the back of the queue
void pushBuffer(MediaBuffer *mbuf);
};
Mutexed<Queue> mQueue;
@@ -186,14 +187,19 @@
}
if (interrupt) {
- // call source->stop if read has been pending for over a second
- // TODO: we should really call this if kWhatStop has not returned for more than a second.
- mSource->stop();
+ interruptSource();
}
}
+void MediaCodecSource::Puller::interruptSource() {
+ // call source->stop if read has been pending for over a second
+ // We have to call this outside the looper as looper is pending on the read.
+ mSource->stop();
+}
+
void MediaCodecSource::Puller::stopSource() {
- (new AMessage(kWhatStop, this))->post();
+ sp<AMessage> msg = new AMessage(kWhatStop, this);
+ (void)postSynchronouslyAndReturnError(msg);
}
void MediaCodecSource::Puller::pause() {
@@ -247,6 +253,13 @@
case kWhatStop:
{
mSource->stop();
+
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", OK);
+
+ sp<AReplyToken> replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+ response->postReply(replyID);
break;
}
@@ -915,7 +928,7 @@
if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
ALOGV("source (%s) stopping", mIsVideo ? "video" : "audio");
- mPuller->stopSource();
+ mPuller->interruptSource();
ALOGV("source (%s) stopped", mIsVideo ? "video" : "audio");
}
signalEOS();
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index 50f235e..8e72405 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -25,19 +25,29 @@
#include <binder/IServiceManager.h>
#include <media/IMediaPlayerService.h>
+#include <media/IMediaCodecService.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/OMXClient.h>
+#include <cutils/properties.h>
#include <utils/KeyedVector.h>
#include "include/OMX.h"
namespace android {
+static bool sCodecProcessEnabled = true;
+
struct MuxOMX : public IOMX {
- MuxOMX(const sp<IOMX> &remoteOMX);
+ MuxOMX(const sp<IOMX> &mediaServerOMX, const sp<IOMX> &mediaCodecOMX);
virtual ~MuxOMX();
- virtual IBinder *onAsBinder() { return IInterface::asBinder(mRemoteOMX).get(); }
+ // Nobody should be calling this. In case someone does anyway, just
+ // return the media server IOMX.
+ // TODO: return NULL
+ virtual IBinder *onAsBinder() {
+ ALOGE("MuxOMX::onAsBinder should not be called");
+ return IInterface::asBinder(mMediaServerOMX).get();
+ }
virtual bool livesLocally(node_id node, pid_t pid);
@@ -45,6 +55,7 @@
virtual status_t allocateNode(
const char *name, const sp<IOMXObserver> &observer,
+ sp<IBinder> *nodeBinder,
node_id *node);
virtual status_t freeNode(node_id node);
@@ -148,23 +159,32 @@
private:
mutable Mutex mLock;
- sp<IOMX> mRemoteOMX;
+ sp<IOMX> mMediaServerOMX;
+ sp<IOMX> mMediaCodecOMX;
sp<IOMX> mLocalOMX;
- KeyedVector<node_id, bool> mIsLocalNode;
+ typedef enum {
+ LOCAL,
+ MEDIAPROCESS,
+ CODECPROCESS
+ } node_location;
+
+ KeyedVector<node_id, node_location> mNodeLocation;
bool isLocalNode(node_id node) const;
bool isLocalNode_l(node_id node) const;
const sp<IOMX> &getOMX(node_id node) const;
const sp<IOMX> &getOMX_l(node_id node) const;
- static bool CanLiveLocally(const char *name);
+ static node_location getPreferredCodecLocation(const char *name);
DISALLOW_EVIL_CONSTRUCTORS(MuxOMX);
};
-MuxOMX::MuxOMX(const sp<IOMX> &remoteOMX)
- : mRemoteOMX(remoteOMX) {
+MuxOMX::MuxOMX(const sp<IOMX> &mediaServerOMX, const sp<IOMX> &mediaCodecOMX)
+ : mMediaServerOMX(mediaServerOMX),
+ mMediaCodecOMX(mediaCodecOMX) {
+ ALOGI("MuxOMX ctor");
}
MuxOMX::~MuxOMX() {
@@ -177,27 +197,49 @@
}
bool MuxOMX::isLocalNode_l(node_id node) const {
- return mIsLocalNode.indexOfKey(node) >= 0;
+ return mNodeLocation.valueFor(node) == LOCAL;
}
// static
-bool MuxOMX::CanLiveLocally(const char *name) {
+MuxOMX::node_location MuxOMX::getPreferredCodecLocation(const char *name) {
+ if (sCodecProcessEnabled) {
+ // all non-secure decoders plus OMX.google.* encoders can go in the codec process
+ if ((strcasestr(name, "decoder") && !strcasestr(name, "secure")) ||
+ !strncasecmp(name, "OMX.google.", 11)) {
+ return CODECPROCESS;
+ }
+ // everything else runs in the media server
+ return MEDIAPROCESS;
+ } else {
#ifdef __LP64__
- (void)name; // disable unused parameter warning
- // 64 bit processes always run OMX remote on MediaServer
- return false;
+ // 64 bit processes always run OMX remote on MediaServer
+ return MEDIAPROCESS;
#else
- // 32 bit processes run only OMX.google.* components locally
- return !strncasecmp(name, "OMX.google.", 11);
+ // 32 bit processes run only OMX.google.* components locally
+ if (!strncasecmp(name, "OMX.google.", 11)) {
+ return LOCAL;
+ }
+ return MEDIAPROCESS;
#endif
+ }
}
const sp<IOMX> &MuxOMX::getOMX(node_id node) const {
- return isLocalNode(node) ? mLocalOMX : mRemoteOMX;
+ Mutex::Autolock autoLock(mLock);
+ return getOMX_l(node);
}
const sp<IOMX> &MuxOMX::getOMX_l(node_id node) const {
- return isLocalNode_l(node) ? mLocalOMX : mRemoteOMX;
+ node_location loc = mNodeLocation.valueFor(node);
+ if (loc == LOCAL) {
+ return mLocalOMX;
+ } else if (loc == MEDIAPROCESS) {
+ return mMediaServerOMX;
+ } else if (loc == CODECPROCESS) {
+ return mMediaCodecOMX;
+ }
+ ALOGE("Couldn't determine node location for node %d: %d, using local", node, loc);
+ return mLocalOMX;
}
bool MuxOMX::livesLocally(node_id node, pid_t pid) {
@@ -216,29 +258,34 @@
status_t MuxOMX::allocateNode(
const char *name, const sp<IOMXObserver> &observer,
+ sp<IBinder> *nodeBinder,
node_id *node) {
Mutex::Autolock autoLock(mLock);
sp<IOMX> omx;
- if (CanLiveLocally(name)) {
+ node_location loc = getPreferredCodecLocation(name);
+ if (loc == CODECPROCESS) {
+ omx = mMediaCodecOMX;
+ } else if (loc == MEDIAPROCESS) {
+ omx = mMediaServerOMX;
+ } else {
if (mLocalOMX == NULL) {
mLocalOMX = new OMX;
}
omx = mLocalOMX;
- } else {
- omx = mRemoteOMX;
}
- status_t err = omx->allocateNode(name, observer, node);
+ status_t err = omx->allocateNode(name, observer, nodeBinder, node);
+ ALOGV("allocated node_id %x on %s OMX", *node, omx == mMediaCodecOMX ? "codecprocess" :
+ omx == mMediaServerOMX ? "mediaserver" : "local");
+
if (err != OK) {
return err;
}
- if (omx == mLocalOMX) {
- mIsLocalNode.add(*node, true);
- }
+ mNodeLocation.add(*node, loc);
return OK;
}
@@ -252,7 +299,7 @@
return err;
}
- mIsLocalNode.removeItem(node);
+ mNodeLocation.removeItem(node);
return OK;
}
@@ -352,7 +399,7 @@
sp<IGraphicBufferProducer> *bufferProducer,
sp<IGraphicBufferConsumer> *bufferConsumer) {
// TODO: local or remote? Always use remote for now
- return mRemoteOMX->createPersistentInputSurface(
+ return mMediaServerOMX->createPersistentInputSurface(
bufferProducer, bufferConsumer);
}
@@ -415,29 +462,53 @@
}
OMXClient::OMXClient() {
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("media.stagefright.codecremote", value, NULL)
+ && (!strcmp("0", value) || !strcasecmp("false", value))) {
+ sCodecProcessEnabled = false;
+ }
}
status_t OMXClient::connect() {
sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder = sm->getService(String16("media.player"));
- sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+ sp<IBinder> playerbinder = sm->getService(String16("media.player"));
+ sp<IMediaPlayerService> mediaservice = interface_cast<IMediaPlayerService>(playerbinder);
- if (service.get() == NULL) {
+ if (mediaservice.get() == NULL) {
ALOGE("Cannot obtain IMediaPlayerService");
return NO_INIT;
}
- mOMX = service->getOMX();
- if (mOMX.get() == NULL) {
- ALOGE("Cannot obtain IOMX");
+ sp<IOMX> mediaServerOMX = mediaservice->getOMX();
+ if (mediaServerOMX.get() == NULL) {
+ ALOGE("Cannot obtain mediaserver IOMX");
return NO_INIT;
}
- if (!mOMX->livesLocally(0 /* node */, getpid())) {
- ALOGI("Using client-side OMX mux.");
- mOMX = new MuxOMX(mOMX);
+ // If we don't want to use the codec process, and the media server OMX
+ // is local, use it directly instead of going through MuxOMX
+ if (!sCodecProcessEnabled &&
+ mediaServerOMX->livesLocally(0 /* node */, getpid())) {
+ mOMX = mediaServerOMX;
+ return OK;
}
+ sp<IBinder> codecbinder = sm->getService(String16("media.codec"));
+ sp<IMediaCodecService> codecservice = interface_cast<IMediaCodecService>(codecbinder);
+
+ if (codecservice.get() == NULL) {
+ ALOGE("Cannot obtain IMediaCodecService");
+ return NO_INIT;
+ }
+
+ sp<IOMX> mediaCodecOMX = codecservice->getOMX();
+ if (mediaCodecOMX.get() == NULL) {
+ ALOGE("Cannot obtain mediacodec IOMX");
+ return NO_INIT;
+ }
+
+ mOMX = new MuxOMX(mediaServerOMX, mediaCodecOMX);
+
return OK;
}
diff --git a/media/libstagefright/ProcessInfo.cpp b/media/libstagefright/ProcessInfo.cpp
index 353f108..27f1a79 100644
--- a/media/libstagefright/ProcessInfo.cpp
+++ b/media/libstagefright/ProcessInfo.cpp
@@ -20,6 +20,7 @@
#include <media/stagefright/ProcessInfo.h>
+#include <binder/IPCThreadState.h>
#include <binder/IProcessInfoService.h>
#include <binder/IServiceManager.h>
@@ -52,6 +53,12 @@
return true;
}
+bool ProcessInfo::isValidPid(int pid) {
+ int callingPid = IPCThreadState::self()->getCallingPid();
+ // Trust it if this is called from the same process otherwise pid has to match the calling pid.
+ return (callingPid == getpid()) || (callingPid == pid);
+}
+
ProcessInfo::~ProcessInfo() {}
} // namespace android
diff --git a/media/libstagefright/SampleIterator.cpp b/media/libstagefright/SampleIterator.cpp
index 7bf3437..ad7b6fd 100644
--- a/media/libstagefright/SampleIterator.cpp
+++ b/media/libstagefright/SampleIterator.cpp
@@ -320,7 +320,18 @@
*time = mTTSSampleTime + mTTSDuration * (sampleIndex - mTTSSampleIndex);
- *time += mTable->getCompositionTimeOffset(sampleIndex);
+ int32_t offset = mTable->getCompositionTimeOffset(sampleIndex);
+ if ((offset < 0 && *time < (offset == INT32_MIN ?
+ INT32_MAX : uint32_t(-offset))) ||
+ (offset > 0 && *time > UINT32_MAX - offset)) {
+ ALOGE("%u + %d would overflow", *time, offset);
+ return ERROR_OUT_OF_RANGE;
+ }
+ if (offset > 0) {
+ *time += offset;
+ } else {
+ *time -= (offset == INT32_MIN ? INT32_MAX : (-offset));
+ }
*duration = mTTSDuration;
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index 39459e2..f5d9ec7 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -49,14 +49,14 @@
CompositionDeltaLookup();
void setEntries(
- const uint32_t *deltaEntries, size_t numDeltaEntries);
+ const int32_t *deltaEntries, size_t numDeltaEntries);
- uint32_t getCompositionTimeOffset(uint32_t sampleIndex);
+ int32_t getCompositionTimeOffset(uint32_t sampleIndex);
private:
Mutex mLock;
- const uint32_t *mDeltaEntries;
+ const int32_t *mDeltaEntries;
size_t mNumDeltaEntries;
size_t mCurrentDeltaEntry;
@@ -73,7 +73,7 @@
}
void SampleTable::CompositionDeltaLookup::setEntries(
- const uint32_t *deltaEntries, size_t numDeltaEntries) {
+ const int32_t *deltaEntries, size_t numDeltaEntries) {
Mutex::Autolock autolock(mLock);
mDeltaEntries = deltaEntries;
@@ -82,7 +82,7 @@
mCurrentEntrySampleIndex = 0;
}
-uint32_t SampleTable::CompositionDeltaLookup::getCompositionTimeOffset(
+int32_t SampleTable::CompositionDeltaLookup::getCompositionTimeOffset(
uint32_t sampleIndex) {
Mutex::Autolock autolock(mLock);
@@ -372,6 +372,10 @@
return OK;
}
+// NOTE: per 14996-12, version 0 ctts contains unsigned values, while version 1
+// contains signed values, however some software creates version 0 files that
+// contain signed values, so we're always treating the values as signed,
+// regardless of version.
status_t SampleTable::setCompositionTimeToSampleParams(
off64_t data_offset, size_t data_size) {
ALOGI("There are reordered frames present.");
@@ -387,8 +391,12 @@
return ERROR_IO;
}
- if (U32_AT(header) != 0) {
- // Expected version = 0, flags = 0.
+ uint32_t flags = U32_AT(header);
+ uint32_t version = flags >> 24;
+ flags &= 0xffffff;
+
+ if ((version != 0 && version != 1) || flags != 0) {
+ // Expected version = 0 or 1, flags = 0.
return ERROR_MALFORMED;
}
@@ -404,7 +412,7 @@
return ERROR_OUT_OF_RANGE;
}
- mCompositionTimeDeltaEntries = new (std::nothrow) uint32_t[2 * numEntries];
+ mCompositionTimeDeltaEntries = new (std::nothrow) int32_t[2 * numEntries];
if (!mCompositionTimeDeltaEntries)
return ERROR_OUT_OF_RANGE;
@@ -546,12 +554,28 @@
mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex;
- uint32_t compTimeDelta =
+ int32_t compTimeDelta =
mCompositionDeltaLookup->getCompositionTimeOffset(
sampleIndex);
+ if ((compTimeDelta < 0 && sampleTime <
+ (compTimeDelta == INT32_MIN ?
+ INT32_MAX : uint32_t(-compTimeDelta)))
+ || (compTimeDelta > 0 &&
+ sampleTime > UINT32_MAX - compTimeDelta)) {
+ ALOGE("%u + %d would overflow, clamping",
+ sampleTime, compTimeDelta);
+ if (compTimeDelta < 0) {
+ sampleTime = 0;
+ } else {
+ sampleTime = UINT32_MAX;
+ }
+ compTimeDelta = 0;
+ }
+
mSampleTimeEntries[sampleIndex].mCompositionTime =
- sampleTime + compTimeDelta;
+ compTimeDelta > 0 ? sampleTime + compTimeDelta:
+ sampleTime - (-compTimeDelta);
}
++sampleIndex;
@@ -841,7 +865,7 @@
return OK;
}
-uint32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) {
+int32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) {
return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex);
}
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
index 4c27360..c715939 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -36,7 +36,9 @@
virtual status_t listNodes(List<ComponentInfo> *list);
virtual status_t allocateNode(
- const char *name, const sp<IOMXObserver> &observer, node_id *node);
+ const char *name, const sp<IOMXObserver> &observer,
+ sp<IBinder> *nodeBinder,
+ node_id *node);
virtual status_t freeNode(node_id node);
diff --git a/media/libstagefright/include/SampleTable.h b/media/libstagefright/include/SampleTable.h
index 460492b..738f864 100644
--- a/media/libstagefright/include/SampleTable.h
+++ b/media/libstagefright/include/SampleTable.h
@@ -119,7 +119,7 @@
};
SampleTimeEntry *mSampleTimeEntries;
- uint32_t *mCompositionTimeDeltaEntries;
+ int32_t *mCompositionTimeDeltaEntries;
size_t mNumCompositionTimeDeltaEntries;
CompositionDeltaLookup *mCompositionDeltaLookup;
@@ -148,7 +148,7 @@
}
status_t getSampleSize_l(uint32_t sample_index, size_t *sample_size);
- uint32_t getCompositionTimeOffset(uint32_t sampleIndex);
+ int32_t getCompositionTimeOffset(uint32_t sampleIndex);
static int CompareIncreasingTime(const void *, const void *);
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index a20028b..6be289b 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -235,10 +235,14 @@
}
status_t OMX::allocateNode(
- const char *name, const sp<IOMXObserver> &observer, node_id *node) {
+ const char *name, const sp<IOMXObserver> &observer,
+ sp<IBinder> *nodeBinder, node_id *node) {
Mutex::Autolock autoLock(mLock);
*node = 0;
+ if (nodeBinder != NULL) {
+ *nodeBinder = NULL;
+ }
if (mNodeIDToInstance.size() == kMaxNodeInstances) {
// all possible node IDs are in use
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index a8c55fa..7380ab2 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -543,6 +543,7 @@
status_t OMXNodeInstance::storeMetaDataInBuffers_l(
OMX_U32 portIndex, OMX_BOOL enable, MetadataBufferType *type) {
if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) {
+ android_errorWriteLog(0x534e4554, "26324358");
return BAD_VALUE;
}
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index c0ccb35..50bb0de 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -267,7 +267,7 @@
IOMX::node_id node;
status_t err =
- mOMX->allocateNode(componentName, this, &node);
+ mOMX->allocateNode(componentName, this, NULL, &node);
EXPECT_SUCCESS(err, "allocateNode");
NodeReaper reaper(this, node);
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index eedbb42..6fa83fa 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -235,7 +235,7 @@
sp<AMessage> msg = new AMessage('paus', this);
mPauseGeneration++;
msg->setInt32("pausecheck", mPauseGeneration);
- msg->post(kPauseDelayUs);
+ msg->post();
}
void resume() {
@@ -979,6 +979,11 @@
case 'accu':
{
+ if (mSeekPending) {
+ ALOGV("Stale access unit.");
+ break;
+ }
+
int32_t timeUpdate;
if (msg->findInt32("time-update", &timeUpdate) && timeUpdate) {
size_t trackIndex;
@@ -1070,6 +1075,12 @@
ALOGW("This is a live stream, ignoring pause request.");
break;
}
+
+ if (mPausing) {
+ ALOGV("This stream is already paused.");
+ break;
+ }
+
mCheckPending = true;
++mCheckGeneration;
mPausing = true;
diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk
index 979143c..107d2b6 100644
--- a/media/mediaserver/Android.mk
+++ b/media/mediaserver/Android.mk
@@ -16,7 +16,6 @@
LOCAL_SHARED_LIBRARIES := \
libcamera_metadata\
libcameraservice \
- libmedialogservice \
libresourcemanagerservice \
libcutils \
libmedia \
diff --git a/media/mtp/Android.mk b/media/mtp/Android.mk
index 3af0956..cb7e4aa 100644
--- a/media/mtp/Android.mk
+++ b/media/mtp/Android.mk
@@ -37,7 +37,7 @@
LOCAL_MODULE:= libmtp
-LOCAL_CFLAGS := -DMTP_DEVICE -DMTP_HOST
+LOCAL_CFLAGS := -DMTP_DEVICE -DMTP_HOST -Wall -Wextra -Werror
LOCAL_SHARED_LIBRARIES := libutils libcutils liblog libusbhost libbinder
diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp
index d0ec2a6..0381edf 100644
--- a/media/mtp/MtpDataPacket.cpp
+++ b/media/mtp/MtpDataPacket.cpp
@@ -456,7 +456,7 @@
// look at the length field to see if the data spans multiple packets
uint32_t totalLength = MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET);
allocate(totalLength);
- while (totalLength > length) {
+ while (totalLength > static_cast<uint32_t>(length)) {
request->buffer = mBuffer + length;
request->buffer_length = totalLength - length;
int ret = transfer(request);
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index 7d7ea13..a398aca 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -505,6 +505,7 @@
int remaining = size;
mRequest.reset();
mRequest.setParameter(1, handle);
+ bool error = false;
if (sendRequest(MTP_OPERATION_SEND_OBJECT)) {
// send data header
writeDataHeader(MTP_OPERATION_SEND_OBJECT, remaining);
@@ -514,7 +515,9 @@
while (remaining > 0) {
int count = read(srcFD, buffer, sizeof(buffer));
if (count > 0) {
- int written = mData.write(mRequestOut, buffer, count);
+ if (mData.write(mRequestOut, buffer, count) < 0) {
+ error = true;
+ }
// FIXME check error
remaining -= count;
} else {
@@ -523,7 +526,7 @@
}
}
MtpResponseCode ret = readResponse();
- return (remaining == 0 && ret == MTP_RESPONSE_OK);
+ return (remaining == 0 && ret == MTP_RESPONSE_OK && !error);
}
bool MtpDevice::deleteObject(MtpObjectHandle handle) {
diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp
index bab1335..35ecb4f 100644
--- a/media/mtp/MtpPacket.cpp
+++ b/media/mtp/MtpPacket.cpp
@@ -69,7 +69,7 @@
char buffer[500];
char* bufptr = buffer;
- for (int i = 0; i < mPacketSize; i++) {
+ for (size_t i = 0; i < mPacketSize; i++) {
sprintf(bufptr, "%02X ", mBuffer[i]);
bufptr += strlen(bufptr);
if (i % DUMP_BYTES_PER_ROW == (DUMP_BYTES_PER_ROW - 1)) {
diff --git a/media/mtp/MtpProperty.cpp b/media/mtp/MtpProperty.cpp
index d58e2a4..2be2d79 100644
--- a/media/mtp/MtpProperty.cpp
+++ b/media/mtp/MtpProperty.cpp
@@ -544,7 +544,7 @@
MtpPropertyValue* result = new MtpPropertyValue[length];
for (uint32_t i = 0; i < length; i++)
if (!readValue(packet, result[i])) {
- delete result;
+ delete [] result;
return NULL;
}
return result;
diff --git a/media/mtp/MtpRequestPacket.cpp b/media/mtp/MtpRequestPacket.cpp
index 40b11b0..471967f 100644
--- a/media/mtp/MtpRequestPacket.cpp
+++ b/media/mtp/MtpRequestPacket.cpp
@@ -44,11 +44,12 @@
}
// request packet should have 12 byte header followed by 0 to 5 32-bit arguments
- if (ret >= MTP_CONTAINER_HEADER_SIZE
- && ret <= MTP_CONTAINER_HEADER_SIZE + 5 * sizeof(uint32_t)
- && ((ret - MTP_CONTAINER_HEADER_SIZE) & 3) == 0) {
- mPacketSize = ret;
- mParameterCount = (ret - MTP_CONTAINER_HEADER_SIZE) / sizeof(uint32_t);
+ const size_t read_size = static_cast<size_t>(ret);
+ if (read_size >= MTP_CONTAINER_HEADER_SIZE
+ && read_size <= MTP_CONTAINER_HEADER_SIZE + 5 * sizeof(uint32_t)
+ && ((read_size - MTP_CONTAINER_HEADER_SIZE) & 3) == 0) {
+ mPacketSize = read_size;
+ mParameterCount = (read_size - MTP_CONTAINER_HEADER_SIZE) / sizeof(uint32_t);
} else {
ALOGE("Malformed MTP request packet");
ret = -1;
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 3e0f239..90f1a77 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -923,9 +923,7 @@
if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // image bit depth
if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // parent
if (!mData.getUInt16(temp16)) return MTP_RESPONSE_INVALID_PARAMETER;
- uint16_t associationType = temp16;
if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;
- uint32_t associationDesc = temp32; // association desc
if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // sequence number
MtpStringBuffer name, created, modified;
if (!mData.getString(name)) return MTP_RESPONSE_INVALID_PARAMETER; // file name
@@ -1102,7 +1100,6 @@
}
strcpy(fileSpot, name);
- int type = entry->d_type;
if (entry->d_type == DT_DIR) {
deleteRecursive(pathbuf);
rmdir(pathbuf);
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 4ee8d6c..0a3a832 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -184,8 +184,7 @@
mSystemReady(false)
{
getpid_cached = getpid();
- // disable media.log until the service is reenabled, see b/26306954
- const bool doLog = false; // property_get_bool("ro.test_harness", false);
+ const bool doLog = property_get_bool("ro.test_harness", false);
if (doLog) {
mLogMemoryDealer = new MemoryDealer(kLogMemorySize, "LogWriters",
MemoryHeapBase::READ_ONLY);
@@ -197,6 +196,7 @@
BatteryNotifier::getInstance().noteResetAudio();
#ifdef TEE_SINK
+ char value[PROPERTY_VALUE_MAX];
(void) property_get("ro.debuggable", value, "0");
int debuggable = atoi(value);
int teeEnabled = 0;
@@ -2878,7 +2878,7 @@
// failures at unlink() which are ignored. It's also unlikely since
// normally dumpsys is only done by bugreport or from the command line.
char teePath[32+256];
- strcpy(teePath, "/data/misc/media");
+ strcpy(teePath, "/data/misc/audioserver");
size_t teePathLen = strlen(teePath);
DIR *dir = opendir(teePath);
teePath[teePathLen++] = '/';
@@ -2920,7 +2920,8 @@
}
} else {
if (fd >= 0) {
- dprintf(fd, "unable to rotate tees in %s: %s\n", teePath, strerror(errno));
+ dprintf(fd, "unable to rotate tees in %.*s: %s\n", teePathLen, teePath,
+ strerror(errno));
}
}
char teeTime[16];
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index 1446d19..d31b8d3 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -141,6 +141,10 @@
FastMixerDumpState * const dumpState = (FastMixerDumpState *) mDumpState;
const size_t frameCount = current->mFrameCount;
+ // update boottime offset, in case it has changed
+ mTimestamp.mTimebaseOffset[ExtendedTimestamp::TIMEBASE_BOOTTIME] =
+ mBoottimeOffset.load();
+
// handle state change here, but since we want to diff the state,
// we're prepared for previous == &sInitial the first time through
unsigned previousTrackMask;
@@ -341,21 +345,23 @@
currentTrackMask &= ~(1 << i);
const FastTrack* fastTrack = ¤t->mFastTracks[i];
- // Refresh the per-track timestamp
- if (mTimestampStatus == NO_ERROR) {
- uint32_t trackFramesWrittenButNotPresented =
- mNativeFramesWrittenButNotPresented;
- uint32_t trackFramesWritten = fastTrack->mBufferProvider->framesReleased();
- // Can't provide an AudioTimestamp before first frame presented,
- // or during the brief 32-bit wraparound window
- if (trackFramesWritten >= trackFramesWrittenButNotPresented) {
- AudioTimestamp perTrackTimestamp;
- perTrackTimestamp.mPosition =
- trackFramesWritten - trackFramesWrittenButNotPresented;
- perTrackTimestamp.mTime = mTimestamp.mTime;
- fastTrack->mBufferProvider->onTimestamp(perTrackTimestamp);
- }
+ const int64_t trackFramesWrittenButNotPresented =
+ mNativeFramesWrittenButNotPresented;
+ const int64_t trackFramesWritten = fastTrack->mBufferProvider->framesReleased();
+ ExtendedTimestamp perTrackTimestamp(mTimestamp);
+
+ // Can't provide an ExtendedTimestamp before first frame presented.
+ // Also, timestamp may not go to very last frame on stop().
+ if (trackFramesWritten >= trackFramesWrittenButNotPresented &&
+ perTrackTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0) {
+ perTrackTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] =
+ trackFramesWritten - trackFramesWrittenButNotPresented;
+ } else {
+ perTrackTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] = 0;
+ perTrackTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] = -1;
}
+ perTrackTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER] = trackFramesWritten;
+ fastTrack->mBufferProvider->onTimestamp(perTrackTimestamp);
int name = mFastTrackNames[i];
ALOG_ASSERT(name >= 0);
@@ -449,17 +455,34 @@
mAttemptedWrite = true;
// FIXME count # of writes blocked excessively, CPU usage, etc. for dump
- mTimestampStatus = mOutputSink->getTimestamp(mTimestamp);
- if (mTimestampStatus == NO_ERROR) {
- uint32_t totalNativeFramesPresented = mTimestamp.mPosition;
+ ExtendedTimestamp timestamp; // local
+ status_t status = mOutputSink->getTimestamp(timestamp);
+ if (status == NO_ERROR) {
+ const int64_t totalNativeFramesPresented =
+ timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
if (totalNativeFramesPresented <= mTotalNativeFramesWritten) {
mNativeFramesWrittenButNotPresented =
mTotalNativeFramesWritten - totalNativeFramesPresented;
+ mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] =
+ timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
+ mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] =
+ timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL];
} else {
// HAL reported that more frames were presented than were written
- mTimestampStatus = INVALID_OPERATION;
+ mNativeFramesWrittenButNotPresented = 0;
+ mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] = 0;
+ mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] = -1;
+ status = INVALID_OPERATION;
}
}
+ if (status == NO_ERROR) {
+ mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] =
+ mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL];
+ } else {
+ // fetch server time if we can't get timestamp
+ mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] =
+ systemTime(SYSTEM_TIME_MONOTONIC);
+ }
}
}
diff --git a/services/audioflinger/FastMixer.h b/services/audioflinger/FastMixer.h
index e38878e..3cc7c9f 100644
--- a/services/audioflinger/FastMixer.h
+++ b/services/audioflinger/FastMixer.h
@@ -38,7 +38,9 @@
FastMixerStateQueue* sq();
virtual void setMasterMono(bool mono) { mMasterMono.store(mono); /* memory_order_seq_cst */ }
-
+ virtual void setBoottimeOffset(int64_t boottimeOffset) {
+ mBoottimeOffset.store(boottimeOffset); /* memory_order_seq_cst */
+ }
private:
FastMixerStateQueue mSQ;
@@ -79,14 +81,15 @@
unsigned mSampleRate;
int mFastTracksGen;
FastMixerDumpState mDummyFastMixerDumpState;
- uint32_t mTotalNativeFramesWritten; // copied to dumpState->mFramesWritten
+ int64_t mTotalNativeFramesWritten; // copied to dumpState->mFramesWritten
// next 2 fields are valid only when timestampStatus == NO_ERROR
- AudioTimestamp mTimestamp;
- uint32_t mNativeFramesWrittenButNotPresented;
+ ExtendedTimestamp mTimestamp;
+ int64_t mNativeFramesWrittenButNotPresented;
// accessed without lock between multiple threads.
std::atomic_bool mMasterMono;
+ std::atomic_int_fast64_t mBoottimeOffset;
}; // class FastMixer
} // namespace android
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index fe3cc53..fa61af2 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -88,8 +88,8 @@
// ExtendedAudioBufferProvider interface
virtual size_t framesReady() const;
- virtual size_t framesReleased() const;
- virtual void onTimestamp(const AudioTimestamp ×tamp);
+ virtual int64_t framesReleased() const;
+ virtual void onTimestamp(const ExtendedTimestamp ×tamp);
bool isPausing() const { return mState == PAUSING; }
bool isPaused() const { return mState == PAUSED; }
@@ -101,15 +101,15 @@
void flushAck();
bool isResumePending();
void resumeAck();
- void updateTrackFrameInfo(uint32_t trackFramesReleased, uint32_t sinkFramesWritten,
- AudioTimestamp *timeStamp = NULL);
+ void updateTrackFrameInfo(int64_t trackFramesReleased, int64_t sinkFramesWritten,
+ const ExtendedTimestamp &timeStamp);
sp<IMemory> sharedBuffer() const { return mSharedBuffer; }
// framesWritten is cumulative, never reset, and is shared all tracks
// audioHalFrames is derived from output latency
// FIXME parameters not needed, could get them from the thread
- bool presentationComplete(size_t framesWritten, size_t audioHalFrames);
+ bool presentationComplete(int64_t framesWritten, size_t audioHalFrames);
public:
void triggerEvents(AudioSystem::sync_event_t type);
@@ -142,9 +142,9 @@
// zero means not monitoring
// access these three variables only when holding thread lock.
- LinearMap<uint32_t> mFrameMap; // track frame to server frame mapping
- bool mSinkTimestampValid; // valid cached timestamp
- AudioTimestamp mSinkTimestamp;
+ LinearMap<int64_t> mFrameMap; // track frame to server frame mapping
+
+ ExtendedTimestamp mSinkTimestamp;
private:
// The following fields are only for fast tracks, and should be in a subclass
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 4807400..e3036c6 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -468,6 +468,7 @@
{AUDIO_DEVICE_OUT_AUX_LINE, "AUX_LINE"},
{AUDIO_DEVICE_OUT_SPEAKER_SAFE, "SPEAKER_SAFE"},
{AUDIO_DEVICE_OUT_IP, "IP"},
+ {AUDIO_DEVICE_OUT_BUS, "BUS"},
{AUDIO_DEVICE_NONE, "NONE"}, // must be last
}, mappingsIn[] = {
{AUDIO_DEVICE_IN_COMMUNICATION, "COMMUNICATION"},
@@ -491,6 +492,7 @@
{AUDIO_DEVICE_IN_BLUETOOTH_A2DP, "BLUETOOTH_A2DP"},
{AUDIO_DEVICE_IN_LOOPBACK, "LOOPBACK"},
{AUDIO_DEVICE_IN_IP, "IP"},
+ {AUDIO_DEVICE_IN_BUS, "BUS"},
{AUDIO_DEVICE_NONE, "NONE"}, // must be last
};
String8 result;
@@ -1034,6 +1036,8 @@
mNotifiedBatteryStart = true;
}
gBoottime.acquire(mWakeLockToken);
+ mTimestamp.mTimebaseOffset[ExtendedTimestamp::TIMEBASE_BOOTTIME] =
+ gBoottime.getBoottimeOffset();
}
void AudioFlinger::ThreadBase::releaseWakeLock()
@@ -1563,6 +1567,7 @@
mEffectBufferFormat(AUDIO_FORMAT_INVALID),
mEffectBufferValid(false),
mSuspended(0), mBytesWritten(0),
+ mFramesWritten(0),
mActiveTracksGeneration(0),
// mStreamTypes[] initialized in constructor body
mOutput(output),
@@ -2370,13 +2375,14 @@
if (initCheck() != NO_ERROR) {
return INVALID_OPERATION;
}
- size_t framesWritten = mBytesWritten / mFrameSize;
+ int64_t framesWritten = mBytesWritten / mFrameSize;
*halFrames = framesWritten;
if (isSuspended()) {
// return an estimation of rendered frames when the output is suspended
size_t latencyFrames = (latency_l() * mSampleRate) / 1000;
- *dspFrames = framesWritten >= latencyFrames ? framesWritten - latencyFrames : 0;
+ *dspFrames = (uint32_t)
+ (framesWritten >= (int64_t)latencyFrames ? framesWritten - latencyFrames : 0);
return NO_ERROR;
} else {
status_t status;
@@ -2860,43 +2866,30 @@
// and associate with the sink frames written out. We need
// this to convert the sink timestamp to the track timestamp.
if (mNormalSink != 0) {
- bool updateTracks = true;
- bool cacheTimestamp = false;
- AudioTimestamp timeStamp;
- // FIXME: Use a 64 bit mNormalSink->framesWritten() counter.
- // At this time, we must always use cached timestamps even when
- // going through mPipeSink (which is non-blocking). The reason is that
- // the track may be removed from the active list for many hours and
- // the mNormalSink->framesWritten() will wrap making the linear
- // mapping fail.
- //
- // (Also mAudioTrackServerProxy->framesReleased() needs to be
- // updated to 64 bits for 64 bit frame position.)
- //
- if (true /* see comment above, should be: mNormalSink == mOutputSink */) {
- // If we use a hardware device, we must cache the sink timestamp now.
- // hardware devices can block timestamp access during data writes.
- if (mNormalSink->getTimestamp(timeStamp) == NO_ERROR) {
- cacheTimestamp = true;
- } else {
- updateTracks = false;
- }
- }
- if (updateTracks) {
- // sinkFramesWritten for non-offloaded tracks are contiguous
- // even after standby() is called. This is useful for the track frame
- // to sink frame mapping.
- const uint32_t sinkFramesWritten = mNormalSink->framesWritten();
- const size_t size = mActiveTracks.size();
- for (size_t i = 0; i < size; ++i) {
- sp<Track> t = mActiveTracks[i].promote();
- if (t != 0 && !t->isFastTrack()) {
- t->updateTrackFrameInfo(
- t->mAudioTrackServerProxy->framesReleased(),
- sinkFramesWritten,
- cacheTimestamp ? &timeStamp : NULL);
- }
- }
+ // Note: The DuplicatingThread may not have a mNormalSink.
+ // We always fetch the timestamp here because often the downstream
+ // sink will block whie writing.
+ ExtendedTimestamp timestamp; // use private copy to fetch
+ (void) mNormalSink->getTimestamp(timestamp);
+ // copy over kernel info
+ mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] =
+ timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
+ mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] =
+ timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL];
+ }
+ // mFramesWritten for non-offloaded tracks are contiguous
+ // even after standby() is called. This is useful for the track frame
+ // to sink frame mapping.
+ mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER] = mFramesWritten;
+ mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] = systemTime();
+ const size_t size = mActiveTracks.size();
+ for (size_t i = 0; i < size; ++i) {
+ sp<Track> t = mActiveTracks[i].promote();
+ if (t != 0 && !t->isFastTrack()) {
+ t->updateTrackFrameInfo(
+ t->mAudioTrackServerProxy->framesReleased(),
+ mFramesWritten,
+ mTimestamp);
}
}
@@ -3034,6 +3027,7 @@
mSleepTimeUs = suspendSleepTimeUs();
// simulate write to HAL when suspended
mBytesWritten += mSinkBufferSize;
+ mFramesWritten += mSinkBufferSize / mFrameSize;
mBytesRemaining = 0;
}
@@ -3084,6 +3078,7 @@
} else {
mBytesWritten += ret;
mBytesRemaining -= ret;
+ mFramesWritten += ret / mFrameSize;
}
} else if ((mMixerStatus == MIXER_DRAIN_TRACK) ||
(mMixerStatus == MIXER_DRAIN_ALL)) {
@@ -3209,7 +3204,12 @@
status_t AudioFlinger::PlaybackThread::getTimestamp_l(AudioTimestamp& timestamp)
{
if (mNormalSink != 0) {
- return mNormalSink->getTimestamp(timestamp);
+ ExtendedTimestamp ets;
+ status_t status = mNormalSink->getTimestamp(ets);
+ if (status == NO_ERROR) {
+ status = ets.getBestTimestamp(×tamp);
+ }
+ return status;
}
if ((mType == OFFLOAD || mType == DIRECT)
&& mOutput != NULL && mOutput->stream->get_presentation_position) {
@@ -3925,7 +3925,7 @@
{
size_t audioHALFrames =
(mOutput->stream->get_latency(mOutput->stream)*mSampleRate) / 1000;
- size_t framesWritten = mBytesWritten / mFrameSize;
+ int64_t framesWritten = mBytesWritten / mFrameSize;
if (!(mStandby || track->presentationComplete(framesWritten, audioHALFrames))) {
// track stays in active list until presentation is complete
break;
@@ -4255,7 +4255,7 @@
// TODO: use actual buffer filling status instead of latency when available from
// audio HAL
size_t audioHALFrames = (latency_l() * mSampleRate) / 1000;
- size_t framesWritten = mBytesWritten / mFrameSize;
+ int64_t framesWritten = mBytesWritten / mFrameSize;
if (mStandby || track->presentationComplete(framesWritten, audioHALFrames)) {
if (track->isStopped()) {
track->reset();
@@ -4796,7 +4796,7 @@
audioHALFrames = 0;
}
- size_t framesWritten = mBytesWritten / mFrameSize;
+ int64_t framesWritten = mBytesWritten / mFrameSize;
if (mStandby || !last ||
track->presentationComplete(framesWritten, audioHALFrames)) {
if (track->isStopping_2()) {
@@ -5343,7 +5343,7 @@
track->mState = TrackBase::STOPPED;
size_t audioHALFrames =
(mOutput->stream->get_latency(mOutput->stream)*mSampleRate) / 1000;
- size_t framesWritten =
+ int64_t framesWritten =
mBytesWritten / mOutput->getFrameSize();
track->presentationComplete(framesWritten, audioHALFrames);
track->reset();
@@ -5789,9 +5789,6 @@
}
}
- mTimestamp.mTimebaseOffset[ExtendedTimestamp::TIMEBASE_BOOTTIME] =
- gBoottime.getBoottimeOffset();
-
// used to request a deferred sleep, to be executed later while mutex is unlocked
uint32_t sleepUs = 0;
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 7c92c1c..42b3266 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -381,7 +381,7 @@
};
void acquireWakeLock(int uid = -1);
- void acquireWakeLock_l(int uid = -1);
+ virtual void acquireWakeLock_l(int uid = -1);
void releaseWakeLock();
void releaseWakeLock_l();
void updateWakeLockUids(const SortedVector<int> &uids);
@@ -460,6 +460,7 @@
sp<NBLog::Writer> mNBLogWriter;
bool mSystemReady;
bool mNotifiedBatteryStart;
+ ExtendedTimestamp mTimestamp;
};
// --- PlaybackThread ---
@@ -691,9 +692,8 @@
// 'volatile' means accessed via atomic operations and no lock.
volatile int32_t mSuspended;
- // FIXME overflows every 6+ hours at 44.1 kHz stereo 16-bit samples
- // mFramesWritten would be better, or 64-bit even better
- size_t mBytesWritten;
+ int64_t mBytesWritten;
+ int64_t mFramesWritten; // not reset on standby
private:
// mMasterMute is in both PlaybackThread and in AudioFlinger. When a
// PlaybackThread needs to find out if master-muted, it checks it's local
@@ -868,6 +868,14 @@
virtual uint32_t suspendSleepTimeUs() const;
virtual void cacheParameters_l();
+ virtual void acquireWakeLock_l(int uid = -1) {
+ PlaybackThread::acquireWakeLock_l(uid);
+ if (hasFastMixer()) {
+ mFastMixer->setBoottimeOffset(
+ mTimestamp.mTimebaseOffset[ExtendedTimestamp::TIMEBASE_BOOTTIME]);
+ }
+ }
+
// threadLoop snippets
virtual ssize_t threadLoop_write();
virtual void threadLoop_standby();
@@ -1311,8 +1319,6 @@
// rolling index that is never cleared
int32_t mRsmpInRear; // last filled frame + 1
- ExtendedTimestamp mTimestamp;
-
// For dumpsys
const sp<NBAIO_Sink> mTeeSink;
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 536581c..e684fc2 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -362,7 +362,6 @@
mAuxEffectId(0), mHasVolumeController(false),
mPresentationCompleteFrames(0),
mFrameMap(16 /* sink-frame-to-track-frame map memory */),
- mSinkTimestampValid(false),
// mSinkTimestamp
mFastIndex(-1),
mCachedVolume(1.0),
@@ -591,23 +590,18 @@
return mAudioTrackServerProxy->framesReady();
}
-size_t AudioFlinger::PlaybackThread::Track::framesReleased() const
+int64_t AudioFlinger::PlaybackThread::Track::framesReleased() const
{
return mAudioTrackServerProxy->framesReleased();
}
-void AudioFlinger::PlaybackThread::Track::onTimestamp(const AudioTimestamp ×tamp)
+void AudioFlinger::PlaybackThread::Track::onTimestamp(const ExtendedTimestamp ×tamp)
{
// This call comes from a FastTrack and should be kept lockless.
// The server side frames are already translated to client frames.
+ mAudioTrackServerProxy->setTimestamp(timestamp);
- ExtendedTimestamp ets;
- ets.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] =
- timestamp.mTime.tv_sec * 1000000000LL + timestamp.mTime.tv_nsec;
- ets.mPosition[ExtendedTimestamp::LOCATION_KERNEL] = timestamp.mPosition;
-
- // Caution, this doesn't set the timebase for BOOTTIME properly, but is ignored right now.
- mAudioTrackServerProxy->setTimestamp(ets);
+ // We do not set drained here, as FastTrack timestamp may not go to very last frame.
}
// Don't call for fast tracks; the framesReady() could result in priority inversion
@@ -872,9 +866,8 @@
status_t AudioFlinger::PlaybackThread::Track::getTimestamp(AudioTimestamp& timestamp)
{
- // Client should implement this using SSQ; the unpresented frame count in latch is irrelevant
- if (isFastTrack()) {
- return INVALID_OPERATION;
+ if (!isOffloaded() && !isDirect()) {
+ return INVALID_OPERATION; // normal tracks handled through SSQ
}
sp<ThreadBase> thread = mThread.promote();
if (thread == 0) {
@@ -883,33 +876,7 @@
Mutex::Autolock _l(thread->mLock);
PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
-
- if (isOffloaded() || isDirect()) {
- return playbackThread->getTimestamp_l(timestamp);
- }
-
- if (!mFrameMap.hasData()) {
- // WOULD_BLOCK is consistent with AudioTrack::getTimestamp() in the
- // FLUSHED and STOPPED state. We should only return INVALID_OPERATION
- // when this method is not permitted due to configuration or device.
- return WOULD_BLOCK;
- }
- status_t result = OK;
- if (!mSinkTimestampValid) { // if no sink position, try to fetch again
- result = playbackThread->getTimestamp_l(mSinkTimestamp);
- }
-
- if (result == OK) {
- // Lookup the track frame corresponding to the sink frame position.
- timestamp.mPosition = mFrameMap.findX(mSinkTimestamp.mPosition);
- timestamp.mTime = mSinkTimestamp.mTime;
- // ALOGD("track (server-side) timestamp: mPosition(%u) mTime(%llu)",
- // timestamp.mPosition, TIME_TO_NANOS(timestamp.mTime));
- }
- // (Possible) FIXME: mSinkTimestamp is updated only when the track is on
- // the Thread active list. If the track is no longer on the thread active
- // list should we use current time?
- return result;
+ return playbackThread->getTimestamp_l(timestamp);
}
status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
@@ -972,9 +939,12 @@
mAuxBuffer = buffer;
}
-bool AudioFlinger::PlaybackThread::Track::presentationComplete(size_t framesWritten,
- size_t audioHalFrames)
+bool AudioFlinger::PlaybackThread::Track::presentationComplete(
+ int64_t framesWritten, size_t audioHalFrames)
{
+ // TODO: improve this based on FrameMap if it exists, to ensure full drain.
+ // This assists in proper timestamp computation as well as wakelock management.
+
// a track is considered presented when the total number of frames written to audio HAL
// corresponds to the number of frames written when presentationComplete() is called for the
// first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
@@ -982,15 +952,25 @@
// to detect when all frames have been played. In this case framesWritten isn't
// useful because it doesn't always reflect whether there is data in the h/w
// buffers, particularly if a track has been paused and resumed during draining
- ALOGV("presentationComplete() mPresentationCompleteFrames %d framesWritten %d",
- mPresentationCompleteFrames, framesWritten);
+ ALOGV("presentationComplete() mPresentationCompleteFrames %lld framesWritten %lld",
+ (long long)mPresentationCompleteFrames, (long long)framesWritten);
if (mPresentationCompleteFrames == 0) {
mPresentationCompleteFrames = framesWritten + audioHalFrames;
- ALOGV("presentationComplete() reset: mPresentationCompleteFrames %d audioHalFrames %d",
- mPresentationCompleteFrames, audioHalFrames);
+ ALOGV("presentationComplete() reset: mPresentationCompleteFrames %lld audioHalFrames %zu",
+ (long long)mPresentationCompleteFrames, audioHalFrames);
}
- if (framesWritten >= mPresentationCompleteFrames || isOffloaded()) {
+ bool complete;
+ if (isOffloaded()) {
+ complete = true;
+ } else if (isDirect() || isFastTrack()) { // these do not go through linear map
+ complete = framesWritten >= mPresentationCompleteFrames;
+ } else { // Normal tracks, OutputTracks, and PatchTracks
+ complete = framesWritten >= mPresentationCompleteFrames
+ && mAudioTrackServerProxy->isDrained();
+ }
+
+ if (complete) {
triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
mAudioTrackServerProxy->setStreamEndDone();
return true;
@@ -1101,14 +1081,34 @@
//To be called with thread lock held
void AudioFlinger::PlaybackThread::Track::updateTrackFrameInfo(
- uint32_t trackFramesReleased, uint32_t sinkFramesWritten, AudioTimestamp *timeStamp) {
+ int64_t trackFramesReleased, int64_t sinkFramesWritten,
+ const ExtendedTimestamp &timeStamp) {
+ //update frame map
mFrameMap.push(trackFramesReleased, sinkFramesWritten);
- if (timeStamp == NULL) {
- mSinkTimestampValid = false;
- } else {
- mSinkTimestampValid = true;
- mSinkTimestamp = *timeStamp;
+
+ // adjust server times and set drained state.
+ //
+ // Our timestamps are only updated when the track is on the Thread active list.
+ // We need to ensure that tracks are not removed before full drain.
+ ExtendedTimestamp local = timeStamp;
+ bool checked = false;
+ for (int i = ExtendedTimestamp::LOCATION_MAX - 1;
+ i >= ExtendedTimestamp::LOCATION_SERVER; --i) {
+ // Lookup the track frame corresponding to the sink frame position.
+ if (local.mTimeNs[i] > 0) {
+ local.mPosition[i] = mFrameMap.findX(local.mPosition[i]);
+ // check drain state from the latest stage in the pipeline.
+ if (!checked) {
+ mAudioTrackServerProxy->setDrained(
+ local.mPosition[i] >= mAudioTrackServerProxy->framesReleased());
+ checked = true;
+ }
+ }
}
+ if (!checked) { // no server info, assume drained.
+ mAudioTrackServerProxy->setDrained(true);
+ }
+ mServerProxy->setTimestamp(local);
}
// ----------------------------------------------------------------------------
diff --git a/services/audioflinger/tests/README b/services/audioflinger/tests/README
new file mode 100644
index 0000000..508e960
--- /dev/null
+++ b/services/audioflinger/tests/README
@@ -0,0 +1,13 @@
+For libsonic dependency:
+pushd external/sonic
+mm
+popd
+
+To build resampler library:
+pushd ..
+Optionally uncomment USE_NEON=false in Android.mk
+mm
+popd
+
+Then build here:
+mm
diff --git a/services/audioflinger/tests/run_all_unit_tests.sh b/services/audioflinger/tests/run_all_unit_tests.sh
index ffae6ae..113f39e 100755
--- a/services/audioflinger/tests/run_all_unit_tests.sh
+++ b/services/audioflinger/tests/run_all_unit_tests.sh
@@ -8,4 +8,5 @@
echo "waiting for device"
adb root && adb wait-for-device remount
-adb shell /system/bin/resampler_tests
+#adb shell /system/bin/resampler_tests
+adb shell /data/nativetest/resampler_tests/resampler_tests
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index dd3f144..ce1ae4d 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -337,7 +337,10 @@
virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state) = 0;
virtual void onRecordingConfigurationUpdate(int event, audio_session_t session,
- audio_source_t source) = 0;
+ audio_source_t source,
+ const struct audio_config_base *clientConfig,
+ const struct audio_config_base *deviceConfig,
+ audio_patch_handle_t patchHandle) = 0;
};
extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface);
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index 77c0d07..46309ed 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -18,6 +18,7 @@
#include "AudioPort.h"
#include "AudioSession.h"
+#include "AudioSessionInfoProvider.h"
#include <utils/Errors.h>
#include <system/audio.h>
#include <utils/SortedVector.h>
@@ -30,7 +31,7 @@
// descriptor for audio inputs. Used to maintain current configuration of each opened audio input
// and keep track of the usage of this input.
-class AudioInputDescriptor: public AudioPortConfig
+class AudioInputDescriptor: public AudioPortConfig, public AudioSessionInfoProvider
{
public:
AudioInputDescriptor(const sp<IOProfile>& profile);
@@ -44,7 +45,6 @@
audio_io_handle_t mIoHandle; // input handle
audio_devices_t mDevice; // current device this input is routed to
AudioMix *mPolicyMix; // non NULL when used by a dynamic policy
- audio_patch_handle_t mPatchHandle;
const sp<IOProfile> mProfile; // I/O profile this output derives from
virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
@@ -65,7 +65,14 @@
sp<AudioSession> getAudioSession(audio_session_t session) const;
AudioSessionCollection getActiveAudioSessions() const;
+ // implementation of AudioSessionInfoProvider
+ virtual audio_config_base_t getConfig() const;
+ virtual audio_patch_handle_t getPatchHandle() const;
+
+ void setPatchHandle(audio_patch_handle_t handle);
+
private:
+ audio_patch_handle_t mPatchHandle;
audio_port_handle_t mId;
// audio sessions attached to this input
AudioSessionCollection mSessions;
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index f8439be..dd3f8ae 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -71,9 +71,11 @@
audio_module_handle_t getModuleHandle() const;
+ audio_patch_handle_t getPatchHandle() const { return mPatchHandle; };
+ void setPatchHandle(audio_patch_handle_t handle) { mPatchHandle = handle; };
+
sp<AudioPort> mPort;
audio_devices_t mDevice; // current device this output is routed to
- audio_patch_handle_t mPatchHandle;
uint32_t mRefCount[AUDIO_STREAM_CNT]; // number of streams of each type using this output
nsecs_t mStopTime[AUDIO_STREAM_CNT];
float mCurVolume[AUDIO_STREAM_CNT]; // current stream volume in dB
@@ -83,6 +85,7 @@
AudioPolicyClientInterface *mClientInterface;
protected:
+ audio_patch_handle_t mPatchHandle;
audio_port_handle_t mId;
};
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioSession.h b/services/audiopolicy/common/managerdefinitions/include/AudioSession.h
index 576822c..388c25d 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioSession.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioSession.h
@@ -22,12 +22,13 @@
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
#include <media/AudioPolicy.h>
+#include "AudioSessionInfoProvider.h"
namespace android {
class AudioPolicyClientInterface;
-class AudioSession : public RefBase
+class AudioSession : public RefBase, public AudioSessionInfoUpdateListener
{
public:
AudioSession(audio_session_t session,
@@ -45,9 +46,9 @@
audio_session_t session() const { return mSession; }
audio_source_t inputSource()const { return mInputSource; }
- audio_format_t format() const { return mFormat; }
- uint32_t sampleRate() const { return mSampleRate; }
- audio_channel_mask_t channelMask() const { return mChannelMask; }
+ audio_format_t format() const { return mConfig.format; }
+ uint32_t sampleRate() const { return mConfig.sample_rate; }
+ audio_channel_mask_t channelMask() const { return mConfig.channel_mask; }
audio_input_flags_t flags() const { return mFlags; }
uid_t uid() const { return mUid; }
bool matches(const sp<AudioSession> &other) const;
@@ -58,12 +59,14 @@
uint32_t changeOpenCount(int delta);
uint32_t changeActiveCount(int delta);
+ void setInfoProvider(AudioSessionInfoProvider *provider);
+ // implementation of AudioSessionInfoUpdateListener
+ virtual void onSessionInfoUpdate() const;
+
private:
const audio_session_t mSession;
const audio_source_t mInputSource;
- const audio_format_t mFormat;
- const uint32_t mSampleRate;
- const audio_channel_mask_t mChannelMask;
+ const struct audio_config_base mConfig;
const audio_input_flags_t mFlags;
const uid_t mUid;
bool mIsSoundTrigger;
@@ -71,14 +74,17 @@
uint32_t mActiveCount;
AudioMix* mPolicyMix; // non NULL when used by a dynamic policy
AudioPolicyClientInterface* mClientInterface;
+ const AudioSessionInfoProvider* mInfoProvider;
};
class AudioSessionCollection :
- public DefaultKeyedVector<audio_session_t, sp<AudioSession> >
+ public DefaultKeyedVector<audio_session_t, sp<AudioSession> >,
+ public AudioSessionInfoUpdateListener
{
public:
status_t addSession(audio_session_t session,
- const sp<AudioSession>& audioSession);
+ const sp<AudioSession>& audioSession,
+ AudioSessionInfoProvider *provider);
status_t removeSession(audio_session_t session);
@@ -88,6 +94,9 @@
bool hasActiveSession() const;
bool isSourceActive(audio_source_t source) const;
+ // implementation of AudioSessionInfoUpdateListener
+ virtual void onSessionInfoUpdate() const;
+
status_t dump(int fd, int spaces) const;
};
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioSessionInfoProvider.h b/services/audiopolicy/common/managerdefinitions/include/AudioSessionInfoProvider.h
new file mode 100644
index 0000000..e0037fc
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioSessionInfoProvider.h
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+namespace android {
+
+/**
+ * Interface for input descriptors to implement so dependent audio sessions can query information
+ * about their context
+ */
+class AudioSessionInfoProvider
+{
+public:
+ virtual ~AudioSessionInfoProvider() {};
+
+ virtual audio_config_base_t getConfig() const = 0;
+
+ virtual audio_patch_handle_t getPatchHandle() const = 0;
+
+};
+
+class AudioSessionInfoUpdateListener
+{
+public:
+ virtual ~AudioSessionInfoUpdateListener() {};
+
+ virtual void onSessionInfoUpdate() const = 0;;
+};
+
+} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index 9b6469c..d4992b0 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -28,8 +28,8 @@
AudioInputDescriptor::AudioInputDescriptor(const sp<IOProfile>& profile)
: mIoHandle(0),
- mDevice(AUDIO_DEVICE_NONE), mPolicyMix(NULL), mPatchHandle(0),
- mProfile(profile), mId(0)
+ mDevice(AUDIO_DEVICE_NONE), mPolicyMix(NULL),
+ mProfile(profile), mPatchHandle(0), mId(0)
{
if (profile != NULL) {
profile->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
@@ -150,13 +150,31 @@
status_t AudioInputDescriptor::addAudioSession(audio_session_t session,
const sp<AudioSession>& audioSession) {
- return mSessions.addSession(session, audioSession);
+ return mSessions.addSession(session, audioSession, /*AudioSessionInfoProvider*/this);
}
status_t AudioInputDescriptor::removeAudioSession(audio_session_t session) {
return mSessions.removeSession(session);
}
+audio_port_handle_t AudioInputDescriptor::getPatchHandle() const
+{
+ return mPatchHandle;
+}
+
+void AudioInputDescriptor::setPatchHandle(audio_patch_handle_t handle)
+{
+ mPatchHandle = handle;
+ mSessions.onSessionInfoUpdate();
+}
+
+audio_config_base_t AudioInputDescriptor::getConfig() const
+{
+ const audio_config_base_t config = { .sample_rate = mSamplingRate, .channel_mask = mChannelMask,
+ .format = mFormat };
+ return config;
+}
+
status_t AudioInputDescriptor::dump(int fd)
{
const size_t SIZE = 256;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 5d0f03f..0fe1a84 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -34,7 +34,7 @@
AudioOutputDescriptor::AudioOutputDescriptor(const sp<AudioPort>& port,
AudioPolicyClientInterface *clientInterface)
: mPort(port), mDevice(AUDIO_DEVICE_NONE),
- mPatchHandle(0), mClientInterface(clientInterface), mId(0)
+ mClientInterface(clientInterface), mPatchHandle(0), mId(0)
{
// clear usage count for all stream types
for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
index 597c029..ce9c170 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
@@ -37,9 +37,10 @@
AudioMix* policyMix,
AudioPolicyClientInterface *clientInterface) :
mSession(session), mInputSource(inputSource),
- mFormat(format), mSampleRate(sampleRate), mChannelMask(channelMask),
+ mConfig({ .format = format, .sample_rate = sampleRate, .channel_mask = channelMask}),
mFlags(flags), mUid(uid), mIsSoundTrigger(isSoundTrigger),
- mOpenCount(1), mActiveCount(0), mPolicyMix(policyMix), mClientInterface(clientInterface)
+ mOpenCount(1), mActiveCount(0), mPolicyMix(policyMix), mClientInterface(clientInterface),
+ mInfoProvider(NULL)
{
}
@@ -65,25 +66,31 @@
}
mActiveCount += delta;
ALOGV("%s active count %d", __FUNCTION__, mActiveCount);
+ int event = RECORD_CONFIG_EVENT_NONE;
if ((oldActiveCount == 0) && (mActiveCount > 0)) {
- // if input maps to a dynamic policy with an activity listener, notify of state change
- if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
- {
- mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId,
- MIX_STATE_MIXING);
- }
- mClientInterface->onRecordingConfigurationUpdate(RECORD_CONFIG_EVENT_START,
- mSession, mInputSource);
+ event = RECORD_CONFIG_EVENT_START;
} else if ((oldActiveCount > 0) && (mActiveCount == 0)) {
+ event = RECORD_CONFIG_EVENT_STOP;
+ }
+
+ if (event != RECORD_CONFIG_EVENT_NONE) {
+ // Dynamic policy callback:
// if input maps to a dynamic policy with an activity listener, notify of state change
if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
{
mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId,
- MIX_STATE_IDLE);
+ (event == RECORD_CONFIG_EVENT_START) ? MIX_STATE_MIXING : MIX_STATE_IDLE);
}
- mClientInterface->onRecordingConfigurationUpdate(RECORD_CONFIG_EVENT_STOP,
- mSession, mInputSource);
+
+ // Recording configuration callback:
+ const AudioSessionInfoProvider* provider = mInfoProvider;
+ const audio_config_base_t deviceConfig = (provider != NULL) ? provider->getConfig() :
+ AUDIO_CONFIG_BASE_INITIALIZER;
+ const audio_patch_handle_t patchHandle = (provider != NULL) ? provider->getPatchHandle() :
+ AUDIO_PATCH_HANDLE_NONE;
+ mClientInterface->onRecordingConfigurationUpdate(event, mSession, mInputSource,
+ &mConfig, &deviceConfig, patchHandle);
}
return mActiveCount;
@@ -93,9 +100,9 @@
{
if (other->session() == mSession &&
other->inputSource() == mInputSource &&
- other->format() == mFormat &&
- other->sampleRate() == mSampleRate &&
- other->channelMask() == mChannelMask &&
+ other->format() == mConfig.format &&
+ other->sampleRate() == mConfig.sample_rate &&
+ other->channelMask() == mConfig.channel_mask &&
other->flags() == mFlags &&
other->uid() == mUid) {
return true;
@@ -103,6 +110,25 @@
return false;
}
+void AudioSession::setInfoProvider(AudioSessionInfoProvider *provider)
+{
+ mInfoProvider = provider;
+}
+
+void AudioSession::onSessionInfoUpdate() const
+{
+ if (mActiveCount > 0) {
+ // resend the callback after requerying the informations from the info provider
+ const AudioSessionInfoProvider* provider = mInfoProvider;
+ const audio_config_base_t deviceConfig = (provider != NULL) ? provider->getConfig() :
+ AUDIO_CONFIG_BASE_INITIALIZER;
+ const audio_patch_handle_t patchHandle = (provider != NULL) ? provider->getPatchHandle() :
+ AUDIO_PATCH_HANDLE_NONE;
+ mClientInterface->onRecordingConfigurationUpdate(RECORD_CONFIG_EVENT_START,
+ mSession, mInputSource,
+ &mConfig, &deviceConfig, patchHandle);
+ }
+}
status_t AudioSession::dump(int fd, int spaces, int index) const
{
@@ -118,12 +144,12 @@
result.append(buffer);
snprintf(buffer, SIZE, "%*s- input source: %d\n", spaces, "", mInputSource);
result.append(buffer);
- snprintf(buffer, SIZE, "%*s- format: %08x\n", spaces, "", mFormat);
+ snprintf(buffer, SIZE, "%*s- format: %08x\n", spaces, "", mConfig.format);
result.append(buffer);
- snprintf(buffer, SIZE, "%*s- sample: %d\n", spaces, "", mSampleRate);
+ snprintf(buffer, SIZE, "%*s- sample: %d\n", spaces, "", mConfig.sample_rate);
result.append(buffer);
snprintf(buffer, SIZE, "%*s- channel mask: %08x\n",
- spaces, "", mChannelMask);
+ spaces, "", mConfig.channel_mask);
result.append(buffer);
snprintf(buffer, SIZE, "%*s- is soundtrigger: %s\n",
spaces, "", mIsSoundTrigger ? "true" : "false");
@@ -138,7 +164,8 @@
}
status_t AudioSessionCollection::addSession(audio_session_t session,
- const sp<AudioSession>& audioSession)
+ const sp<AudioSession>& audioSession,
+ AudioSessionInfoProvider *provider)
{
ssize_t index = indexOfKey(session);
@@ -146,6 +173,7 @@
ALOGW("addSession() session %d already in", session);
return ALREADY_EXISTS;
}
+ audioSession->setInfoProvider(provider);
add(session, audioSession);
ALOGV("addSession() session %d client %d source %d",
session, audioSession->uid(), audioSession->inputSource());
@@ -161,6 +189,7 @@
return ALREADY_EXISTS;
}
ALOGV("removeSession() session %d", session);
+ valueAt(index)->setInfoProvider(NULL);
removeItemsAt(index);
return NO_ERROR;
}
@@ -207,6 +236,13 @@
return false;
}
+void AudioSessionCollection::onSessionInfoUpdate() const
+{
+ for (size_t i = 0; i < size(); i++) {
+ valueAt(i)->onSessionInfoUpdate();
+ }
+}
+
status_t AudioSessionCollection::dump(int fd, int spaces) const
{
diff --git a/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
index f613f94..c6ed53e 100644
--- a/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
@@ -50,6 +50,7 @@
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_FM),
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_IN_AMBIENT),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
@@ -72,6 +73,7 @@
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_A2DP),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_LOOPBACK),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_IP),
+ MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUS),
};
template<>
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
index c65de92..8221496 100755
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
@@ -1,5 +1,7 @@
LOCAL_PATH := $(call my-dir)
+ifneq ($(USE_CUSTOM_PARAMETER_FRAMEWORK), true)
+
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
@@ -33,3 +35,4 @@
include $(BUILD_SHARED_LIBRARY)
+endif # ifneq ($(USE_CUSTOM_PARAMETER_FRAMEWORK), true)
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 758673b..8ef6b1fc 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1765,7 +1765,7 @@
for(size_t input_index = 0; input_index < mInputs.size(); input_index++) {
sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(input_index);
- ssize_t patch_index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle);
+ ssize_t patch_index = mAudioPatches.indexOfKey(inputDesc->getPatchHandle());
if (patch_index >= 0) {
sp<AudioPatch> patchDesc = mAudioPatches.valueAt(patch_index);
status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0);
@@ -3939,7 +3939,7 @@
nextAudioPortGeneration();
- ssize_t index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle);
+ ssize_t index = mAudioPatches.indexOfKey(outputDesc->getPatchHandle());
if (index >= 0) {
sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0);
@@ -3968,7 +3968,7 @@
nextAudioPortGeneration();
- ssize_t index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle);
+ ssize_t index = mAudioPatches.indexOfKey(inputDesc->getPatchHandle());
if (index >= 0) {
sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0);
@@ -4153,12 +4153,12 @@
{
audio_devices_t device = AUDIO_DEVICE_NONE;
- ssize_t index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle);
+ ssize_t index = mAudioPatches.indexOfKey(outputDesc->getPatchHandle());
if (index >= 0) {
sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
if (patchDesc->mUid != mUidCached) {
ALOGV("getNewOutputDevice() device %08x forced by patch %d",
- outputDesc->device(), outputDesc->mPatchHandle);
+ outputDesc->device(), outputDesc->getPatchHandle());
return outputDesc->device();
}
}
@@ -4214,12 +4214,12 @@
{
sp<AudioInputDescriptor> inputDesc = mInputs.valueFor(input);
- ssize_t index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle);
+ ssize_t index = mAudioPatches.indexOfKey(inputDesc->getPatchHandle());
if (index >= 0) {
sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
if (patchDesc->mUid != mUidCached) {
ALOGV("getNewInputDevice() device %08x forced by patch %d",
- inputDesc->mDevice, inputDesc->mPatchHandle);
+ inputDesc->mDevice, inputDesc->getPatchHandle());
return inputDesc->mDevice;
}
}
@@ -4513,7 +4513,7 @@
// Doing this check here allows the caller to call setOutputDevice() without conditions
if ((device == AUDIO_DEVICE_NONE || device == prevDevice) &&
!force &&
- outputDesc->mPatchHandle != 0) {
+ outputDesc->getPatchHandle() != 0) {
ALOGV("setOutputDevice() setting same device 0x%04x or null device", device);
return muteWaitMs;
}
@@ -4540,7 +4540,7 @@
if (patchHandle && *patchHandle != AUDIO_PATCH_HANDLE_NONE) {
index = mAudioPatches.indexOfKey(*patchHandle);
} else {
- index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle);
+ index = mAudioPatches.indexOfKey(outputDesc->getPatchHandle());
}
sp< AudioPatch> patchDesc;
audio_patch_handle_t afPatchHandle = AUDIO_PATCH_HANDLE_NONE;
@@ -4566,7 +4566,7 @@
if (patchHandle) {
*patchHandle = patchDesc->mHandle;
}
- outputDesc->mPatchHandle = patchDesc->mHandle;
+ outputDesc->setPatchHandle(patchDesc->mHandle);
nextAudioPortGeneration();
mpClientInterface->onAudioPatchListUpdate();
}
@@ -4601,7 +4601,7 @@
if (patchHandle) {
index = mAudioPatches.indexOfKey(*patchHandle);
} else {
- index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle);
+ index = mAudioPatches.indexOfKey(outputDesc->getPatchHandle());
}
if (index < 0) {
return INVALID_OPERATION;
@@ -4609,7 +4609,7 @@
sp< AudioPatch> patchDesc = mAudioPatches.valueAt(index);
status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, delayMs);
ALOGV("resetOutputDevice() releaseAudioPatch returned %d", status);
- outputDesc->mPatchHandle = 0;
+ outputDesc->setPatchHandle(0);
removeAudioPatch(patchDesc->mHandle);
nextAudioPortGeneration();
mpClientInterface->onAudioPatchListUpdate();
@@ -4645,7 +4645,7 @@
if (patchHandle && *patchHandle != AUDIO_PATCH_HANDLE_NONE) {
index = mAudioPatches.indexOfKey(*patchHandle);
} else {
- index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle);
+ index = mAudioPatches.indexOfKey(inputDesc->getPatchHandle());
}
sp< AudioPatch> patchDesc;
audio_patch_handle_t afPatchHandle = AUDIO_PATCH_HANDLE_NONE;
@@ -4670,7 +4670,7 @@
if (patchHandle) {
*patchHandle = patchDesc->mHandle;
}
- inputDesc->mPatchHandle = patchDesc->mHandle;
+ inputDesc->setPatchHandle(patchDesc->mHandle);
nextAudioPortGeneration();
mpClientInterface->onAudioPatchListUpdate();
}
@@ -4687,7 +4687,7 @@
if (patchHandle) {
index = mAudioPatches.indexOfKey(*patchHandle);
} else {
- index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle);
+ index = mAudioPatches.indexOfKey(inputDesc->getPatchHandle());
}
if (index < 0) {
return INVALID_OPERATION;
@@ -4695,7 +4695,7 @@
sp< AudioPatch> patchDesc = mAudioPatches.valueAt(index);
status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0);
ALOGV("resetInputDevice() releaseAudioPatch returned %d", status);
- inputDesc->mPatchHandle = 0;
+ inputDesc->setPatchHandle(0);
removeAudioPatch(patchDesc->mHandle);
nextAudioPortGeneration();
mpClientInterface->onAudioPatchListUpdate();
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index 3d51f48..c4790b5 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -220,9 +220,12 @@
}
void AudioPolicyService::AudioPolicyClient::onRecordingConfigurationUpdate(
- int event, audio_session_t session, audio_source_t source)
+ int event, audio_session_t session, audio_source_t source,
+ const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
+ audio_patch_handle_t patchHandle)
{
- mAudioPolicyService->onRecordingConfigurationUpdate(event, session, source);
+ mAudioPolicyService->onRecordingConfigurationUpdate(event, session, source,
+ clientConfig, deviceConfig, patchHandle);
}
audio_unique_id_t AudioPolicyService::AudioPolicyClient::newAudioUniqueId()
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 363968c..94e0701 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -239,17 +239,21 @@
}
void AudioPolicyService::onRecordingConfigurationUpdate(int event, audio_session_t session,
- audio_source_t source)
+ audio_source_t source, const audio_config_base_t *clientConfig,
+ const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle)
{
- mOutputCommandThread->recordingConfigurationUpdateCommand(event, session, source);
+ mOutputCommandThread->recordingConfigurationUpdateCommand(event, session, source,
+ clientConfig, deviceConfig, patchHandle);
}
void AudioPolicyService::doOnRecordingConfigurationUpdate(int event, audio_session_t session,
- audio_source_t source)
+ audio_source_t source, const audio_config_base_t *clientConfig,
+ const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle)
{
Mutex::Autolock _l(mNotificationClientsLock);
for (size_t i = 0; i < mNotificationClients.size(); i++) {
- mNotificationClients.valueAt(i)->onRecordingConfigurationUpdate(event, session, source);
+ mNotificationClients.valueAt(i)->onRecordingConfigurationUpdate(event, session, source,
+ clientConfig, deviceConfig, patchHandle);
}
}
@@ -316,10 +320,13 @@
}
void AudioPolicyService::NotificationClient::onRecordingConfigurationUpdate(
- int event, audio_session_t session, audio_source_t source)
+ int event, audio_session_t session, audio_source_t source,
+ const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
+ audio_patch_handle_t patchHandle)
{
if (mAudioPolicyServiceClient != 0) {
- mAudioPolicyServiceClient->onRecordingConfigurationUpdate(event, session, source);
+ mAudioPolicyServiceClient->onRecordingConfigurationUpdate(event, session, source,
+ clientConfig, deviceConfig, patchHandle);
}
}
@@ -601,7 +608,8 @@
}
mLock.unlock();
svc->doOnRecordingConfigurationUpdate(data->mEvent, data->mSession,
- data->mSource);
+ data->mSource, &data->mClientConfig, &data->mDeviceConfig,
+ data->mPatchHandle);
mLock.lock();
} break;
default:
@@ -865,7 +873,9 @@
}
void AudioPolicyService::AudioCommandThread::recordingConfigurationUpdateCommand(
- int event, audio_session_t session, audio_source_t source)
+ int event, audio_session_t session, audio_source_t source,
+ const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
+ audio_patch_handle_t patchHandle)
{
sp<AudioCommand>command = new AudioCommand();
command->mCommand = RECORDING_CONFIGURATION_UPDATE;
@@ -873,6 +883,9 @@
data->mEvent = event;
data->mSession = session;
data->mSource = source;
+ data->mClientConfig = *clientConfig;
+ data->mDeviceConfig = *deviceConfig;
+ data->mPatchHandle = patchHandle;
command->mParam = data;
ALOGV("AudioCommandThread() adding recording configuration update event %d, source %d",
event, source);
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index a91c560..8d15eac 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -229,9 +229,11 @@
void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
void doOnDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
void onRecordingConfigurationUpdate(int event, audio_session_t session,
- audio_source_t source);
+ audio_source_t source, const audio_config_base_t *clientConfig,
+ const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle);
void doOnRecordingConfigurationUpdate(int event, audio_session_t session,
- audio_source_t source);
+ audio_source_t source, const audio_config_base_t *clientConfig,
+ const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle);
private:
AudioPolicyService() ANDROID_API;
@@ -305,7 +307,10 @@
void dynamicPolicyMixStateUpdateCommand(String8 regId, int32_t state);
void recordingConfigurationUpdateCommand(
int event, audio_session_t session,
- audio_source_t source);
+ audio_source_t source,
+ const audio_config_base_t *clientConfig,
+ const audio_config_base_t *deviceConfig,
+ audio_patch_handle_t patchHandle);
void insertCommand_l(AudioCommand *command, int delayMs = 0);
private:
@@ -401,6 +406,9 @@
int mEvent;
audio_session_t mSession;
audio_source_t mSource;
+ struct audio_config_base mClientConfig;
+ struct audio_config_base mDeviceConfig;
+ audio_patch_handle_t mPatchHandle;
};
Mutex mLock;
@@ -510,7 +518,9 @@
virtual void onAudioPatchListUpdate();
virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
virtual void onRecordingConfigurationUpdate(int event,
- audio_session_t session, audio_source_t source);
+ audio_session_t session, audio_source_t source,
+ const audio_config_base_t *clientConfig,
+ const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle);
virtual audio_unique_id_t newAudioUniqueId();
@@ -531,7 +541,10 @@
void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
void onRecordingConfigurationUpdate(
int event, audio_session_t session,
- audio_source_t source);
+ audio_source_t source,
+ const audio_config_base_t *clientConfig,
+ const audio_config_base_t *deviceConfig,
+ audio_patch_handle_t patchHandle);
void setAudioPortCallbacksEnabled(bool enabled);
// IBinder::DeathRecipient
diff --git a/services/mediaextractor/minijail/seccomp_policy/mediaextractor-seccomp-x86.policy b/services/mediaextractor/minijail/seccomp_policy/mediaextractor-seccomp-x86.policy
index f321366..6c44886 100644
--- a/services/mediaextractor/minijail/seccomp_policy/mediaextractor-seccomp-x86.policy
+++ b/services/mediaextractor/minijail/seccomp_policy/mediaextractor-seccomp-x86.policy
@@ -28,3 +28,10 @@
exit_group: 1
rt_sigreturn: 1
faccessat: 1
+
+# for attaching to debuggerd on process crash
+socketcall: 1
+sigaction: 1
+tgkill: 1
+rt_sigprocmask: 1
+fcntl64: 1
diff --git a/services/medialog/MediaLogService.cpp b/services/medialog/MediaLogService.cpp
index 41dab1f..98a71bb 100644
--- a/services/medialog/MediaLogService.cpp
+++ b/services/medialog/MediaLogService.cpp
@@ -28,7 +28,7 @@
void MediaLogService::registerWriter(const sp<IMemory>& shared, size_t size, const char *name)
{
- if (IPCThreadState::self()->getCallingUid() != AID_MEDIA || shared == 0 ||
+ if (IPCThreadState::self()->getCallingUid() != AID_AUDIOSERVER || shared == 0 ||
size < kMinSize || size > kMaxSize || name == NULL ||
shared->size() < NBLog::Timeline::sharedSize(size)) {
return;
@@ -41,7 +41,7 @@
void MediaLogService::unregisterWriter(const sp<IMemory>& shared)
{
- if (IPCThreadState::self()->getCallingUid() != AID_MEDIA || shared == 0) {
+ if (IPCThreadState::self()->getCallingUid() != AID_AUDIOSERVER || shared == 0) {
return;
}
Mutex::Autolock _l(mLock);
@@ -58,7 +58,7 @@
{
// FIXME merge with similar but not identical code at services/audioflinger/ServiceUtilities.cpp
static const String16 sDump("android.permission.DUMP");
- if (!(IPCThreadState::self()->getCallingUid() == AID_MEDIA ||
+ if (!(IPCThreadState::self()->getCallingUid() == AID_AUDIOSERVER ||
PermissionCache::checkCallingPermission(sDump))) {
dprintf(fd, "Permission Denial: can't dump media.log from pid=%d, uid=%d\n",
IPCThreadState::self()->getCallingPid(),
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index 4f99860..3d4e0b5 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -206,6 +206,10 @@
mServiceLog->add(log);
Mutex::Autolock lock(mLock);
+ if (!mProcessInfo->isValidPid(pid)) {
+ ALOGE("Rejected addResource call with invalid pid.");
+ return;
+ }
ResourceInfos& infos = getResourceInfosForEdit(pid, mMap);
ResourceInfo& info = getResourceInfoForEdit(clientId, client, infos);
// TODO: do the merge instead of append.
@@ -220,6 +224,10 @@
mServiceLog->add(log);
Mutex::Autolock lock(mLock);
+ if (!mProcessInfo->isValidPid(pid)) {
+ ALOGE("Rejected removeResource call with invalid pid.");
+ return;
+ }
ssize_t index = mMap.indexOfKey(pid);
if (index < 0) {
ALOGV("removeResource: didn't find pid %d for clientId %lld", pid, (long long) clientId);
@@ -259,6 +267,10 @@
Vector<sp<IResourceManagerClient>> clients;
{
Mutex::Autolock lock(mLock);
+ if (!mProcessInfo->isValidPid(callingPid)) {
+ ALOGE("Rejected reclaimResource call with invalid callingPid.");
+ return false;
+ }
const MediaResource *secureCodec = NULL;
const MediaResource *nonSecureCodec = NULL;
const MediaResource *graphicMemory = NULL;
diff --git a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
index df49ddc..cffedc6 100644
--- a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
+++ b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
@@ -44,6 +44,10 @@
return true;
}
+ virtual bool isValidPid(int /* pid */) {
+ return true;
+ }
+
private:
DISALLOW_EVIL_CONSTRUCTORS(TestProcessInfo);
};