Merge "Treblize audio policy xml config file location"
diff --git a/camera/cameraserver/Android.mk b/camera/cameraserver/Android.mk
index bdafff1..1548e64 100644
--- a/camera/cameraserver/Android.mk
+++ b/camera/cameraserver/Android.mk
@@ -23,6 +23,7 @@
libcameraservice \
liblog \
libutils \
+ libui \
libbinder \
android.hardware.camera.common@1.0 \
android.hardware.camera.provider@2.4 \
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index f1f3b01..5732613 100644
--- a/drm/libmediadrm/CryptoHal.cpp
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -95,17 +95,6 @@
}
-static ::SharedBuffer toSharedBuffer(const sp<IMemory>& sharedBuffer) {
- ssize_t offset;
- size_t size;
- sharedBuffer->getMemory(&offset, &size);
-
- ::SharedBuffer buffer;
- buffer.offset = offset >= 0 ? offset : 0;
- buffer.size = size;
- return buffer;
-}
-
static String8 toString8(hidl_string hString) {
return String8(hString.c_str());
}
@@ -114,7 +103,7 @@
CryptoHal::CryptoHal()
: mFactory(makeCryptoFactory()),
mInitCheck((mFactory == NULL) ? ERROR_UNSUPPORTED : NO_INIT),
- mHeapBase(NULL) {
+ mNextBufferId(0) {
}
CryptoHal::~CryptoHal() {
@@ -206,20 +195,45 @@
* size. Once the heap base is established, shared memory buffers
* are sent by providing an offset into the heap and a buffer size.
*/
-status_t CryptoHal::setHeapBase(const sp<IMemory>& sharedBuffer) {
- sp<IMemoryHeap> heap = sharedBuffer->getMemory(NULL, NULL);
- if (mHeapBase != heap->getBase()) {
- int fd = heap->getHeapID();
- native_handle_t* nativeHandle = native_handle_create(1, 0);
- nativeHandle->data[0] = fd;
- auto hidlHandle = hidl_handle(nativeHandle);
- auto hidlMemory = hidl_memory("ashmem", hidlHandle, heap->getSize());
- mHeapBase = heap->getBase();
- Return<void> hResult = mPlugin->setSharedBufferBase(hidlMemory);
- if (!hResult.isOk()) {
- return DEAD_OBJECT;
- }
+void CryptoHal::setHeapBase(const sp<IMemoryHeap>& heap) {
+ native_handle_t* nativeHandle = native_handle_create(1, 0);
+ if (!nativeHandle) {
+ ALOGE("setSharedBufferBase(), failed to create native handle");
+ return;
}
+ if (heap == NULL) {
+ ALOGE("setSharedBufferBase(): heap is NULL");
+ return;
+ }
+ int fd = heap->getHeapID();
+ nativeHandle->data[0] = fd;
+ auto hidlHandle = hidl_handle(nativeHandle);
+ auto hidlMemory = hidl_memory("ashmem", hidlHandle, heap->getSize());
+ mHeapBases.add(heap->getBase(), mNextBufferId);
+ Return<void> hResult = mPlugin->setSharedBufferBase(hidlMemory, mNextBufferId++);
+ ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
+}
+
+status_t CryptoHal::toSharedBuffer(const sp<IMemory>& memory, ::SharedBuffer* buffer) {
+ ssize_t offset;
+ size_t size;
+
+ if (memory == NULL && buffer == NULL) {
+ return UNEXPECTED_NULL;
+ }
+
+ sp<IMemoryHeap> heap = memory->getMemory(&offset, &size);
+ if (heap == NULL) {
+ return UNEXPECTED_NULL;
+ }
+
+ if (mHeapBases.indexOfKey(heap->getBase()) < 0) {
+ setHeapBase(heap);
+ }
+
+ buffer->bufferId = mHeapBases.valueFor(heap->getBase());
+ buffer->offset = offset >= 0 ? offset : 0;
+ buffer->size = size;
return OK;
}
@@ -234,9 +248,6 @@
return mInitCheck;
}
- // Establish the base of the shared memory heap
- setHeapBase(source);
-
Mode hMode;
switch(mode) {
case CryptoPlugin::kMode_Unencrypted:
@@ -272,7 +283,11 @@
::DestinationBuffer hDestination;
if (destination.mType == kDestinationTypeSharedMemory) {
hDestination.type = BufferType::SHARED_MEMORY;
- hDestination.nonsecureMemory = toSharedBuffer(destination.mSharedMemory);
+ status_t status = toSharedBuffer(destination.mSharedMemory,
+ &hDestination.nonsecureMemory);
+ if (status != OK) {
+ return status;
+ }
secure = false;
} else {
hDestination.type = BufferType::NATIVE_HANDLE;
@@ -280,12 +295,17 @@
secure = true;
}
+ ::SharedBuffer hSource;
+ status_t status = toSharedBuffer(source, &hSource);
+ if (status != OK) {
+ return status;
+ }
status_t err = UNKNOWN_ERROR;
uint32_t bytesWritten = 0;
Return<void> hResult = mPlugin->decrypt(secure, toHidlArray16(keyId), toHidlArray16(iv), hMode,
- hPattern, hSubSamples, toSharedBuffer(source), offset, hDestination,
+ hPattern, hSubSamples, hSource, offset, hDestination,
[&](Status status, uint32_t hBytesWritten, hidl_string hDetailedError) {
if (status == Status::OK) {
bytesWritten = hBytesWritten;
diff --git a/include/media/CryptoHal.h b/include/media/CryptoHal.h
index 1ace957..9d0c3e4 100644
--- a/include/media/CryptoHal.h
+++ b/include/media/CryptoHal.h
@@ -26,6 +26,8 @@
#include "SharedLibrary.h"
+class IMemoryHeap;
+
namespace android {
struct CryptoHal : public BnCrypto {
@@ -70,7 +72,8 @@
*/
status_t mInitCheck;
- void *mHeapBase;
+ KeyedVector<void *, uint32_t> mHeapBases;
+ uint32_t mNextBufferId;
sp<::android::hardware::drm::V1_0::ICryptoFactory>
makeCryptoFactory();
@@ -78,7 +81,10 @@
makeCryptoPlugin(const uint8_t uuid[16], const void *initData,
size_t size);
- status_t setHeapBase(const sp<IMemory> &sharedBuffer);
+ void setHeapBase(const sp<IMemoryHeap>& heap);
+
+ status_t toSharedBuffer(const sp<IMemory>& memory,
+ ::android::hardware::drm::V1_0::SharedBuffer* buffer);
DISALLOW_EVIL_CONSTRUCTORS(CryptoHal);
};
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index d5aec3f..9d0341a 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -53,6 +53,7 @@
virtual status_t setClientName(const String16& clientName) = 0;
virtual status_t prepare() = 0;
virtual status_t getMaxAmplitude(int* max) = 0;
+ virtual status_t getMetrics(Parcel *reply) = 0;
virtual status_t start() = 0;
virtual status_t stop() = 0;
virtual status_t reset() = 0;
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index ec1d4b6..39b9ad4 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -19,9 +19,9 @@
#define ANDROID_IOMX_H_
#include <binder/IInterface.h>
-#include <gui/IGraphicBufferProducer.h>
#include <utils/List.h>
#include <utils/String8.h>
+#include <cutils/native_handle.h>
#include <list>
diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h
index c273da7..0b0f916 100644
--- a/include/media/MediaRecorderBase.h
+++ b/include/media/MediaRecorderBase.h
@@ -58,6 +58,7 @@
virtual status_t close() = 0;
virtual status_t reset() = 0;
virtual status_t getMaxAmplitude(int *max) = 0;
+ virtual status_t getMetrics(Parcel *reply) = 0;
virtual status_t dump(int fd, const Vector<String16>& args) const = 0;
virtual status_t setInputSurface(const sp<PersistentSurface>& surface) = 0;
virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() const = 0;
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index c2916be..071e7a1 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -249,6 +249,7 @@
void notify(int msg, int ext1, int ext2);
status_t setInputSurface(const sp<PersistentSurface>& surface);
sp<IGraphicBufferProducer> querySurfaceMediaSourceFromMediaServer();
+ status_t getMetrics(Parcel *reply);
private:
void doCleanUp();
diff --git a/include/media/nbaio/NBLog.h b/include/media/nbaio/NBLog.h
index ff10b8c..043f15e 100644
--- a/include/media/nbaio/NBLog.h
+++ b/include/media/nbaio/NBLog.h
@@ -23,6 +23,8 @@
#include <utils/Mutex.h>
#include <audio_utils/fifo.h>
+#include <vector>
+
namespace android {
class String8;
@@ -40,14 +42,106 @@
EVENT_RESERVED,
EVENT_STRING, // ASCII string, not NUL-terminated
EVENT_TIMESTAMP, // clock_gettime(CLOCK_MONOTONIC)
- EVENT_INTEGER,
- EVENT_FLOAT,
- EVENT_PID,
+ EVENT_INTEGER, // integer value entry
+ EVENT_FLOAT, // floating point value entry
+ EVENT_PID, // process ID and process name
+ EVENT_AUTHOR, // author index (present in merged logs) tracks entry's original log
EVENT_START_FMT, // logFormat start event: entry includes format string, following
// entries contain format arguments
EVENT_END_FMT, // end of logFormat argument list
};
+
+// ---------------------------------------------------------------------------
+// API for handling format entry operations
+
+// a formatted entry has the following structure:
+// * START_FMT entry, containing the format string
+// * author entry of the thread that generated it (optional, present in merged log)
+// * TIMESTAMP entry
+// * format arg1
+// * format arg2
+// * ...
+// * END_FMT entry
+
+class FormatEntry {
+public:
+ // build a Format Entry starting in the given pointer
+ class iterator;
+ explicit FormatEntry(const uint8_t *entry);
+ explicit FormatEntry(const iterator &it);
+
+ // entry representation in memory
+ struct entry {
+ const uint8_t type;
+ const uint8_t length;
+ const uint8_t data[0];
+ };
+
+ // entry tail representation (after data)
+ struct ending {
+ uint8_t length;
+ uint8_t next[0];
+ };
+
+ // entry iterator
+ class iterator {
+ public:
+ iterator(const uint8_t *entry);
+ iterator(const iterator &other);
+
+ // dereference underlying entry
+ const entry& operator*() const;
+ const entry* operator->() const;
+ // advance to next entry
+ iterator& operator++(); // ++i
+ // back to previous entry
+ iterator& operator--(); // --i
+ bool operator!=(const iterator &other) const;
+ int operator-(const iterator &other) const;
+
+ bool hasConsistentLength() const;
+ void copyTo(std::unique_ptr<audio_utils_fifo_writer> &dst) const;
+ void copyData(uint8_t *dst) const;
+
+ template<typename T>
+ inline const T& payload() {
+ return *reinterpret_cast<const T *>(ptr + 2);
+ }
+
+ private:
+ friend class FormatEntry;
+ const uint8_t *ptr;
+ };
+
+ // Entry's format string
+ const char* formatString() const;
+
+ // Enrty's format string length
+ size_t formatStringLength() const;
+
+ // Format arguments (excluding format string, timestamp and author)
+ iterator args() const;
+
+ // get format entry timestamp
+ timespec timestamp() const;
+
+ // entry's author index (-1 if none present)
+ // a Merger has a vector of Readers, author simply points to the index of the
+ // Reader that originated the entry
+ int author() const;
+
+ // copy entry, adding author before timestamp, returns size of original entry
+ size_t copyTo(std::unique_ptr<audio_utils_fifo_writer> &dst, int author) const;
+
+ iterator begin() const;
+
+private:
+ // copies ordinary entry from src to dst, and returns length of entry
+ // size_t copyEntry(audio_utils_fifo_writer *dst, const iterator &it);
+ const uint8_t *mEntry;
+};
+
// ---------------------------------------------------------------------------
// representation of a single log entry in private memory
@@ -65,7 +159,11 @@
const void *mData; // event type-specific data
static const size_t kMaxLength = 255;
public:
- static const size_t kOverhead = 3; // mEvent, mLength, mData[...], duplicate mLength
+ // mEvent, mLength, mData[...], duplicate mLength
+ static const size_t kOverhead = sizeof(FormatEntry::entry) + sizeof(FormatEntry::ending);
+ // endind length of previous entry
+ static const size_t kPreviousLengthOffset = - sizeof(FormatEntry::ending) +
+ offsetof(FormatEntry::ending, length);
};
// representation of a single log entry in shared memory
@@ -81,10 +179,9 @@
static void appendInt(String8 *body, const void *data);
static void appendFloat(String8 *body, const void *data);
- static void appendPID(String8 *body, const void *data);
- static int handleFormat(const char *fmt, size_t length, const uint8_t *data,
- String8 *timestamp, String8 *body);
+ static void appendPID(String8 *body, const void *data, size_t length);
static void appendTimestamp(String8 *body, const void *data);
+ static size_t fmtEntryLength(const uint8_t *data);
public:
@@ -177,6 +274,11 @@
audio_utils_fifo_writer * const mFifoWriter; // used to write to FIFO,
// non-NULL unless dummy constructor used
bool mEnabled; // whether to actually log
+
+ // cached pid and process name to use in %p format specifier
+ // total tag length is mPidTagSize and process name is not zero terminated
+ char *mPidTag;
+ size_t mPidTagSize;
};
// ---------------------------------------------------------------------------
@@ -210,6 +312,31 @@
class Reader : public RefBase {
public:
+ // A snapshot of a readers buffer
+ class Snapshot {
+ public:
+ Snapshot() : mData(NULL), mAvail(0), mLost(0) {}
+
+ Snapshot(size_t bufferSize) : mData(new uint8_t[bufferSize]) {}
+
+ ~Snapshot() { delete[] mData; }
+
+ // copy of the buffer
+ const uint8_t *data() const { return mData; }
+
+ // amount of data available (given by audio_utils_fifo_reader)
+ size_t available() const { return mAvail; }
+
+ // amount of data lost (given by audio_utils_fifo_reader)
+ size_t lost() const { return mLost; }
+
+ private:
+ friend class Reader;
+ const uint8_t *mData;
+ size_t mAvail;
+ size_t mLost;
+ };
+
// Input parameter 'size' is the desired size of the timeline in byte units.
// The size of the shared memory must be at least Timeline::sharedSize(size).
Reader(const void *shared, size_t size);
@@ -217,8 +344,13 @@
virtual ~Reader();
- void dump(int fd, size_t indent = 0);
- bool isIMemory(const sp<IMemory>& iMemory) const;
+ // get snapshot of readers fifo buffer, effectively consuming the buffer
+ std::unique_ptr<Snapshot> getSnapshot();
+ // dump a particular snapshot of the reader
+ void dump(int fd, size_t indent, Snapshot & snap);
+ // dump the current content of the reader's buffer
+ void dump(int fd, size_t indent = 0);
+ bool isIMemory(const sp<IMemory>& iMemory) const;
private:
/*const*/ Shared* const mShared; // raw pointer to shared memory, actually const but not
@@ -233,9 +365,66 @@
void dumpLine(const String8& timestamp, String8& body);
+ FormatEntry::iterator handleFormat(const FormatEntry &fmtEntry,
+ String8 *timestamp,
+ String8 *body);
+ // dummy method for handling absent author entry
+ virtual size_t handleAuthor(const FormatEntry &fmtEntry, String8 *body) { return 0; }
+
static const size_t kSquashTimestamp = 5; // squash this many or more adjacent timestamps
};
+// Wrapper for a reader with a name. Contains a pointer to the reader and a pointer to the name
+class NamedReader {
+public:
+ NamedReader() { mName[0] = '\0'; } // for Vector
+ NamedReader(const sp<NBLog::Reader>& reader, const char *name) :
+ mReader(reader)
+ { strlcpy(mName, name, sizeof(mName)); }
+ ~NamedReader() { }
+ const sp<NBLog::Reader>& reader() const { return mReader; }
+ const char* name() const { return mName; }
+
+private:
+ sp<NBLog::Reader> mReader;
+ static const size_t kMaxName = 32;
+ char mName[kMaxName];
+};
+
+// ---------------------------------------------------------------------------
+
+class Merger : public RefBase {
+public:
+ Merger(const void *shared, size_t size);
+
+ virtual ~Merger() {}
+
+ void addReader(const NamedReader &reader);
+ // TODO add removeReader
+ void merge();
+ const std::vector<NamedReader> *getNamedReaders() const;
+private:
+ // vector of the readers the merger is supposed to merge from.
+ // every reader reads from a writer's buffer
+ std::vector<NamedReader> mNamedReaders;
+ uint8_t *mBuffer;
+ Shared * const mShared;
+ std::unique_ptr<audio_utils_fifo> mFifo;
+ std::unique_ptr<audio_utils_fifo_writer> mFifoWriter;
+
+ static struct timespec getTimestamp(const uint8_t *data);
+};
+
+class MergeReader : public Reader {
+public:
+ MergeReader(const void *shared, size_t size, Merger &merger);
+private:
+ const std::vector<NamedReader> *mNamedReaders;
+ // handle author entry by looking up the author's name and appending it to the body
+ // returns number of bytes read from fmtEntry
+ size_t handleAuthor(const FormatEntry &fmtEntry, String8 *body);
+};
+
}; // class NBLog
} // namespace android
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 90d9942..998716f 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -29,6 +29,7 @@
#include <media/stagefright/SkipCutBuffer.h>
#include <utils/NativeHandle.h>
#include <OMX_Audio.h>
+#include <hardware/gralloc.h>
#define TRACK_BUFFER_TIMING 0
@@ -42,11 +43,20 @@
struct DataConverter;
// Treble shared memory
-namespace hidl { namespace memory { namespace V1_0 {
+namespace hidl {
+namespace allocator {
+namespace V1_0 {
struct IAllocator;
+} // V1_0
+} // allocator
+namespace memory {
+namespace V1_0 {
struct IMemory;
-}}};
-typedef hidl::memory::V1_0::IAllocator TAllocator;
+} // V1_0
+} // memory
+} // hidl
+
+typedef hidl::allocator::V1_0::IAllocator TAllocator;
typedef hidl::memory::V1_0::IMemory TMemory;
struct ACodec : public AHierarchicalStateMachine, public CodecBase {
diff --git a/include/media/stagefright/SurfaceUtils.h b/include/media/stagefright/SurfaceUtils.h
index 13d580c..a7747c7 100644
--- a/include/media/stagefright/SurfaceUtils.h
+++ b/include/media/stagefright/SurfaceUtils.h
@@ -33,6 +33,8 @@
ANativeWindow *nativeWindow /* nonnull */,
int width, int height, int format, int rotation, int usage, bool reconnect);
status_t pushBlankBuffersToNativeWindow(ANativeWindow *nativeWindow /* nonnull */);
+status_t nativeWindowConnect(ANativeWindow *surface, const char *reason);
+status_t nativeWindowDisconnect(ANativeWindow *surface, const char *reason);
} // namespace android
diff --git a/include/ndk/NdkMediaCodec.h b/include/ndk/NdkMediaCodec.h
index ad17321..a63f39a 100644
--- a/include/ndk/NdkMediaCodec.h
+++ b/include/ndk/NdkMediaCodec.h
@@ -29,8 +29,6 @@
#include <sys/cdefs.h>
-#include <android/native_window.h>
-
#include "NdkMediaCrypto.h"
#include "NdkMediaError.h"
#include "NdkMediaFormat.h"
@@ -39,6 +37,8 @@
extern "C" {
#endif
+struct ANativeWindow;
+
#if __ANDROID_API__ >= 21
struct AMediaCodec;
diff --git a/media/audioserver/Android.mk b/media/audioserver/Android.mk
index 7dc4e1d..63fa16b 100644
--- a/media/audioserver/Android.mk
+++ b/media/audioserver/Android.mk
@@ -12,6 +12,7 @@
libcutils \
liblog \
libmedialogservice \
+ libnbaio \
libradioservice \
libsoundtriggerservice \
libutils \
diff --git a/media/audioserver/audioserver.rc b/media/audioserver/audioserver.rc
index 4b0f6a2..9d42bce 100644
--- a/media/audioserver/audioserver.rc
+++ b/media/audioserver/audioserver.rc
@@ -5,4 +5,9 @@
group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct
ioprio rt 4
writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
- onrestart restart audio-hal-2-0
\ No newline at end of file
+ onrestart restart audio-hal-2-0
+
+on property:vts.native_server.on=1
+ stop audioserver
+on property:vts.native_server.on=0
+ start audioserver
diff --git a/media/libaudiohal/Android.mk b/media/libaudiohal/Android.mk
index 617eb35..286c6b7 100644
--- a/media/libaudiohal/Android.mk
+++ b/media/libaudiohal/Android.mk
@@ -45,6 +45,7 @@
android.hardware.audio.common@2.0 \
android.hardware.audio.common@2.0-util \
android.hardware.audio.effect@2.0 \
+ android.hidl.allocator@1.0 \
android.hidl.memory@1.0 \
libmedia_helper \
libmediautils
diff --git a/media/libaudiohal/EffectBufferHalHidl.cpp b/media/libaudiohal/EffectBufferHalHidl.cpp
index 82b4a75..ce581f2 100644
--- a/media/libaudiohal/EffectBufferHalHidl.cpp
+++ b/media/libaudiohal/EffectBufferHalHidl.cpp
@@ -19,7 +19,7 @@
#define LOG_TAG "EffectBufferHalHidl"
//#define LOG_NDEBUG 0
-#include <android/hidl/memory/1.0/IAllocator.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
#include <hidlmemory/mapping.h>
#include <utils/Log.h>
@@ -28,7 +28,7 @@
using ::android::hardware::Return;
using ::android::hardware::Status;
-using ::android::hidl::memory::V1_0::IAllocator;
+using ::android::hidl::allocator::V1_0::IAllocator;
namespace android {
diff --git a/media/libaudiohal/EffectHalHidl.cpp b/media/libaudiohal/EffectHalHidl.cpp
index 67022de..d17f8bd 100644
--- a/media/libaudiohal/EffectHalHidl.cpp
+++ b/media/libaudiohal/EffectHalHidl.cpp
@@ -74,12 +74,33 @@
}
// static
+void EffectHalHidl::effectBufferConfigToHal(
+ const EffectBufferConfig& config, buffer_config_t* halConfig) {
+ halConfig->buffer.frameCount = 0;
+ halConfig->buffer.raw = NULL;
+ halConfig->samplingRate = config.samplingRateHz;
+ halConfig->channels = static_cast<uint32_t>(config.channels);
+ halConfig->bufferProvider.cookie = NULL;
+ halConfig->bufferProvider.getBuffer = NULL;
+ halConfig->bufferProvider.releaseBuffer = NULL;
+ halConfig->format = static_cast<uint8_t>(config.format);
+ halConfig->accessMode = static_cast<uint8_t>(config.accessMode);
+ halConfig->mask = static_cast<uint8_t>(config.mask);
+}
+
+// static
void EffectHalHidl::effectConfigFromHal(const effect_config_t& halConfig, EffectConfig* config) {
effectBufferConfigFromHal(halConfig.inputCfg, &config->inputCfg);
effectBufferConfigFromHal(halConfig.outputCfg, &config->outputCfg);
}
// static
+void EffectHalHidl::effectConfigToHal(const EffectConfig& config, effect_config_t* halConfig) {
+ effectBufferConfigToHal(config.inputCfg, &halConfig->inputCfg);
+ effectBufferConfigToHal(config.outputCfg, &halConfig->outputCfg);
+}
+
+// static
status_t EffectHalHidl::analyzeResult(const Result& result) {
switch (result) {
case Result::OK: return OK;
@@ -193,6 +214,8 @@
// Special cases.
if (cmdCode == EFFECT_CMD_SET_CONFIG || cmdCode == EFFECT_CMD_SET_CONFIG_REVERSE) {
return setConfigImpl(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
+ } else if (cmdCode == EFFECT_CMD_GET_CONFIG || cmdCode == EFFECT_CMD_GET_CONFIG_REVERSE) {
+ return getConfigImpl(cmdCode, replySize, pReplyData);
}
// Common case.
@@ -235,6 +258,34 @@
return ret.isOk() ? analyzeResult(ret) : FAILED_TRANSACTION;
}
+status_t EffectHalHidl::getConfigImpl(
+ uint32_t cmdCode, uint32_t *replySize, void *pReplyData) {
+ if (replySize == NULL || *replySize != sizeof(effect_config_t) || pReplyData == NULL) {
+ return BAD_VALUE;
+ }
+ status_t result = FAILED_TRANSACTION;
+ Return<void> ret;
+ if (cmdCode == EFFECT_CMD_GET_CONFIG) {
+ ret = mEffect->getConfig([&] (Result r, const EffectConfig &hidlConfig) {
+ result = analyzeResult(r);
+ if (r == Result::OK) {
+ effectConfigToHal(hidlConfig, static_cast<effect_config_t*>(pReplyData));
+ }
+ });
+ } else {
+ ret = mEffect->getConfigReverse([&] (Result r, const EffectConfig &hidlConfig) {
+ result = analyzeResult(r);
+ if (r == Result::OK) {
+ effectConfigToHal(hidlConfig, static_cast<effect_config_t*>(pReplyData));
+ }
+ });
+ }
+ if (!ret.isOk()) {
+ result = FAILED_TRANSACTION;
+ }
+ return result;
+}
+
status_t EffectHalHidl::setConfigImpl(
uint32_t cmdCode, uint32_t cmdSize, void *pCmdData, uint32_t *replySize, void *pReplyData) {
if (pCmdData == NULL || cmdSize != sizeof(effect_config_t) ||
diff --git a/media/libaudiohal/EffectHalHidl.h b/media/libaudiohal/EffectHalHidl.h
index d6a8791..c8db36f 100644
--- a/media/libaudiohal/EffectHalHidl.h
+++ b/media/libaudiohal/EffectHalHidl.h
@@ -79,7 +79,10 @@
static status_t analyzeResult(const hardware::audio::effect::V2_0::Result& result);
static void effectBufferConfigFromHal(
const buffer_config_t& halConfig, EffectBufferConfig* config);
+ static void effectBufferConfigToHal(
+ const EffectBufferConfig& config, buffer_config_t* halConfig);
static void effectConfigFromHal(const effect_config_t& halConfig, EffectConfig* config);
+ static void effectConfigToHal(const EffectConfig& config, effect_config_t* halConfig);
// Can not be constructed directly by clients.
EffectHalHidl(const sp<IEffect>& effect, uint64_t effectId);
@@ -87,6 +90,7 @@
// The destructor automatically releases the effect.
virtual ~EffectHalHidl();
+ status_t getConfigImpl(uint32_t cmdCode, uint32_t *replySize, void *pReplyData);
status_t prepareForProcessing();
status_t processImpl(uint32_t mqFlag);
status_t setConfigImpl(
diff --git a/media/libaudiohal/EffectsFactoryHalHidl.cpp b/media/libaudiohal/EffectsFactoryHalHidl.cpp
index ad12654..0ec9f9e 100644
--- a/media/libaudiohal/EffectsFactoryHalHidl.cpp
+++ b/media/libaudiohal/EffectsFactoryHalHidl.cpp
@@ -17,7 +17,7 @@
#define LOG_TAG "EffectsFactoryHalHidl"
//#define LOG_NDEBUG 0
-#include <android/hidl/memory/1.0/IAllocator.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
#include <cutils/native_handle.h>
#include <hidl/ServiceManagement.h>
#include <media/EffectsFactoryApi.h>
@@ -50,7 +50,7 @@
// TODO: Waiting should not be needed (b/34772726).
// Also remove include of IAllocator.h and ServiceManagement.h
android::hardware::details::waitForHwService(
- hidl::memory::V1_0::IAllocator::descriptor, "ashmem");
+ hidl::allocator::V1_0::IAllocator::descriptor, "ashmem");
}
EffectsFactoryHalHidl::~EffectsFactoryHalHidl() {
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 5730c76..5282352 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -59,7 +59,9 @@
SET_LISTENER,
SET_CLIENT_NAME,
PAUSE,
- RESUME
+ RESUME,
+ GET_METRICS,
+
};
class BpMediaRecorder: public BpInterface<IMediaRecorder>
@@ -261,6 +263,18 @@
return reply.readInt32();
}
+ status_t getMetrics(Parcel* reply)
+ {
+ ALOGV("getMetrics");
+ Parcel data;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ status_t ret = remote()->transact(GET_METRICS, data, reply);
+ if (ret == NO_ERROR) {
+ return OK;
+ }
+ return UNKNOWN_ERROR;
+ }
+
status_t start()
{
ALOGV("start");
@@ -397,6 +411,11 @@
reply->writeInt32(ret);
return NO_ERROR;
} break;
+ case GET_METRICS: {
+ ALOGV("GET_METRICS");
+ status_t ret = getMetrics(reply);
+ return ret;
+ } break;
case SET_VIDEO_SOURCE: {
ALOGV("SET_VIDEO_SOURCE");
CHECK_INTERFACE(IMediaRecorder, data, reply);
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 3d466b1..67939b2 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -25,8 +25,9 @@
#include <media/IOMX.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/openmax/OMX_IndexExt.h>
-#include <utils/NativeHandle.h>
#include <media/OMXBuffer.h>
+#include <utils/NativeHandle.h>
+#include <gui/IGraphicBufferProducer.h>
#include <android/IGraphicBufferSource.h>
#include <android/IOMXBufferSource.h>
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index dbe4b3b..4405930 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -513,6 +513,17 @@
return ret;
}
+status_t MediaRecorder::getMetrics(Parcel *reply) {
+
+ ALOGV("getMetrics");
+
+ status_t ret = mMediaRecorder->getMetrics(reply);
+ if (OK != ret) {
+ ALOGE("getMetrics failed: %d", ret);
+ }
+ return ret;
+}
+
status_t MediaRecorder::start()
{
ALOGV("start");
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index dbc7e21..a8b6c66 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -60,6 +60,7 @@
#include <media/stagefright/Utils.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooperRoster.h>
+#include <media/stagefright/SurfaceUtils.h>
#include <mediautils/BatteryNotifier.h>
#include <memunreachable/memunreachable.h>
@@ -903,11 +904,11 @@
void MediaPlayerService::Client::disconnectNativeWindow() {
if (mConnectedWindow != NULL) {
- status_t err = native_window_api_disconnect(mConnectedWindow.get(),
- NATIVE_WINDOW_API_MEDIA);
+ status_t err = nativeWindowDisconnect(
+ mConnectedWindow.get(), "disconnectNativeWindow");
if (err != OK) {
- ALOGW("native_window_api_disconnect returned an error: %s (%d)",
+ ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
strerror(-err), err);
}
}
@@ -929,8 +930,7 @@
sp<ANativeWindow> anw;
if (bufferProducer != NULL) {
anw = new Surface(bufferProducer, true /* controlledByApp */);
- status_t err = native_window_api_connect(anw.get(),
- NATIVE_WINDOW_API_MEDIA);
+ status_t err = nativeWindowConnect(anw.get(), "setVideoSurfaceTexture");
if (err != OK) {
ALOGE("setVideoSurfaceTexture failed: %d", err);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 763f509..c00a951 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -238,6 +238,17 @@
return mRecorder->getMaxAmplitude(max);
}
+status_t MediaRecorderClient::getMetrics(Parcel* reply)
+{
+ ALOGV("MediaRecorderClient::getMetrics");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ ALOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->getMetrics(reply);
+}
+
status_t MediaRecorderClient::start()
{
ALOGV("start");
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index 101b8f6..7868a91 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -79,6 +79,7 @@
virtual status_t setClientName(const String16& clientName);
virtual status_t prepare();
virtual status_t getMaxAmplitude(int* max);
+ virtual status_t getMetrics(Parcel* reply);
virtual status_t start();
virtual status_t stop();
virtual status_t reset();
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 170659a..73570c8 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -30,6 +30,7 @@
#include <binder/IServiceManager.h>
#include <media/IMediaPlayerService.h>
+#include <media/MediaAnalyticsItem.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -65,6 +66,10 @@
static const float kMinTypicalDisplayRefreshingRate = kTypicalDisplayRefreshingRate / 2;
static const int kMaxNumVideoTemporalLayers = 8;
+// key for media statistics
+static const char *kKeyRecorder = "recorder";
+// attrs for media statistics
+//
// To collect the encoder usage for the battery app
static void addBatteryData(uint32_t params) {
sp<IBinder> binder =
@@ -85,6 +90,8 @@
mStarted(false) {
ALOGV("Constructor");
+
+ mAnalyticsDirty = false;
reset();
}
@@ -95,6 +102,80 @@
if (mLooper != NULL) {
mLooper->stop();
}
+
+ // log the current record, provided it has some information worth recording
+ if (mAnalyticsDirty && mAnalyticsItem != NULL) {
+ updateMetrics();
+ if (mAnalyticsItem->count() > 0) {
+ mAnalyticsItem->setFinalized(true);
+ mAnalyticsItem->selfrecord();
+ }
+ delete mAnalyticsItem;
+ mAnalyticsItem = NULL;
+ }
+}
+
+void StagefrightRecorder::updateMetrics() {
+ ALOGV("updateMetrics");
+
+ // we'll populate the values from the raw fields.
+ // (NOT going to populate as we go through the various set* ops)
+
+ // TBD mOutputFormat = OUTPUT_FORMAT_THREE_GPP;
+ // TBD mAudioEncoder = AUDIO_ENCODER_AMR_NB;
+ // TBD mVideoEncoder = VIDEO_ENCODER_DEFAULT;
+ mAnalyticsItem->setInt32("ht", mVideoHeight);
+ mAnalyticsItem->setInt32("wid", mVideoWidth);
+ mAnalyticsItem->setInt32("frame-rate", mFrameRate);
+ mAnalyticsItem->setInt32("video-bitrate", mVideoBitRate);
+ mAnalyticsItem->setInt32("audio-samplerate", mSampleRate);
+ mAnalyticsItem->setInt32("audio-channels", mAudioChannels);
+ mAnalyticsItem->setInt32("audio-bitrate", mAudioBitRate);
+ // TBD mInterleaveDurationUs = 0;
+ mAnalyticsItem->setInt32("video-iframe-interval", mIFramesIntervalSec);
+ // TBD mAudioSourceNode = 0;
+ // TBD mUse64BitFileOffset = false;
+ mAnalyticsItem->setInt32("movie-timescale", mMovieTimeScale);
+ mAnalyticsItem->setInt32("audio-timescale", mAudioTimeScale);
+ mAnalyticsItem->setInt32("video-timescale", mVideoTimeScale);
+ // TBD mCameraId = 0;
+ // TBD mStartTimeOffsetMs = -1;
+ mAnalyticsItem->setInt32("video-encoder-profile", mVideoEncoderProfile);
+ mAnalyticsItem->setInt32("video-encoder-level", mVideoEncoderLevel);
+ // TBD mMaxFileDurationUs = 0;
+ // TBD mMaxFileSizeBytes = 0;
+ // TBD mTrackEveryTimeDurationUs = 0;
+ mAnalyticsItem->setInt32("capture-fpsenable", mCaptureFpsEnable);
+ mAnalyticsItem->setInt32("capture-fps", mCaptureFps);
+ // TBD mTimeBetweenCaptureUs = -1;
+ // TBD mCameraSourceTimeLapse = NULL;
+ // TBD mMetaDataStoredInVideoBuffers = kMetadataBufferTypeInvalid;
+ // TBD mEncoderProfiles = MediaProfiles::getInstance();
+ mAnalyticsItem->setInt32("rotation", mRotationDegrees);
+ // PII mLatitudex10000 = -3600000;
+ // PII mLongitudex10000 = -3600000;
+ // TBD mTotalBitRate = 0;
+
+ // TBD: some duration information (capture, paused)
+ //
+
+}
+
+void StagefrightRecorder::resetMetrics() {
+ ALOGV("resetMetrics");
+ // flush anything we have, restart the record
+ if (mAnalyticsDirty && mAnalyticsItem != NULL) {
+ updateMetrics();
+ if (mAnalyticsItem->count() > 0) {
+ mAnalyticsItem->setFinalized(true);
+ mAnalyticsItem->selfrecord();
+ }
+ delete mAnalyticsItem;
+ mAnalyticsItem = NULL;
+ }
+ mAnalyticsItem = new MediaAnalyticsItem(kKeyRecorder);
+ (void) mAnalyticsItem->generateSessionID();
+ mAnalyticsDirty = false;
}
status_t StagefrightRecorder::init() {
@@ -387,6 +468,7 @@
// Additional check on the sample rate will be performed later.
mSampleRate = sampleRate;
+
return OK;
}
@@ -399,6 +481,7 @@
// Additional check on the number of channels will be performed later.
mAudioChannels = channels;
+
return OK;
}
@@ -930,6 +1013,7 @@
}
if ((status == OK) && (!mStarted)) {
+ mAnalyticsDirty = true;
mStarted = true;
uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted;
@@ -1899,6 +1983,9 @@
err = mWriter->stop();
mWriter.clear();
}
+
+ resetMetrics();
+
mTotalPausedDurationUs = 0;
mPauseStartTimeUs = 0;
@@ -2002,6 +2089,23 @@
return OK;
}
+status_t StagefrightRecorder::getMetrics(Parcel *reply) {
+ ALOGD("StagefrightRecorder::getMetrics");
+
+ if (reply == NULL) {
+ ALOGE("Null pointer argument");
+ return BAD_VALUE;
+ }
+
+ if (mAnalyticsItem == NULL) {
+ return UNKNOWN_ERROR;
+ }
+
+ updateMetrics();
+ mAnalyticsItem->writeToParcel(reply);
+ return OK;
+}
+
status_t StagefrightRecorder::dump(
int fd, const Vector<String16>& args) const {
ALOGV("dump");
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index b7d0b0e..38377d2 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -18,6 +18,7 @@
#define STAGEFRIGHT_RECORDER_H_
+#include <media/MediaAnalyticsItem.h>
#include <media/MediaRecorderBase.h>
#include <camera/CameraParameters.h>
#include <utils/String8.h>
@@ -67,6 +68,7 @@
virtual status_t close();
virtual status_t reset();
virtual status_t getMaxAmplitude(int *max);
+ virtual status_t getMetrics(Parcel *reply);
virtual status_t dump(int fd, const Vector<String16> &args) const;
// Querying a SurfaceMediaSourcer
virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() const;
@@ -85,6 +87,11 @@
int mOutputFd;
sp<AudioSource> mAudioSourceNode;
+ MediaAnalyticsItem *mAnalyticsItem;
+ bool mAnalyticsDirty;
+ void resetMetrics();
+ void updateMetrics();
+
audio_source_t mAudioSource;
video_source mVideoSource;
output_format mOutputFormat;
diff --git a/media/libmediaplayerservice/nuplayer/Android.mk b/media/libmediaplayerservice/nuplayer/Android.mk
index 8686560..56c558d 100644
--- a/media/libmediaplayerservice/nuplayer/Android.mk
+++ b/media/libmediaplayerservice/nuplayer/Android.mk
@@ -35,6 +35,7 @@
LOCAL_SHARED_LIBRARIES := \
libbinder \
+ libui \
libmedia \
libmediadrm \
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index e800d13..50d5343 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -199,7 +199,8 @@
mSourceStarted(false),
mPaused(false),
mPausedByClient(true),
- mPausedForBuffering(false) {
+ mPausedForBuffering(false),
+ mIsDrmProtected(false) {
clearFlushComplete();
}
@@ -1145,12 +1146,6 @@
case SHUTTING_DOWN_DECODER:
break; // Wait for shutdown to complete.
case FLUSHED:
- // Both secure audio/video now. Legacy Widevine did it for secure video.
- // Widevine source reads must stop before releasing the video decoder.
- if (mSource != NULL && mIsDrmProtected) {
- mSource->stop();
- mSourceStarted = false;
- }
getDecoder(audio)->initiateShutdown(); // In the middle of a seek.
*flushing = SHUTTING_DOWN_DECODER; // Shut down.
break;
@@ -1574,12 +1569,6 @@
*state = SHUTTING_DOWN_DECODER;
ALOGV("initiating %s decoder shutdown", audio ? "audio" : "video");
- // Both secure audio/video now. Legacy Widevine did it for secure video only.
- // Widevine source reads must stop before releasing the video decoder.
- if (mSource != NULL && mIsDrmProtected) {
- mSource->stop();
- mSourceStarted = false;
- }
getDecoder(audio)->initiateShutdown();
break;
}
@@ -2724,7 +2713,11 @@
// TODO change to ALOGV
ALOGD("onReleaseDrm ");
- mIsDrmProtected = true;
+ if (!mIsDrmProtected) {
+ ALOGW("onReleaseDrm: Unexpected. mIsDrmProtected is already false.");
+ }
+
+ mIsDrmProtected = false;
status_t status;
if (mCrypto != NULL) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 5689e95..9a2224e 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -37,7 +37,7 @@
#include <media/stagefright/MediaCodec.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
-
+#include <media/stagefright/SurfaceUtils.h>
#include <gui/Surface.h>
#include "avc_utils.h"
@@ -232,21 +232,21 @@
//
// at this point MediaPlayerService::client has already connected to the
// surface, which MediaCodec does not expect
- err = native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_MEDIA);
+ err = nativeWindowDisconnect(surface.get(), "kWhatSetVideoSurface(surface)");
if (err == OK) {
err = mCodec->setSurface(surface);
ALOGI_IF(err, "codec setSurface returned: %d", err);
if (err == OK) {
// reconnect to the old surface as MPS::Client will expect to
// be able to disconnect from it.
- (void)native_window_api_connect(mSurface.get(), NATIVE_WINDOW_API_MEDIA);
+ (void)nativeWindowConnect(mSurface.get(), "kWhatSetVideoSurface(mSurface)");
mSurface = surface;
}
}
if (err != OK) {
// reconnect to the new surface on error as MPS::Client will expect to
// be able to disconnect from it.
- (void)native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
+ (void)nativeWindowConnect(surface.get(), "kWhatSetVideoSurface(err)");
}
}
@@ -313,8 +313,7 @@
status_t err;
if (mSurface != NULL) {
// disconnect from surface as MediaCodec will reconnect
- err = native_window_api_disconnect(
- mSurface.get(), NATIVE_WINDOW_API_MEDIA);
+ err = nativeWindowDisconnect(mSurface.get(), "onConfigure");
// We treat this as a warning, as this is a preparatory step.
// Codec will try to connect to the surface, which is where
// any error signaling will occur.
@@ -510,8 +509,7 @@
if (mSurface != NULL) {
// reconnect to surface as MediaCodec disconnected from it
- status_t error =
- native_window_api_connect(mSurface.get(), NATIVE_WINDOW_API_MEDIA);
+ status_t error = nativeWindowConnect(mSurface.get(), "onShutdown");
ALOGW_IF(error != NO_ERROR,
"[%s] failed to connect to native window, error=%d",
mComponentName.c_str(), error);
diff --git a/media/libnbaio/NBLog.cpp b/media/libnbaio/NBLog.cpp
index 7c2523d..f480c16 100644
--- a/media/libnbaio/NBLog.cpp
+++ b/media/libnbaio/NBLog.cpp
@@ -21,6 +21,7 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
+#include <sys/prctl.h>
#include <time.h>
#include <new>
#include <audio_utils/roundup.h>
@@ -28,6 +29,8 @@
#include <utils/Log.h>
#include <utils/String8.h>
+#include <queue>
+
namespace android {
int NBLog::Entry::readAt(size_t offset) const
@@ -47,6 +50,120 @@
// ---------------------------------------------------------------------------
+NBLog::FormatEntry::FormatEntry(const uint8_t *entry) : mEntry(entry) {
+ ALOGW_IF(entry[offsetof(struct entry, type)] != EVENT_START_FMT,
+ "Created format entry with invalid event type %d", entry[offsetof(struct entry, type)]);
+}
+
+NBLog::FormatEntry::FormatEntry(const NBLog::FormatEntry::iterator &it) : FormatEntry(it.ptr) {}
+
+const char *NBLog::FormatEntry::formatString() const {
+ return (const char*) mEntry + offsetof(entry, data);
+}
+
+size_t NBLog::FormatEntry::formatStringLength() const {
+ return mEntry[offsetof(entry, length)];
+}
+
+NBLog::FormatEntry::iterator NBLog::FormatEntry::args() const {
+ auto it = begin();
+ // Second entry can be author or timestamp. Skip author if present
+ if ((++it)->type == EVENT_AUTHOR) {
+ ++it;
+ }
+ return ++it;
+}
+
+timespec NBLog::FormatEntry::timestamp() const {
+ auto it = begin();
+ if ((++it)->type != EVENT_TIMESTAMP) {
+ ++it;
+ }
+ return it.payload<timespec>();
+}
+
+pid_t NBLog::FormatEntry::author() const {
+ auto it = begin();
+ if ((++it)->type == EVENT_AUTHOR) {
+ return it.payload<int>();
+ }
+ return -1;
+}
+
+size_t NBLog::FormatEntry::copyTo(std::unique_ptr<audio_utils_fifo_writer> &dst, int author) const {
+ auto it = this->begin();
+ // copy fmt start entry
+ it.copyTo(dst);
+ // insert author entry
+ size_t authorEntrySize = NBLog::Entry::kOverhead + sizeof(author);
+ uint8_t authorEntry[authorEntrySize];
+ authorEntry[offsetof(entry, type)] = EVENT_AUTHOR;
+ authorEntry[offsetof(entry, length)] =
+ authorEntry[authorEntrySize + NBLog::Entry::kPreviousLengthOffset] =
+ sizeof(author);
+ *(int*) (&authorEntry[offsetof(entry, data)]) = author;
+ dst->write(authorEntry, authorEntrySize);
+ // copy rest of entries
+ while ((++it)->type != EVENT_END_FMT) {
+ it.copyTo(dst);
+ }
+ it.copyTo(dst);
+ ++it;
+ return it - this->begin();
+}
+
+void NBLog::FormatEntry::iterator::copyTo(std::unique_ptr<audio_utils_fifo_writer> &dst) const {
+ size_t length = ptr[offsetof(entry, length)] + NBLog::Entry::kOverhead;
+ dst->write(ptr, length);
+}
+
+void NBLog::FormatEntry::iterator::copyData(uint8_t *dst) const {
+ memcpy((void*) dst, ptr + offsetof(entry, data), ptr[offsetof(entry, length)]);
+}
+
+NBLog::FormatEntry::iterator NBLog::FormatEntry::begin() const {
+ return iterator(mEntry);
+}
+
+NBLog::FormatEntry::iterator::iterator(const uint8_t *entry)
+ : ptr(entry) {}
+
+NBLog::FormatEntry::iterator::iterator(const NBLog::FormatEntry::iterator &other)
+ : ptr(other.ptr) {}
+
+const NBLog::FormatEntry::entry& NBLog::FormatEntry::iterator::operator*() const {
+ return *(entry*) ptr;
+}
+
+const NBLog::FormatEntry::entry* NBLog::FormatEntry::iterator::operator->() const {
+ return (entry*) ptr;
+}
+
+NBLog::FormatEntry::iterator& NBLog::FormatEntry::iterator::operator++() {
+ ptr += ptr[offsetof(entry, length)] + NBLog::Entry::kOverhead;
+ return *this;
+}
+
+NBLog::FormatEntry::iterator& NBLog::FormatEntry::iterator::operator--() {
+ ptr -= ptr[NBLog::Entry::kPreviousLengthOffset] + NBLog::Entry::kOverhead;
+ return *this;
+}
+
+int NBLog::FormatEntry::iterator::operator-(const NBLog::FormatEntry::iterator &other) const {
+ return ptr - other.ptr;
+}
+
+bool NBLog::FormatEntry::iterator::operator!=(const iterator &other) const {
+ return ptr != other.ptr;
+}
+
+bool NBLog::FormatEntry::iterator::hasConsistentLength() const {
+ return ptr[offsetof(entry, length)] == ptr[ptr[offsetof(entry, length)] +
+ NBLog::Entry::kOverhead + NBLog::Entry::kPreviousLengthOffset];
+}
+
+// ---------------------------------------------------------------------------
+
#if 0 // FIXME see note in NBLog.h
NBLog::Timeline::Timeline(size_t size, void *shared)
: mSize(roundup(size)), mOwn(shared == NULL),
@@ -74,7 +191,7 @@
// ---------------------------------------------------------------------------
NBLog::Writer::Writer()
- : mShared(NULL), mFifo(NULL), mFifoWriter(NULL), mEnabled(false)
+ : mShared(NULL), mFifo(NULL), mFifoWriter(NULL), mEnabled(false), mPidTag(NULL), mPidTagSize(0)
{
}
@@ -86,6 +203,18 @@
mFifoWriter(mFifo != NULL ? new audio_utils_fifo_writer(*mFifo) : NULL),
mEnabled(mFifoWriter != NULL)
{
+ // caching pid and process name
+ pid_t id = ::getpid();
+ char procName[16];
+ int status = prctl(PR_GET_NAME, procName);
+ if (status) { // error getting process name
+ procName[0] = '\0';
+ }
+ size_t length = strlen(procName);
+ mPidTagSize = length + sizeof(pid_t);
+ mPidTag = new char[mPidTagSize];
+ memcpy(mPidTag, &id, sizeof(pid_t));
+ memcpy(mPidTag + sizeof(pid_t), procName, length);
}
NBLog::Writer::Writer(const sp<IMemory>& iMemory, size_t size)
@@ -98,6 +227,7 @@
{
delete mFifoWriter;
delete mFifo;
+ delete[] mPidTag;
}
void NBLog::Writer::log(const char *string)
@@ -181,15 +311,7 @@
if (!mEnabled) {
return;
}
- pid_t id = ::getpid();
- // TODO: append process name to pid
- // const char* path = sprintf("/proc/%d/status", id);
- // FILE* f = fopen(path);
- // size_t length = 30
- // char buffer[length];
- // getline(&buffer, &length, f);
- // char* pidTag = sprintf("")
- log(EVENT_PID, &id, sizeof(pid_t));
+ log(EVENT_PID, mPidTag, mPidTagSize);
}
void NBLog::Writer::logStart(const char *fmt)
@@ -271,10 +393,12 @@
--p;
break;
+ case '%':
+ break;
+
default:
ALOGW("NBLog Writer parsed invalid format specifier: %c", *p);
break;
- // the '%' case is handled using the formatted string in the reader
}
}
Writer::logEnd();
@@ -455,53 +579,53 @@
delete mFifo;
}
-void NBLog::Reader::dump(int fd, size_t indent)
+std::unique_ptr<NBLog::Reader::Snapshot> NBLog::Reader::getSnapshot()
{
if (mFifoReader == NULL) {
- return;
+ return std::unique_ptr<NBLog::Reader::Snapshot>(new Snapshot());
}
// make a copy to avoid race condition with writer
size_t capacity = mFifo->capacity();
- // TODO Stack-based allocation of large objects may fail.
- // Currently the log buffers are a page or two, which should be safe.
- // But if the log buffers ever get a lot larger,
- // then change this to allocate from heap when necessary.
- static size_t kReasonableStackObjectSize = 32768;
- ALOGW_IF(capacity > kReasonableStackObjectSize, "Stack-based allocation of object may fail");
- uint8_t copy[capacity];
+ std::unique_ptr<Snapshot> snapshot(new Snapshot(capacity));
- size_t lost;
- ssize_t actual = mFifoReader->read(copy, capacity, NULL /*timeout*/, &lost);
+ ssize_t actual = mFifoReader->read((void*) snapshot->mData, capacity, NULL /*timeout*/,
+ &(snapshot->mLost));
ALOG_ASSERT(actual <= capacity);
- size_t avail = actual > 0 ? (size_t) actual : 0;
- size_t i = avail;
- Event event;
- size_t length;
+ snapshot->mAvail = actual > 0 ? (size_t) actual : 0;
+ return snapshot;
+}
+
+void NBLog::Reader::dump(int fd, size_t indent, NBLog::Reader::Snapshot &snapshot)
+{
+ NBLog::FormatEntry::iterator entry(snapshot.data() + snapshot.available());
+ NBLog::FormatEntry::iterator prevEntry = entry;
+ --prevEntry;
+ NBLog::FormatEntry::iterator start(snapshot.data());
+
struct timespec ts;
time_t maxSec = -1;
- while (i >= Entry::kOverhead) {
- length = copy[i - 1];
- if (length + Entry::kOverhead > i || copy[i - length - 2] != length) {
+ while (entry - start >= (int) Entry::kOverhead) {
+ if (prevEntry - start < 0 || !prevEntry.hasConsistentLength()) {
break;
}
- event = (Event) copy[i - length - Entry::kOverhead];
- if (event == EVENT_TIMESTAMP) {
- if (length != sizeof(struct timespec)) {
+ if (prevEntry->type == EVENT_TIMESTAMP) {
+ if (prevEntry->length != sizeof(struct timespec)) {
// corrupt
break;
}
- memcpy(&ts, ©[i - length - 1], sizeof(struct timespec));
+ prevEntry.copyData((uint8_t*) &ts);
if (ts.tv_sec > maxSec) {
maxSec = ts.tv_sec;
}
}
- i -= length + Entry::kOverhead;
+ --entry;
+ --prevEntry;
}
mFd = fd;
mIndent = indent;
String8 timestamp, body;
- lost += i;
+ size_t lost = snapshot.lost() + (entry - start);
if (lost > 0) {
body.appendFormat("warning: lost %zu bytes worth of events", lost);
// TODO timestamp empty here, only other choice to wait for the first timestamp event in the
@@ -517,30 +641,29 @@
timestamp.appendFormat("[%*s]", (int) width + 4, "");
}
bool deferredTimestamp = false;
- while (i < avail) {
- event = (Event) copy[i];
- length = copy[i + 1];
- const void *data = ©[i + 2];
- size_t advance = length + Entry::kOverhead;
- switch (event) {
+ NBLog::FormatEntry::iterator end(snapshot.data() + snapshot.available());
+
+ while (entry != end) {
+ switch (entry->type) {
+#if 0
case EVENT_STRING:
- body.appendFormat("%.*s", (int) length, (const char *) data);
+ body.appendFormat("%.*s", (int) entry.length(), entry.data());
break;
case EVENT_TIMESTAMP: {
// already checked that length == sizeof(struct timespec);
- memcpy(&ts, data, sizeof(struct timespec));
+ entry.copyData((const uint8_t*) &ts);
long prevNsec = ts.tv_nsec;
long deltaMin = LONG_MAX;
long deltaMax = -1;
long deltaTotal = 0;
- size_t j = i;
+ auto aux(entry);
for (;;) {
- j += sizeof(struct timespec) + 3 /*Entry::kOverhead?*/;
- if (j >= avail || (Event) copy[j] != EVENT_TIMESTAMP) {
+ ++aux;
+ if (end - aux >= 0 || aux.type() != EVENT_TIMESTAMP) {
break;
}
struct timespec tsNext;
- memcpy(&tsNext, ©[j + 2], sizeof(struct timespec));
+ aux.copyData((const uint8_t*) &tsNext);
if (tsNext.tv_sec != ts.tv_sec) {
break;
}
@@ -557,7 +680,7 @@
deltaTotal += delta;
prevNsec = tsNext.tv_nsec;
}
- size_t n = (j - i) / (sizeof(struct timespec) + 3 /*Entry::kOverhead?*/);
+ size_t n = (aux - entry) / (sizeof(struct timespec) + 3 /*Entry::kOverhead?*/);
if (deferredTimestamp) {
dumpLine(timestamp, body);
deferredTimestamp = false;
@@ -568,36 +691,37 @@
(int) ts.tv_sec, (int) (ts.tv_nsec / 1000000),
(int) ((ts.tv_nsec + deltaTotal) / 1000000),
(int) (deltaMin / 1000000), (int) (deltaMax / 1000000));
- i = j;
- advance = 0;
+ entry = aux;
+ // advance = 0;
break;
}
timestamp.appendFormat("[%d.%03d]", (int) ts.tv_sec,
(int) (ts.tv_nsec / 1000000));
deferredTimestamp = true;
- } break;
+ }
+ break;
case EVENT_INTEGER:
- appendInt(&body, data);
+ appendInt(&body, entry.data());
break;
case EVENT_FLOAT:
- appendFloat(&body, data);
+ appendFloat(&body, entry.data());
break;
case EVENT_PID:
- appendPID(&body, data);
+ appendPID(&body, entry.data(), entry.length());
break;
+#endif
case EVENT_START_FMT:
- advance += handleFormat((const char*) ©[i + 2], length,
- ©[i + Entry::kOverhead + length], ×tamp, &body);
+ // right now, this is the only supported case
+ entry = handleFormat(FormatEntry(entry), ×tamp, &body);
break;
case EVENT_END_FMT:
body.appendFormat("warning: got to end format event");
break;
case EVENT_RESERVED:
default:
- body.appendFormat("warning: unknown event %d", event);
+ body.appendFormat("warning: unknown event %d", entry->type);
break;
}
- i += advance;
if (!body.isEmpty()) {
dumpLine(timestamp, body);
@@ -609,6 +733,13 @@
}
}
+void NBLog::Reader::dump(int fd, size_t indent)
+{
+ // get a snapshot, dump it
+ std::unique_ptr<Snapshot> snap = getSnapshot();
+ dump(fd, indent, *snap);
+}
+
void NBLog::Reader::dumpLine(const String8 ×tamp, String8 &body)
{
if (mFd >= 0) {
@@ -642,86 +773,189 @@
body->appendFormat("<%f>", f);
}
-void NBLog::appendPID(String8 *body, const void* data) {
+void NBLog::appendPID(String8 *body, const void* data, size_t length) {
pid_t id = *((pid_t*) data);
- body->appendFormat("<PID: %d>", id);
+ char * name = &((char*) data)[sizeof(pid_t)];
+ body->appendFormat("<PID: %d, name: %.*s>", id, (int) (length - sizeof(pid_t)), name);
}
-int NBLog::handleFormat(const char *fmt, size_t fmt_length, const uint8_t *data,
- String8 *timestamp, String8 *body) {
- if (data[0] != EVENT_TIMESTAMP) {
- ALOGW("NBLog Reader Expected timestamp event %d, got %d", EVENT_TIMESTAMP, data[0]);
- }
- struct timespec ts;
- memcpy(&ts, &data[2], sizeof(ts));
+NBLog::FormatEntry::iterator NBLog::Reader::handleFormat(const FormatEntry &fmtEntry,
+ String8 *timestamp,
+ String8 *body) {
+ // log timestamp
+ struct timespec ts = fmtEntry.timestamp();
timestamp->clear();
timestamp->appendFormat("[%d.%03d]", (int) ts.tv_sec,
(int) (ts.tv_nsec / 1000000));
- size_t data_offset = Entry::kOverhead + sizeof ts;
+
+ // log author (if present)
+ handleAuthor(fmtEntry, body);
+
+ // log string
+ NBLog::FormatEntry::iterator arg = fmtEntry.args();
+
+ const char* fmt = fmtEntry.formatString();
+ size_t fmt_length = fmtEntry.formatStringLength();
for (size_t fmt_offset = 0; fmt_offset < fmt_length; ++fmt_offset) {
if (fmt[fmt_offset] != '%') {
body->append(&fmt[fmt_offset], 1); // TODO optimize to write consecutive strings at once
continue;
}
+ // case "%%""
if (fmt[++fmt_offset] == '%') {
body->append("%");
continue;
}
+ // case "%\0"
if (fmt_offset == fmt_length) {
continue;
}
- NBLog::Event event = (NBLog::Event) data[data_offset];
- size_t length = data[data_offset + 1];
+ NBLog::Event event = (NBLog::Event) arg->type;
+ size_t length = arg->length;
// TODO check length for event type is correct
- if(length != data[data_offset + length + 2]) {
- ALOGW("NBLog Reader recieved different lengths %zu and %d for event %d", length,
- data[data_offset + length + 2], event);
+ if (!arg.hasConsistentLength()) {
+ // TODO: corrupt, resync buffer
body->append("<invalid entry>");
++fmt_offset;
continue;
}
+ if (event == EVENT_END_FMT) {
+ break;
+ }
+
// TODO: implement more complex formatting such as %.3f
- void * datum = (void*) &data[data_offset + 2]; // pointer to the current event data
+ const uint8_t *datum = arg->data; // pointer to the current event args
switch(fmt[fmt_offset])
{
case 's': // string
- ALOGW_IF(event != EVENT_STRING, "NBLog Reader incompatible event for string specifier: %d", event);
+ ALOGW_IF(event != EVENT_STRING,
+ "NBLog Reader incompatible event for string specifier: %d", event);
body->append((const char*) datum, length);
break;
case 't': // timestamp
- ALOGW_IF(event != EVENT_TIMESTAMP, "NBLog Reader incompatible event for timestamp specifier: %d", event);
+ ALOGW_IF(event != EVENT_TIMESTAMP,
+ "NBLog Reader incompatible event for timestamp specifier: %d", event);
appendTimestamp(body, datum);
break;
case 'd': // integer
- ALOGW_IF(event != EVENT_INTEGER, "NBLog Reader incompatible event for integer specifier: %d", event);
+ ALOGW_IF(event != EVENT_INTEGER,
+ "NBLog Reader incompatible event for integer specifier: %d", event);
appendInt(body, datum);
-
break;
case 'f': // float
- ALOGW_IF(event != EVENT_FLOAT, "NBLog Reader incompatible event for float specifier: %d", event);
+ ALOGW_IF(event != EVENT_FLOAT,
+ "NBLog Reader incompatible event for float specifier: %d", event);
appendFloat(body, datum);
break;
case 'p': // pid
- ALOGW_IF(event != EVENT_PID, "NBLog Reader incompatible event for pid specifier: %d", event);
- appendPID(body, datum);
+ ALOGW_IF(event != EVENT_PID,
+ "NBLog Reader incompatible event for pid specifier: %d", event);
+ appendPID(body, datum, length);
break;
default:
ALOGW("NBLog Reader encountered unknown character %c", fmt[fmt_offset]);
}
-
- data_offset += length + Entry::kOverhead;
-
+ ++arg;
}
- return data_offset + Entry::kOverhead; // data offset + size of END_FMT event
+ ALOGW_IF(arg->type != EVENT_END_FMT, "Expected end of format, got %d", arg->type);
+ ++arg;
+ return arg;
+}
+
+// ---------------------------------------------------------------------------
+
+NBLog::Merger::Merger(const void *shared, size_t size):
+ mBuffer(NULL),
+ mShared((Shared *) shared),
+ mFifo(mShared != NULL ?
+ new audio_utils_fifo(size, sizeof(uint8_t),
+ mShared->mBuffer, mShared->mRear, NULL /*throttlesFront*/) : NULL),
+ mFifoWriter(mFifo != NULL ? new audio_utils_fifo_writer(*mFifo) : NULL)
+ {}
+
+void NBLog::Merger::addReader(const NBLog::NamedReader &reader) {
+ mNamedReaders.push_back(reader);
+}
+
+// items placed in priority queue during merge
+// composed by a timestamp and the index of the snapshot where the timestamp came from
+struct MergeItem
+{
+ struct timespec ts;
+ int index;
+ MergeItem(struct timespec ts, int index): ts(ts), index(index) {}
+};
+
+// operators needed for priority queue in merge
+bool operator>(const struct timespec &t1, const struct timespec &t2) {
+ return t1.tv_sec > t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_nsec > t2.tv_nsec);
+}
+
+bool operator>(const struct MergeItem &i1, const struct MergeItem &i2) {
+ return i1.ts > i2.ts ||
+ (i1.ts.tv_sec == i2.ts.tv_sec && i1.ts.tv_nsec == i2.ts.tv_nsec && i1.index > i2.index);
+}
+
+// Merge registered readers, sorted by timestamp
+void NBLog::Merger::merge() {
+ int nLogs = mNamedReaders.size();
+ std::vector<std::unique_ptr<NBLog::Reader::Snapshot>> snapshots(nLogs);
+ for (int i = 0; i < nLogs; ++i) {
+ snapshots[i] = mNamedReaders[i].reader()->getSnapshot();
+ }
+ // initialize offsets
+ std::vector<size_t> offsets(nLogs, 0);
+ // TODO custom heap implementation could allow to update top, improving performance
+ // for bursty buffers
+ std::priority_queue<MergeItem, std::vector<MergeItem>, std::greater<MergeItem>> timestamps;
+ for (int i = 0; i < nLogs; ++i)
+ {
+ if (snapshots[i]->available() > 0) {
+ timespec ts = FormatEntry(snapshots[i]->data()).timestamp();
+ MergeItem item(ts, i);
+ timestamps.push(item);
+ }
+ }
+
+ while (!timestamps.empty()) {
+ // find minimum timestamp
+ int index = timestamps.top().index;
+ // copy it to the log
+ size_t length = FormatEntry(snapshots[index]->data() + offsets[index]).copyTo(
+ mFifoWriter, index);
+ // update data structures
+ offsets[index] += length;
+ ALOGW_IF(offsets[index] > snapshots[index]->available(), "Overflown snapshot capacity");
+ timestamps.pop();
+ if (offsets[index] != snapshots[index]->available()) {
+ timespec ts = FormatEntry(snapshots[index]->data() + offsets[index]).timestamp();
+ MergeItem item(ts, index);
+ timestamps.emplace(item);
+ }
+ }
+}
+
+const std::vector<NBLog::NamedReader> *NBLog::Merger::getNamedReaders() const {
+ return &mNamedReaders;
+}
+
+NBLog::MergeReader::MergeReader(const void *shared, size_t size, Merger &merger)
+ : Reader(shared, size), mNamedReaders(merger.getNamedReaders()) {}
+
+size_t NBLog::MergeReader::handleAuthor(const NBLog::FormatEntry &fmtEntry, String8 *body) {
+ int author = fmtEntry.author();
+ const char* name = (*mNamedReaders)[author].name();
+ body->appendFormat("%s: ", name);
+ return NBLog::Entry::kOverhead + sizeof(author);
}
} // namespace android
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 3f56725..78f28ae 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -61,7 +61,7 @@
#include "include/SharedMemoryBuffer.h"
#include "omx/OMXUtils.h"
-#include <android/hidl/memory/1.0/IAllocator.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMemory.h>
#include "omx/hal/1.0/utils/WOmxNode.h"
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 410dbc9..d044754 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -115,6 +115,7 @@
libRScpp \
libhidlbase \
libhidlmemory \
+ android.hidl.allocator@1.0 \
android.hidl.memory@1.0 \
android.hardware.media.omx@1.0 \
android.hardware.media.omx@1.0-utils \
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index cbd5802..03010ab 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -2914,7 +2914,7 @@
return ALREADY_EXISTS;
}
- err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
+ err = nativeWindowConnect(surface.get(), "connectToSurface");
if (err == OK) {
// Require a fresh set of buffers after each connect by using a unique generation
// number. Rely on the fact that max supported process id by Linux is 2^22.
@@ -2929,12 +2929,12 @@
// This is needed as the consumer may be holding onto stale frames that it can reattach
// to this surface after disconnect/connect, and those free frames would inherit the new
// generation number. Disconnecting after setting a unique generation prevents this.
- native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_MEDIA);
- err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
+ nativeWindowDisconnect(surface.get(), "connectToSurface(reconnect)");
+ err = nativeWindowConnect(surface.get(), "connectToSurface(reconnect)");
}
if (err != OK) {
- ALOGE("native_window_api_connect returned an error: %s (%d)", strerror(-err), err);
+ ALOGE("nativeWindowConnect returned an error: %s (%d)", strerror(-err), err);
}
}
// do not return ALREADY_EXISTS unless surfaces are the same
@@ -2946,9 +2946,9 @@
if (mSurface != NULL) {
// Resetting generation is not technically needed, but there is no need to keep it either
mSurface->setGenerationNumber(0);
- err = native_window_api_disconnect(mSurface.get(), NATIVE_WINDOW_API_MEDIA);
+ err = nativeWindowDisconnect(mSurface.get(), "disconnectFromSurface");
if (err != OK) {
- ALOGW("native_window_api_disconnect returned an error: %s (%d)", strerror(-err), err);
+ ALOGW("nativeWindowDisconnect returned an error: %s (%d)", strerror(-err), err);
}
// assume disconnected even on error
mSurface.clear();
diff --git a/media/libstagefright/SurfaceUtils.cpp b/media/libstagefright/SurfaceUtils.cpp
index 568837a..82e959e 100644
--- a/media/libstagefright/SurfaceUtils.cpp
+++ b/media/libstagefright/SurfaceUtils.cpp
@@ -31,15 +31,15 @@
// In some cases we need to reconnect so that we can dequeue all buffers
if (reconnect) {
- err = native_window_api_disconnect(nativeWindow, NATIVE_WINDOW_API_MEDIA);
+ err = nativeWindowDisconnect(nativeWindow, "setNativeWindowSizeFormatAndUsage");
if (err != NO_ERROR) {
- ALOGE("native_window_api_disconnect failed: %s (%d)", strerror(-err), -err);
+ ALOGE("nativeWindowDisconnect failed: %s (%d)", strerror(-err), -err);
return err;
}
- err = native_window_api_connect(nativeWindow, NATIVE_WINDOW_API_MEDIA);
+ err = nativeWindowConnect(nativeWindow, "setNativeWindowSizeFormatAndUsage");
if (err != NO_ERROR) {
- ALOGE("native_window_api_connect failed: %s (%d)", strerror(-err), -err);
+ ALOGE("nativeWindowConnect failed: %s (%d)", strerror(-err), -err);
return err;
}
}
@@ -127,7 +127,7 @@
// We need to reconnect to the ANativeWindow as a CPU client to ensure that
// no frames get dropped by SurfaceFlinger assuming that these are video
// frames.
- err = native_window_api_disconnect(nativeWindow, NATIVE_WINDOW_API_MEDIA);
+ err = nativeWindowDisconnect(nativeWindow, "pushBlankBuffersToNativeWindow");
if (err != NO_ERROR) {
ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)", strerror(-err), -err);
return err;
@@ -136,7 +136,7 @@
err = native_window_api_connect(nativeWindow, NATIVE_WINDOW_API_CPU);
if (err != NO_ERROR) {
ALOGE("error pushing blank frames: api_connect failed: %s (%d)", strerror(-err), -err);
- (void)native_window_api_connect(nativeWindow, NATIVE_WINDOW_API_MEDIA);
+ (void)nativeWindowConnect(nativeWindow, "pushBlankBuffersToNativeWindow(err)");
return err;
}
@@ -219,7 +219,7 @@
}
}
- err2 = native_window_api_connect(nativeWindow, NATIVE_WINDOW_API_MEDIA);
+ err2 = nativeWindowConnect(nativeWindow, "pushBlankBuffersToNativeWindow(err2)");
if (err2 != NO_ERROR) {
ALOGE("error pushing blank frames: api_connect failed: %s (%d)", strerror(-err), -err);
if (err == NO_ERROR) {
@@ -230,5 +230,22 @@
return err;
}
+status_t nativeWindowConnect(ANativeWindow *surface, const char *reason) {
+ ALOGD("connecting to surface %p, reason %s", surface, reason);
+
+ status_t err = native_window_api_connect(surface, NATIVE_WINDOW_API_MEDIA);
+ ALOGE_IF(err != OK, "Failed to connect to surface %p, err %d", surface, err);
+
+ return err;
+}
+
+status_t nativeWindowDisconnect(ANativeWindow *surface, const char *reason) {
+ ALOGD("disconnecting from surface %p, reason %s", surface, reason);
+
+ status_t err = native_window_api_disconnect(surface, NATIVE_WINDOW_API_MEDIA);
+ ALOGE_IF(err != OK, "Failed to disconnect from surface %p, err %d", surface, err);
+
+ return err;
+}
} // namespace android
diff --git a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
index 9e7a3be..b057ffe 100644
--- a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
+++ b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
@@ -30,7 +30,6 @@
#include <media/stagefright/Utils.h>
#include <OMX_IndexExt.h>
#include <OMX_VideoExt.h>
-#include <ui/Rect.h>
#include "ih264_typedefs.h"
#include "iv2.h"
diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
index d5a26d3..6d4cb69 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
@@ -30,8 +30,6 @@
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/Utils.h>
-#include <ui/Rect.h>
-#include <ui/GraphicBufferMapper.h>
#include "SoftMPEG4Encoder.h"
diff --git a/media/libstagefright/colorconversion/Android.mk b/media/libstagefright/colorconversion/Android.mk
index ba74740..1e82727 100644
--- a/media/libstagefright/colorconversion/Android.mk
+++ b/media/libstagefright/colorconversion/Android.mk
@@ -10,6 +10,9 @@
$(TOP)/hardware/msm7k \
$(TOP)/external/libyuv/files/include
+LOCAL_SHARED_LIBRARIES := \
+ libui \
+
LOCAL_STATIC_LIBRARIES := \
libyuv_static \
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index bbc4d26..54487b3 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -24,7 +24,8 @@
#include <media/stagefright/foundation/AMessage.h>
#include <system/window.h>
#include <ui/GraphicBufferMapper.h>
-#include <gui/IGraphicBufferProducer.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/Rect.h>
namespace android {
diff --git a/media/libstagefright/filters/Android.mk b/media/libstagefright/filters/Android.mk
index 830d2aa..07b2eb8 100644
--- a/media/libstagefright/filters/Android.mk
+++ b/media/libstagefright/filters/Android.mk
@@ -23,6 +23,7 @@
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
LOCAL_SHARED_LIBRARIES := \
+ libgui \
libmedia \
libhidlmemory \
diff --git a/media/libstagefright/foundation/Android.bp b/media/libstagefright/foundation/Android.bp
index f7bd3f2..0557d95 100644
--- a/media/libstagefright/foundation/Android.bp
+++ b/media/libstagefright/foundation/Android.bp
@@ -29,12 +29,13 @@
shared_libs: [
"libbinder",
"libutils",
+ "libui",
"libcutils",
"liblog",
"libpowermanager",
],
- export_shared_lib_headers: ["libbinder"],
+ export_shared_lib_headers: ["libbinder", "libui"],
cflags: [
"-Wno-multichar",
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index c7e60ca..8e08d15 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -30,6 +30,7 @@
#include <android/hidl/memory/1.0/IMemory.h>
namespace android {
+class GraphicBuffer;
class IOMXBufferSource;
class IOMXObserver;
struct OMXMaster;
diff --git a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
index adf846a..c49403d 100644
--- a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
@@ -30,8 +30,8 @@
#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/MediaDefs.h>
-#include <ui/GraphicBuffer.h>
#include <ui/GraphicBufferMapper.h>
+#include <ui/Rect.h>
#include <OMX_IndexExt.h>
diff --git a/media/libstagefright/omx/hal/1.0/impl/WOmxObserver.cpp b/media/libstagefright/omx/hal/1.0/impl/WOmxObserver.cpp
index ecd1db5..433a8b8 100644
--- a/media/libstagefright/omx/hal/1.0/impl/WOmxObserver.cpp
+++ b/media/libstagefright/omx/hal/1.0/impl/WOmxObserver.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#define LOG_TAG "WOmxObserver-impl"
#include "WOmxObserver.h"
#include <vector>
@@ -43,7 +44,10 @@
wrapAs(&tMessages[i], &handles[i], message);
++i;
}
- mBase->onMessages(tMessages);
+ auto transResult = mBase->onMessages(tMessages);
+ if (!transResult.isOk()) {
+ ALOGE("LWOmxObserver::onMessages transaction failed");
+ }
for (auto& handle : handles) {
native_handle_close(handle);
native_handle_delete(handle);
diff --git a/media/libstagefright/omx/hal/1.0/utils/WOmxObserver.cpp b/media/libstagefright/omx/hal/1.0/utils/WOmxObserver.cpp
index db971f8..bab6a09 100644
--- a/media/libstagefright/omx/hal/1.0/utils/WOmxObserver.cpp
+++ b/media/libstagefright/omx/hal/1.0/utils/WOmxObserver.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#define LOG_TAG "WOmxObserver-utils"
#include "WOmxObserver.h"
#include <vector>
@@ -43,7 +44,10 @@
wrapAs(&tMessages[i], &handles[i], message);
++i;
}
- mBase->onMessages(tMessages);
+ auto transResult = mBase->onMessages(tMessages);
+ if (!transResult.isOk()) {
+ ALOGE("LWOmxObserver::onMessages transaction failed");
+ }
for (auto& handle : handles) {
native_handle_close(handle);
native_handle_delete(handle);
diff --git a/media/libstagefright/omx/tests/OMXHarness.h b/media/libstagefright/omx/tests/OMXHarness.h
index 022707f..94a37da 100644
--- a/media/libstagefright/omx/tests/OMXHarness.h
+++ b/media/libstagefright/omx/tests/OMXHarness.h
@@ -24,7 +24,7 @@
#include <utils/threads.h>
#include <binder/MemoryDealer.h>
-#include <android/hidl/memory/1.0/IAllocator.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMemory.h>
#include <OMX_Component.h>
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 3989f95..8bf1688 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -3041,12 +3041,12 @@
}
#if 0
// logFormat example
- if (!(z % 100)) {
+ if (z % 100 == 0) {
timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
- LOGF("This is an integer %d, this is a float %f, this is my "
+ LOGT("This is an integer %d, this is a float %f, this is my "
"pid %p %% %s %t", 42, 3.14, "and this is a timestamp", ts);
- LOGF("A deceptive null-terminated string %\0");
+ LOGT("A deceptive null-terminated string %\0");
}
++z;
#endif
diff --git a/services/audioflinger/TypedLogger.cpp b/services/audioflinger/TypedLogger.cpp
index b5b1bc5..e08f6f6 100644
--- a/services/audioflinger/TypedLogger.cpp
+++ b/services/audioflinger/TypedLogger.cpp
@@ -1,19 +1,19 @@
/*
-*
-* Copyright 2017, The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
+ *
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#define LOG_TAG "AudioFlinger"
//#define LOG_NDEBUG 0
@@ -22,4 +22,6 @@
#include <pthread.h>
#include "TypedLogger.h"
-thread_local android::NBLog::Writer *logWriterTLS;
+namespace android {
+thread_local NBLog::Writer *logWriterTLS;
+}
diff --git a/services/audioflinger/TypedLogger.h b/services/audioflinger/TypedLogger.h
index 2d71ab4..0b23c7c 100644
--- a/services/audioflinger/TypedLogger.h
+++ b/services/audioflinger/TypedLogger.h
@@ -1,29 +1,30 @@
/*
-*
-* Copyright 2017, The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
+ *
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-#ifndef TYPED_LOGGER_H
-#define TYPED_LOGGER_H
+#ifndef ANDROID_TYPED_LOGGER_H
+#define ANDROID_TYPED_LOGGER_H
#include <media/nbaio/NBLog.h>
+#define LOGT(fmt, ...) logWriterTLS->logFormat(fmt, ##__VA_ARGS__) // TODO: check null pointer
+namespace android {
extern "C" {
- extern thread_local android::NBLog::Writer *logWriterTLS;
+extern thread_local NBLog::Writer *logWriterTLS;
}
+} // namespace android
-#define LOGF(fmt, ...) logWriterTLS->logFormat(fmt, ##__VA_ARGS__)
-
-#endif
\ No newline at end of file
+#endif // ANDROID_TYPED_LOGGER_H
diff --git a/services/camera/libcameraservice/gui/RingBufferConsumer.h b/services/camera/libcameraservice/gui/RingBufferConsumer.h
index 28dc5d5..2bafe4a 100644
--- a/services/camera/libcameraservice/gui/RingBufferConsumer.h
+++ b/services/camera/libcameraservice/gui/RingBufferConsumer.h
@@ -19,18 +19,16 @@
#include <gui/BufferItem.h>
#include <gui/ConsumerBase.h>
+#include <gui/BufferQueue.h>
-#include <ui/GraphicBuffer.h>
-
-#include <utils/String8.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
#include <utils/List.h>
#define ANDROID_GRAPHICS_RINGBUFFERCONSUMER_JNI_ID "mRingBufferConsumer"
namespace android {
+class String8;
+
/**
* The RingBufferConsumer maintains a ring buffer of BufferItem objects,
* (which are 'acquired' as long as they are part of the ring buffer, and
diff --git a/services/mediacodec/Android.mk b/services/mediacodec/Android.mk
index cb14bb5..6dcc35c 100644
--- a/services/mediacodec/Android.mk
+++ b/services/mediacodec/Android.mk
@@ -6,6 +6,7 @@
LOCAL_SHARED_LIBRARIES := \
libmedia \
libbinder \
+ libgui \
libutils \
liblog \
libstagefright_omx
@@ -26,6 +27,7 @@
libmediacodecservice \
libbinder \
libutils \
+ libgui \
liblog \
libbase \
libavservices_minijail \
diff --git a/services/medialog/MediaLogService.cpp b/services/medialog/MediaLogService.cpp
index ab2f925..4c81436 100644
--- a/services/medialog/MediaLogService.cpp
+++ b/services/medialog/MediaLogService.cpp
@@ -26,7 +26,7 @@
namespace android {
-static const char kDeadlockedString[] = "MediaLogService may be deadlocked\n";
+// static const char kDeadlockedString[] = "MediaLogService may be deadlocked\n";
void MediaLogService::registerWriter(const sp<IMemory>& shared, size_t size, const char *name)
{
@@ -36,9 +36,10 @@
return;
}
sp<NBLog::Reader> reader(new NBLog::Reader(shared, size));
- NamedReader namedReader(reader, name);
+ NBLog::NamedReader namedReader(reader, name);
Mutex::Autolock _l(mLock);
mNamedReaders.add(namedReader);
+ mMerger.addReader(namedReader);
}
void MediaLogService::unregisterWriter(const sp<IMemory>& shared)
@@ -81,7 +82,8 @@
return NO_ERROR;
}
- Vector<NamedReader> namedReaders;
+#if 0
+ Vector<NBLog::NamedReader> namedReaders;
{
bool locked = dumpTryLock(mLock);
@@ -95,19 +97,23 @@
}
return NO_ERROR;
}
- namedReaders = mNamedReaders;
+ // namedReaders = mNamedReaders;
+ // for (size_t i = 0; i < namedReaders.size(); i++) {
+ // const NBLog::NamedReader& namedReader = namedReaders[i];
+ // if (fd >= 0) {
+ // dprintf(fd, "\n%s:\n", namedReader.name());
+ // } else {
+ // ALOGI("%s:", namedReader.name());
+ // }
+ // namedReader.reader()->dump(fd, 0 /*indent*/);
+ // }
+
mLock.unlock();
}
+#endif
- for (size_t i = 0; i < namedReaders.size(); i++) {
- const NamedReader& namedReader = namedReaders[i];
- if (fd >= 0) {
- dprintf(fd, "\n%s:\n", namedReader.name());
- } else {
- ALOGI("%s:", namedReader.name());
- }
- namedReader.reader()->dump(fd, 0 /*indent*/);
- }
+ mMerger.merge();
+ mMergeReader.dump(fd);
return NO_ERROR;
}
diff --git a/services/medialog/MediaLogService.h b/services/medialog/MediaLogService.h
index c9bf2eb..e934844 100644
--- a/services/medialog/MediaLogService.h
+++ b/services/medialog/MediaLogService.h
@@ -27,8 +27,13 @@
{
friend class BinderService<MediaLogService>; // for MediaLogService()
public:
- MediaLogService() : BnMediaLogService() { }
- virtual ~MediaLogService() { }
+ MediaLogService() :
+ BnMediaLogService(),
+ mMergerShared((NBLog::Shared*) malloc(NBLog::Timeline::sharedSize(kMergeBufferSize))),
+ mMerger(mMergerShared, kMergeBufferSize),
+ mMergeReader(mMergerShared, kMergeBufferSize, mMerger)
+ {ALOGI("Nico creating MergeReader");}
+ virtual ~MediaLogService() { free(mMergerShared); }
virtual void onFirstRef() { }
static const char* getServiceName() { return "media.log"; }
@@ -47,23 +52,16 @@
// Internal dump
static const int kDumpLockRetries = 50;
static const int kDumpLockSleepUs = 20000;
+ static const size_t kMergeBufferSize = 16 * 1024; // TODO determine good value for this
static bool dumpTryLock(Mutex& mutex);
Mutex mLock;
- class NamedReader {
- public:
- NamedReader() : mReader(0) { mName[0] = '\0'; } // for Vector
- NamedReader(const sp<NBLog::Reader>& reader, const char *name) : mReader(reader)
- { strlcpy(mName, name, sizeof(mName)); }
- ~NamedReader() { }
- const sp<NBLog::Reader>& reader() const { return mReader; }
- const char* name() const { return mName; }
- private:
- sp<NBLog::Reader> mReader;
- static const size_t kMaxName = 32;
- char mName[kMaxName];
- };
- Vector<NamedReader> mNamedReaders;
+
+ Vector<NBLog::NamedReader> mNamedReaders;
+
+ NBLog::Shared *mMergerShared;
+ NBLog::Merger mMerger;
+ NBLog::MergeReader mMergeReader;
};
} // namespace android
diff --git a/services/minijail/minijail.cpp b/services/minijail/minijail.cpp
index 7b61ae8..f213287 100644
--- a/services/minijail/minijail.cpp
+++ b/services/minijail/minijail.cpp
@@ -53,20 +53,19 @@
return pipefd[0];
}
-int SetUpMinijail(const std::string& base_policy_path, const std::string& additional_policy_path)
+void SetUpMinijail(const std::string& base_policy_path, const std::string& additional_policy_path)
{
// No seccomp policy defined for this architecture.
if (access(base_policy_path.c_str(), R_OK) == -1) {
LOG(WARNING) << "No seccomp policy defined for this architecture.";
- return 0;
+ return;
}
std::string base_policy_content;
std::string additional_policy_content;
if (!base::ReadFileToString(base_policy_path, &base_policy_content,
false /* follow_symlinks */)) {
- LOG(ERROR) << "Could not read base policy file '" << base_policy_path << "'";
- return -1;
+ LOG(FATAL) << "Could not read base policy file '" << base_policy_path << "'";
}
if (additional_policy_path.length() > 0 &&
@@ -78,14 +77,12 @@
base::unique_fd policy_fd(WritePolicyToPipe(base_policy_content, additional_policy_content));
if (policy_fd.get() == -1) {
- LOG(ERROR) << "Could not write seccomp policy to fd";
- return -1;
+ LOG(FATAL) << "Could not write seccomp policy to fd";
}
ScopedMinijail jail{minijail_new()};
if (!jail) {
- LOG(ERROR) << "Failed to create minijail.";
- return -1;
+ LOG(FATAL) << "Failed to create minijail.";
}
minijail_no_new_privs(jail.get());
@@ -94,6 +91,5 @@
// Transfer ownership of |policy_fd|.
minijail_parse_seccomp_filters_from_fd(jail.get(), policy_fd.release());
minijail_enter(jail.get());
- return 0;
}
}
diff --git a/services/minijail/minijail.h b/services/minijail/minijail.h
index 3d6db37..c8a2149 100644
--- a/services/minijail/minijail.h
+++ b/services/minijail/minijail.h
@@ -20,8 +20,7 @@
namespace android {
int WritePolicyToPipe(const std::string& base_policy_content,
const std::string& additional_policy_content);
-int SetUpMinijail(const std::string& base_policy_path,
- const std::string& additional_policy_path);
+void SetUpMinijail(const std::string& base_policy_path, const std::string& additional_policy_path);
}
#endif // AV_SERVICES_MINIJAIL_MINIJAIL