Merge "C2SoftAVCEnc: Change default dimensions and frame rate" into rvc-dev
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index f408b6a..b58ebe2 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -35,6 +35,7 @@
const char* CameraManagerGlobal::kPhysicalCameraIdKey = "PhysicalCameraId";
const char* CameraManagerGlobal::kCallbackFpKey = "CallbackFp";
const char* CameraManagerGlobal::kContextKey = "CallbackContext";
+const nsecs_t CameraManagerGlobal::kCallbackDrainTimeout = 5000000; // 5 ms
Mutex CameraManagerGlobal::sLock;
CameraManagerGlobal* CameraManagerGlobal::sInstance = nullptr;
@@ -117,7 +118,7 @@
return nullptr;
}
if (mHandler == nullptr) {
- mHandler = new CallbackHandler();
+ mHandler = new CallbackHandler(this);
}
mCbLooper->registerHandler(mHandler);
}
@@ -211,6 +212,9 @@
void CameraManagerGlobal::unregisterExtendedAvailabilityCallback(
const ACameraManager_ExtendedAvailabilityCallbacks *callback) {
Mutex::Autolock _l(mLock);
+
+ drainPendingCallbacksLocked();
+
Callback cb(callback);
mCallbacks.erase(cb);
}
@@ -223,10 +227,32 @@
void CameraManagerGlobal::unregisterAvailabilityCallback(
const ACameraManager_AvailabilityCallbacks *callback) {
Mutex::Autolock _l(mLock);
+
+ drainPendingCallbacksLocked();
+
Callback cb(callback);
mCallbacks.erase(cb);
}
+void CameraManagerGlobal::onCallbackCalled() {
+ Mutex::Autolock _l(mLock);
+ if (mPendingCallbackCnt > 0) {
+ mPendingCallbackCnt--;
+ }
+ mCallbacksCond.signal();
+}
+
+void CameraManagerGlobal::drainPendingCallbacksLocked() {
+ while (mPendingCallbackCnt > 0) {
+ auto res = mCallbacksCond.waitRelative(mLock, kCallbackDrainTimeout);
+ if (res != NO_ERROR) {
+ ALOGE("%s: Error waiting to drain callbacks: %s(%d)",
+ __FUNCTION__, strerror(-res), res);
+ break;
+ }
+ }
+}
+
template<class T>
void CameraManagerGlobal::registerAvailCallback(const T *callback) {
Mutex::Autolock _l(mLock);
@@ -250,6 +276,7 @@
msg->setPointer(kCallbackFpKey, (void *) cbFunc);
msg->setPointer(kContextKey, cb.mContext);
msg->setString(kCameraIdKey, AString(cameraId));
+ mPendingCallbackCnt++;
msg->post();
// Physical camera unavailable callback
@@ -263,6 +290,7 @@
msg->setPointer(kContextKey, cb.mContext);
msg->setString(kCameraIdKey, AString(cameraId));
msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId));
+ mPendingCallbackCnt++;
msg->post();
}
}
@@ -323,6 +351,16 @@
}
void CameraManagerGlobal::CallbackHandler::onMessageReceived(
+ const sp<AMessage> &msg) {
+ onMessageReceivedInternal(msg);
+ if (msg->what() == kWhatSendSingleCallback ||
+ msg->what() == kWhatSendSingleAccessCallback ||
+ msg->what() == kWhatSendSinglePhysicalCameraCallback) {
+ notifyParent();
+ }
+}
+
+void CameraManagerGlobal::CallbackHandler::onMessageReceivedInternal(
const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatSendSingleCallback:
@@ -405,6 +443,13 @@
}
}
+void CameraManagerGlobal::CallbackHandler::notifyParent() {
+ sp<CameraManagerGlobal> parent = mParent.promote();
+ if (parent != nullptr) {
+ parent->onCallbackCalled();
+ }
+}
+
binder::Status CameraManagerGlobal::CameraServiceListener::onCameraAccessPrioritiesChanged() {
sp<CameraManagerGlobal> cm = mCameraManager.promote();
if (cm != nullptr) {
@@ -445,6 +490,7 @@
if (cbFp != nullptr) {
msg->setPointer(kCallbackFpKey, (void *) cbFp);
msg->setPointer(kContextKey, cb.mContext);
+ mPendingCallbackCnt++;
msg->post();
}
}
@@ -491,6 +537,7 @@
msg->setPointer(kCallbackFpKey, (void *) cbFp);
msg->setPointer(kContextKey, cb.mContext);
msg->setString(kCameraIdKey, AString(cameraId));
+ mPendingCallbackCnt++;
msg->post();
}
}
@@ -545,6 +592,7 @@
msg->setPointer(kContextKey, cb.mContext);
msg->setString(kCameraIdKey, AString(cameraId));
msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId));
+ mPendingCallbackCnt++;
msg->post();
}
}
diff --git a/camera/ndk/impl/ACameraManager.h b/camera/ndk/impl/ACameraManager.h
index 7fba188..ccbfaa9 100644
--- a/camera/ndk/impl/ACameraManager.h
+++ b/camera/ndk/impl/ACameraManager.h
@@ -163,6 +163,12 @@
ACameraManager_PhysicalCameraAvailabilityCallback mPhysicalCamUnavailable;
void* mContext;
};
+
+ android::Condition mCallbacksCond;
+ size_t mPendingCallbackCnt = 0;
+ void onCallbackCalled();
+ void drainPendingCallbacksLocked();
+
std::set<Callback> mCallbacks;
// definition of handler and message
@@ -175,10 +181,16 @@
static const char* kPhysicalCameraIdKey;
static const char* kCallbackFpKey;
static const char* kContextKey;
+ static const nsecs_t kCallbackDrainTimeout;
class CallbackHandler : public AHandler {
public:
- CallbackHandler() {}
+ CallbackHandler(wp<CameraManagerGlobal> parent) : mParent(parent) {}
void onMessageReceived(const sp<AMessage> &msg) override;
+
+ private:
+ wp<CameraManagerGlobal> mParent;
+ void notifyParent();
+ void onMessageReceivedInternal(const sp<AMessage> &msg);
};
sp<CallbackHandler> mHandler;
sp<ALooper> mCbLooper; // Looper thread where callbacks actually happen on
diff --git a/camera/ndk/include/camera/NdkCameraManager.h b/camera/ndk/include/camera/NdkCameraManager.h
index e2b71bf..0a2ee57 100644
--- a/camera/ndk/include/camera/NdkCameraManager.h
+++ b/camera/ndk/include/camera/NdkCameraManager.h
@@ -191,6 +191,9 @@
*
* <p>Removing a callback that isn't registered has no effect.</p>
*
+ * <p>This function must not be called with a mutex lock also held by
+ * the availability callbacks.</p>
+ *
* @param manager the {@link ACameraManager} of interest.
* @param callback the {@link ACameraManager_AvailabilityCallbacks} to be unregistered.
*
@@ -382,6 +385,9 @@
*
* <p>Removing a callback that isn't registered has no effect.</p>
*
+ * <p>This function must not be called with a mutex lock also held by
+ * the extended availability callbacks.</p>
+ *
* @param manager the {@link ACameraManager} of interest.
* @param callback the {@link ACameraManager_ExtendedAvailabilityCallbacks} to be unregistered.
*
diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
index e2097b5..5aa9c46 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
@@ -45,6 +45,7 @@
const char* CameraManagerGlobal::kPhysicalCameraIdKey = "PhysicalCameraId";
const char* CameraManagerGlobal::kCallbackFpKey = "CallbackFp";
const char* CameraManagerGlobal::kContextKey = "CallbackContext";
+const nsecs_t CameraManagerGlobal::kCallbackDrainTimeout = 5000000; // 5 ms
Mutex CameraManagerGlobal::sLock;
CameraManagerGlobal* CameraManagerGlobal::sInstance = nullptr;
@@ -249,7 +250,7 @@
return nullptr;
}
if (mHandler == nullptr) {
- mHandler = new CallbackHandler();
+ mHandler = new CallbackHandler(this);
}
mCbLooper->registerHandler(mHandler);
}
@@ -317,6 +318,7 @@
void CameraManagerGlobal::unregisterAvailabilityCallback(
const ACameraManager_AvailabilityCallbacks *callback) {
Mutex::Autolock _l(mLock);
+ drainPendingCallbacksLocked();
Callback cb(callback);
mCallbacks.erase(cb);
}
@@ -329,10 +331,30 @@
void CameraManagerGlobal::unregisterExtendedAvailabilityCallback(
const ACameraManager_ExtendedAvailabilityCallbacks *callback) {
Mutex::Autolock _l(mLock);
+ drainPendingCallbacksLocked();
Callback cb(callback);
mCallbacks.erase(cb);
}
+void CameraManagerGlobal::onCallbackCalled() {
+ Mutex::Autolock _l(mLock);
+ if (mPendingCallbackCnt > 0) {
+ mPendingCallbackCnt--;
+ }
+ mCallbacksCond.signal();
+}
+
+void CameraManagerGlobal::drainPendingCallbacksLocked() {
+ while (mPendingCallbackCnt > 0) {
+ auto res = mCallbacksCond.waitRelative(mLock, kCallbackDrainTimeout);
+ if (res != NO_ERROR) {
+ ALOGE("%s: Error waiting to drain callbacks: %s(%d)",
+ __FUNCTION__, strerror(-res), res);
+ break;
+ }
+ }
+}
+
template <class T>
void CameraManagerGlobal::registerAvailCallback(const T *callback) {
Mutex::Autolock _l(mLock);
@@ -351,6 +373,7 @@
msg->setPointer(kCallbackFpKey, (void *) cbFunc);
msg->setPointer(kContextKey, cb.mContext);
msg->setString(kCameraIdKey, AString(cameraId.c_str()));
+ mPendingCallbackCnt++;
msg->post();
// Physical camera unavailable callback
@@ -363,6 +386,7 @@
msg->setPointer(kContextKey, cb.mContext);
msg->setString(kCameraIdKey, AString(cameraId.c_str()));
msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId.c_str()));
+ mPendingCallbackCnt++;
msg->post();
}
}
@@ -406,6 +430,15 @@
}
void CameraManagerGlobal::CallbackHandler::onMessageReceived(
+ const sp<AMessage> &msg) {
+ onMessageReceivedInternal(msg);
+ if (msg->what() == kWhatSendSingleCallback ||
+ msg->what() == kWhatSendSinglePhysicalCameraCallback) {
+ notifyParent();
+ }
+}
+
+void CameraManagerGlobal::CallbackHandler::onMessageReceivedInternal(
const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatSendSingleCallback:
@@ -466,6 +499,13 @@
}
}
+void CameraManagerGlobal::CallbackHandler::notifyParent() {
+ sp<CameraManagerGlobal> parent = mParent.promote();
+ if (parent != nullptr) {
+ parent->onCallbackCalled();
+ }
+}
+
hardware::Return<void> CameraManagerGlobal::CameraServiceListener::onStatusChanged(
const CameraStatusAndId &statusAndId) {
sp<CameraManagerGlobal> cm = mCameraManager.promote();
@@ -512,6 +552,7 @@
msg->setPointer(kCallbackFpKey, (void *) cbFp);
msg->setPointer(kContextKey, cb.mContext);
msg->setString(kCameraIdKey, AString(cameraId.c_str()));
+ mPendingCallbackCnt++;
msg->post();
}
if (status == CameraDeviceStatus::STATUS_NOT_PRESENT) {
@@ -577,6 +618,7 @@
msg->setPointer(kContextKey, cb.mContext);
msg->setString(kCameraIdKey, AString(cameraId.c_str()));
msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId.c_str()));
+ mPendingCallbackCnt++;
msg->post();
}
}
diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.h b/camera/ndk/ndk_vendor/impl/ACameraManager.h
index 36c8e2b..85da3e9 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraManager.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraManager.h
@@ -156,6 +156,12 @@
ACameraManager_PhysicalCameraAvailabilityCallback mPhysicalCamUnavailable;
void* mContext;
};
+
+ android::Condition mCallbacksCond;
+ size_t mPendingCallbackCnt = 0;
+ void onCallbackCalled();
+ void drainPendingCallbacksLocked();
+
std::set<Callback> mCallbacks;
// definition of handler and message
@@ -167,10 +173,15 @@
static const char* kPhysicalCameraIdKey;
static const char* kCallbackFpKey;
static const char* kContextKey;
+ static const nsecs_t kCallbackDrainTimeout;
class CallbackHandler : public AHandler {
public:
- CallbackHandler() {}
+ CallbackHandler(wp<CameraManagerGlobal> parent) : mParent(parent) {}
void onMessageReceived(const sp<AMessage> &msg) override;
+ private:
+ wp<CameraManagerGlobal> mParent;
+ void notifyParent();
+ void onMessageReceivedInternal(const sp<AMessage> &msg);
};
sp<CallbackHandler> mHandler;
sp<ALooper> mCbLooper; // Looper thread where callbacks actually happen on
diff --git a/drm/drmserver/Android.bp b/drm/drmserver/Android.bp
index f427834..b68e6c2 100644
--- a/drm/drmserver/Android.bp
+++ b/drm/drmserver/Android.bp
@@ -24,8 +24,8 @@
],
shared_libs: [
- "libmedia",
"libmediametrics",
+ "libmediautils",
"libcutils",
"libutils",
"liblog",
diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp
index 4b8b3f6..c830c6e 100644
--- a/drm/drmserver/DrmManagerService.cpp
+++ b/drm/drmserver/DrmManagerService.cpp
@@ -19,7 +19,7 @@
#include <utils/Log.h>
#include <private/android_filesystem_config.h>
-#include <media/MemoryLeakTrackUtil.h>
+#include <mediautils/MemoryLeakTrackUtil.h>
#include <errno.h>
#include <utils/threads.h>
diff --git a/drm/libmediadrm/DrmUtils.cpp b/drm/libmediadrm/DrmUtils.cpp
index 51c2e24..d85fa61 100644
--- a/drm/libmediadrm/DrmUtils.cpp
+++ b/drm/libmediadrm/DrmUtils.cpp
@@ -27,7 +27,7 @@
#include <android/hardware/drm/1.2/IDrmFactory.h>
#include <android/hardware/drm/1.3/ICryptoFactory.h>
#include <android/hardware/drm/1.3/IDrmFactory.h>
-#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
#include <hidl/HidlSupport.h>
#include <utils/Errors.h>
@@ -41,7 +41,7 @@
#include <mediadrm/ICrypto.h>
#include <mediadrm/IDrm.h>
-using HServiceManager = ::android::hidl::manager::V1_0::IServiceManager;
+using HServiceManager = ::android::hidl::manager::V1_2::IServiceManager;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
@@ -72,7 +72,7 @@
exit(-1);
}
- serviceManager->listByInterface(Hal::descriptor, [&](const hidl_vec<hidl_string> ®istered) {
+ serviceManager->listManifestByInterface(Hal::descriptor, [&](const hidl_vec<hidl_string> ®istered) {
for (const auto &instance : registered) {
auto factory = Hal::getService(instance);
if (factory != nullptr) {
diff --git a/include/media/VolumeShaper.h b/include/media/VolumeShaper.h
index 79afd6c..fe519bb 100644
--- a/include/media/VolumeShaper.h
+++ b/include/media/VolumeShaper.h
@@ -132,7 +132,7 @@
, mDurationMs(1000.) {
}
- explicit Configuration(const Configuration &configuration)
+ Configuration(const Configuration &configuration)
: Interpolator<S, T>(*static_cast<const Interpolator<S, T> *>(&configuration))
, RefBase()
, mType(configuration.mType)
@@ -361,7 +361,7 @@
: Operation(flags, replaceId, std::numeric_limits<S>::quiet_NaN() /* xOffset */) {
}
- explicit Operation(const Operation &operation)
+ Operation(const Operation &operation)
: Operation(operation.mFlags, operation.mReplaceId, operation.mXOffset) {
}
diff --git a/media/audioserver/audioserver.rc b/media/audioserver/audioserver.rc
index 5484613..f9bef5f 100644
--- a/media/audioserver/audioserver.rc
+++ b/media/audioserver/audioserver.rc
@@ -6,16 +6,22 @@
capabilities BLOCK_SUSPEND
ioprio rt 4
writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
- onrestart restart vendor.audio-hal
- onrestart restart vendor.audio-hal-4-0-msd
- # Keep the original service names for backward compatibility
- onrestart restart vendor.audio-hal-2-0
- onrestart restart audio-hal-2-0
+
+ onrestart setprop sys.audio.restart.hal 1
on property:vts.native_server.on=1
stop audioserver
on property:vts.native_server.on=0
start audioserver
+on property:sys.audio.restart.hal=1
+ restart vendor.audio-hal
+ restart vendor.audio-hal-4-0-msd
+ # Keep the original service names for backward compatibility
+ restart vendor.audio-hal-2-0
+ restart audio-hal-2-0
+ # reset the property
+ setprop sys.audio.restart.hal 0
+
on init
mkdir /dev/socket/audioserver 0775 audioserver audioserver
diff --git a/media/codec2/components/avc/C2SoftAvcDec.cpp b/media/codec2/components/avc/C2SoftAvcDec.cpp
index 56813c4..c1edb98 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.cpp
+++ b/media/codec2/components/avc/C2SoftAvcDec.cpp
@@ -35,6 +35,7 @@
constexpr char COMPONENT_NAME[] = "c2.android.avc.decoder";
constexpr uint32_t kDefaultOutputDelay = 8;
constexpr uint32_t kMaxOutputDelay = 16;
+constexpr uint32_t kMinInputBytes = 4;
} // namespace
class C2SoftAvcDec::IntfImpl : public SimpleInterface<void>::BaseParams {
@@ -501,7 +502,7 @@
status_t C2SoftAvcDec::initDecoder() {
if (OK != createDecoder()) return UNKNOWN_ERROR;
mNumCores = MIN(getCpuCoreCount(), MAX_NUM_CORES);
- mStride = ALIGN128(mWidth);
+ mStride = ALIGN32(mWidth);
mSignalledError = false;
resetPlugin();
(void) setNumCores();
@@ -519,10 +520,20 @@
size_t inSize,
uint32_t tsMarker) {
uint32_t displayStride = mStride;
+ if (outBuffer) {
+ C2PlanarLayout layout;
+ layout = outBuffer->layout();
+ displayStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
+ }
uint32_t displayHeight = mHeight;
size_t lumaSize = displayStride * displayHeight;
size_t chromaSize = lumaSize >> 2;
+ if (mStride != displayStride) {
+ mStride = displayStride;
+ if (OK != setParams(mStride, IVD_DECODE_FRAME)) return false;
+ }
+
ps_decode_ip->u4_size = sizeof(ivd_video_decode_ip_t);
ps_decode_ip->e_cmd = IVD_CMD_VIDEO_DECODE;
if (inBuffer) {
@@ -756,24 +767,21 @@
ALOGE("not supposed to be here, invalid decoder context");
return C2_CORRUPTED;
}
- if (mStride != ALIGN128(mWidth)) {
- mStride = ALIGN128(mWidth);
- if (OK != setParams(mStride, IVD_DECODE_FRAME)) return C2_CORRUPTED;
- }
if (mOutBlock &&
- (mOutBlock->width() != mStride || mOutBlock->height() != mHeight)) {
+ (mOutBlock->width() != ALIGN32(mWidth) || mOutBlock->height() != mHeight)) {
mOutBlock.reset();
}
if (!mOutBlock) {
uint32_t format = HAL_PIXEL_FORMAT_YV12;
C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- c2_status_t err = pool->fetchGraphicBlock(mStride, mHeight, format, usage, &mOutBlock);
+ c2_status_t err =
+ pool->fetchGraphicBlock(ALIGN32(mWidth), mHeight, format, usage, &mOutBlock);
if (err != C2_OK) {
ALOGE("fetchGraphicBlock for Output failed with status %d", err);
return err;
}
ALOGV("provided (%dx%d) required (%dx%d)",
- mOutBlock->width(), mOutBlock->height(), mStride, mHeight);
+ mOutBlock->width(), mOutBlock->height(), ALIGN32(mWidth), mHeight);
}
return C2_OK;
@@ -817,7 +825,7 @@
inSize, (int)work->input.ordinal.timestamp.peeku(),
(int)work->input.ordinal.frameIndex.peeku(), work->input.flags);
size_t inPos = 0;
- while (inPos < inSize) {
+ while (inPos < inSize && inSize - inPos >= kMinInputBytes) {
if (C2_OK != ensureDecoderState(pool)) {
mSignalledError = true;
work->workletsProcessed = 1u;
@@ -904,12 +912,12 @@
work->result = C2_CORRUPTED;
return;
}
- continue;
}
if (0 < s_decode_op.u4_pic_wd && 0 < s_decode_op.u4_pic_ht) {
if (mHeaderDecoded == false) {
mHeaderDecoded = true;
- setParams(ALIGN128(s_decode_op.u4_pic_wd), IVD_DECODE_FRAME);
+ mStride = ALIGN32(s_decode_op.u4_pic_wd);
+ setParams(mStride, IVD_DECODE_FRAME);
}
if (s_decode_op.u4_pic_wd != mWidth || s_decode_op.u4_pic_ht != mHeight) {
mWidth = s_decode_op.u4_pic_wd;
@@ -937,16 +945,7 @@
if (s_decode_op.u4_output_present) {
finishWork(s_decode_op.u4_ts, work);
}
- if (0 == s_decode_op.u4_num_bytes_consumed) {
- ALOGD("Bytes consumed is zero. Ignoring remaining bytes");
- break;
- }
inPos += s_decode_op.u4_num_bytes_consumed;
- if (hasPicture && (inSize - inPos)) {
- ALOGD("decoded frame in current access nal, ignoring further trailing bytes %d",
- (int)inSize - (int)inPos);
- break;
- }
}
if (eos) {
drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
diff --git a/media/codec2/components/avc/C2SoftAvcDec.h b/media/codec2/components/avc/C2SoftAvcDec.h
index ed27493..bd84de0 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.h
+++ b/media/codec2/components/avc/C2SoftAvcDec.h
@@ -39,8 +39,7 @@
#define ivdext_ctl_set_num_cores_op_t ih264d_ctl_set_num_cores_op_t
#define ivdext_ctl_get_vui_params_ip_t ih264d_ctl_get_vui_params_ip_t
#define ivdext_ctl_get_vui_params_op_t ih264d_ctl_get_vui_params_op_t
-#define ALIGN64(x) ((((x) + 63) >> 6) << 6)
-#define ALIGN128(x) ((((x) + 127) >> 7) << 7)
+#define ALIGN32(x) ((((x) + 31) >> 5) << 5)
#define MAX_NUM_CORES 4
#define IVDEXT_CMD_CTL_SET_NUM_CORES \
(IVD_CONTROL_API_COMMAND_TYPE_T)IH264D_CMD_CTL_SET_NUM_CORES
diff --git a/media/codec2/components/hevc/C2SoftHevcDec.cpp b/media/codec2/components/hevc/C2SoftHevcDec.cpp
index 6db4387..e4b911d 100644
--- a/media/codec2/components/hevc/C2SoftHevcDec.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcDec.cpp
@@ -497,7 +497,7 @@
status_t C2SoftHevcDec::initDecoder() {
if (OK != createDecoder()) return UNKNOWN_ERROR;
mNumCores = MIN(getCpuCoreCount(), MAX_NUM_CORES);
- mStride = ALIGN128(mWidth);
+ mStride = ALIGN32(mWidth);
mSignalledError = false;
resetPlugin();
(void) setNumCores();
@@ -515,10 +515,20 @@
size_t inSize,
uint32_t tsMarker) {
uint32_t displayStride = mStride;
+ if (outBuffer) {
+ C2PlanarLayout layout;
+ layout = outBuffer->layout();
+ displayStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
+ }
uint32_t displayHeight = mHeight;
size_t lumaSize = displayStride * displayHeight;
size_t chromaSize = lumaSize >> 2;
+ if (mStride != displayStride) {
+ mStride = displayStride;
+ if (OK != setParams(mStride, IVD_DECODE_FRAME)) return false;
+ }
+
ps_decode_ip->u4_size = sizeof(ivd_video_decode_ip_t);
ps_decode_ip->e_cmd = IVD_CMD_VIDEO_DECODE;
if (inBuffer) {
@@ -752,24 +762,21 @@
ALOGE("not supposed to be here, invalid decoder context");
return C2_CORRUPTED;
}
- if (mStride != ALIGN128(mWidth)) {
- mStride = ALIGN128(mWidth);
- if (OK != setParams(mStride, IVD_DECODE_FRAME)) return C2_CORRUPTED;
- }
if (mOutBlock &&
- (mOutBlock->width() != mStride || mOutBlock->height() != mHeight)) {
+ (mOutBlock->width() != ALIGN32(mWidth) || mOutBlock->height() != mHeight)) {
mOutBlock.reset();
}
if (!mOutBlock) {
uint32_t format = HAL_PIXEL_FORMAT_YV12;
C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- c2_status_t err = pool->fetchGraphicBlock(mStride, mHeight, format, usage, &mOutBlock);
+ c2_status_t err =
+ pool->fetchGraphicBlock(ALIGN32(mWidth), mHeight, format, usage, &mOutBlock);
if (err != C2_OK) {
ALOGE("fetchGraphicBlock for Output failed with status %d", err);
return err;
}
ALOGV("provided (%dx%d) required (%dx%d)",
- mOutBlock->width(), mOutBlock->height(), mStride, mHeight);
+ mOutBlock->width(), mOutBlock->height(), ALIGN32(mWidth), mHeight);
}
return C2_OK;
@@ -904,7 +911,7 @@
if (0 < s_decode_op.u4_pic_wd && 0 < s_decode_op.u4_pic_ht) {
if (mHeaderDecoded == false) {
mHeaderDecoded = true;
- setParams(ALIGN128(s_decode_op.u4_pic_wd), IVD_DECODE_FRAME);
+ setParams(ALIGN32(s_decode_op.u4_pic_wd), IVD_DECODE_FRAME);
}
if (s_decode_op.u4_pic_wd != mWidth || s_decode_op.u4_pic_ht != mHeight) {
mWidth = s_decode_op.u4_pic_wd;
diff --git a/media/codec2/components/hevc/C2SoftHevcDec.h b/media/codec2/components/hevc/C2SoftHevcDec.h
index aecd101..600d7c1 100644
--- a/media/codec2/components/hevc/C2SoftHevcDec.h
+++ b/media/codec2/components/hevc/C2SoftHevcDec.h
@@ -37,8 +37,7 @@
#define ivdext_ctl_set_num_cores_op_t ihevcd_cxa_ctl_set_num_cores_op_t
#define ivdext_ctl_get_vui_params_ip_t ihevcd_cxa_ctl_get_vui_params_ip_t
#define ivdext_ctl_get_vui_params_op_t ihevcd_cxa_ctl_get_vui_params_op_t
-#define ALIGN64(x) ((((x) + 63) >> 6) << 6)
-#define ALIGN128(x) ((((x) + 127) >> 7) << 7)
+#define ALIGN32(x) ((((x) + 31) >> 5) << 5)
#define MAX_NUM_CORES 4
#define IVDEXT_CMD_CTL_SET_NUM_CORES \
(IVD_CONTROL_API_COMMAND_TYPE_T)IHEVCD_CXA_CMD_CTL_SET_NUM_CORES
diff --git a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
index e0365fc..c7ca18c 100644
--- a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
+++ b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
@@ -571,7 +571,7 @@
if (OK != createDecoder()) return UNKNOWN_ERROR;
mNumCores = MIN(getCpuCoreCount(), MAX_NUM_CORES);
- mStride = ALIGN64(mWidth);
+ mStride = ALIGN32(mWidth);
mSignalledError = false;
resetPlugin();
(void) setNumCores();
@@ -589,10 +589,20 @@
size_t inSize,
uint32_t tsMarker) {
uint32_t displayStride = mStride;
+ if (outBuffer) {
+ C2PlanarLayout layout;
+ layout = outBuffer->layout();
+ displayStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
+ }
uint32_t displayHeight = mHeight;
size_t lumaSize = displayStride * displayHeight;
size_t chromaSize = lumaSize >> 2;
+ if (mStride != displayStride) {
+ mStride = displayStride;
+ if (OK != setParams(mStride)) return false;
+ }
+
ps_decode_ip->u4_size = sizeof(ivd_video_decode_ip_t);
ps_decode_ip->e_cmd = IVD_CMD_VIDEO_DECODE;
if (inBuffer) {
@@ -833,24 +843,21 @@
ALOGE("not supposed to be here, invalid decoder context");
return C2_CORRUPTED;
}
- if (mStride != ALIGN64(mWidth)) {
- mStride = ALIGN64(mWidth);
- if (OK != setParams(mStride)) return C2_CORRUPTED;
- }
if (mOutBlock &&
- (mOutBlock->width() != mStride || mOutBlock->height() != mHeight)) {
+ (mOutBlock->width() != ALIGN32(mWidth) || mOutBlock->height() != mHeight)) {
mOutBlock.reset();
}
if (!mOutBlock) {
uint32_t format = HAL_PIXEL_FORMAT_YV12;
C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
- c2_status_t err = pool->fetchGraphicBlock(mStride, mHeight, format, usage, &mOutBlock);
+ c2_status_t err =
+ pool->fetchGraphicBlock(ALIGN32(mWidth), mHeight, format, usage, &mOutBlock);
if (err != C2_OK) {
ALOGE("fetchGraphicBlock for Output failed with status %d", err);
return err;
}
ALOGV("provided (%dx%d) required (%dx%d)",
- mOutBlock->width(), mOutBlock->height(), mStride, mHeight);
+ mOutBlock->width(), mOutBlock->height(), ALIGN32(mWidth), mHeight);
}
return C2_OK;
diff --git a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h
index 65d3b87..fd66304a 100644
--- a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h
+++ b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h
@@ -37,7 +37,7 @@
#define ivdext_ctl_set_num_cores_op_t impeg2d_ctl_set_num_cores_op_t
#define ivdext_ctl_get_seq_info_ip_t impeg2d_ctl_get_seq_info_ip_t
#define ivdext_ctl_get_seq_info_op_t impeg2d_ctl_get_seq_info_op_t
-#define ALIGN64(x) ((((x) + 63) >> 6) << 6)
+#define ALIGN32(x) ((((x) + 31) >> 5) << 5)
#define MAX_NUM_CORES 4
#define IVDEXT_CMD_CTL_SET_NUM_CORES \
(IVD_CONTROL_API_COMMAND_TYPE_T)IMPEG2D_CMD_CTL_SET_NUM_CORES
diff --git a/media/codec2/hidl/1.0/vts/functional/common/Android.bp b/media/codec2/hidl/1.0/vts/functional/common/Android.bp
index a011ba3..3b4e232 100644
--- a/media/codec2/hidl/1.0/vts/functional/common/Android.bp
+++ b/media/codec2/hidl/1.0/vts/functional/common/Android.bp
@@ -1,7 +1,7 @@
cc_library_static {
name: "VtsHalMediaC2V1_0CommonUtil",
defaults: [
- "VtsHalTargetTestDefaults",
+ "Vts10HalTargetTestDefaults",
"libcodec2-hidl-client-defaults",
],
@@ -19,7 +19,7 @@
cc_defaults {
name: "VtsHalMediaC2V1_0Defaults",
defaults: [
- "VtsHalTargetTestDefaults",
+ "Vts10HalTargetTestDefaults",
"libcodec2-hidl-client-defaults",
],
diff --git a/media/codec2/sfplugin/CCodecBuffers.cpp b/media/codec2/sfplugin/CCodecBuffers.cpp
index 668f892..d7cc175 100644
--- a/media/codec2/sfplugin/CCodecBuffers.cpp
+++ b/media/codec2/sfplugin/CCodecBuffers.cpp
@@ -261,6 +261,7 @@
std::shared_ptr<C2Buffer> result = mBuffers[index].compBuffer.lock();
if (!result) {
result = clientBuffer->asC2Buffer();
+ clientBuffer->clearC2BufferRefs();
mBuffers[index].compBuffer = result;
}
if (c2buffer) {
@@ -379,6 +380,7 @@
std::shared_ptr<C2Buffer> result = mBuffers[index].compBuffer.lock();
if (!result) {
result = clientBuffer->asC2Buffer();
+ clientBuffer->clearC2BufferRefs();
mBuffers[index].compBuffer = result;
}
if (c2buffer) {
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index b6d18e2..5b3a62f 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -111,7 +111,11 @@
}
std::shared_ptr<C2Buffer> DummyContainerBuffer::asC2Buffer() {
- return std::move(mBufferRef);
+ return mBufferRef;
+}
+
+void DummyContainerBuffer::clearC2BufferRefs() {
+ mBufferRef.reset();
}
bool DummyContainerBuffer::canCopy(const std::shared_ptr<C2Buffer> &) const {
@@ -187,7 +191,11 @@
}
std::shared_ptr<C2Buffer> ConstLinearBlockBuffer::asC2Buffer() {
- return std::move(mBufferRef);
+ return mBufferRef;
+}
+
+void ConstLinearBlockBuffer::clearC2BufferRefs() {
+ mBufferRef.reset();
}
// GraphicView2MediaImageConverter
@@ -689,8 +697,12 @@
}
std::shared_ptr<C2Buffer> ConstGraphicBlockBuffer::asC2Buffer() {
+ return mBufferRef;
+}
+
+void ConstGraphicBlockBuffer::clearC2BufferRefs() {
mView.reset();
- return std::move(mBufferRef);
+ mBufferRef.reset();
}
bool ConstGraphicBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
diff --git a/media/codec2/sfplugin/Codec2Buffer.h b/media/codec2/sfplugin/Codec2Buffer.h
index 09475ef..ff79946 100644
--- a/media/codec2/sfplugin/Codec2Buffer.h
+++ b/media/codec2/sfplugin/Codec2Buffer.h
@@ -59,6 +59,8 @@
sp<ABuffer> getImageData() const { return mImageData; }
+ virtual void clearC2BufferRefs() {}
+
protected:
/**
* canCopy() implementation for linear buffers.
@@ -102,6 +104,7 @@
const std::shared_ptr<C2Buffer> &buffer = nullptr);
std::shared_ptr<C2Buffer> asC2Buffer() override;
+ void clearC2BufferRefs() override;
bool canCopy(const std::shared_ptr<C2Buffer> &buffer) const override;
bool copy(const std::shared_ptr<C2Buffer> &buffer) override;
@@ -161,6 +164,7 @@
virtual ~ConstLinearBlockBuffer() = default;
std::shared_ptr<C2Buffer> asC2Buffer() override;
+ void clearC2BufferRefs() override;
private:
ConstLinearBlockBuffer(
@@ -280,6 +284,7 @@
virtual ~ConstGraphicBlockBuffer() = default;
std::shared_ptr<C2Buffer> asC2Buffer() override;
+ void clearC2BufferRefs() override;
bool canCopy(const std::shared_ptr<C2Buffer> &buffer) const override;
bool copy(const std::shared_ptr<C2Buffer> &buffer) override;
diff --git a/media/extractors/flac/Android.bp b/media/extractors/flac/Android.bp
index 3675611..826c1a0 100644
--- a/media/extractors/flac/Android.bp
+++ b/media/extractors/flac/Android.bp
@@ -9,6 +9,7 @@
],
shared_libs: [
+ "libbase",
"libbinder_ndk",
],
diff --git a/media/extractors/flac/FLACExtractor.cpp b/media/extractors/flac/FLACExtractor.cpp
index 5329bd1..0617e88 100644
--- a/media/extractors/flac/FLACExtractor.cpp
+++ b/media/extractors/flac/FLACExtractor.cpp
@@ -24,6 +24,7 @@
// libFLAC parser
#include "FLAC/stream_decoder.h"
+#include <android-base/properties.h>
#include <android/binder_ibinder.h> // for AIBinder_getCallingUid
#include <audio_utils/primitives.h>
#include <media/MediaExtractorPluginApi.h>
@@ -47,7 +48,8 @@
// (Note: duplicated with WAVExtractor.cpp)
static inline bool shouldExtractorOutputFloat(int bitsPerSample)
{
- return bitsPerSample > 16 && AIBinder_getCallingUid() == AID_MEDIA;
+ return bitsPerSample > 16 && AIBinder_getCallingUid() == AID_MEDIA
+ && android::base::GetBoolProperty("media.extractor.float", true);
}
class FLACParser;
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index b72a8cc..54f1fa2 100755
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -113,6 +113,7 @@
const Trex *mTrex;
off64_t mFirstMoofOffset;
off64_t mCurrentMoofOffset;
+ off64_t mCurrentMoofSize;
off64_t mNextMoofOffset;
uint32_t mCurrentTime; // in media timescale ticks
int32_t mLastParsedTrackId;
@@ -165,8 +166,9 @@
status_t parseTrackFragmentRun(off64_t offset, off64_t size);
status_t parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size);
status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size);
- status_t parseClearEncryptedSizes(off64_t offset, bool isSubsampleEncryption, uint32_t flags);
- status_t parseSampleEncryption(off64_t offset);
+ status_t parseClearEncryptedSizes(off64_t offset, bool isSampleEncryption,
+ uint32_t flags, off64_t size);
+ status_t parseSampleEncryption(off64_t offset, off64_t size);
// returns -1 for invalid layer ID
int32_t parseHEVCLayerId(const uint8_t *data, size_t size);
@@ -2896,7 +2898,7 @@
return ERROR_MALFORMED;
}
- parseID3v2MetaData(data_offset + 6);
+ parseID3v2MetaData(data_offset + 6, chunk_data_size - 6);
break;
}
@@ -4167,8 +4169,19 @@
return OK;
}
-void MPEG4Extractor::parseID3v2MetaData(off64_t offset) {
- ID3 id3(mDataSource, true /* ignorev1 */, offset);
+void MPEG4Extractor::parseID3v2MetaData(off64_t offset, uint64_t size) {
+ uint8_t *buffer = new (std::nothrow) uint8_t[size];
+ if (buffer == NULL) {
+ return;
+ }
+ if (mDataSource->readAt(offset, buffer, size) != (ssize_t)size) {
+ delete[] buffer;
+ buffer = NULL;
+ return;
+ }
+
+ ID3 id3(buffer, size, true /* ignorev1 */);
+ delete[] buffer;
if (id3.isValid()) {
struct Map {
@@ -4848,6 +4861,7 @@
mTrex(trex),
mFirstMoofOffset(firstMoofOffset),
mCurrentMoofOffset(firstMoofOffset),
+ mCurrentMoofSize(0),
mNextMoofOffset(-1),
mCurrentTime(0),
mDefaultEncryptedByteBlock(0),
@@ -5098,6 +5112,9 @@
case FOURCC("moof"): {
off64_t stop_offset = *offset + chunk_size;
*offset = data_offset;
+ if (chunk_type == FOURCC("moof")) {
+ mCurrentMoofSize = chunk_data_size;
+ }
while (*offset < stop_offset) {
status_t err = parseChunk(offset);
if (err != OK) {
@@ -5186,7 +5203,7 @@
case FOURCC("senc"): {
status_t err;
- if ((err = parseSampleEncryption(data_offset)) != OK) {
+ if ((err = parseSampleEncryption(data_offset, chunk_data_size)) != OK) {
return err;
}
*offset += chunk_size;
@@ -5379,11 +5396,11 @@
drmoffset += mCurrentMoofOffset;
- return parseClearEncryptedSizes(drmoffset, false, 0);
+ return parseClearEncryptedSizes(drmoffset, false, 0, mCurrentMoofSize);
}
status_t MPEG4Source::parseClearEncryptedSizes(
- off64_t offset, bool isSubsampleEncryption, uint32_t flags) {
+ off64_t offset, bool isSampleEncryption, uint32_t flags, off64_t size) {
int32_t ivlength;
if (!AMediaFormat_getInt32(mFormat, AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE, &ivlength)) {
@@ -5397,11 +5414,15 @@
}
uint32_t sampleCount = mCurrentSampleInfoCount;
- if (isSubsampleEncryption) {
+ if (isSampleEncryption) {
+ if (size < 4) {
+ return ERROR_MALFORMED;
+ }
if (!mDataSource->getUInt32(offset, &sampleCount)) {
return ERROR_IO;
}
offset += 4;
+ size -= 4;
}
// read CencSampleAuxiliaryDataFormats
@@ -5416,14 +5437,18 @@
}
memset(smpl->iv, 0, 16);
+ if (size < ivlength) {
+ return ERROR_MALFORMED;
+ }
if (mDataSource->readAt(offset, smpl->iv, ivlength) != ivlength) {
return ERROR_IO;
}
offset += ivlength;
+ size -= ivlength;
bool readSubsamples;
- if (isSubsampleEncryption) {
+ if (isSampleEncryption) {
readSubsamples = flags & 2;
} else {
int32_t smplinfosize = mCurrentDefaultSampleInfoSize;
@@ -5435,13 +5460,20 @@
if (readSubsamples) {
uint16_t numsubsamples;
+ if (size < 2) {
+ return ERROR_MALFORMED;
+ }
if (!mDataSource->getUInt16(offset, &numsubsamples)) {
return ERROR_IO;
}
offset += 2;
+ size -= 2;
for (size_t j = 0; j < numsubsamples; j++) {
uint16_t numclear;
uint32_t numencrypted;
+ if (size < 6) {
+ return ERROR_MALFORMED;
+ }
if (!mDataSource->getUInt16(offset, &numclear)) {
return ERROR_IO;
}
@@ -5450,6 +5482,7 @@
return ERROR_IO;
}
offset += 4;
+ size -= 6;
smpl->clearsizes.add(numclear);
smpl->encryptedsizes.add(numencrypted);
}
@@ -5462,12 +5495,15 @@
return OK;
}
-status_t MPEG4Source::parseSampleEncryption(off64_t offset) {
+status_t MPEG4Source::parseSampleEncryption(off64_t offset, off64_t chunk_data_size) {
uint32_t flags;
+ if (chunk_data_size < 4) {
+ return ERROR_MALFORMED;
+ }
if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags
return ERROR_MALFORMED;
}
- return parseClearEncryptedSizes(offset + 4, true, flags);
+ return parseClearEncryptedSizes(offset + 4, true, flags, chunk_data_size - 4);
}
status_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) {
diff --git a/media/extractors/mp4/MPEG4Extractor.h b/media/extractors/mp4/MPEG4Extractor.h
index 3af432d..1e49d50 100644
--- a/media/extractors/mp4/MPEG4Extractor.h
+++ b/media/extractors/mp4/MPEG4Extractor.h
@@ -161,7 +161,7 @@
status_t parseITunesMetaData(off64_t offset, size_t size);
status_t parseColorInfo(off64_t offset, size_t size);
status_t parse3GPPMetaData(off64_t offset, size_t size, int depth);
- void parseID3v2MetaData(off64_t offset);
+ void parseID3v2MetaData(off64_t offset, uint64_t size);
status_t parseQTMetaKey(off64_t data_offset, size_t data_size);
status_t parseQTMetaVal(int32_t keyId, off64_t data_offset, size_t data_size);
diff --git a/media/extractors/wav/Android.bp b/media/extractors/wav/Android.bp
index 8ce5c3f..5d38a81 100644
--- a/media/extractors/wav/Android.bp
+++ b/media/extractors/wav/Android.bp
@@ -10,6 +10,7 @@
],
shared_libs: [
+ "libbase",
"libbinder_ndk",
],
diff --git a/media/extractors/wav/WAVExtractor.cpp b/media/extractors/wav/WAVExtractor.cpp
index 4fa7f27..d19447a 100644
--- a/media/extractors/wav/WAVExtractor.cpp
+++ b/media/extractors/wav/WAVExtractor.cpp
@@ -20,6 +20,7 @@
#include "WAVExtractor.h"
+#include <android-base/properties.h>
#include <android/binder_ibinder.h> // for AIBinder_getCallingUid
#include <audio_utils/primitives.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -43,7 +44,8 @@
// (Note: duplicated with FLACExtractor.cpp)
static inline bool shouldExtractorOutputFloat(int bitsPerSample)
{
- return bitsPerSample > 16 && AIBinder_getCallingUid() == AID_MEDIA;
+ return bitsPerSample > 16 && AIBinder_getCallingUid() == AID_MEDIA
+ && android::base::GetBoolProperty("media.extractor.float", true);
}
enum {
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index fcccf03..6723ec9 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -714,12 +714,8 @@
aaudio_result_t AudioStreamInternal::setBufferSize(int32_t requestedFrames) {
int32_t adjustedFrames = requestedFrames;
const int32_t maximumSize = getBufferCapacity() - mFramesPerBurst;
- // The buffer size can be set to zero.
- // This means that the callback may be called when the internal buffer becomes empty.
- // This will be fine on some devices in ideal circumstances and will result in the
- // lowest possible latency.
- // If there are glitches then they should be detected as XRuns and the size can be increased.
- static const int32_t minimumSize = 0;
+ // Minimum size should be a multiple number of bursts.
+ const int32_t minimumSize = 1 * mFramesPerBurst;
// Clip to minimum size so that rounding up will work better.
adjustedFrames = std::max(minimumSize, adjustedFrames);
@@ -731,12 +727,14 @@
// Round to the next highest burst size.
int32_t numBursts = (adjustedFrames + mFramesPerBurst - 1) / mFramesPerBurst;
adjustedFrames = numBursts * mFramesPerBurst;
+ // Clip just in case maximumSize is not a multiple of mFramesPerBurst.
+ adjustedFrames = std::min(maximumSize, adjustedFrames);
}
// Clip against the actual size from the endpoint.
int32_t actualFrames = 0;
mAudioEndpoint.setBufferSizeInFrames(maximumSize, &actualFrames);
- // actualFrames should be <= maximumSize
+ // actualFrames should be <= actual maximum size of endpoint
adjustedFrames = std::min(actualFrames, adjustedFrames);
mBufferSizeInFrames = adjustedFrames;
diff --git a/media/libaaudio/src/client/IsochronousClockModel.cpp b/media/libaaudio/src/client/IsochronousClockModel.cpp
index bd46d05..f0dcd44 100644
--- a/media/libaaudio/src/client/IsochronousClockModel.cpp
+++ b/media/libaaudio/src/client/IsochronousClockModel.cpp
@@ -47,6 +47,7 @@
, mMarkerNanoTime(0)
, mSampleRate(48000)
, mFramesPerBurst(48)
+ , mBurstPeriodNanos(0) // this will be updated before use
, mMaxMeasuredLatenessNanos(0)
, mLatenessForDriftNanos(kInitialLatenessForDriftNanos)
, mState(STATE_STOPPED)
@@ -57,9 +58,6 @@
}
}
-IsochronousClockModel::~IsochronousClockModel() {
-}
-
void IsochronousClockModel::setPositionAndTime(int64_t framePosition, int64_t nanoTime) {
ALOGV("setPositionAndTime, %lld, %lld", (long long) framePosition, (long long) nanoTime);
mMarkerFramePosition = framePosition;
@@ -186,7 +184,7 @@
// Calculate upper region that will trigger a drift forwards.
mLatenessForDriftNanos = mMaxMeasuredLatenessNanos - (mMaxMeasuredLatenessNanos >> 4);
} else { // decrease
- // If these is an outlier in lateness then mMaxMeasuredLatenessNanos can go high
+ // If this is an outlier in lateness then mMaxMeasuredLatenessNanos can go high
// and stay there. So we slowly reduce mMaxMeasuredLatenessNanos for better
// long term stability. The two opposing forces will keep mMaxMeasuredLatenessNanos
// within a reasonable range.
diff --git a/media/libaaudio/src/client/IsochronousClockModel.h b/media/libaaudio/src/client/IsochronousClockModel.h
index 40f066b..6280013 100644
--- a/media/libaaudio/src/client/IsochronousClockModel.h
+++ b/media/libaaudio/src/client/IsochronousClockModel.h
@@ -35,7 +35,7 @@
public:
IsochronousClockModel();
- virtual ~IsochronousClockModel();
+ virtual ~IsochronousClockModel() = default;
void start(int64_t nanoTime);
void stop(int64_t nanoTime);
@@ -130,6 +130,7 @@
private:
int32_t getLateTimeOffsetNanos() const;
+ void update();
enum clock_model_state_t {
STATE_STOPPED,
@@ -164,7 +165,6 @@
// distribution of timestamps relative to earliest
std::unique_ptr<android::audio_utils::Histogram> mHistogramMicros;
- void update();
};
} /* namespace aaudio */
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index d54d043..6da63e8 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -215,6 +215,9 @@
: (aaudio_session_id_t) mAudioTrack->getSessionId();
setSessionId(actualSessionId);
+ mInitialBufferCapacity = getBufferCapacity();
+ mInitialFramesPerBurst = getFramesPerBurst();
+
mAudioTrack->addAudioDeviceCallback(mDeviceCallback);
// Update performance mode based on the actual stream flags.
@@ -265,7 +268,16 @@
// Stream got rerouted so we disconnect.
case AudioTrack::EVENT_NEW_IAUDIOTRACK:
- processCallbackCommon(AAUDIO_CALLBACK_OPERATION_DISCONNECTED, info);
+ // request stream disconnect if the restored AudioTrack has properties not matching
+ // what was requested initially
+ if (mAudioTrack->channelCount() != getSamplesPerFrame()
+ || mAudioTrack->format() != getFormat()
+ || mAudioTrack->getSampleRate() != getSampleRate()
+ || mAudioTrack->getRoutedDeviceId() != getDeviceId()
+ || getBufferCapacity() != mInitialBufferCapacity
+ || getFramesPerBurst() != mInitialFramesPerBurst) {
+ processCallbackCommon(AAUDIO_CALLBACK_OPERATION_DISCONNECTED, info);
+ }
break;
default:
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.h b/media/libaaudio/src/legacy/AudioStreamTrack.h
index 550f693..93a1ff4 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.h
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.h
@@ -104,6 +104,10 @@
// TODO add 64-bit position reporting to AudioTrack and use it.
aaudio_wrapping_frames_t mPositionWhenPausing = 0;
+
+ // initial AudioTrack frame count and notification period
+ int32_t mInitialBufferCapacity = 0;
+ int32_t mInitialFramesPerBurst = 0;
};
} /* namespace aaudio */
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index f9d1798..fc50e07 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -394,7 +394,7 @@
AutoMutex lock(mLock);
status_t status = NO_ERROR;
- mediametrics::Defer([&] {
+ mediametrics::Defer defer([&] {
mediametrics::LogItem(mMetricsId)
.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_START)
.set(AMEDIAMETRICS_PROP_DURATIONNS, (int64_t)(systemTime() - beginNs))
@@ -411,6 +411,9 @@
mFramesReadServerOffset -= mFramesRead + framesFlushed;
mFramesRead = 0;
mProxy->clearTimestamp(); // timestamp is invalid until next server push
+ mPreviousTimestamp.clear();
+ mTimestampRetrogradePositionReported = false;
+ mTimestampRetrogradeTimeReported = false;
// reset current position as seen by client to 0
mProxy->setEpoch(mProxy->getEpoch() - mProxy->getPosition());
@@ -467,7 +470,7 @@
{
const int64_t beginNs = systemTime();
AutoMutex lock(mLock);
- mediametrics::Defer([&] {
+ mediametrics::Defer defer([&] {
mediametrics::LogItem(mMetricsId)
.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_STOP)
.set(AMEDIAMETRICS_PROP_DURATIONNS, (int64_t)(systemTime() - beginNs))
@@ -600,6 +603,39 @@
timestamp->mPosition[i] += mFramesReadServerOffset;
}
}
+
+ bool timestampRetrogradeTimeReported = false;
+ bool timestampRetrogradePositionReported = false;
+ for (int i = 0; i < ExtendedTimestamp::LOCATION_MAX; ++i) {
+ if (timestamp->mTimeNs[i] >= 0 && mPreviousTimestamp.mTimeNs[i] >= 0) {
+ if (timestamp->mTimeNs[i] < mPreviousTimestamp.mTimeNs[i]) {
+ if (!mTimestampRetrogradeTimeReported) {
+ ALOGD("%s: retrograde time adjusting [%d] current:%lld to previous:%lld",
+ __func__, i, (long long)timestamp->mTimeNs[i],
+ (long long)mPreviousTimestamp.mTimeNs[i]);
+ timestampRetrogradeTimeReported = true;
+ }
+ timestamp->mTimeNs[i] = mPreviousTimestamp.mTimeNs[i];
+ }
+ if (timestamp->mPosition[i] < mPreviousTimestamp.mPosition[i]) {
+ if (!mTimestampRetrogradePositionReported) {
+ ALOGD("%s: retrograde position"
+ " adjusting [%d] current:%lld to previous:%lld",
+ __func__, i, (long long)timestamp->mPosition[i],
+ (long long)mPreviousTimestamp.mPosition[i]);
+ timestampRetrogradePositionReported = true;
+ }
+ timestamp->mPosition[i] = mPreviousTimestamp.mPosition[i];
+ }
+ }
+ }
+ mPreviousTimestamp = *timestamp;
+ if (timestampRetrogradeTimeReported) {
+ mTimestampRetrogradeTimeReported = true;
+ }
+ if (timestampRetrogradePositionReported) {
+ mTimestampRetrogradePositionReported = true;
+ }
}
return status;
}
@@ -1340,7 +1376,7 @@
{
status_t result = NO_ERROR; // logged: make sure to set this before returning.
const int64_t beginNs = systemTime();
- mediametrics::Defer([&] {
+ mediametrics::Defer defer([&] {
mediametrics::LogItem(mMetricsId)
.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_RESTORE)
.set(AMEDIAMETRICS_PROP_DURATIONNS, (int64_t)(systemTime() - beginNs))
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 74fa343..6357da4 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -55,6 +55,7 @@
{
sp<IAudioFlinger> af;
sp<AudioFlingerClient> afc;
+ bool reportNoError = false;
{
Mutex::Autolock _l(gLock);
if (gAudioFlinger == 0) {
@@ -70,7 +71,7 @@
if (gAudioFlingerClient == NULL) {
gAudioFlingerClient = new AudioFlingerClient();
} else {
- reportError(NO_ERROR);
+ reportNoError = true;
}
binder->linkToDeath(gAudioFlingerClient);
gAudioFlinger = interface_cast<IAudioFlinger>(binder);
@@ -86,6 +87,7 @@
af->registerClient(afc);
IPCThreadState::self()->restoreCallingIdentity(token);
}
+ if (reportNoError) reportError(NO_ERROR);
return af;
}
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 2f95886..8b357a3 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -73,7 +73,7 @@
static inline struct timespec convertNsToTimespec(int64_t ns) {
struct timespec tv;
tv.tv_sec = static_cast<time_t>(ns / NANOS_PER_SECOND);
- tv.tv_nsec = static_cast<long>(ns % NANOS_PER_SECOND);
+ tv.tv_nsec = static_cast<int64_t>(ns % NANOS_PER_SECOND);
return tv;
}
@@ -639,7 +639,7 @@
AutoMutex lock(mLock);
status_t status = NO_ERROR; // logged: make sure to set this before returning.
- mediametrics::Defer([&] {
+ mediametrics::Defer defer([&] {
mediametrics::LogItem(mMetricsId)
.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_START)
.set(AMEDIAMETRICS_PROP_DURATIONNS, (int64_t)(systemTime() - beginNs))
@@ -772,7 +772,7 @@
const int64_t beginNs = systemTime();
AutoMutex lock(mLock);
- mediametrics::Defer([&]() {
+ mediametrics::Defer defer([&]() {
mediametrics::LogItem(mMetricsId)
.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_STOP)
.set(AMEDIAMETRICS_PROP_DURATIONNS, (int64_t)(systemTime() - beginNs))
@@ -832,7 +832,7 @@
{
const int64_t beginNs = systemTime();
AutoMutex lock(mLock);
- mediametrics::Defer([&]() {
+ mediametrics::Defer defer([&]() {
mediametrics::LogItem(mMetricsId)
.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_FLUSH)
.set(AMEDIAMETRICS_PROP_DURATIONNS, (int64_t)(systemTime() - beginNs))
@@ -1767,7 +1767,7 @@
} else if (waitCount > 0) {
time_t ms = WAIT_PERIOD_MS * (time_t) waitCount;
timeout.tv_sec = ms / 1000;
- timeout.tv_nsec = (long) (ms % 1000) * 1000000;
+ timeout.tv_nsec = (ms % 1000) * 1000000;
requested = &timeout;
} else {
ALOGE("%s(%d): invalid waitCount %d", __func__, mPortId, waitCount);
diff --git a/media/libaudioclient/include/media/AudioAttributes.h b/media/libaudioclient/include/media/AudioAttributes.h
index 0a35e9e..001c629 100644
--- a/media/libaudioclient/include/media/AudioAttributes.h
+++ b/media/libaudioclient/include/media/AudioAttributes.h
@@ -28,7 +28,7 @@
{
public:
AudioAttributes() = default;
- AudioAttributes(const audio_attributes_t &attributes) : mAttributes(attributes) {}
+ AudioAttributes(const audio_attributes_t &attributes) : mAttributes(attributes) {} // NOLINT
AudioAttributes(volume_group_t groupId,
audio_stream_type_t stream,
const audio_attributes_t &attributes) :
diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h
index 5c300ed..b3c1cdf 100644
--- a/media/libaudioclient/include/media/AudioRecord.h
+++ b/media/libaudioclient/include/media/AudioRecord.h
@@ -711,6 +711,10 @@
bool mInOverrun; // whether recorder is currently in overrun state
+ ExtendedTimestamp mPreviousTimestamp{}; // used to detect retrograde motion
+ bool mTimestampRetrogradePositionReported = false; // reduce log spam
+ bool mTimestampRetrogradeTimeReported = false; // reduce log spam
+
private:
class DeathNotifier : public IBinder::DeathRecipient {
public:
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index 4adaaea..afae4d8 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -947,7 +947,7 @@
class AudioTrackThread : public Thread
{
public:
- AudioTrackThread(AudioTrack& receiver);
+ explicit AudioTrackThread(AudioTrack& receiver);
// Do not call Thread::requestExitAndWait() without first calling requestExit().
// Thread::requestExitAndWait() is not virtual, and the implementation doesn't do enough.
@@ -1226,7 +1226,7 @@
private:
class DeathNotifier : public IBinder::DeathRecipient {
public:
- DeathNotifier(AudioTrack* audioTrack) : mAudioTrack(audioTrack) { }
+ explicit DeathNotifier(AudioTrack* audioTrack) : mAudioTrack(audioTrack) { }
protected:
virtual void binderDied(const wp<IBinder>& who);
private:
diff --git a/media/libmedia/include/media/Modulo.h b/media/libmedia/include/media/Modulo.h
index 23280ac..c66928d 100644
--- a/media/libmedia/include/media/Modulo.h
+++ b/media/libmedia/include/media/Modulo.h
@@ -90,7 +90,7 @@
typedef typename std::make_unsigned<T>::type unsignedT;
Modulo() { } // intentionally uninitialized data
- Modulo(const T &value) { mValue = value; }
+ Modulo(const T &value) { mValue = value; } // NOLINT
const T & value() const { return mValue; } // not assignable
signedT signedValue() const { return mValue; }
unsignedT unsignedValue() const { return mValue; }
diff --git a/media/libmediametrics/include/media/MediaMetricsItem.h b/media/libmediametrics/include/media/MediaMetricsItem.h
index 08720f1..8477f8d 100644
--- a/media/libmediametrics/include/media/MediaMetricsItem.h
+++ b/media/libmediametrics/include/media/MediaMetricsItem.h
@@ -208,11 +208,11 @@
template<size_t N>
static inline bool startsWith(const std::string &s, const char (&comp)[N]) {
- return !strncmp(s.c_str(), comp, N - 1);
+ return !strncmp(s.c_str(), comp, N - 1); // last char is null termination
}
static inline bool startsWith(const std::string& s, const std::string& comp) {
- return !strncmp(s.c_str(), comp.c_str(), comp.size() - 1);
+ return !strncmp(s.c_str(), comp.c_str(), comp.size());
}
/**
@@ -223,7 +223,7 @@
class Defer {
public:
template <typename U>
- Defer(U &&f) : mThunk(std::forward<U>(f)) {}
+ explicit Defer(U &&f) : mThunk(std::forward<U>(f)) {}
~Defer() { mThunk(); }
private:
@@ -522,7 +522,7 @@
BufferedItem(const BufferedItem&) = delete;
BufferedItem& operator=(const BufferedItem&) = delete;
- BufferedItem(const std::string key, char *begin, char *end)
+ BufferedItem(const std::string& key, char *begin, char *end)
: BufferedItem(key.c_str(), begin, end) { }
BufferedItem(const char *key, char *begin, char *end)
@@ -687,7 +687,7 @@
template <size_t N = 4096>
class LogItem : public BufferedItem {
public:
- explicit LogItem(const std::string key) : LogItem(key.c_str()) { }
+ explicit LogItem(const std::string& key) : LogItem(key.c_str()) { }
// Since this class will not be defined before the base class, we initialize variables
// in our own order.
@@ -742,10 +742,10 @@
mElem = other.mElem;
return *this;
}
- Prop(Prop&& other) {
+ Prop(Prop&& other) noexcept {
*this = std::move(other);
}
- Prop& operator=(Prop&& other) {
+ Prop& operator=(Prop&& other) noexcept {
mName = std::move(other.mName);
mElem = std::move(other.mElem);
return *this;
@@ -856,7 +856,7 @@
// Iteration of props within item
class iterator {
public:
- iterator(const std::map<std::string, Prop>::const_iterator &_it) : it(_it) { }
+ explicit iterator(const std::map<std::string, Prop>::const_iterator &_it) : it(_it) { }
iterator &operator++() {
++it;
return *this;
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 81ffcbc..42a0622 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -57,7 +57,6 @@
#include <media/MediaMetadataRetrieverInterface.h>
#include <media/Metadata.h>
#include <media/AudioTrack.h>
-#include <media/MemoryLeakTrackUtil.h>
#include <media/stagefright/InterfaceUtils.h>
#include <media/stagefright/MediaCodecConstants.h>
#include <media/stagefright/MediaCodecList.h>
@@ -68,7 +67,7 @@
#include <media/stagefright/foundation/ALooperRoster.h>
#include <media/stagefright/SurfaceUtils.h>
#include <mediautils/BatteryNotifier.h>
-
+#include <mediautils/MemoryLeakTrackUtil.h>
#include <memunreachable/memunreachable.h>
#include <system/audio.h>
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AData.h b/media/libstagefright/foundation/include/media/stagefright/foundation/AData.h
index c6c12ff..87cf58b 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/AData.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/AData.h
@@ -28,6 +28,10 @@
#undef HIDE
#define HIDE __attribute__((visibility("hidden")))
+// The internals of AUnion cause problems with CFI
+#undef NO_CFI
+#define NO_CFI __attribute__((no_sanitize("cfi")))
+
namespace android {
/**
@@ -93,7 +97,7 @@
* \param args arbitrary arguments for constructor
*/
template<typename T, typename ...Args>
- inline static void emplace(size_t totalSize, T *addr, Args&&... args) {
+ inline static void NO_CFI emplace(size_t totalSize, T *addr, Args&&... args) {
new(addr)T(std::forward<Args>(args)...);
// clear slack space - this is not technically required
constexpr size_t size = sizeof(T);
@@ -160,7 +164,7 @@
template<
typename T, typename ...Args,
typename=typename std::enable_if<is_one_of<T, void, Ts...>::value>::type>
- inline void emplace(Args&&... args) {
+ inline void NO_CFI emplace(Args&&... args) {
_AUnion_impl::emplace(
sizeof(_type), reinterpret_cast<T*>(&mValue), std::forward<Args>(args)...);
}
diff --git a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
index 9df3508..7bd33c1 100644
--- a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
+++ b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
@@ -203,6 +203,14 @@
unsigned mSerial;
};
+bool AMPEG4ElementaryAssembler::initCheck() {
+ if(mSizeLength == 0 || mIndexLength == 0 || mIndexDeltaLength == 0) {
+ android_errorWriteLog(0x534e4554, "124777537");
+ return false;
+ }
+ return true;
+}
+
ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::addPacket(
const sp<ARTPSource> &source) {
List<sp<ABuffer> > *queue = source->queue();
@@ -250,12 +258,16 @@
} else {
// hexdump(buffer->data(), buffer->size());
if (buffer->size() < 2) {
+ android_errorWriteLog(0x534e4554, "124783982");
+ queue->erase(queue->begin());
return MALFORMED_PACKET;
}
unsigned AU_headers_length = U16_AT(buffer->data()); // in bits
if (buffer->size() < 2 + (AU_headers_length + 7) / 8) {
+ android_errorWriteLog(0x534e4554, "124783982");
+ queue->erase(queue->begin());
return MALFORMED_PACKET;
}
@@ -359,6 +371,8 @@
return MALFORMED_PACKET;
}
if (buffer->size() < offset + header.mSize) {
+ android_errorWriteLog(0x534e4554, "124783982");
+ queue->erase(queue->begin());
return MALFORMED_PACKET;
}
diff --git a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.h b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.h
index 693fca5..57b7d71 100644
--- a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.h
+++ b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.h
@@ -36,6 +36,7 @@
AMPEG4ElementaryAssembler(
const sp<AMessage> ¬ify, const AString &desc,
const AString ¶ms);
+ virtual bool initCheck();
protected:
virtual ~AMPEG4ElementaryAssembler();
diff --git a/media/libstagefright/rtsp/ARTPAssembler.h b/media/libstagefright/rtsp/ARTPAssembler.h
index 7c147be..4082d4c 100644
--- a/media/libstagefright/rtsp/ARTPAssembler.h
+++ b/media/libstagefright/rtsp/ARTPAssembler.h
@@ -39,6 +39,7 @@
void onPacketReceived(const sp<ARTPSource> &source);
virtual void onByeReceived() = 0;
+ virtual bool initCheck() { return true; }
protected:
virtual AssemblyStatus assembleMore(const sp<ARTPSource> &source) = 0;
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
index 4afa6f4..f5f8128 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -82,6 +82,10 @@
} else {
TRESPASS();
}
+
+ if (mAssembler != NULL && !mAssembler->initCheck()) {
+ mAssembler.clear();
+ }
}
static uint32_t AbsDiff(uint32_t seq1, uint32_t seq2) {
@@ -89,7 +93,7 @@
}
void ARTPSource::processRTPPacket(const sp<ABuffer> &buffer) {
- if (queuePacket(buffer) && mAssembler != NULL) {
+ if (mAssembler != NULL && queuePacket(buffer)) {
mAssembler->onPacketReceived(this);
}
}
@@ -171,7 +175,9 @@
}
void ARTPSource::byeReceived() {
- mAssembler->onByeReceived();
+ if (mAssembler != NULL) {
+ mAssembler->onByeReceived();
+ }
}
void ARTPSource::addFIR(const sp<ABuffer> &buffer) {
diff --git a/media/libstagefright/timedtext/TextDescriptions.cpp b/media/libstagefright/timedtext/TextDescriptions.cpp
index 0dc7722..2c2d11d 100644
--- a/media/libstagefright/timedtext/TextDescriptions.cpp
+++ b/media/libstagefright/timedtext/TextDescriptions.cpp
@@ -445,51 +445,75 @@
| *(tmpData + 10) << 8 | *(tmpData + 11);
parcel->writeInt32(rgba);
+ // tx3g box contains class FontTableBox() which extends ftab box
+ // This information is part of the 3gpp Timed Text Format
+ // Specification#: 26.245 / Section: 5.16(Sample Description Format)
+ // https://www.3gpp.org/ftp/Specs/archive/26_series/26.245/
+
tmpData += 12;
remaining -= 12;
- if (remaining < 2) {
+ if (remaining < 8) {
return OK;
}
- size_t dataPos = parcel->dataPosition();
-
- parcel->writeInt32(KEY_STRUCT_FONT_LIST);
- uint16_t count = U16_AT(tmpData);
- parcel->writeInt32(count);
-
- tmpData += 2;
- remaining -= 2;
-
- for (int i = 0; i < count; i++) {
- if (remaining < 3) {
- // roll back
- parcel->setDataPosition(dataPos);
- return OK;
- }
- // font ID
- parcel->writeInt32(U16_AT(tmpData));
-
- // font name length
- parcel->writeInt32(*(tmpData + 2));
-
- size_t len = *(tmpData + 2);
-
- tmpData += 3;
- remaining -= 3;
-
- if (remaining < len) {
- // roll back
- parcel->setDataPosition(dataPos);
- return OK;
- }
-
- parcel->write(tmpData, len);
- tmpData += len;
- remaining -= len;
+ size_t subChunkSize = U32_AT(tmpData);
+ if(remaining < subChunkSize) {
+ return OK;
}
- // there is a "DisparityBox" after this according to the spec, but we ignore it
+ uint32_t subChunkType = U32_AT(tmpData + 4);
+
+ if (subChunkType == FOURCC('f', 't', 'a', 'b'))
+ {
+ tmpData += 8;
+ size_t subChunkRemaining = subChunkSize - 8;
+
+ if(subChunkRemaining < 2) {
+ return OK;
+ }
+ size_t dataPos = parcel->dataPosition();
+
+ parcel->writeInt32(KEY_STRUCT_FONT_LIST);
+ uint16_t count = U16_AT(tmpData);
+ parcel->writeInt32(count);
+
+ tmpData += 2;
+ subChunkRemaining -= 2;
+
+ for (int i = 0; i < count; i++) {
+ if (subChunkRemaining < 3) {
+ // roll back
+ parcel->setDataPosition(dataPos);
+ return OK;
+ }
+ // font ID
+ parcel->writeInt32(U16_AT(tmpData));
+
+ // font name length
+ size_t len = *(tmpData + 2);
+
+ parcel->writeInt32(len);
+
+ tmpData += 3;
+ subChunkRemaining -=3;
+
+ if (subChunkRemaining < len) {
+ // roll back
+ parcel->setDataPosition(dataPos);
+ return OK;
+ }
+
+ parcel->writeByteArray(len, tmpData);
+ tmpData += len;
+ subChunkRemaining -= len;
+ }
+ tmpData += subChunkRemaining;
+ remaining -= subChunkSize;
+ } else {
+ tmpData += subChunkSize;
+ remaining -= subChunkSize;
+ }
break;
}
default:
diff --git a/media/utils/MemoryLeakTrackUtil.cpp b/media/utils/MemoryLeakTrackUtil.cpp
index 6166859..fdb8c4f 100644
--- a/media/utils/MemoryLeakTrackUtil.cpp
+++ b/media/utils/MemoryLeakTrackUtil.cpp
@@ -19,7 +19,7 @@
#define LOG_TAG "MemoryLeackTrackUtil"
#include <utils/Log.h>
-#include "media/MemoryLeakTrackUtil.h"
+#include <mediautils/MemoryLeakTrackUtil.h>
#include <sstream>
#include <bionic/malloc.h>
diff --git a/media/libmedia/include/media/MemoryLeakTrackUtil.h b/media/utils/include/mediautils/MemoryLeakTrackUtil.h
similarity index 100%
rename from media/libmedia/include/media/MemoryLeakTrackUtil.h
rename to media/utils/include/mediautils/MemoryLeakTrackUtil.h
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 1be2fcb..03c16f3 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -67,10 +67,10 @@
#include <powermanager/PowerManager.h>
#include <media/IMediaLogService.h>
-#include <media/MemoryLeakTrackUtil.h>
#include <media/nbaio/Pipe.h>
#include <media/nbaio/PipeReader.h>
#include <mediautils/BatteryNotifier.h>
+#include <mediautils/MemoryLeakTrackUtil.h>
#include <mediautils/ServiceUtilities.h>
#include <mediautils/TimeCheck.h>
#include <private/android_filesystem_config.h>
@@ -1185,15 +1185,21 @@
}
AutoMutex lock(mHardwareLock);
+ sp<DeviceHalInterface> primaryDev = mPrimaryHardwareDev->hwDevice();
+ if (primaryDev == nullptr) {
+ ALOGW("%s: no primary HAL device", __func__);
+ return INVALID_OPERATION;
+ }
mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
+ ret = primaryDev->setMicMute(state);
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
- status_t result = dev->setMicMute(state);
- if (result != NO_ERROR) {
- ret = result;
+ if (dev != primaryDev) {
+ (void)dev->setMicMute(state);
}
}
mHardwareStatus = AUDIO_HW_IDLE;
+ ALOGW_IF(ret != NO_ERROR, "%s: error %d setting state to HAL", __func__, ret);
return ret;
}
@@ -1203,20 +1209,18 @@
if (ret != NO_ERROR) {
return false;
}
- bool mute = true;
- bool state = AUDIO_MODE_INVALID;
AutoMutex lock(mHardwareLock);
- mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
- for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
- sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
- status_t result = dev->getMicMute(&state);
- if (result == NO_ERROR) {
- mute = mute && state;
- }
+ sp<DeviceHalInterface> primaryDev = mPrimaryHardwareDev->hwDevice();
+ if (primaryDev == nullptr) {
+ ALOGW("%s: no primary HAL device", __func__);
+ return false;
}
+ bool state;
+ mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
+ ret = primaryDev->getMicMute(&state);
mHardwareStatus = AUDIO_HW_IDLE;
-
- return mute;
+ ALOGE_IF(ret != NO_ERROR, "%s: error %d getting state from HAL", __func__, ret);
+ return (ret == NO_ERROR) && state;
}
void AudioFlinger::setRecordSilenced(audio_port_handle_t portId, bool silenced)
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioIODescriptorInterface.h b/services/audiopolicy/common/managerdefinitions/include/AudioIODescriptorInterface.h
index 6e29632..6167f95 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioIODescriptorInterface.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioIODescriptorInterface.h
@@ -34,6 +34,8 @@
virtual audio_patch_handle_t getPatchHandle() const = 0;
virtual void setPatchHandle(audio_patch_handle_t handle) = 0;
+
+ virtual bool isMmap() = 0;
};
template <class IoDescriptor, class Filter>
@@ -41,11 +43,24 @@
IoDescriptor& desc, Filter filter, bool& active, const DeviceVector& devices)
{
auto activeClients = desc->clientsList(true /*activeOnly*/);
- auto activeClientsWithRoute =
- desc->clientsList(true /*activeOnly*/, filter, true /*preferredDevice*/);
active = activeClients.size() > 0;
- if (active && activeClients.size() == activeClientsWithRoute.size()) {
- return devices.getDeviceFromId(activeClientsWithRoute[0]->preferredDeviceId());
+
+ if (active) {
+ // On MMAP IOs, the preferred device is selected by the first client (virtual client
+ // created when the mmap stream is opened). This client is never active.
+ // On non MMAP IOs, the preferred device is honored only if all active clients have
+ // a preferred device in which case the first client drives the selection.
+ if (desc->isMmap()) {
+ // The client list is never empty on a MMAP IO
+ return devices.getDeviceFromId(
+ desc->clientsList(false /*activeOnly*/)[0]->preferredDeviceId());
+ } else {
+ auto activeClientsWithRoute =
+ desc->clientsList(true /*activeOnly*/, filter, true /*preferredDevice*/);
+ if (activeClients.size() == activeClientsWithRoute.size()) {
+ return devices.getDeviceFromId(activeClientsWithRoute[0]->preferredDeviceId());
+ }
+ }
}
return nullptr;
}
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index c67a006..6f47abc 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -92,6 +92,12 @@
audio_config_base_t getConfig() const override;
audio_patch_handle_t getPatchHandle() const override;
void setPatchHandle(audio_patch_handle_t handle) override;
+ bool isMmap() override {
+ if (getPolicyAudioPort() != nullptr) {
+ return getPolicyAudioPort()->isMmap();
+ }
+ return false;
+ }
status_t open(const audio_config_t *config,
const sp<DeviceDescriptor> &device,
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 41f7dfc..39d1140 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -268,6 +268,12 @@
audio_config_base_t getConfig() const override;
audio_patch_handle_t getPatchHandle() const override;
void setPatchHandle(audio_patch_handle_t handle) override;
+ bool isMmap() override {
+ if (getPolicyAudioPort() != nullptr) {
+ return getPolicyAudioPort()->isMmap();
+ }
+ return false;
+ }
TrackClientVector clientsList(bool activeOnly = false,
product_strategy_t strategy = PRODUCT_STRATEGY_NONE,
diff --git a/services/audiopolicy/common/managerdefinitions/include/PolicyAudioPort.h b/services/audiopolicy/common/managerdefinitions/include/PolicyAudioPort.h
index 99df3c0..d2f6297 100644
--- a/services/audiopolicy/common/managerdefinitions/include/PolicyAudioPort.h
+++ b/services/audiopolicy/common/managerdefinitions/include/PolicyAudioPort.h
@@ -107,6 +107,15 @@
(mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD));
}
+ inline bool isMmap() const
+ {
+ return (asAudioPort()->getType() == AUDIO_PORT_TYPE_MIX)
+ && (((asAudioPort()->getRole() == AUDIO_PORT_ROLE_SOURCE) &&
+ ((mFlags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) != 0))
+ || ((asAudioPort()->getRole() == AUDIO_PORT_ROLE_SINK) &&
+ ((mFlags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)));
+ }
+
void addRoute(const sp<AudioRoute> &route) { mRoutes.add(route); }
const AudioRouteVector &getRoutes() const { return mRoutes; }
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index bdd2427..3d16977 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2405,9 +2405,7 @@
for (size_t i = 0; i < mInputs.size(); i++) {
const sp<AudioInputDescriptor> input = mInputs.valueAt(i);
if (input->clientsList().size() == 0
- || !mAvailableInputDevices.containsAtLeastOne(input->supportedDevices())
- || (input->getPolicyAudioPort()->getFlags()
- & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
+ || !mAvailableInputDevices.containsAtLeastOne(input->supportedDevices())) {
inputsToClose.push_back(mInputs.keyAt(i));
} else {
bool close = false;
@@ -3758,6 +3756,22 @@
removeAudioPatch(patchDesc->getHandle());
nextAudioPortGeneration();
mpClientInterface->onAudioPatchListUpdate();
+ // SW Bridge
+ if (patch->num_sources > 1 && patch->sources[1].type == AUDIO_PORT_TYPE_MIX) {
+ sp<SwAudioOutputDescriptor> outputDesc =
+ mOutputs.getOutputFromId(patch->sources[1].id);
+ if (outputDesc == NULL) {
+ ALOGE("%s output not found for id %d", __func__, patch->sources[0].id);
+ return BAD_VALUE;
+ }
+ // Reset handle so that setOutputDevice will force new AF patch to reach the sink
+ outputDesc->setPatchHandle(AUDIO_PATCH_HANDLE_NONE);
+ setOutputDevices(outputDesc,
+ getNewOutputDevices(outputDesc, true /*fromCache*/),
+ true, /*force*/
+ 0,
+ NULL);
+ }
} else {
return BAD_VALUE;
}
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 9af1c36..f92d673 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -2742,7 +2742,7 @@
mClientPackageName(clientPackageName),
mClientPid(clientPid), mClientUid(clientUid),
mServicePid(servicePid),
- mDisconnected(false),
+ mDisconnected(false), mUidIsTrusted(false),
mAudioRestriction(hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE),
mRemoteBinder(remoteCallback)
{
@@ -2791,6 +2791,8 @@
if (getCurrentServingCall() != BinderCallType::HWBINDER) {
mAppOpsManager = std::make_unique<AppOpsManager>();
}
+
+ mUidIsTrusted = isTrustedCallingUid(mClientUid);
}
CameraService::BasicClient::~BasicClient() {
@@ -2905,7 +2907,9 @@
return PERMISSION_DENIED;
}
- if (res == AppOpsManager::MODE_IGNORED) {
+ // If the calling Uid is trusted (a native service), the AppOpsManager could
+ // return MODE_IGNORED. Do not treat such case as error.
+ if (!mUidIsTrusted && res == AppOpsManager::MODE_IGNORED) {
ALOGI("Camera %s: Access for \"%s\" has been restricted",
mCameraIdStr.string(), String8(mClientPackageName).string());
// Return the same error as for device policy manager rejection
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 1adf15a..18cf77a 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -323,6 +323,7 @@
const uid_t mClientUid;
const pid_t mServicePid;
bool mDisconnected;
+ bool mUidIsTrusted;
mutable Mutex mAudioRestrictionLock;
int32_t mAudioRestriction;
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
index 8f20685..237c24b 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
@@ -197,7 +197,9 @@
return PERMISSION_DENIED;
}
- if (res == AppOpsManager::MODE_IGNORED) {
+ // If the calling Uid is trusted (a native service), the AppOpsManager could
+ // return MODE_IGNORED. Do not treat such case as error.
+ if (!mUidIsTrusted && res == AppOpsManager::MODE_IGNORED) {
ALOGI("Offline Camera %s: Access for \"%s\" has been restricted",
mCameraIdStr.string(), String8(mClientPackageName).string());
// Return the same error as for device policy manager rejection
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index cc369fa..10b653e 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -841,13 +841,6 @@
itDuration++; itSize++;
}
- c.update(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS,
- dynamicDepthEntries.data(), dynamicDepthEntries.size());
- c.update(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS,
- dynamicDepthMinDurationEntries.data(), dynamicDepthMinDurationEntries.size());
- c.update(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS,
- dynamicDepthStallDurationEntries.data(), dynamicDepthStallDurationEntries.size());
-
std::vector<int32_t> supportedChTags;
supportedChTags.reserve(chTags.count + 3);
supportedChTags.insert(supportedChTags.end(), chTags.data.i32,
@@ -855,6 +848,12 @@
supportedChTags.push_back(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS);
supportedChTags.push_back(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS);
supportedChTags.push_back(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS);
+ c.update(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS,
+ dynamicDepthEntries.data(), dynamicDepthEntries.size());
+ c.update(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS,
+ dynamicDepthMinDurationEntries.data(), dynamicDepthMinDurationEntries.size());
+ c.update(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS,
+ dynamicDepthStallDurationEntries.data(), dynamicDepthStallDurationEntries.size());
c.update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, supportedChTags.data(),
supportedChTags.size());
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
index 238356e..4c8366f 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
@@ -246,6 +246,8 @@
frameNumber);
return;
}
+ nsecs_t sensorTimestamp = timestamp.data.i64[0];
+
for (auto& physicalMetadata : captureResult.mPhysicalMetadatas) {
camera_metadata_entry timestamp =
physicalMetadata.mPhysicalCameraMetadata.find(ANDROID_SENSOR_TIMESTAMP);
@@ -337,7 +339,7 @@
CameraMetadata(m.mPhysicalCameraMetadata));
}
states.tagMonitor.monitorMetadata(TagMonitor::RESULT,
- frameNumber, timestamp.data.i64[0], captureResult.mMetadata,
+ frameNumber, sensorTimestamp, captureResult.mMetadata,
monitoredPhysicalMetadata);
insertResultLocked(states, &captureResult, frameNumber);
diff --git a/services/camera/libcameraservice/tests/Android.mk b/services/camera/libcameraservice/tests/Android.mk
index fa5d69e..3ead715 100644
--- a/services/camera/libcameraservice/tests/Android.mk
+++ b/services/camera/libcameraservice/tests/Android.mk
@@ -48,6 +48,8 @@
LOCAL_CFLAGS += -Wall -Wextra -Werror
+LOCAL_SANITIZE := address
+
LOCAL_MODULE:= cameraservice_test
LOCAL_COMPATIBILITY_SUITE := device-tests
LOCAL_MODULE_TAGS := tests
diff --git a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
index a8f6889..855b5ab 100644
--- a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
+++ b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
@@ -40,8 +40,15 @@
*/
struct TestDeviceInterface : public device::V3_2::ICameraDevice {
std::vector<hardware::hidl_string> mDeviceNames;
+ android::hardware::hidl_vec<uint8_t> mCharacteristics;
+
+ TestDeviceInterface(std::vector<hardware::hidl_string> deviceNames,
+ android::hardware::hidl_vec<uint8_t> chars) :
+ mDeviceNames(deviceNames), mCharacteristics(chars) {}
+
TestDeviceInterface(std::vector<hardware::hidl_string> deviceNames) :
mDeviceNames(deviceNames) {}
+
using getResourceCost_cb = std::function<void(
hardware::camera::common::V1_0::Status status,
const hardware::camera::common::V1_0::CameraResourceCost& resourceCost)>;
@@ -58,8 +65,7 @@
const hardware::hidl_vec<uint8_t>& cameraCharacteristics)>;
hardware::Return<void> getCameraCharacteristics(
getCameraCharacteristics_cb _hidl_cb) override {
- hardware::hidl_vec<uint8_t> cameraCharacteristics;
- _hidl_cb(Status::OK, cameraCharacteristics);
+ _hidl_cb(Status::OK, mCharacteristics);
return hardware::Void();
}
@@ -100,6 +106,13 @@
mDeviceInterface(new TestDeviceInterface(devices)),
mVendorTagSections (vendorSection) {}
+ TestICameraProvider(const std::vector<hardware::hidl_string> &devices,
+ const hardware::hidl_vec<common::V1_0::VendorTagSection> &vendorSection,
+ android::hardware::hidl_vec<uint8_t> chars) :
+ mDeviceNames(devices),
+ mDeviceInterface(new TestDeviceInterface(devices, chars)),
+ mVendorTagSections (vendorSection) {}
+
virtual hardware::Return<Status> setCallback(
const sp<provider::V2_4::ICameraProviderCallback>& callbacks) override {
mCalledCounter[SET_CALLBACK]++;
@@ -243,6 +256,52 @@
void onNewProviderRegistered() override {}
};
+TEST(CameraProviderManagerTest, InitializeDynamicDepthTest) {
+ std::vector<hardware::hidl_string> deviceNames;
+ deviceNames.push_back("device@3.2/test/0");
+ hardware::hidl_vec<common::V1_0::VendorTagSection> vendorSection;
+ status_t res;
+ sp<CameraProviderManager> providerManager = new CameraProviderManager();
+ sp<TestStatusListener> statusListener = new TestStatusListener();
+ TestInteractionProxy serviceProxy;
+
+ android::hardware::hidl_vec<uint8_t> chars;
+ CameraMetadata meta;
+ int32_t charKeys[] = { ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE,
+ ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS };
+ meta.update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, charKeys,
+ sizeof(charKeys) / sizeof(charKeys[0]));
+ uint8_t depthIsExclusive = ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE_FALSE;
+ meta.update(ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE, &depthIsExclusive, 1);
+ int32_t sizes[] = { HAL_PIXEL_FORMAT_BLOB,
+ 640, 480, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT };
+ meta.update(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, sizes,
+ sizeof(sizes) / sizeof(sizes[0]));
+ sizes[0] = HAL_PIXEL_FORMAT_Y16;
+ meta.update(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS, sizes,
+ sizeof(sizes) / sizeof(sizes[0]));
+ int64_t durations[] = { HAL_PIXEL_FORMAT_BLOB, 640, 480, 0 };
+ meta.update(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS, durations,
+ sizeof(durations) / sizeof(durations[0]));
+ meta.update(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS, durations,
+ sizeof(durations) / sizeof(durations[0]));
+ durations[0]= HAL_PIXEL_FORMAT_Y16;
+ meta.update(ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS, durations,
+ sizeof(durations) / sizeof(durations[0]));
+ meta.update(ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS, durations,
+ sizeof(durations) / sizeof(durations[0]));
+ camera_metadata_t* metaBuffer = const_cast<camera_metadata_t*>(meta.getAndLock());
+ chars.setToExternal(reinterpret_cast<uint8_t*>(metaBuffer),
+ get_camera_metadata_size(metaBuffer));
+
+ sp<TestICameraProvider> provider = new TestICameraProvider(deviceNames,
+ vendorSection, chars);
+ serviceProxy.setProvider(provider);
+
+ res = providerManager->initialize(statusListener, &serviceProxy);
+ ASSERT_EQ(res, OK) << "Unable to initialize provider manager";
+}
+
TEST(CameraProviderManagerTest, InitializeTest) {
std::vector<hardware::hidl_string> deviceNames;
deviceNames.push_back("device@3.2/test/0");
diff --git a/services/camera/libcameraservice/tests/RotateAndCropMapperTest.cpp b/services/camera/libcameraservice/tests/RotateAndCropMapperTest.cpp
index c638d40..3c187cd 100644
--- a/services/camera/libcameraservice/tests/RotateAndCropMapperTest.cpp
+++ b/services/camera/libcameraservice/tests/RotateAndCropMapperTest.cpp
@@ -38,10 +38,9 @@
#define EXPECT_EQUAL_WITHIN_N(vec, array, N, msg) \
{ \
- std::vector<int32_t> vec_diff; \
- std::transform(vec.begin(), vec.end(), array, \
- std::back_inserter(vec_diff), std::minus()); \
- EXPECT_THAT(vec_diff, Each(AllOf(Ge(-N), Le(N)))) << msg; \
+ for (size_t i = 0; i < vec.size(); i++) { \
+ EXPECT_THAT(vec[i] - array[i], AllOf(Ge(-N), Le(N))) << msg " failed at index:" << i; \
+ } \
}
int32_t testActiveArray[] = {100, 100, 4000, 3000};
diff --git a/services/mediametrics/AnalyticsState.h b/services/mediametrics/AnalyticsState.h
index 290ed21..b648947 100644
--- a/services/mediametrics/AnalyticsState.h
+++ b/services/mediametrics/AnalyticsState.h
@@ -84,8 +84,11 @@
* delivered.
*
* \param lines the maximum number of lines in the string returned.
+ * \param sinceNs the nanoseconds since Unix epoch to start dump (0 shows all)
+ * \param prefix the desired key prefix to match (nullptr shows all)
*/
- std::pair<std::string, int32_t> dump(int32_t lines = INT32_MAX) const {
+ std::pair<std::string, int32_t> dump(
+ int32_t lines = INT32_MAX, int64_t sinceNs = 0, const char *prefix = nullptr) const {
std::stringstream ss;
int32_t ll = lines;
@@ -94,7 +97,7 @@
--ll;
}
if (ll > 0) {
- auto [s, l] = mTransactionLog.dump(ll);
+ auto [s, l] = mTransactionLog.dump(ll, sinceNs, prefix);
ss << s;
ll -= l;
}
@@ -103,7 +106,7 @@
--ll;
}
if (ll > 0) {
- auto [s, l] = mTimeMachine.dump(ll);
+ auto [s, l] = mTimeMachine.dump(ll, sinceNs, prefix);
ss << s;
ll -= l;
}
diff --git a/services/mediametrics/Android.bp b/services/mediametrics/Android.bp
index ec59ec1..58f3ea8 100644
--- a/services/mediametrics/Android.bp
+++ b/services/mediametrics/Android.bp
@@ -57,6 +57,7 @@
"liblog",
"libmediametrics",
"libmediautils",
+ "libmemunreachable",
"libprotobuf-cpp-lite",
"libstatslog",
"libutils",
diff --git a/services/mediametrics/AudioAnalytics.cpp b/services/mediametrics/AudioAnalytics.cpp
index 126e501..3f9a42f 100644
--- a/services/mediametrics/AudioAnalytics.cpp
+++ b/services/mediametrics/AudioAnalytics.cpp
@@ -107,13 +107,14 @@
return NO_ERROR;
}
-std::pair<std::string, int32_t> AudioAnalytics::dump(int32_t lines) const
+std::pair<std::string, int32_t> AudioAnalytics::dump(
+ int32_t lines, int64_t sinceNs, const char *prefix) const
{
std::stringstream ss;
int32_t ll = lines;
if (ll > 0) {
- auto [s, l] = mAnalyticsState->dump(ll);
+ auto [s, l] = mAnalyticsState->dump(ll, sinceNs, prefix);
ss << s;
ll -= l;
}
@@ -122,7 +123,7 @@
--ll;
}
if (ll > 0) {
- auto [s, l] = mPreviousAnalyticsState->dump(ll);
+ auto [s, l] = mPreviousAnalyticsState->dump(ll, sinceNs, prefix);
ss << s;
ll -= l;
}
diff --git a/services/mediametrics/AudioAnalytics.h b/services/mediametrics/AudioAnalytics.h
index 4a42e22..ba4c3f2 100644
--- a/services/mediametrics/AudioAnalytics.h
+++ b/services/mediametrics/AudioAnalytics.h
@@ -60,8 +60,17 @@
* delivered.
*
* \param lines the maximum number of lines in the string returned.
+ * \param sinceNs the nanoseconds since Unix epoch to start dump (0 shows all)
+ * \param prefix the desired key prefix to match (nullptr shows all)
*/
- std::pair<std::string, int32_t> dump(int32_t lines = INT32_MAX) const;
+ std::pair<std::string, int32_t> dump(
+ int32_t lines = INT32_MAX, int64_t sinceNs = 0, const char *prefix = nullptr) const;
+
+ void clear() {
+ // underlying state is locked.
+ mPreviousAnalyticsState->clear();
+ mAnalyticsState->clear();
+ }
private:
diff --git a/services/mediametrics/MediaMetricsService.cpp b/services/mediametrics/MediaMetricsService.cpp
index a6fefd2..b9703ba 100644
--- a/services/mediametrics/MediaMetricsService.cpp
+++ b/services/mediametrics/MediaMetricsService.cpp
@@ -26,6 +26,8 @@
#include <audio_utils/clock.h> // clock conversions
#include <binder/IPCThreadState.h> // get calling uid
#include <cutils/properties.h> // for property_get
+#include <mediautils/MemoryLeakTrackUtil.h>
+#include <memunreachable/memunreachable.h>
#include <private/android_filesystem_config.h> // UID
namespace android {
@@ -205,91 +207,112 @@
return NO_ERROR;
}
- // crack any parameters
- const String16 protoOption("--proto");
- const String16 clearOption("--clear");
+ static const String16 allOption("--all");
+ static const String16 clearOption("--clear");
+ static const String16 heapOption("--heap");
+ static const String16 helpOption("--help");
+ static const String16 prefixOption("--prefix");
+ static const String16 sinceOption("--since");
+ static const String16 unreachableOption("--unreachable");
+
+ bool all = false;
bool clear = false;
- const String16 sinceOption("--since");
- nsecs_t ts_since = 0;
- const String16 helpOption("--help");
- const String16 onlyOption("--only");
- std::string only;
- const int n = args.size();
- for (int i = 0; i < n; i++) {
- if (args[i] == clearOption) {
+ bool heap = false;
+ bool unreachable = false;
+ int64_t sinceNs = 0;
+ std::string prefix;
+
+ const size_t n = args.size();
+ for (size_t i = 0; i < n; i++) {
+ if (args[i] == allOption) {
+ all = true;
+ } else if (args[i] == clearOption) {
clear = true;
- } else if (args[i] == protoOption) {
- i++;
- if (i < n) {
- // ignore
- } else {
- result.append("missing value for -proto\n\n");
- }
- } else if (args[i] == sinceOption) {
- i++;
- if (i < n) {
- String8 value(args[i]);
- char *endp;
- const char *p = value.string();
- ts_since = strtoll(p, &endp, 10);
- if (endp == p || *endp != '\0') {
- ts_since = 0;
- }
- } else {
- ts_since = 0;
- }
- // command line is milliseconds; internal units are nano-seconds
- ts_since *= NANOS_PER_MILLISECOND;
- } else if (args[i] == onlyOption) {
- i++;
- if (i < n) {
- String8 value(args[i]);
- only = value.string();
- }
+ } else if (args[i] == heapOption) {
+ heap = true;
} else if (args[i] == helpOption) {
// TODO: consider function area dumping.
// dumpsys media.metrics audiotrack,codec
// or dumpsys media.metrics audiotrack codec
result.append("Recognized parameters:\n");
- result.append("--help this help message\n");
- result.append("--proto # dump using protocol #");
- result.append("--clear clears out saved records\n");
- result.append("--only X process records for component X\n");
- result.append("--since X include records since X\n");
- result.append(" (X is milliseconds since the UNIX epoch)\n");
+ result.append("--all show all records\n");
+ result.append("--clear clear out saved records\n");
+ result.append("--heap show heap usage (top 100)\n");
+ result.append("--help display help\n");
+ result.append("--prefix X process records for component X\n");
+ result.append("--since X X < 0: records from -X seconds in the past\n");
+ result.append(" X = 0: ignore\n");
+ result.append(" X > 0: records from X seconds since Unix epoch\n");
+ result.append("--unreachable show unreachable memory (leaks)\n");
write(fd, result.string(), result.size());
return NO_ERROR;
+ } else if (args[i] == prefixOption) {
+ ++i;
+ if (i < n) {
+ prefix = String8(args[i]).string();
+ }
+ } else if (args[i] == sinceOption) {
+ ++i;
+ if (i < n) {
+ String8 value(args[i]);
+ char *endp;
+ const char *p = value.string();
+ long long sec = strtoll(p, &endp, 10);
+ if (endp == p || *endp != '\0' || sec == 0) {
+ sinceNs = 0;
+ } else if (sec < 0) {
+ sinceNs = systemTime(SYSTEM_TIME_REALTIME) + sec * NANOS_PER_SECOND;
+ } else {
+ sinceNs = sec * NANOS_PER_SECOND;
+ }
+ }
+ } else if (args[i] == unreachableOption) {
+ unreachable = true;
}
}
{
std::lock_guard _l(mLock);
- result.appendFormat("Dump of the %s process:\n", kServiceName);
- dumpHeaders_l(result, ts_since);
- dumpRecent_l(result, ts_since, only.c_str());
-
if (clear) {
mItemsDiscarded += mItems.size();
mItems.clear();
- // shall we clear the summary data too?
- }
- // TODO: maybe consider a better way of dumping audio analytics info.
- constexpr int32_t linesToDump = 1000;
- auto [ dumpString, lines ] = mAudioAnalytics.dump(linesToDump);
- result.append(dumpString.c_str());
- if (lines == linesToDump) {
- result.append("-- some lines may be truncated --\n");
+ mAudioAnalytics.clear();
+ } else {
+ result.appendFormat("Dump of the %s process:\n", kServiceName);
+ const char *prefixptr = prefix.size() > 0 ? prefix.c_str() : nullptr;
+ dumpHeaders_l(result, sinceNs, prefixptr);
+ dumpQueue_l(result, sinceNs, prefixptr);
+
+ // TODO: maybe consider a better way of dumping audio analytics info.
+ const int32_t linesToDump = all ? INT32_MAX : 1000;
+ auto [ dumpString, lines ] = mAudioAnalytics.dump(linesToDump, sinceNs, prefixptr);
+ result.append(dumpString.c_str());
+ if (lines == linesToDump) {
+ result.append("-- some lines may be truncated --\n");
+ }
}
}
-
write(fd, result.string(), result.size());
+
+ // Check heap and unreachable memory outside of lock.
+ if (heap) {
+ dprintf(fd, "\nDumping heap:\n");
+ std::string s = dumpMemoryAddresses(100 /* limit */);
+ write(fd, s.c_str(), s.size());
+ }
+ if (unreachable) {
+ dprintf(fd, "\nDumping unreachable memory:\n");
+ // TODO - should limit be an argument parameter?
+ std::string s = GetUnreachableMemoryString(true /* contents */, 100 /* limit */);
+ write(fd, s.c_str(), s.size());
+ }
return NO_ERROR;
}
// dump headers
-void MediaMetricsService::dumpHeaders_l(String8 &result, nsecs_t ts_since)
+void MediaMetricsService::dumpHeaders_l(String8 &result, int64_t sinceNs, const char* prefix)
{
if (mediametrics::Item::isEnabled()) {
result.append("Metrics gathering: enabled\n");
@@ -303,54 +326,36 @@
"Records Discarded: %lld (by Count: %lld by Expiration: %lld)\n",
(long long)mItemsDiscarded, (long long)mItemsDiscardedCount,
(long long)mItemsDiscardedExpire);
- if (ts_since != 0) {
+ if (prefix != nullptr) {
+ result.appendFormat("Restricting to prefix %s", prefix);
+ }
+ if (sinceNs != 0) {
result.appendFormat(
"Emitting Queue entries more recent than: %lld\n",
- (long long)ts_since);
+ (long long)sinceNs);
}
}
-void MediaMetricsService::dumpRecent_l(
- String8 &result, nsecs_t ts_since, const char * only)
+// TODO: should prefix be a set<string>?
+void MediaMetricsService::dumpQueue_l(String8 &result, int64_t sinceNs, const char* prefix)
{
- if (only != nullptr && *only == '\0') {
- only = nullptr;
- }
- result.append("\nFinalized Metrics (oldest first):\n");
- dumpQueue_l(result, ts_since, only);
-
- // show who is connected and injecting records?
- // talk about # records fed to the 'readers'
- // talk about # records we discarded, perhaps "discarded w/o reading" too
-}
-
-void MediaMetricsService::dumpQueue_l(String8 &result) {
- dumpQueue_l(result, (nsecs_t) 0, nullptr /* only */);
-}
-
-void MediaMetricsService::dumpQueue_l(
- String8 &result, nsecs_t ts_since, const char * only) {
- int slot = 0;
-
if (mItems.empty()) {
result.append("empty\n");
- } else {
- for (const auto &item : mItems) {
- nsecs_t when = item->getTimestamp();
- if (when < ts_since) {
- continue;
- }
- // TODO: Only should be a set<string>
- if (only != nullptr &&
- item->getKey() /* std::string */ != only) {
- ALOGV("%s: omit '%s', it's not '%s'",
- __func__, item->getKey().c_str(), only);
- continue;
- }
- result.appendFormat("%5d: %s\n",
- slot, item->toString().c_str());
- slot++;
+ return;
+ }
+
+ int slot = 0;
+ for (const auto &item : mItems) { // TODO: consider std::lower_bound() on mItems
+ if (item->getTimestamp() < sinceNs) { // sinceNs == 0 means all items shown
+ continue;
}
+ if (prefix != nullptr && !startsWith(item->getKey(), prefix)) {
+ ALOGV("%s: omit '%s', it's not '%s'",
+ __func__, item->getKey().c_str(), prefix);
+ continue;
+ }
+ result.appendFormat("%5d: %s\n", slot, item->toString().c_str());
+ slot++;
}
}
diff --git a/services/mediametrics/MediaMetricsService.h b/services/mediametrics/MediaMetricsService.h
index 935bee2..a93f7fb 100644
--- a/services/mediametrics/MediaMetricsService.h
+++ b/services/mediametrics/MediaMetricsService.h
@@ -85,11 +85,8 @@
bool expirations_l(const std::shared_ptr<const mediametrics::Item>& item);
// support for generating output
- void dumpQueue_l(String8 &result);
- void dumpQueue_l(String8 &result, nsecs_t, const char *only);
- void dumpHeaders_l(String8 &result, nsecs_t ts_since);
- void dumpSummaries_l(String8 &result, nsecs_t ts_since, const char * only);
- void dumpRecent_l(String8 &result, nsecs_t ts_since, const char * only);
+ void dumpQueue_l(String8 &result, int64_t sinceNs, const char* prefix);
+ void dumpHeaders_l(String8 &result, int64_t sinceNs, const char* prefix);
// The following variables accessed without mLock
diff --git a/services/mediametrics/TimeMachine.h b/services/mediametrics/TimeMachine.h
index a4c3693..29adeae 100644
--- a/services/mediametrics/TimeMachine.h
+++ b/services/mediametrics/TimeMachine.h
@@ -149,8 +149,11 @@
int32_t ll = lines;
for (auto& tsPair : mPropertyMap) {
if (ll <= 0) break;
- ss << dump(mKey, tsPair, time);
- --ll;
+ std::string s = dump(mKey, tsPair, time);
+ if (s.size() > 0) {
+ --ll;
+ ss << s;
+ }
}
return { ss.str(), lines - ll };
}
@@ -165,7 +168,7 @@
const auto timeSequence = tsPair.second;
auto eptr = timeSequence.lower_bound(time);
if (eptr == timeSequence.end()) {
- return tsPair.first + "={};\n";
+ return {}; // don't dump anything. tsPair.first + "={};\n";
}
std::stringstream ss;
ss << key << "." << tsPair.first << "={";
@@ -316,7 +319,7 @@
if (it == mHistory.end()) continue;
remoteKeyHistory = it->second;
}
- std::lock_guard(getLockForKey(remoteKey));
+ std::lock_guard lock(getLockForKey(remoteKey));
remoteKeyHistory->putProp(remoteName, prop, time);
}
return NO_ERROR;
@@ -407,24 +410,22 @@
*
* \param lines the maximum number of lines in the string returned.
* \param key selects only that key.
- * \param time to start the dump from.
+ * \param sinceNs the nanoseconds since Unix epoch to start dump (0 shows all)
+ * \param prefix the desired key prefix to match (nullptr shows all)
*/
std::pair<std::string, int32_t> dump(
- int32_t lines = INT32_MAX, const std::string &key = {}, int64_t time = 0) const {
+ int32_t lines = INT32_MAX, int64_t sinceNs = 0, const char *prefix = nullptr) const {
std::lock_guard lock(mLock);
- if (!key.empty()) { // use std::regex
- const auto it = mHistory.find(key);
- if (it == mHistory.end()) return {};
- std::lock_guard lock(getLockForKey(it->first));
- return it->second->dump(lines, time);
- }
-
std::stringstream ss;
int32_t ll = lines;
- for (const auto &[lkey, lhist] : mHistory) {
- std::lock_guard lock(getLockForKey(lkey));
- if (lines <= 0) break;
- auto [s, l] = lhist->dump(ll, time);
+
+ for (auto it = prefix != nullptr ? mHistory.lower_bound(prefix) : mHistory.begin();
+ it != mHistory.end();
+ ++it) {
+ if (ll <= 0) break;
+ if (prefix != nullptr && !startsWith(it->first, prefix)) break;
+ std::lock_guard lock(getLockForKey(it->first));
+ auto [s, l] = it->second->dump(ll, sinceNs);
ss << s;
ll -= l;
}
@@ -440,7 +441,7 @@
// Finds a KeyHistory from a URL. Returns nullptr if not found.
std::shared_ptr<KeyHistory> getKeyHistoryFromUrl(
- std::string url, std::string* key, std::string *prop) const {
+ const std::string& url, std::string* key, std::string *prop) const {
std::lock_guard lock(mLock);
auto it = mHistory.upper_bound(url);
diff --git a/services/mediametrics/TransactionLog.h b/services/mediametrics/TransactionLog.h
index 190a99e..4f09bb0 100644
--- a/services/mediametrics/TransactionLog.h
+++ b/services/mediametrics/TransactionLog.h
@@ -127,8 +127,11 @@
* for subsequent line limiting.
*
* \param lines the maximum number of lines in the string returned.
+ * \param sinceNs the nanoseconds since Unix epoch to start dump (0 shows all)
+ * \param prefix the desired key prefix to match (nullptr shows all)
*/
- std::pair<std::string, int32_t> dump(int32_t lines) const {
+ std::pair<std::string, int32_t> dump(
+ int32_t lines, int64_t sinceNs, const char *prefix = nullptr) const {
std::stringstream ss;
int32_t ll = lines;
std::lock_guard lock(mLock);
@@ -138,26 +141,25 @@
ss << "Consolidated:\n";
--ll;
}
- for (const auto &log : mLog) {
- if (ll <= 0) break;
- ss << " " << log.second->toString() << "\n";
- --ll;
- }
+ auto [s, l] = dumpMapTimeItem(mLog, ll, sinceNs, prefix);
+ ss << s;
+ ll -= l;
// Grouped by item key (category)
if (ll > 0) {
ss << "Categorized:\n";
--ll;
}
- for (const auto &itemMap : mItemMap) {
+
+ for (auto it = prefix != nullptr ? mItemMap.lower_bound(prefix) : mItemMap.begin();
+ it != mItemMap.end();
+ ++it) {
if (ll <= 0) break;
- ss << " " << itemMap.first << "\n";
- --ll;
- for (const auto &item : itemMap.second) {
- if (ll <= 0) break;
- ss << " " << item.second->toString() << "\n";
- --ll;
- }
+ if (prefix != nullptr && !startsWith(it->first, prefix)) break;
+ auto [s, l] = dumpMapTimeItem(it->second, ll - 1, sinceNs, prefix);
+ if (l == 0) continue; // don't show empty groups (due to sinceNs).
+ ss << " " << it->first << "\n" << s;
+ ll -= l + 1;
}
return { ss.str(), lines - ll };
}
@@ -184,6 +186,24 @@
using MapTimeItem =
std::multimap<int64_t /* time */, std::shared_ptr<const mediametrics::Item>>;
+ static std::pair<std::string, int32_t> dumpMapTimeItem(
+ const MapTimeItem& mapTimeItem,
+ int32_t lines, int64_t sinceNs = 0, const char *prefix = nullptr) {
+ std::stringstream ss;
+ int32_t ll = lines;
+ // Note: for our data, mapTimeItem.lower_bound(0) == mapTimeItem.begin().
+ for (auto it = mapTimeItem.lower_bound(sinceNs);
+ it != mapTimeItem.end(); ++it) {
+ if (ll <= 0) break;
+ if (prefix != nullptr && !startsWith(it->second->getKey(), prefix)) {
+ continue;
+ }
+ ss << " " << it->second->toString() << "\n";
+ --ll;
+ }
+ return { ss.str(), lines - ll };
+ }
+
// GUARDED_BY mLock
/**
* Garbage collects if the TimeMachine size exceeds the high water mark.
diff --git a/services/mediametrics/tests/mediametrics_tests.cpp b/services/mediametrics/tests/mediametrics_tests.cpp
index b8e566e..78eb71c 100644
--- a/services/mediametrics/tests/mediametrics_tests.cpp
+++ b/services/mediametrics/tests/mediametrics_tests.cpp
@@ -79,7 +79,7 @@
const int mFinal;
public:
- Thunk(decltype(mF) f, int final) : mF(f), mFinal(final) {}
+ explicit Thunk(decltype(mF) f, int final) : mF(std::move(f)), mFinal(final) {}
~Thunk() { mF(mFinal); }
void thunk(int value) { mF(value); }
};
@@ -139,7 +139,7 @@
std::function<void()> mF;
public:
- Thunk(decltype(mF) f) : mF(f) {}
+ explicit Thunk(decltype(mF) f) : mF(std::move(f)) {}
void thunk() { mF(); }
};
diff --git a/services/minijail/Android.bp b/services/minijail/Android.bp
index 0713a87..5ea6d1e 100644
--- a/services/minijail/Android.bp
+++ b/services/minijail/Android.bp
@@ -39,4 +39,5 @@
srcs: [
"av_services_minijail_unittest.cpp",
],
+ test_suites: ["device-tests"],
}
diff --git a/services/minijail/TEST_MAPPING b/services/minijail/TEST_MAPPING
new file mode 100644
index 0000000..0d89760
--- /dev/null
+++ b/services/minijail/TEST_MAPPING
@@ -0,0 +1,5 @@
+{
+ "presubmit": [
+ { "name": "libavservices_minijail_unittest" }
+ ]
+}
diff --git a/services/minijail/av_services_minijail_unittest.cpp b/services/minijail/av_services_minijail_unittest.cpp
index 31313f8..896a764 100644
--- a/services/minijail/av_services_minijail_unittest.cpp
+++ b/services/minijail/av_services_minijail_unittest.cpp
@@ -34,13 +34,32 @@
"mmap: 1\n"
"munmap: 1\n";
+ const std::string third_policy_ =
+ "open: 1\n"
+ "close: 1\n";
+
const std::string full_policy_ = base_policy_ + std::string("\n") + additional_policy_;
+ const std::string triple_policy_ = base_policy_ +
+ std::string("\n") + additional_policy_ +
+ std::string("\n") + third_policy_;
};
TEST_F(WritePolicyTest, OneFile)
{
std::string final_string;
- android::base::unique_fd fd(android::WritePolicyToPipe(base_policy_, std::string()));
+ // vector with an empty pathname
+ android::base::unique_fd fd(android::WritePolicyToPipe(base_policy_, {std::string()}));
+ EXPECT_LE(0, fd.get());
+ bool success = android::base::ReadFdToString(fd.get(), &final_string);
+ EXPECT_TRUE(success);
+ EXPECT_EQ(final_string, base_policy_);
+}
+
+TEST_F(WritePolicyTest, OneFileAlternate)
+{
+ std::string final_string;
+ // empty vector
+ android::base::unique_fd fd(android::WritePolicyToPipe(base_policy_, {}));
EXPECT_LE(0, fd.get());
bool success = android::base::ReadFdToString(fd.get(), &final_string);
EXPECT_TRUE(success);
@@ -50,9 +69,19 @@
TEST_F(WritePolicyTest, TwoFiles)
{
std::string final_string;
- android::base::unique_fd fd(android::WritePolicyToPipe(base_policy_, additional_policy_));
+ android::base::unique_fd fd(android::WritePolicyToPipe(base_policy_, {additional_policy_}));
EXPECT_LE(0, fd.get());
bool success = android::base::ReadFdToString(fd.get(), &final_string);
EXPECT_TRUE(success);
EXPECT_EQ(final_string, full_policy_);
}
+
+TEST_F(WritePolicyTest, ThreeFiles)
+{
+ std::string final_string;
+ android::base::unique_fd fd(android::WritePolicyToPipe(base_policy_, {additional_policy_, third_policy_}));
+ EXPECT_LE(0, fd.get());
+ bool success = android::base::ReadFdToString(fd.get(), &final_string);
+ EXPECT_TRUE(success);
+ EXPECT_EQ(final_string, triple_policy_);
+}
diff --git a/services/minijail/minijail.cpp b/services/minijail/minijail.cpp
index f213287..c7832b9 100644
--- a/services/minijail/minijail.cpp
+++ b/services/minijail/minijail.cpp
@@ -29,7 +29,7 @@
namespace android {
int WritePolicyToPipe(const std::string& base_policy_content,
- const std::string& additional_policy_content)
+ const std::vector<std::string>& additional_policy_contents)
{
int pipefd[2];
if (pipe(pipefd) == -1) {
@@ -40,9 +40,11 @@
base::unique_fd write_end(pipefd[1]);
std::string content = base_policy_content;
- if (additional_policy_content.length() > 0) {
- content += "\n";
- content += additional_policy_content;
+ for (auto one_content : additional_policy_contents) {
+ if (one_content.length() > 0) {
+ content += "\n";
+ content += one_content;
+ }
}
if (!base::WriteStringToFd(content, write_end.get())) {
@@ -53,29 +55,34 @@
return pipefd[0];
}
-void 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;
- }
+ SetUpMinijailList(base_policy_path, {additional_policy_path});
+}
+void SetUpMinijailList(const std::string& base_policy_path,
+ const std::vector<std::string>& additional_policy_paths)
+{
std::string base_policy_content;
- std::string additional_policy_content;
+ std::vector<std::string> additional_policy_contents;
if (!base::ReadFileToString(base_policy_path, &base_policy_content,
false /* follow_symlinks */)) {
LOG(FATAL) << "Could not read base policy file '" << base_policy_path << "'";
}
- if (additional_policy_path.length() > 0 &&
- !base::ReadFileToString(additional_policy_path, &additional_policy_content,
- false /* follow_symlinks */)) {
- LOG(WARNING) << "Could not read additional policy file '" << additional_policy_path << "'";
- additional_policy_content = std::string();
+ for (auto one_policy_path : additional_policy_paths) {
+ std::string one_policy_content;
+ if (one_policy_path.length() > 0 &&
+ !base::ReadFileToString(one_policy_path, &one_policy_content,
+ false /* follow_symlinks */)) {
+ // TODO: harder failure (fatal unless ENOENT?)
+ LOG(WARNING) << "Could not read additional policy file '" << one_policy_path << "'";
+ }
+ additional_policy_contents.push_back(one_policy_content);
}
- base::unique_fd policy_fd(WritePolicyToPipe(base_policy_content, additional_policy_content));
+ base::unique_fd policy_fd(WritePolicyToPipe(base_policy_content, additional_policy_contents));
if (policy_fd.get() == -1) {
LOG(FATAL) << "Could not write seccomp policy to fd";
}
diff --git a/services/minijail/minijail.h b/services/minijail/minijail.h
index c8a2149..298af86 100644
--- a/services/minijail/minijail.h
+++ b/services/minijail/minijail.h
@@ -16,11 +16,15 @@
#define AV_SERVICES_MINIJAIL_MINIJAIL
#include <string>
+#include <vector>
namespace android {
int WritePolicyToPipe(const std::string& base_policy_content,
- const std::string& additional_policy_content);
-void SetUpMinijail(const std::string& base_policy_path, const std::string& additional_policy_path);
+ const std::vector<std::string>& additional_policy_contents);
+void SetUpMinijail(const std::string& base_policy_path,
+ const std::string& additional_policy_path);
+void SetUpMinijailList(const std::string& base_policy_path,
+ const std::vector<std::string>& additional_policy_paths);
}
#endif // AV_SERVICES_MINIJAIL_MINIJAIL