Merge "audiopolicy: More XML deserializer refactorings"
diff --git a/camera/ndk/impl/ACameraMetadata.cpp b/camera/ndk/impl/ACameraMetadata.cpp
index d73f744..94b5713 100644
--- a/camera/ndk/impl/ACameraMetadata.cpp
+++ b/camera/ndk/impl/ACameraMetadata.cpp
@@ -430,6 +430,7 @@
ANDROID_STATISTICS_INFO_MAX_HISTOGRAM_COUNT,
ANDROID_STATISTICS_INFO_MAX_SHARPNESS_MAP_VALUE,
ANDROID_STATISTICS_INFO_SHARPNESS_MAP_SIZE,
+ ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION,
ANDROID_DEPTH_MAX_DEPTH_SAMPLES,
});
diff --git a/include/media/MediaExtractorPluginHelper.h b/include/media/MediaExtractorPluginHelper.h
index c817b30..a659660 100644
--- a/include/media/MediaExtractorPluginHelper.h
+++ b/include/media/MediaExtractorPluginHelper.h
@@ -129,11 +129,13 @@
mSource = source->mSource;
}
- ssize_t readAt(off64_t offset, void *data, size_t size) {
+ virtual ~DataSourceHelper() {}
+
+ virtual ssize_t readAt(off64_t offset, void *data, size_t size) {
return mSource->readAt(mSource->handle, offset, data, size);
}
- status_t getSize(off64_t *size) {
+ virtual status_t getSize(off64_t *size) {
return mSource->getSize(mSource->handle, size);
}
@@ -141,7 +143,7 @@
return mSource->getUri(mSource->handle, uriString, bufferSize);
}
- uint32_t flags() {
+ virtual uint32_t flags() {
return mSource->flags(mSource->handle);
}
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index f52d451..9d2f5d2 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -198,13 +198,14 @@
// possibly wrapping multiple times to cover all tracks, i.e.
// Each CachedRangedDataSource caches the sampletable metadata for a single track.
-struct CachedRangedDataSource : public DataSourceHelper {
+class CachedRangedDataSource : public DataSourceHelper {
+public:
explicit CachedRangedDataSource(DataSourceHelper *source);
virtual ~CachedRangedDataSource();
- virtual ssize_t readAt(off64_t offset, void *data, size_t size);
- virtual status_t getSize(off64_t *size);
- virtual uint32_t flags();
+ ssize_t readAt(off64_t offset, void *data, size_t size) override;
+ status_t getSize(off64_t *size) override;
+ uint32_t flags() override;
status_t setCachedRange(off64_t offset, size_t size, bool assumeSourceOwnershipOnSuccess);
@@ -236,7 +237,7 @@
CachedRangedDataSource::~CachedRangedDataSource() {
clearCache();
if (mOwnsDataSource) {
- delete (CachedRangedDataSource*)mSource;
+ delete mSource;
}
}
@@ -366,7 +367,6 @@
mMoofFound(false),
mMdatFound(false),
mDataSource(source),
- mCachedSource(NULL),
mInitCheck(NO_INIT),
mHeaderTimescale(0),
mIsQT(false),
@@ -393,9 +393,6 @@
}
mPssh.clear();
- if (mCachedSource != mDataSource) {
- delete mCachedSource;
- }
delete mDataSource;
}
@@ -909,8 +906,8 @@
if (cachedSource->setCachedRange(
*offset, chunk_size,
- mCachedSource != NULL /* assume ownership on success */) == OK) {
- mDataSource = mCachedSource = cachedSource;
+ true /* assume ownership on success */) == OK) {
+ mDataSource = cachedSource;
} else {
delete cachedSource;
}
diff --git a/media/extractors/mp4/MPEG4Extractor.h b/media/extractors/mp4/MPEG4Extractor.h
index ca273e0..b1e04c7 100644
--- a/media/extractors/mp4/MPEG4Extractor.h
+++ b/media/extractors/mp4/MPEG4Extractor.h
@@ -33,7 +33,6 @@
struct AMessage;
struct CDataSource;
class DataSourceHelper;
-struct CachedRangedDataSource;
class SampleTable;
class String8;
namespace heif {
@@ -99,7 +98,6 @@
Vector<Trex> mTrex;
DataSourceHelper *mDataSource;
- CachedRangedDataSource *mCachedSource;
status_t mInitCheck;
uint32_t mHeaderTimescale;
bool mIsQT;
diff --git a/media/libheif/include/HeifDecoderAPI.h b/media/libheif/include/HeifDecoderAPI.h
index 5183c39..aa10f33 100644
--- a/media/libheif/include/HeifDecoderAPI.h
+++ b/media/libheif/include/HeifDecoderAPI.h
@@ -74,7 +74,7 @@
int32_t mRotationAngle; // Rotation angle, clockwise, should be multiple of 90
uint32_t mBytesPerPixel; // Number of bytes for one pixel
uint32_t mIccSize; // Number of bytes in mIccData
- std::unique_ptr<uint8_t> mIccData; // Actual ICC data, memory is owned by this structure
+ std::unique_ptr<uint8_t[]> mIccData; // Actual ICC data, memory is owned by this structure
};
/*
diff --git a/media/libmediaextractor/include/media/DataSourceBase.h b/media/libmediaextractor/include/media/DataSourceBase.h
index 51993da..fc620fd 100644
--- a/media/libmediaextractor/include/media/DataSourceBase.h
+++ b/media/libmediaextractor/include/media/DataSourceBase.h
@@ -66,6 +66,12 @@
virtual void close() {};
+ virtual void disconnect() {}
+
+ virtual ssize_t getAvailableSize(status_t * /*err*/) {
+ return -1;
+ }
+
protected:
virtual ~DataSourceBase() {}
diff --git a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Types.h b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Types.h
index 1fe2efa..10e07ea 100644
--- a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Types.h
+++ b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Types.h
@@ -154,8 +154,8 @@
enum mediaplayer2_states {
MEDIAPLAYER2_STATE_IDLE = 1001,
MEDIAPLAYER2_STATE_PREPARED = 1002,
- MEDIAPLAYER2_STATE_PLAYING = 1003,
- MEDIAPLAYER2_STATE_PAUSED = 1004,
+ MEDIAPLAYER2_STATE_PAUSED = 1003,
+ MEDIAPLAYER2_STATE_PLAYING = 1004,
MEDIAPLAYER2_STATE_ERROR = 1005,
};
diff --git a/media/libmediaplayer2/mediaplayer2.cpp b/media/libmediaplayer2/mediaplayer2.cpp
index bafd32c..d9c9826 100644
--- a/media/libmediaplayer2/mediaplayer2.cpp
+++ b/media/libmediaplayer2/mediaplayer2.cpp
@@ -660,7 +660,7 @@
Mutex::Autolock _l(mLock);
if (mCurrentState & (MEDIA_PLAYER2_PAUSED|MEDIA_PLAYER2_PLAYBACK_COMPLETE))
return NO_ERROR;
- if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER2_STARTED)) {
+ if ((mPlayer != 0) && (mCurrentState & (MEDIA_PLAYER2_STARTED | MEDIA_PLAYER2_PREPARED))) {
status_t ret = mPlayer->pause();
if (ret != NO_ERROR) {
mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
index e51727b..5bd1674 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
@@ -969,7 +969,7 @@
onResume();
}
} else {
- onStart();
+ onStart(true /* play */);
}
mPausedByClient = false;
notifyListener(mSrcId, MEDIA2_STARTED, 0, 0);
@@ -1502,6 +1502,9 @@
case kWhatPause:
{
+ if (!mStarted) {
+ onStart(false /* play */);
+ }
onPause();
notifyListener(mSrcId, MEDIA2_PAUSED, 0, 0);
mPausedByClient = true;
@@ -1575,7 +1578,7 @@
startPlaybackTimer("onresume");
}
-void NuPlayer2::onStart() {
+void NuPlayer2::onStart(bool play) {
ALOGV("onStart: mCrypto: %p", mCrypto.get());
if (!mSourceStarted) {
@@ -1649,6 +1652,11 @@
mRenderer->setVideoFrameRate(rate);
}
+ // Renderer is created in paused state.
+ if (play) {
+ mRenderer->resume();
+ }
+
if (mVideoDecoder != NULL) {
mVideoDecoder->setRenderer(mRenderer);
}
@@ -2472,7 +2480,7 @@
mRenderer->resume();
}
- onStart();
+ onStart(true /* play */);
mPausedByClient = false;
notifyListener(mSrcId, MEDIA2_STARTED, 0, 0);
}
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2.h b/media/libmediaplayer2/nuplayer2/NuPlayer2.h
index 77845ac..e55cdbe 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2.h
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2.h
@@ -301,7 +301,7 @@
void handleFlushComplete(bool audio, bool isDecoder);
void finishFlushIfPossible();
- void onStart();
+ void onStart(bool play);
void onResume();
void onPause();
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
index b02e3f6..cb4b06d 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
@@ -327,9 +327,9 @@
switch (mState) {
case STATE_PAUSED:
- case STATE_PREPARED:
return OK;
+ case STATE_PREPARED:
case STATE_RUNNING:
mState = STATE_PAUSED;
mPlayer->pause();
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
index 021ddde..c5ce15a 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
@@ -115,7 +115,7 @@
mNotifyCompleteAudio(false),
mNotifyCompleteVideo(false),
mSyncQueues(false),
- mPaused(false),
+ mPaused(true),
mPauseDrainAudioAllowedUs(0),
mVideoSampleReceived(false),
mVideoRenderingStarted(false),
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index c0e65e8..c62c05a 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -501,10 +501,15 @@
return ERROR_MALFORMED;
}
- int32_t width, height, stride;
- CHECK(outputFormat->findInt32("width", &width));
- CHECK(outputFormat->findInt32("height", &height));
- CHECK(outputFormat->findInt32("stride", &stride));
+ int32_t width, height, stride, srcFormat;
+ if (!outputFormat->findInt32("width", &width) ||
+ !outputFormat->findInt32("height", &height) ||
+ !outputFormat->findInt32("stride", &stride) ||
+ !outputFormat->findInt32("color-format", &srcFormat)) {
+ ALOGE("format missing dimension or color: %s",
+ outputFormat->debugString().c_str());
+ return ERROR_MALFORMED;
+ }
int32_t crop_left, crop_top, crop_right, crop_bottom;
if (!outputFormat->findRect("crop", &crop_left, &crop_top, &crop_right, &crop_bottom)) {
@@ -523,9 +528,6 @@
addFrame(frameMem);
VideoFrame* frame = static_cast<VideoFrame*>(frameMem->pointer());
- int32_t srcFormat;
- CHECK(outputFormat->findInt32("color-format", &srcFormat));
-
ColorConverter converter((OMX_COLOR_FORMATTYPE)srcFormat, dstFormat());
uint32_t standard, range, transfer;
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index a0a3a75..f1c6acd 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -271,6 +271,9 @@
if (libDir) {
struct dirent* libEntry;
while ((libEntry = readdir(libDir))) {
+ if (libEntry->d_name[0] == '.') {
+ continue;
+ }
String8 libPath = String8(libDirPath) + "/" + libEntry->d_name;
void *libHandle = dlopen(libPath.string(), RTLD_NOW | RTLD_LOCAL);
if (libHandle) {
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 8e8c77c..e42d8d0 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -21,7 +21,6 @@
#include <media/stagefright/NuMediaExtractor.h>
#include "include/ESDS.h"
-#include "include/NuCachedSource2.h"
#include <media/DataSource.h>
#include <media/MediaSource.h>
@@ -207,10 +206,7 @@
void NuMediaExtractor::disconnect() {
if (mDataSource != NULL) {
- // disconnect data source
- if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
- static_cast<NuCachedSource2 *>(mDataSource.get())->disconnect();
- }
+ mDataSource->disconnect();
}
}
@@ -790,16 +786,13 @@
int64_t *durationUs, bool *eos) const {
Mutex::Autolock autoLock(mLock);
+ status_t finalStatus;
+ ssize_t cachedDataRemaining =
+ mDataSource->getAvailableSize(&finalStatus);
+
int64_t bitrate;
- if ((mDataSource->flags() & DataSource::kIsCachingDataSource)
+ if (cachedDataRemaining >= 0
&& getTotalBitrate(&bitrate)) {
- sp<NuCachedSource2> cachedSource =
- static_cast<NuCachedSource2 *>(mDataSource.get());
-
- status_t finalStatus;
- size_t cachedDataRemaining =
- cachedSource->approxDataRemaining(&finalStatus);
-
*durationUs = cachedDataRemaining * 8000000ll / bitrate;
*eos = (finalStatus != OK);
return true;
diff --git a/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp b/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
index 06b15b3..f352fba 100644
--- a/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
+++ b/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
@@ -79,7 +79,7 @@
static const OMX_U32 kSupportedProfiles[] = {
OMX_AUDIO_AACObjectLC, OMX_AUDIO_AACObjectHE, OMX_AUDIO_AACObjectHE_PS,
- OMX_AUDIO_AACObjectLD, OMX_AUDIO_AACObjectELD,
+ OMX_AUDIO_AACObjectLD, OMX_AUDIO_AACObjectELD, OMX_AUDIO_AACObjectXHE
};
SoftXAAC::SoftXAAC(const char* name, const OMX_CALLBACKTYPE* callbacks, OMX_PTR appData,
diff --git a/media/libstagefright/foundation/AString.cpp b/media/libstagefright/foundation/AString.cpp
index c6ef75f..a8adff5 100644
--- a/media/libstagefright/foundation/AString.cpp
+++ b/media/libstagefright/foundation/AString.cpp
@@ -125,12 +125,10 @@
}
void AString::clear() {
- if (mData && mData != kEmptyString) {
+ if (mData != kEmptyString) {
free(mData);
- mData = NULL;
+ mData = (char *)kEmptyString;
}
-
- mData = (char *)kEmptyString;
mSize = 0;
mAllocSize = 1;
}
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/ADebug.h b/media/libstagefright/foundation/include/media/stagefright/foundation/ADebug.h
index bac8fa9..a8b88fd 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/ADebug.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/ADebug.h
@@ -63,38 +63,21 @@
__FILE__ ":" LITERAL_TO_STRING(__LINE__) \
" CHECK(" #condition ") failed.")
-#define MAKE_COMPARATOR(suffix,op) \
- template<class A, class B> \
- AString Compare_##suffix(const A &a, const B &b) { \
- AString res; \
- if (!(a op b)) { \
- res.append(a); \
- res.append(" vs. "); \
- res.append(b); \
- } \
- return res; \
- }
-
-MAKE_COMPARATOR(EQ,==)
-MAKE_COMPARATOR(NE,!=)
-MAKE_COMPARATOR(LE,<=)
-MAKE_COMPARATOR(GE,>=)
-MAKE_COMPARATOR(LT,<)
-MAKE_COMPARATOR(GT,>)
-
#ifdef CHECK_OP
#undef CHECK_OP
#endif
#define CHECK_OP(x,y,suffix,op) \
do { \
- AString ___res = Compare_##suffix(x, y); \
- if (!___res.empty()) { \
+ const auto &a = x; \
+ const auto &b = y; \
+ if (!(a op b)) { \
AString ___full = \
__FILE__ ":" LITERAL_TO_STRING(__LINE__) \
" CHECK_" #suffix "( " #x "," #y ") failed: "; \
- ___full.append(___res); \
- \
+ ___full.append(a); \
+ ___full.append(" vs. "); \
+ ___full.append(b); \
LOG_ALWAYS_FATAL("%s", ___full.c_str()); \
} \
} while (false)
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 7eff8eb..86872c5 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -445,7 +445,7 @@
return -EAGAIN;
};
(*accessUnit)->meta()->setInt32(
- "trackIndex", mPlaylist->getSelectedIndex());
+ "track-index", mPlaylist->getSelectedIndex());
(*accessUnit)->meta()->setInt64("baseUs", mRealTimeBaseUs);
} else if (stream == STREAMTYPE_METADATA) {
HLSTime mdTime((*accessUnit)->meta());
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index f439a1c..f4aab25 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -51,6 +51,10 @@
return mName;
}
+ ssize_t getAvailableSize(status_t *finalStatus) {
+ return approxDataRemaining(finalStatus);
+ }
+
////////////////////////////////////////////////////////////////////////////
size_t cachedSize();
diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp
index f25fc71..ad3c068 100644
--- a/media/mtp/MtpFfsHandle.cpp
+++ b/media/mtp/MtpFfsHandle.cpp
@@ -212,7 +212,6 @@
uint16_t value = setup->wValue;
std::vector<char> buf;
buf.resize(length);
- int ret = 0;
if (!(type & USB_DIR_IN)) {
if (::read(mControl, buf.data(), length) != length) {
@@ -225,8 +224,8 @@
case MTP_REQ_RESET:
case MTP_REQ_CANCEL:
errno = ECANCELED;
- ret = -1;
- break;
+ return -1;
+ // break;
case MTP_REQ_GET_DEVICE_STATUS:
{
if (length < sizeof(struct mtp_device_status) + 4) {
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 2f298cf..417f1df 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -83,6 +83,7 @@
"libgui",
"libui",
"libmedia2_jni_core",
+ "libmediandk_utils",
],
export_include_dirs: ["include"],
@@ -99,3 +100,44 @@
symbol_file: "libmediandk.map.txt",
export_include_dirs: ["include"],
}
+
+cc_library {
+ name: "libmediandk_utils",
+
+ srcs: [
+ "NdkMediaDataSourceCallbacks.cpp",
+ ],
+
+ include_dirs: [
+ "frameworks/av/media/libstagefright/include",
+ "frameworks/av/media/ndk/include",
+ ],
+
+ export_include_dirs: [
+ "include",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wno-error=deprecated-declarations",
+ "-Wall",
+ ],
+
+ shared_libs: [
+ "libstagefright_foundation",
+ "liblog",
+ "libutils",
+ "libcutils",
+ ],
+
+ sanitize: {
+ misc_undefined: [
+ "unsigned-integer-overflow",
+ "signed-integer-overflow",
+ ],
+ cfi: true,
+ diag: {
+ cfi: true,
+ },
+ },
+}
diff --git a/media/ndk/NdkMediaDataSource.cpp b/media/ndk/NdkMediaDataSource.cpp
index ec2aed6..9ea734b 100644
--- a/media/ndk/NdkMediaDataSource.cpp
+++ b/media/ndk/NdkMediaDataSource.cpp
@@ -32,12 +32,14 @@
#include <media/IMediaHTTPService.h>
#include <media/NdkMediaError.h>
#include <media/NdkMediaDataSource.h>
+#include <media/stagefright/DataSourceFactory.h>
#include <media/stagefright/InterfaceUtils.h>
#include <mediaplayer2/JavaVMHelper.h>
#include <mediaplayer2/JMedia2HTTPService.h>
#include "../../libstagefright/include/HTTPBase.h"
#include "../../libstagefright/include/NuCachedSource2.h"
+#include "NdkMediaDataSourceCallbacksPriv.h"
using namespace android;
@@ -188,6 +190,24 @@
}
EXPORT
+AMediaDataSource* AMediaDataSource_newUri(
+ const char *uri,
+ int numheaders,
+ const char * const *key_values) {
+
+ sp<MediaHTTPService> service = createMediaHttpService(uri, /* version = */ 1);
+ KeyedVector<String8, String8> headers;
+ for (int i = 0; i < numheaders; ++i) {
+ String8 key8(key_values[i * 2]);
+ String8 value8(key_values[i * 2 + 1]);
+ headers.add(key8, value8);
+ }
+
+ sp<DataSource> source = DataSourceFactory::CreateFromURI(service, uri, &headers);
+ return convertDataSourceToAMediaDataSource(source);
+}
+
+EXPORT
void AMediaDataSource_delete(AMediaDataSource *mSource) {
ALOGV("dtor");
if (mSource != NULL) {
diff --git a/media/ndk/NdkMediaDataSourceCallbacks.cpp b/media/ndk/NdkMediaDataSourceCallbacks.cpp
new file mode 100644
index 0000000..4338048
--- /dev/null
+++ b/media/ndk/NdkMediaDataSourceCallbacks.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2018, 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_NDEBUG 0
+#define LOG_TAG "NdkMediaDataSourceCallbacks"
+
+#include "NdkMediaDataSourceCallbacksPriv.h"
+#include <media/DataSource.h>
+
+namespace android {
+
+ssize_t DataSource_getSize(void *userdata) {
+ DataSource *source = static_cast<DataSource *>(userdata);
+ off64_t size = -1;
+ source->getSize(&size);
+ return size;
+}
+
+ssize_t DataSource_readAt(void *userdata, off64_t offset, void * buf, size_t size) {
+ DataSource *source = static_cast<DataSource *>(userdata);
+ return source->readAt(offset, buf, size);
+}
+
+void DataSource_close(void *userdata) {
+ DataSource *source = static_cast<DataSource *>(userdata);
+ source->close();
+}
+
+} // namespace android
diff --git a/media/ndk/NdkMediaDataSourceCallbacksPriv.h b/media/ndk/NdkMediaDataSourceCallbacksPriv.h
new file mode 100644
index 0000000..65fb0aa
--- /dev/null
+++ b/media/ndk/NdkMediaDataSourceCallbacksPriv.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2018, 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 A_MEDIA_DATA_SOURCE_CALLBACKS_H
+
+#define A_MEDIA_DATA_SOURCE_CALLBACKS_H
+
+#include <media/DataSource.h>
+#include <media/NdkMediaDataSource.h>
+#include <media/NdkMediaError.h>
+#include <sys/types.h>
+
+namespace android {
+
+ssize_t DataSource_getSize(void *userdata);
+
+ssize_t DataSource_readAt(void *userdata, off64_t offset, void * buf, size_t size);
+
+void DataSource_close(void *userdata);
+
+static inline AMediaDataSource* convertDataSourceToAMediaDataSource(const sp<DataSource> &source) {
+ if (source == NULL) {
+ return NULL;
+ }
+ AMediaDataSource *mSource = AMediaDataSource_new();
+ AMediaDataSource_setUserdata(mSource, source.get());
+ AMediaDataSource_setReadAt(mSource, DataSource_readAt);
+ AMediaDataSource_setGetSize(mSource, DataSource_getSize);
+ AMediaDataSource_setClose(mSource, DataSource_close);
+ return mSource;
+}
+
+} // namespace android
+
+#endif // A_MEDIA_DATA_SOURCE_CALLBACKS_H
diff --git a/media/ndk/include/media/NdkMediaDataSource.h b/media/ndk/include/media/NdkMediaDataSource.h
index ea5ba0c..021029b 100644
--- a/media/ndk/include/media/NdkMediaDataSource.h
+++ b/media/ndk/include/media/NdkMediaDataSource.h
@@ -86,6 +86,30 @@
*/
AMediaDataSource* AMediaDataSource_new() __INTRODUCED_IN(28);
+#if __ANDROID_API__ >= 29
+
+/**
+ * Create new media data source. Returns NULL if memory allocation
+ * for the new data source object fails.
+ *
+ * Set the |uri| from which the data source will read,
+ * plus additional http headers when initiating the request.
+ *
+ * Headers will contain corresponding items from |key_values|
+ * in the following fashion:
+ *
+ * key_values[0]:key_values[1]
+ * key_values[2]:key_values[3]
+ * ...
+ * key_values[(numheaders - 1) * 2]:key_values[(numheaders - 1) * 2 + 1]
+ *
+ */
+AMediaDataSource* AMediaDataSource_newUri(const char *uri,
+ int numheaders,
+ const char * const *key_values) __INTRODUCED_IN(29);
+
+#endif /*__ANDROID_API__ >= 29 */
+
/**
* Delete a previously created media data source.
*/
diff --git a/media/ndk/libmediandk.map.txt b/media/ndk/libmediandk.map.txt
index 1fd69a2..a805e87 100644
--- a/media/ndk/libmediandk.map.txt
+++ b/media/ndk/libmediandk.map.txt
@@ -141,6 +141,7 @@
AMediaDataSource_setGetSize; # introduced=28
AMediaDataSource_setReadAt; # introduced=28
AMediaDataSource_setUserdata; # introduced=28
+ AMediaDataSource_newUri; # introduced=29
AMediaDrm_closeSession;
AMediaDrm_createByUUID;
AMediaDrm_decrypt;
diff --git a/packages/MediaComponents/Android.mk b/packages/MediaComponents/Android.mk
index 55a5424..fff3a62 100644
--- a/packages/MediaComponents/Android.mk
+++ b/packages/MediaComponents/Android.mk
@@ -14,59 +14,57 @@
# limitations under the License.
#
-# This package is excluded from build for now since APIs using this apk became hidden.
-#
-#LOCAL_PATH := $(call my-dir)
-#ifneq ($(TARGET_BUILD_PDK),true) # Build MediaComponents only if this is not a PDK build. MediaComponents won't
-## build in PDK builds because frameworks/base/core/java is not available but
-## IMediaSession2.aidl and IMediaController2.aidl are using classes from
-## frameworks/base/core/java.
-#
-#include $(CLEAR_VARS)
-#
-#LOCAL_PACKAGE_NAME := MediaComponents
-#LOCAL_MODULE_OWNER := google
-#
-## TODO: create a separate key for this package.
-#LOCAL_CERTIFICATE := platform
-#
-## TODO: Use System SDK once public APIs are approved
-## LOCAL_SDK_VERSION := system_current
-#LOCAL_PRIVATE_PLATFORM_APIS := true
-#
-#LOCAL_SRC_FILES := \
-# $(call all-java-files-under, src) \
-# $(call all-Iaidl-files-under, src)
-#
-#LOCAL_PROGUARD_FLAG_FILES := proguard.cfg
-#
-#LOCAL_MULTILIB := first
-#
-#LOCAL_JAVA_LIBRARIES += androidx.annotation_annotation
-#
-## To embed native libraries in package, uncomment the lines below.
-##LOCAL_MODULE_TAGS := samples
-##LOCAL_JNI_SHARED_LIBRARIES := \
-## libaacextractor \
-## libamrextractor \
-## libflacextractor \
-## libmidiextractor \
-## libmkvextractor \
-## libmp3extractor \
-## libmp4extractor \
-## libmpeg2extractor \
-## liboggextractor \
-## libwavextractor \
-#
-## TODO: Remove dependency with other support libraries.
-#LOCAL_STATIC_ANDROID_LIBRARIES += \
-# androidx.legacy_legacy-support-v4 \
-# androidx.appcompat_appcompat \
-# androidx.palette_palette
-#LOCAL_USE_AAPT2 := true
-#
-#include $(BUILD_PACKAGE)
-#
-#endif # ifneq ($(TARGET_BUILD_PDK),true)
-#
-#include $(call all-makefiles-under,$(LOCAL_PATH))
+LOCAL_PATH := $(call my-dir)
+ifneq ($(TARGET_BUILD_PDK),true) # Build MediaComponents only if this is not a PDK build. MediaComponents won't
+# build in PDK builds because frameworks/base/core/java is not available but
+# IMediaSession2.aidl and IMediaController2.aidl are using classes from
+# frameworks/base/core/java.
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := MediaComponents
+LOCAL_MODULE_OWNER := google
+
+# TODO: create a separate key for this package.
+LOCAL_CERTIFICATE := platform
+
+# TODO: Use System SDK once public APIs are approved
+# LOCAL_SDK_VERSION := system_current
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
+LOCAL_SRC_FILES := \
+ $(call all-java-files-under, src) \
+ $(call all-Iaidl-files-under, src)
+
+LOCAL_PROGUARD_FLAG_FILES := proguard.cfg
+
+LOCAL_MULTILIB := first
+
+LOCAL_JAVA_LIBRARIES += androidx.annotation_annotation
+
+# To embed native libraries in package, uncomment the lines below.
+#LOCAL_MODULE_TAGS := samples
+#LOCAL_JNI_SHARED_LIBRARIES := \
+# libaacextractor \
+# libamrextractor \
+# libflacextractor \
+# libmidiextractor \
+# libmkvextractor \
+# libmp3extractor \
+# libmp4extractor \
+# libmpeg2extractor \
+# liboggextractor \
+# libwavextractor \
+
+# TODO: Remove dependency with other support libraries.
+LOCAL_STATIC_ANDROID_LIBRARIES += \
+ androidx.legacy_legacy-support-v4 \
+ androidx.appcompat_appcompat \
+ androidx.palette_palette
+LOCAL_USE_AAPT2 := true
+
+include $(BUILD_PACKAGE)
+
+endif # ifneq ($(TARGET_BUILD_PDK),true)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java b/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
index ffb145a..54ef719 100644
--- a/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
+++ b/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
@@ -33,8 +33,7 @@
import android.media.MediaMetadata2;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer2;
-import android.media.MediaPlayer2.MediaPlayer2EventCallback;
-import android.media.MediaPlayer2.OnSubtitleDataListener;
+import android.media.MediaPlayer2.EventCallback;
import android.media.MediaPlayer2Impl;
import android.media.Metadata;
import android.media.PlaybackParams;
@@ -733,12 +732,11 @@
runnable.run();
}
};
- mMediaPlayer.setMediaPlayer2EventCallback(executor, mMediaPlayer2Callback);
+ mMediaPlayer.registerEventCallback(executor, mMediaPlayer2Callback);
mCurrentBufferPercentage = -1;
mMediaPlayer.setDataSource(dsd);
mMediaPlayer.setAudioAttributes(mAudioAttributes);
- mMediaPlayer.setOnSubtitleDataListener(mSubtitleListener);
// we don't set the target state here either, but preserve the
// target state that was there before.
mCurrentState = STATE_PREPARING;
@@ -1106,10 +1104,10 @@
mInstance.addView(mMusicView, 0);
}
- OnSubtitleDataListener mSubtitleListener =
- new OnSubtitleDataListener() {
+ EventCallback mMediaPlayer2Callback =
+ new EventCallback() {
@Override
- public void onSubtitleData(MediaPlayer2 mp, SubtitleData data) {
+ public void onSubtitleData(MediaPlayer2 mp, DataSourceDesc dsd, SubtitleData data) {
if (DEBUG) {
Log.d(TAG, "onSubtitleData(): getTrackIndex: " + data.getTrackIndex()
+ ", getCurrentPosition: " + mp.getCurrentPosition()
@@ -1133,10 +1131,7 @@
}
}
}
- };
- MediaPlayer2EventCallback mMediaPlayer2Callback =
- new MediaPlayer2EventCallback() {
@Override
public void onVideoSizeChanged(
MediaPlayer2 mp, DataSourceDesc dsd, int width, int height) {
@@ -1169,7 +1164,7 @@
extractTracks();
} else if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
this.onPrepared(mp, dsd);
- } else if (what == MediaPlayer2.MEDIA_INFO_PLAYBACK_COMPLETE) {
+ } else if (what == MediaPlayer2.MEDIA_INFO_DATA_SOURCE_END) {
this.onCompletion(mp, dsd);
} else if (what == MediaPlayer2.MEDIA_INFO_BUFFERING_UPDATE) {
this.onBufferingUpdate(mp, dsd, extra);
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 06975ac..62fd5f7 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2500,7 +2500,9 @@
if (recordThread != 0) {
ALOGV("closeInput() %d", input);
+#if 0
dumpToThreadLog_l(recordThread);
+#endif
// If we still have effect chains, it means that a client still holds a handle
// on at least one effect. We must either move the chain to an existing thread with the
@@ -2544,7 +2546,9 @@
if (mmapThread == 0) {
return BAD_VALUE;
}
+#if 0
dumpToThreadLog_l(mmapThread);
+#endif
mMmapThreads.removeItem(input);
}
const sp<AudioIoDescriptor> ioDesc = new AudioIoDescriptor();
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index d7a4451..13ca912 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -6963,7 +6963,7 @@
framesIn, mSampleRate, activeTrack->mSampleRate));
if (activeTrack->isDirect()) {
- // No RecordBufferConverter used for compressed formats. Pass
+ // No RecordBufferConverter used for direct streams. Pass
// straight from RecordThread buffer to RecordTrack buffer.
AudioBufferProvider::Buffer buffer;
buffer.frameCount = framesOut;
@@ -6973,7 +6973,7 @@
"%s() read less than expected (%zu vs %zu)",
__func__, buffer.frameCount, framesOut);
framesOut = buffer.frameCount;
- memcpy(activeTrack->mSink.raw, buffer.raw, buffer.frameCount);
+ memcpy(activeTrack->mSink.raw, buffer.raw, buffer.frameCount * mFrameSize);
activeTrack->mResamplerBufferProvider->releaseBuffer(&buffer);
} else {
framesOut = 0;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 600f968..380f0fb 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2697,7 +2697,7 @@
mAudioSources.dump(fd);
if (!mSurroundFormats.empty()) {
- result = String8("\nManually Enabled Surround Formats:\n");
+ result = String8("\nEnabled Surround Formats:\n");
size_t i = 0;
for (const auto& fmt : mSurroundFormats) {
result.append(i++ == 0 ? " " : ", ");
@@ -3554,50 +3554,6 @@
return computeVolume(stream, index, device);
}
-status_t AudioPolicyManager::getSupportedFormats(audio_io_handle_t ioHandle,
- FormatVector& formats) {
- if (ioHandle == AUDIO_IO_HANDLE_NONE) {
- return BAD_VALUE;
- }
- String8 reply;
- reply = mpClientInterface->getParameters(
- ioHandle, String8(AudioParameter::keyStreamSupportedFormats));
- ALOGV("%s: supported formats %s", __FUNCTION__, reply.string());
- AudioParameter repliedParameters(reply);
- if (repliedParameters.get(
- String8(AudioParameter::keyStreamSupportedFormats), reply) != NO_ERROR) {
- ALOGE("%s: failed to retrieve format, bailing out", __FUNCTION__);
- return BAD_VALUE;
- }
- for (auto format : formatsFromString(reply.string())) {
- // Only AUDIO_FORMAT_AAC_LC will be used in Settings UI for all AAC formats.
- for (size_t i = 0; i < ARRAY_SIZE(AAC_FORMATS); i++) {
- if (format == AAC_FORMATS[i]) {
- format = AUDIO_FORMAT_AAC_LC;
- break;
- }
- }
- bool exist = false;
- for (size_t i = 0; i < formats.size(); i++) {
- if (format == formats[i]) {
- exist = true;
- break;
- }
- }
- bool isSurroundFormat = false;
- for (size_t i = 0; i < ARRAY_SIZE(SURROUND_FORMATS); i++) {
- if (SURROUND_FORMATS[i] == format) {
- isSurroundFormat = true;
- break;
- }
- }
- if (!exist && isSurroundFormat) {
- formats.add(format);
- }
- }
- return NO_ERROR;
-}
-
status_t AudioPolicyManager::getSurroundFormats(unsigned int *numSurroundFormats,
audio_format_t *surroundFormats,
bool *surroundFormatsEnabled,
@@ -3618,89 +3574,45 @@
size_t formatsWritten = 0;
size_t formatsMax = *numSurroundFormats;
*numSurroundFormats = 0;
- FormatVector formats;
+ std::unordered_set<audio_format_t> formats;
if (reported) {
- // Only get surround formats which are reported by device.
- // First list already open outputs that can be routed to this device
- audio_devices_t device = AUDIO_DEVICE_OUT_HDMI;
- SortedVector<audio_io_handle_t> outputs;
- bool reportedFormatFound = false;
- status_t status;
- sp<SwAudioOutputDescriptor> desc;
- for (size_t i = 0; i < mOutputs.size(); i++) {
- desc = mOutputs.valueAt(i);
- if (!desc->isDuplicated() && (desc->supportedDevices() & device)) {
- outputs.add(mOutputs.keyAt(i));
- }
- }
- // Open an output to query dynamic parameters.
- DeviceVector hdmiOutputDevices = mAvailableOutputDevices.getDevicesFromTypeMask(
- AUDIO_DEVICE_OUT_HDMI);
- for (size_t i = 0; i < hdmiOutputDevices.size(); i++) {
- String8 address = hdmiOutputDevices[i]->mAddress;
- for (const auto& hwModule : mHwModules) {
- for (size_t i = 0; i < hwModule->getOutputProfiles().size(); i++) {
- sp<IOProfile> profile = hwModule->getOutputProfiles()[i];
- if (profile->supportDevice(AUDIO_DEVICE_OUT_HDMI) &&
- profile->supportDeviceAddress(address)) {
- size_t j;
- for (j = 0; j < outputs.size(); j++) {
- desc = mOutputs.valueFor(outputs.itemAt(j));
- if (!desc->isDuplicated() && desc->mProfile == profile) {
- break;
- }
- }
- if (j != outputs.size()) {
- status = getSupportedFormats(outputs.itemAt(j), formats);
- reportedFormatFound |= (status == NO_ERROR);
- continue;
- }
-
- if (!profile->canOpenNewIo()) {
- ALOGW("Max Output number %u already opened for this profile %s",
- profile->maxOpenCount, profile->getTagName().c_str());
- continue;
- }
-
- ALOGV("opening output for device %08x with params %s profile %p name %s",
- device, address.string(), profile.get(), profile->getName().string());
- desc = new SwAudioOutputDescriptor(profile, mpClientInterface);
- audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
- status_t status = desc->open(nullptr, device, address,
- AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE,
- &output);
-
- if (status == NO_ERROR) {
- status = getSupportedFormats(output, formats);
- reportedFormatFound |= (status == NO_ERROR);
- desc->close();
- output = AUDIO_IO_HANDLE_NONE;
- }
- }
- }
- }
- }
-
- if (!reportedFormatFound) {
- return UNKNOWN_ERROR;
+ // Return formats from HDMI profiles, that have already been resolved by
+ // checkOutputsForDevice().
+ DeviceVector hdmiOutputDevs = mAvailableOutputDevices.getDevicesFromTypeMask(
+ AUDIO_DEVICE_OUT_HDMI);
+ for (size_t i = 0; i < hdmiOutputDevs.size(); i++) {
+ FormatVector supportedFormats =
+ hdmiOutputDevs[i]->getAudioPort()->getAudioProfiles().getSupportedFormats();
+ for (size_t j = 0; j < supportedFormats.size(); j++) {
+ if (std::find(std::begin(SURROUND_FORMATS),
+ std::end(SURROUND_FORMATS),
+ supportedFormats[j]) != std::end(SURROUND_FORMATS)) {
+ formats.insert(supportedFormats[j]);
+ } else if (std::find(std::begin(AAC_FORMATS),
+ std::end(AAC_FORMATS),
+ supportedFormats[j]) != std::end(AAC_FORMATS)) {
+ // if any format in AAC_FORMATS is reported, insert AUDIO_FORMAT_AAC_LC as this
+ // is the only AAC format used in the TvSettings UI for all AAC formats.
+ formats.insert(AUDIO_FORMAT_AAC_LC);
+ }
+ }
}
} else {
for (size_t i = 0; i < ARRAY_SIZE(SURROUND_FORMATS); i++) {
- formats.add(SURROUND_FORMATS[i]);
+ formats.insert(SURROUND_FORMATS[i]);
}
}
- for (size_t i = 0; i < formats.size(); i++) {
+ for (const auto& format: formats) {
if (formatsWritten < formatsMax) {
- surroundFormats[formatsWritten] = formats[i];
+ surroundFormats[formatsWritten] = format;
bool formatEnabled = false;
- if (formats[i] == AUDIO_FORMAT_AAC_LC) {
- for (size_t j = 0; j < ARRAY_SIZE(AAC_FORMATS); j++) {
+ if (format == AUDIO_FORMAT_AAC_LC) {
+ for (size_t j = 0; j < ARRAY_SIZE(AAC_FORMATS) && !formatEnabled; j++) {
formatEnabled =
- mSurroundFormats.find(AAC_FORMATS[i]) != mSurroundFormats.end();
- break;
+ mSurroundFormats.find(AAC_FORMATS[j]) != mSurroundFormats.end();
}
} else {
- formatEnabled = mSurroundFormats.find(formats[i]) != mSurroundFormats.end();
+ formatEnabled = mSurroundFormats.find(format) != mSurroundFormats.end();
}
surroundFormatsEnabled[formatsWritten++] = formatEnabled;
}
@@ -3744,6 +3656,7 @@
return INVALID_OPERATION;
}
+ std::unordered_set<audio_format_t> surroundFormatsBackup(mSurroundFormats);
if (enabled) {
if (audioFormat == AUDIO_FORMAT_AAC_LC) {
for (size_t i = 0; i < ARRAY_SIZE(AAC_FORMATS); i++) {
@@ -3806,23 +3719,7 @@
// Undo the surround formats change due to no audio profiles updated.
if (!profileUpdated) {
ALOGW("%s() no audio profiles updated, undoing surround formats change", __func__);
- if (enabled) {
- if (audioFormat == AUDIO_FORMAT_AAC_LC) {
- for (size_t i = 0; i < ARRAY_SIZE(AAC_FORMATS); i++) {
- mSurroundFormats.erase(AAC_FORMATS[i]);
- }
- } else {
- mSurroundFormats.erase(audioFormat);
- }
- } else {
- if (audioFormat == AUDIO_FORMAT_AAC_LC) {
- for (size_t i = 0; i < ARRAY_SIZE(AAC_FORMATS); i++) {
- mSurroundFormats.insert(AAC_FORMATS[i]);
- }
- } else {
- mSurroundFormats.insert(audioFormat);
- }
- }
+ mSurroundFormats = std::move(surroundFormatsBackup);
}
return profileUpdated ? NO_ERROR : INVALID_OPERATION;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 6f4cce1..fcb9d25 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -613,8 +613,6 @@
void filterSurroundFormats(FormatVector *formatsPtr);
void filterSurroundChannelMasks(ChannelsVector *channelMasksPtr);
- status_t getSupportedFormats(audio_io_handle_t ioHandle, FormatVector& formats);
-
// Support for Multi-Stream Decoder (MSD) module
sp<DeviceDescriptor> getMsdAudioInDevice() const;
audio_devices_t getMsdAudioOutDeviceTypes() const;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 1bc5d33..48e38bb 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -281,7 +281,6 @@
status_t Camera3Device::disconnectImpl() {
ATRACE_CALL();
Mutex::Autolock il(mInterfaceLock);
- Mutex::Autolock stLock(mTrackerLock);
ALOGI("%s: E", __FUNCTION__);
@@ -346,6 +345,7 @@
{
Mutex::Autolock l(mLock);
mRequestThread.clear();
+ Mutex::Autolock stLock(mTrackerLock);
mStatusTracker.clear();
interface = mInterface.get();
}
@@ -2014,6 +2014,13 @@
{
Mutex::Autolock l(mLock);
+
+ // b/116514106 "disconnect()" can get called twice for the same device. The
+ // camera device will not be initialized during the second run.
+ if (mStatus == STATUS_UNINITIALIZED) {
+ return OK;
+ }
+
mRequestThread->clear(/*out*/frameNumber);
}
diff --git a/services/mediaanalytics/MediaAnalyticsService.cpp b/services/mediaanalytics/MediaAnalyticsService.cpp
index 45da56a..ae832ba 100644
--- a/services/mediaanalytics/MediaAnalyticsService.cpp
+++ b/services/mediaanalytics/MediaAnalyticsService.cpp
@@ -26,6 +26,7 @@
#include <sys/stat.h>
#include <sys/time.h>
#include <dirent.h>
+#include <pthread.h>
#include <unistd.h>
#include <string.h>
@@ -80,11 +81,18 @@
using namespace android::content::pm;
// individual records kept in memory: age or count
-// age: <= 36 hours (1.5 days)
+// age: <= 28 hours (1 1/6 days)
// count: hard limit of # records
// (0 for either of these disables that threshold)
-static const nsecs_t kMaxRecordAgeNs = 36 * 3600 * (1000*1000*1000ll);
-static const int kMaxRecords = 0;
+//
+static constexpr nsecs_t kMaxRecordAgeNs = 28 * 3600 * (1000*1000*1000ll);
+static constexpr int kMaxRecords = 0;
+
+// max we expire in a single call, to constrain how long we hold the
+// mutex, which also constrains how long a client might wait.
+static constexpr int kMaxExpiredAtOnce = 50;
+
+// TODO: need to look at tuning kMaxRecords and friends for low-memory devices
static const char *kServiceName = "media.metrics";
@@ -96,6 +104,7 @@
MediaAnalyticsService::MediaAnalyticsService()
: mMaxRecords(kMaxRecords),
mMaxRecordAgeNs(kMaxRecordAgeNs),
+ mMaxRecordsExpiredAtOnce(kMaxExpiredAtOnce),
mDumpProto(MediaAnalyticsItem::PROTO_V1),
mDumpProtoDefault(MediaAnalyticsItem::PROTO_V1) {
@@ -432,23 +441,29 @@
//
// Our Cheap in-core, non-persistent records management.
-// insert appropriately into queue
-void MediaAnalyticsService::saveItem(MediaAnalyticsItem * item)
+
+// we hold mLock when we get here
+// if item != NULL, it's the item we just inserted
+// true == more items eligible to be recovered
+bool MediaAnalyticsService::expirations_l(MediaAnalyticsItem *item)
{
-
- Mutex::Autolock _l(mLock);
- // mutex between insertion and dumping the contents
-
- // we want to dump 'in FIFO order', so insert at the end
- mItems.push_back(item);
+ bool more = false;
+ int handled = 0;
// keep removing old records the front until we're in-bounds (count)
+ // since we invoke this with each insertion, it should be 0/1 iterations.
if (mMaxRecords > 0) {
while (mItems.size() > (size_t) mMaxRecords) {
MediaAnalyticsItem * oitem = *(mItems.begin());
if (oitem == item) {
break;
}
+ if (handled >= mMaxRecordsExpiredAtOnce) {
+ // unlikely in this loop
+ more = true;
+ break;
+ }
+ handled++;
mItems.erase(mItems.begin());
delete oitem;
mItemsDiscarded++;
@@ -456,8 +471,8 @@
}
}
- // keep removing old records the front until we're in-bounds (count)
- // NB: expired entries aren't removed until the next insertion, which could be a while
+ // keep removing old records the front until we're in-bounds (age)
+ // limited to mMaxRecordsExpiredAtOnce items per invocation.
if (mMaxRecordAgeNs > 0) {
nsecs_t now = systemTime(SYSTEM_TIME_REALTIME);
while (mItems.size() > 0) {
@@ -471,12 +486,65 @@
// this (and the rest) are recent enough to keep
break;
}
+ if (handled >= mMaxRecordsExpiredAtOnce) {
+ // this represents "one too many"; tell caller there are
+ // more to be reclaimed.
+ more = true;
+ break;
+ }
+ handled++;
mItems.erase(mItems.begin());
delete oitem;
mItemsDiscarded++;
mItemsDiscardedExpire++;
}
}
+
+ // we only indicate whether there's more to clean;
+ // caller chooses whether to schedule further cleanup.
+ return more;
+}
+
+// process expirations in bite sized chunks, allowing new insertions through
+// runs in a pthread specifically started for this (which then exits)
+bool MediaAnalyticsService::processExpirations()
+{
+ bool more;
+ do {
+ sleep(1);
+ {
+ Mutex::Autolock _l(mLock);
+ more = expirations_l(NULL);
+ if (!more) {
+ break;
+ }
+ }
+ } while (more);
+ return true; // value is for std::future thread synchronization
+}
+
+// insert appropriately into queue
+void MediaAnalyticsService::saveItem(MediaAnalyticsItem * item)
+{
+
+ Mutex::Autolock _l(mLock);
+ // mutex between insertion and dumping the contents
+
+ // we want to dump 'in FIFO order', so insert at the end
+ mItems.push_back(item);
+
+ // clean old stuff from the queue
+ bool more = expirations_l(item);
+
+ // consider scheduling some asynchronous cleaning, if not running
+ if (more) {
+ if (!mExpireFuture.valid()
+ || mExpireFuture.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
+
+ mExpireFuture = std::async(std::launch::async, [this]()
+ {return this->processExpirations();});
+ }
+ }
}
static std::string allowedKeys[] =
diff --git a/services/mediaanalytics/MediaAnalyticsService.h b/services/mediaanalytics/MediaAnalyticsService.h
index b3c902a..632c692 100644
--- a/services/mediaanalytics/MediaAnalyticsService.h
+++ b/services/mediaanalytics/MediaAnalyticsService.h
@@ -26,6 +26,8 @@
#include <utils/String8.h>
#include <utils/List.h>
+#include <future>
+
#include <media/IMediaAnalyticsService.h>
namespace android {
@@ -44,6 +46,8 @@
MediaAnalyticsService();
virtual ~MediaAnalyticsService();
+ bool processExpirations();
+
private:
MediaAnalyticsItem::SessionID_t generateUniqueSessionID();
@@ -65,6 +69,8 @@
int32_t mMaxRecords;
// by time (none older than this long agan
nsecs_t mMaxRecordAgeNs;
+ // max to expire per expirations_l() invocation
+ int32_t mMaxRecordsExpiredAtOnce;
//
// # of sets of summaries
int32_t mMaxRecordSets;
@@ -79,6 +85,9 @@
List<MediaAnalyticsItem *> mItems;
void saveItem(MediaAnalyticsItem *);
+ bool expirations_l(MediaAnalyticsItem *);
+ std::future<bool> mExpireFuture;
+
// support for generating output
int mDumpProto;
int mDumpProtoDefault;