diff options
author | Kevin F. Haggerty <haggertk@lineageos.org> | 2020-06-01 20:40:36 -0600 |
---|---|---|
committer | Kevin F. Haggerty <haggertk@lineageos.org> | 2020-06-01 20:40:36 -0600 |
commit | 472ff18aac21b921e25756ed917ffb70ead1dc0d (patch) | |
tree | e94a56e2ac52ce9fb7cd5cebaf75b9fe2f11d242 | |
parent | 27237460f5410f69a6d41984ac16d0f03f1e8dde (diff) | |
parent | bc7c5411d6fdd81ad8705db48cfa69b1bc3ff4e0 (diff) | |
download | frameworks_av-472ff18aac21b921e25756ed917ffb70ead1dc0d.tar.gz frameworks_av-472ff18aac21b921e25756ed917ffb70ead1dc0d.tar.bz2 frameworks_av-472ff18aac21b921e25756ed917ffb70ead1dc0d.zip |
Merge tag 'android-10.0.0_r37' into staging/lineage-17.1_merge-android-10.0.0_r37
Android 10.0.0 Release 37 (QQ3A.200605.001)
* tag 'android-10.0.0_r37': (47 commits)
RESTRICT AUTOMERGE: Camera: fix use after free in sensor timestamp
keep tx3g{Buffer,Size,Filled} in sync
Fix race condition in AudioTrack::releaseBuffer()
Fix race condition in AudioRecord::releaseBuffer()
rtsp: fix integer overflow caused by malformed packets
IDrm: fix uninitialized variable in GET_OFFLINE_LICENSE_STATE
audio policy: fix disordered sequence while changing device
RESTRICT AUTOMERGE: Camera: fix use after free in sensor timestamp
RESTRICT AUTOMERGE: Camera: fix use after free in sensor timestamp
BnCrypto: fix use-before-init in CREATE_PLUGIN
Camera: Add onCameraOpened/onCameraClosed callbacks
[DO NOT MERGE] Fix Heap use after free in clearkey getSecureStops
Check if calling uid is system uid for setAllowedPolicyCapture.
clearkey default: parsePssh securely
RESTRICT AUTOMERGE CCodec: make config consistent before/after flush
Reduce the latecy of encoding 1st frame
[media][sfplugin] fix -Wdangling-gsl
[DO NOT MERGE] Fix uninitialized data in IHDCP decrypt
OpusHeader: Fix integer overflow in GetOpusHeaderBuffers
MPEG4Extractor: check the default sample info before checking the validity of sample size.
...
Change-Id: Ibb33de8b4828ed99095af7d629ffc290c188e10d
53 files changed, 769 insertions, 306 deletions
diff --git a/camera/aidl/android/hardware/ICameraServiceListener.aidl b/camera/aidl/android/hardware/ICameraServiceListener.aidl index e9dcbdb6f6..47580f8e68 100644 --- a/camera/aidl/android/hardware/ICameraServiceListener.aidl +++ b/camera/aidl/android/hardware/ICameraServiceListener.aidl @@ -83,4 +83,12 @@ interface ICameraServiceListener * can retry after receiving this callback. */ oneway void onCameraAccessPrioritiesChanged(); + + /** + * Notify registered clients about cameras being opened/closed. + * Only clients with android.permission.CAMERA_OPEN_CLOSE_LISTENER permission + * will receive such callbacks. + */ + oneway void onCameraOpened(String cameraId, String clientPackageId); + oneway void onCameraClosed(String cameraId); } diff --git a/camera/ndk/impl/ACameraManager.h b/camera/ndk/impl/ACameraManager.h index 8c1da36418..28fec826a1 100644 --- a/camera/ndk/impl/ACameraManager.h +++ b/camera/ndk/impl/ACameraManager.h @@ -92,6 +92,12 @@ class CameraManagerGlobal final : public RefBase { } virtual binder::Status onCameraAccessPrioritiesChanged(); + virtual binder::Status onCameraOpened(const String16&, const String16&) { + return binder::Status::ok(); + } + virtual binder::Status onCameraClosed(const String16&) { + return binder::Status::ok(); + } private: const wp<CameraManagerGlobal> mCameraManager; diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp index 8fe029aea7..dc5afc557b 100644 --- a/camera/tests/CameraBinderTests.cpp +++ b/camera/tests/CameraBinderTests.cpp @@ -95,6 +95,17 @@ public: return binder::Status::ok(); } + virtual binder::Status onCameraOpened(const String16& /*cameraId*/, + const String16& /*clientPackageName*/) { + // No op + return binder::Status::ok(); + } + + virtual binder::Status onCameraClosed(const String16& /*cameraId*/) { + // No op + return binder::Status::ok(); + } + bool waitForNumCameras(size_t num) const { Mutex::Autolock l(mLock); diff --git a/drm/libmediadrm/IDrm.cpp b/drm/libmediadrm/IDrm.cpp index 51274d16c1..c2cc429859 100644 --- a/drm/libmediadrm/IDrm.cpp +++ b/drm/libmediadrm/IDrm.cpp @@ -1071,6 +1071,7 @@ status_t BnDrm::onTransact( Vector<uint8_t> keySetId; readVector(data, keySetId); DrmPlugin::OfflineLicenseState state; + state = DrmPlugin::OfflineLicenseState::kOfflineLicenseStateUnknown; status_t result = getOfflineLicenseState(keySetId, &state); reply->writeInt32(static_cast<DrmPlugin::OfflineLicenseState>(state)); reply->writeInt32(result); diff --git a/drm/mediadrm/plugins/clearkey/default/InitDataParser.cpp b/drm/mediadrm/plugins/clearkey/default/InitDataParser.cpp index caff3939be..121a4e2952 100644 --- a/drm/mediadrm/plugins/clearkey/default/InitDataParser.cpp +++ b/drm/mediadrm/plugins/clearkey/default/InitDataParser.cpp @@ -76,10 +76,21 @@ android::status_t InitDataParser::parse(const Vector<uint8_t>& initData, android::status_t InitDataParser::parsePssh(const Vector<uint8_t>& initData, Vector<const uint8_t*>* keyIds) { + // Description of PSSH format: + // https://w3c.github.io/encrypted-media/format-registry/initdata/cenc.html size_t readPosition = 0; - // Validate size field uint32_t expectedSize = initData.size(); + const char psshIdentifier[4] = {'p', 's', 's', 'h'}; + const uint8_t psshVersion1[4] = {1, 0, 0, 0}; + uint32_t keyIdCount = 0; + size_t headerSize = sizeof(expectedSize) + sizeof(psshIdentifier) + + sizeof(psshVersion1) + kSystemIdSize + sizeof(keyIdCount); + if (initData.size() < headerSize) { + return android::ERROR_DRM_CANNOT_HANDLE; + } + + // Validate size field expectedSize = htonl(expectedSize); if (memcmp(&initData[readPosition], &expectedSize, sizeof(expectedSize)) != 0) { @@ -88,7 +99,6 @@ android::status_t InitDataParser::parsePssh(const Vector<uint8_t>& initData, readPosition += sizeof(expectedSize); // Validate PSSH box identifier - const char psshIdentifier[4] = {'p', 's', 's', 'h'}; if (memcmp(&initData[readPosition], psshIdentifier, sizeof(psshIdentifier)) != 0) { return android::ERROR_DRM_CANNOT_HANDLE; @@ -96,7 +106,6 @@ android::status_t InitDataParser::parsePssh(const Vector<uint8_t>& initData, readPosition += sizeof(psshIdentifier); // Validate EME version number - const uint8_t psshVersion1[4] = {1, 0, 0, 0}; if (memcmp(&initData[readPosition], psshVersion1, sizeof(psshVersion1)) != 0) { return android::ERROR_DRM_CANNOT_HANDLE; @@ -110,12 +119,14 @@ android::status_t InitDataParser::parsePssh(const Vector<uint8_t>& initData, readPosition += kSystemIdSize; // Read key ID count - uint32_t keyIdCount; memcpy(&keyIdCount, &initData[readPosition], sizeof(keyIdCount)); keyIdCount = ntohl(keyIdCount); readPosition += sizeof(keyIdCount); - if (readPosition + ((uint64_t)keyIdCount * kKeyIdSize) != - initData.size() - sizeof(uint32_t)) { + + uint64_t psshSize = 0; + if (__builtin_mul_overflow(keyIdCount, kKeyIdSize, &psshSize) || + __builtin_add_overflow(readPosition, psshSize, &psshSize) || + psshSize != initData.size() - sizeof(uint32_t) /* DataSize(0) */) { return android::ERROR_DRM_CANNOT_HANDLE; } diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp index aab475ed88..546eb3eba9 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp +++ b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp @@ -111,6 +111,8 @@ void DrmPlugin::initProperties() { // The content in this secure stop is implementation dependent, the clearkey // secureStop does not serve as a reference implementation. void DrmPlugin::installSecureStop(const hidl_vec<uint8_t>& sessionId) { + Mutex::Autolock lock(mSecureStopLock); + ClearkeySecureStop clearkeySecureStop; clearkeySecureStop.id = uint32ToVector(++mNextSecureStopId); clearkeySecureStop.data.assign(sessionId.begin(), sessionId.end()); @@ -744,6 +746,7 @@ Return<void> DrmPlugin::getOfflineLicenseState(const KeySetId& keySetId, } Return<void> DrmPlugin::getSecureStops(getSecureStops_cb _hidl_cb) { + mSecureStopLock.lock(); std::vector<SecureStop> stops; for (auto itr = mSecureStops.begin(); itr != mSecureStops.end(); ++itr) { ClearkeySecureStop clearkeyStop = itr->second; @@ -755,26 +758,32 @@ Return<void> DrmPlugin::getSecureStops(getSecureStops_cb _hidl_cb) { stop.opaqueData = toHidlVec(stopVec); stops.push_back(stop); } + mSecureStopLock.unlock(); + _hidl_cb(Status::OK, stops); return Void(); } Return<void> DrmPlugin::getSecureStop(const hidl_vec<uint8_t>& secureStopId, getSecureStop_cb _hidl_cb) { - SecureStop stop; + std::vector<uint8_t> stopVec; + + mSecureStopLock.lock(); auto itr = mSecureStops.find(toVector(secureStopId)); if (itr != mSecureStops.end()) { ClearkeySecureStop clearkeyStop = itr->second; - std::vector<uint8_t> stopVec; stopVec.insert(stopVec.end(), clearkeyStop.id.begin(), clearkeyStop.id.end()); stopVec.insert(stopVec.end(), clearkeyStop.data.begin(), clearkeyStop.data.end()); + } + mSecureStopLock.unlock(); + SecureStop stop; + if (!stopVec.empty()) { stop.opaqueData = toHidlVec(stopVec); _hidl_cb(Status::OK, stop); } else { _hidl_cb(Status::BAD_VALUE, stop); } - return Void(); } @@ -787,10 +796,12 @@ Return<Status> DrmPlugin::releaseAllSecureStops() { } Return<void> DrmPlugin::getSecureStopIds(getSecureStopIds_cb _hidl_cb) { + mSecureStopLock.lock(); std::vector<SecureStopId> ids; for (auto itr = mSecureStops.begin(); itr != mSecureStops.end(); ++itr) { ids.push_back(itr->first); } + mSecureStopLock.unlock(); _hidl_cb(Status::OK, toHidlVec(ids)); return Void(); @@ -856,6 +867,8 @@ Return<Status> DrmPlugin::releaseSecureStops(const SecureStopRelease& ssRelease) } Return<Status> DrmPlugin::removeSecureStop(const hidl_vec<uint8_t>& secureStopId) { + Mutex::Autolock lock(mSecureStopLock); + if (1 != mSecureStops.erase(toVector(secureStopId))) { return Status::BAD_VALUE; } @@ -863,6 +876,8 @@ Return<Status> DrmPlugin::removeSecureStop(const hidl_vec<uint8_t>& secureStopId } Return<Status> DrmPlugin::removeAllSecureStops() { + Mutex::Autolock lock(mSecureStopLock); + mSecureStops.clear(); mNextSecureStopId = kSecureStopIdStart; return Status::OK; diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h index f294d4d736..3de758945b 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h +++ b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h @@ -416,6 +416,7 @@ private: } DeviceFiles mFileHandle; + Mutex mSecureStopLock; CLEARKEY_DISALLOW_COPY_AND_ASSIGN_AND_NEW(DrmPlugin); }; diff --git a/media/codec2/components/raw/C2SoftRawDec.cpp b/media/codec2/components/raw/C2SoftRawDec.cpp index 95eb909206..7b6f21aee4 100644 --- a/media/codec2/components/raw/C2SoftRawDec.cpp +++ b/media/codec2/components/raw/C2SoftRawDec.cpp @@ -58,7 +58,7 @@ public: addParameter( DefineParam(mSampleRate, C2_PARAMKEY_SAMPLE_RATE) .withDefault(new C2StreamSampleRateInfo::output(0u, 44100)) - .withFields({C2F(mSampleRate, value).inRange(8000, 384000)}) + .withFields({C2F(mSampleRate, value).greaterThan(0)}) .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps)) .build()); diff --git a/media/codec2/hidl/1.0/utils/InputBufferManager.cpp b/media/codec2/hidl/1.0/utils/InputBufferManager.cpp index a023a05dc8..8c0d0a4ba0 100644 --- a/media/codec2/hidl/1.0/utils/InputBufferManager.cpp +++ b/media/codec2/hidl/1.0/utils/InputBufferManager.cpp @@ -70,7 +70,7 @@ void InputBufferManager::_registerFrameData( << "."; std::lock_guard<std::mutex> lock(mMutex); - std::set<TrackedBuffer> &bufferIds = + std::set<TrackedBuffer*> &bufferIds = mTrackedBuffersMap[listener][frameIndex]; for (size_t i = 0; i < input.buffers.size(); ++i) { @@ -79,13 +79,14 @@ void InputBufferManager::_registerFrameData( << "Input buffer at index " << i << " is null."; continue; } - const TrackedBuffer &bufferId = - *bufferIds.emplace(listener, frameIndex, i, input.buffers[i]). - first; + TrackedBuffer *bufferId = + new TrackedBuffer(listener, frameIndex, i, input.buffers[i]); + mTrackedBufferCache.emplace(bufferId); + bufferIds.emplace(bufferId); c2_status_t status = input.buffers[i]->registerOnDestroyNotify( onBufferDestroyed, - const_cast<void*>(reinterpret_cast<const void*>(&bufferId))); + reinterpret_cast<void*>(bufferId)); if (status != C2_OK) { LOG(DEBUG) << "InputBufferManager::_registerFrameData -- " << "registerOnDestroyNotify() failed " @@ -119,31 +120,32 @@ void InputBufferManager::_unregisterFrameData( auto findListener = mTrackedBuffersMap.find(listener); if (findListener != mTrackedBuffersMap.end()) { - std::map<uint64_t, std::set<TrackedBuffer>> &frameIndex2BufferIds + std::map<uint64_t, std::set<TrackedBuffer*>> &frameIndex2BufferIds = findListener->second; auto findFrameIndex = frameIndex2BufferIds.find(frameIndex); if (findFrameIndex != frameIndex2BufferIds.end()) { - std::set<TrackedBuffer> &bufferIds = findFrameIndex->second; - for (const TrackedBuffer& bufferId : bufferIds) { - std::shared_ptr<C2Buffer> buffer = bufferId.buffer.lock(); + std::set<TrackedBuffer*> &bufferIds = findFrameIndex->second; + for (TrackedBuffer* bufferId : bufferIds) { + std::shared_ptr<C2Buffer> buffer = bufferId->buffer.lock(); if (buffer) { c2_status_t status = buffer->unregisterOnDestroyNotify( onBufferDestroyed, - const_cast<void*>( - reinterpret_cast<const void*>(&bufferId))); + reinterpret_cast<void*>(bufferId)); if (status != C2_OK) { LOG(DEBUG) << "InputBufferManager::_unregisterFrameData " << "-- unregisterOnDestroyNotify() failed " << "(listener @ 0x" << std::hex - << bufferId.listener.unsafe_get() + << bufferId->listener.unsafe_get() << ", frameIndex = " - << std::dec << bufferId.frameIndex - << ", bufferIndex = " << bufferId.bufferIndex + << std::dec << bufferId->frameIndex + << ", bufferIndex = " << bufferId->bufferIndex << ") => status = " << status << "."; } } + mTrackedBufferCache.erase(bufferId); + delete bufferId; } frameIndex2BufferIds.erase(findFrameIndex); @@ -179,31 +181,32 @@ void InputBufferManager::_unregisterFrameData( auto findListener = mTrackedBuffersMap.find(listener); if (findListener != mTrackedBuffersMap.end()) { - std::map<uint64_t, std::set<TrackedBuffer>> &frameIndex2BufferIds = + std::map<uint64_t, std::set<TrackedBuffer*>> &frameIndex2BufferIds = findListener->second; for (auto findFrameIndex = frameIndex2BufferIds.begin(); findFrameIndex != frameIndex2BufferIds.end(); ++findFrameIndex) { - std::set<TrackedBuffer> &bufferIds = findFrameIndex->second; - for (const TrackedBuffer& bufferId : bufferIds) { - std::shared_ptr<C2Buffer> buffer = bufferId.buffer.lock(); + std::set<TrackedBuffer*> &bufferIds = findFrameIndex->second; + for (TrackedBuffer* bufferId : bufferIds) { + std::shared_ptr<C2Buffer> buffer = bufferId->buffer.lock(); if (buffer) { c2_status_t status = buffer->unregisterOnDestroyNotify( onBufferDestroyed, - const_cast<void*>( - reinterpret_cast<const void*>(&bufferId))); + reinterpret_cast<void*>(bufferId)); if (status != C2_OK) { LOG(DEBUG) << "InputBufferManager::_unregisterFrameData " << "-- unregisterOnDestroyNotify() failed " << "(listener @ 0x" << std::hex - << bufferId.listener.unsafe_get() + << bufferId->listener.unsafe_get() << ", frameIndex = " - << std::dec << bufferId.frameIndex - << ", bufferIndex = " << bufferId.bufferIndex + << std::dec << bufferId->frameIndex + << ", bufferIndex = " << bufferId->bufferIndex << ") => status = " << status << "."; } + mTrackedBufferCache.erase(bufferId); + delete bufferId; } } } @@ -236,50 +239,59 @@ void InputBufferManager::_onBufferDestroyed(const C2Buffer* buf, void* arg) { << std::dec << "."; return; } - TrackedBuffer id(*reinterpret_cast<TrackedBuffer*>(arg)); + + std::lock_guard<std::mutex> lock(mMutex); + TrackedBuffer *bufferId = reinterpret_cast<TrackedBuffer*>(arg); + + if (mTrackedBufferCache.find(bufferId) == mTrackedBufferCache.end()) { + LOG(VERBOSE) << "InputBufferManager::_onBufferDestroyed -- called with " + << "unregistered buffer: " + << "buf @ 0x" << std::hex << buf + << ", arg @ 0x" << std::hex << arg + << std::dec << "."; + return; + } + LOG(VERBOSE) << "InputBufferManager::_onBufferDestroyed -- called with " << "buf @ 0x" << std::hex << buf << ", arg @ 0x" << std::hex << arg << std::dec << " -- " - << "listener @ 0x" << std::hex << id.listener.unsafe_get() - << ", frameIndex = " << std::dec << id.frameIndex - << ", bufferIndex = " << id.bufferIndex + << "listener @ 0x" << std::hex << bufferId->listener.unsafe_get() + << ", frameIndex = " << std::dec << bufferId->frameIndex + << ", bufferIndex = " << bufferId->bufferIndex << "."; - - std::lock_guard<std::mutex> lock(mMutex); - - auto findListener = mTrackedBuffersMap.find(id.listener); + auto findListener = mTrackedBuffersMap.find(bufferId->listener); if (findListener == mTrackedBuffersMap.end()) { - LOG(DEBUG) << "InputBufferManager::_onBufferDestroyed -- " - << "received invalid listener: " - << "listener @ 0x" << std::hex << id.listener.unsafe_get() - << " (frameIndex = " << std::dec << id.frameIndex - << ", bufferIndex = " << id.bufferIndex - << ")."; + LOG(VERBOSE) << "InputBufferManager::_onBufferDestroyed -- " + << "received invalid listener: " + << "listener @ 0x" << std::hex << bufferId->listener.unsafe_get() + << " (frameIndex = " << std::dec << bufferId->frameIndex + << ", bufferIndex = " << bufferId->bufferIndex + << ")."; return; } - std::map<uint64_t, std::set<TrackedBuffer>> &frameIndex2BufferIds + std::map<uint64_t, std::set<TrackedBuffer*>> &frameIndex2BufferIds = findListener->second; - auto findFrameIndex = frameIndex2BufferIds.find(id.frameIndex); + auto findFrameIndex = frameIndex2BufferIds.find(bufferId->frameIndex); if (findFrameIndex == frameIndex2BufferIds.end()) { LOG(DEBUG) << "InputBufferManager::_onBufferDestroyed -- " << "received invalid frame index: " - << "frameIndex = " << id.frameIndex - << " (listener @ 0x" << std::hex << id.listener.unsafe_get() - << ", bufferIndex = " << std::dec << id.bufferIndex + << "frameIndex = " << bufferId->frameIndex + << " (listener @ 0x" << std::hex << bufferId->listener.unsafe_get() + << ", bufferIndex = " << std::dec << bufferId->bufferIndex << ")."; return; } - std::set<TrackedBuffer> &bufferIds = findFrameIndex->second; - auto findBufferId = bufferIds.find(id); + std::set<TrackedBuffer*> &bufferIds = findFrameIndex->second; + auto findBufferId = bufferIds.find(bufferId); if (findBufferId == bufferIds.end()) { LOG(DEBUG) << "InputBufferManager::_onBufferDestroyed -- " << "received invalid buffer index: " - << "bufferIndex = " << id.bufferIndex - << " (frameIndex = " << id.frameIndex - << ", listener @ 0x" << std::hex << id.listener.unsafe_get() + << "bufferIndex = " << bufferId->bufferIndex + << " (frameIndex = " << bufferId->frameIndex + << ", listener @ 0x" << std::hex << bufferId->listener.unsafe_get() << std::dec << ")."; return; } @@ -292,10 +304,13 @@ void InputBufferManager::_onBufferDestroyed(const C2Buffer* buf, void* arg) { } } - DeathNotifications &deathNotifications = mDeathNotifications[id.listener]; - deathNotifications.indices[id.frameIndex].emplace_back(id.bufferIndex); + DeathNotifications &deathNotifications = mDeathNotifications[bufferId->listener]; + deathNotifications.indices[bufferId->frameIndex].emplace_back(bufferId->bufferIndex); ++deathNotifications.count; mOnBufferDestroyed.notify_one(); + + mTrackedBufferCache.erase(bufferId); + delete bufferId; } // Notify the clients about buffer destructions. diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputBufferManager.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputBufferManager.h index b6857d5f71..42fa557a6b 100644 --- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputBufferManager.h +++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputBufferManager.h @@ -196,13 +196,9 @@ private: frameIndex(frameIndex), bufferIndex(bufferIndex), buffer(buffer) {} - TrackedBuffer(const TrackedBuffer&) = default; - bool operator<(const TrackedBuffer& other) const { - return bufferIndex < other.bufferIndex; - } }; - // Map: listener -> frameIndex -> set<TrackedBuffer>. + // Map: listener -> frameIndex -> set<TrackedBuffer*>. // Essentially, this is used to store triples (listener, frameIndex, // bufferIndex) that's searchable by listener and (listener, frameIndex). // However, the value of the innermost map is TrackedBuffer, which also @@ -210,7 +206,7 @@ private: // because onBufferDestroyed() needs to know listener and frameIndex too. typedef std::map<wp<IComponentListener>, std::map<uint64_t, - std::set<TrackedBuffer>>> TrackedBuffersMap; + std::set<TrackedBuffer*>>> TrackedBuffersMap; // Storage for pending (unsent) death notifications for one listener. // Each pair in member named "indices" are (frameIndex, bufferIndex) from @@ -247,6 +243,16 @@ private: // Mutex for the management of all input buffers. std::mutex mMutex; + // Cache for all TrackedBuffers. + // + // Whenever registerOnDestroyNotify() is called, an argument of type + // TrackedBuffer is created and stored into this cache. + // Whenever unregisterOnDestroyNotify() or onBufferDestroyed() is called, + // the TrackedBuffer is removed from this cache. + // + // mTrackedBuffersMap stores references to TrackedBuffers inside this cache. + std::set<TrackedBuffer*> mTrackedBufferCache; + // Tracked input buffers. TrackedBuffersMap mTrackedBuffersMap; diff --git a/media/codec2/sfplugin/C2OMXNode.cpp b/media/codec2/sfplugin/C2OMXNode.cpp index 78d221ebb3..c7588e9a51 100644 --- a/media/codec2/sfplugin/C2OMXNode.cpp +++ b/media/codec2/sfplugin/C2OMXNode.cpp @@ -62,7 +62,7 @@ public: android::base::unique_fd &&fd0, android::base::unique_fd &&fd1) { Mutexed<Jobs>::Locked jobs(mJobs); - auto it = jobs->queues.try_emplace(comp, comp, systemTime()).first; + auto it = jobs->queues.try_emplace(comp, comp).first; it->second.workList.emplace_back( std::move(work), fenceFd, std::move(fd0), std::move(fd1)); jobs->cond.broadcast(); @@ -79,7 +79,8 @@ protected: for (auto it = jobs->queues.begin(); it != jobs->queues.end(); ) { Queue &queue = it->second; if (queue.workList.empty() - || nowNs - queue.lastQueuedTimestampNs < kIntervalNs) { + || (queue.lastQueuedTimestampNs != 0 && + nowNs - queue.lastQueuedTimestampNs < kIntervalNs)) { ++it; continue; } @@ -104,6 +105,7 @@ protected: sp<Fence> fence(new Fence(fenceFd)); fence->waitForever(LOG_TAG); } + queue.lastQueuedTimestampNs = nowNs; comp->queue(&items); for (android::base::unique_fd &ufd : uniqueFds) { (void)ufd.release(); @@ -143,8 +145,8 @@ private: android::base::unique_fd fd1; }; struct Queue { - Queue(const std::shared_ptr<Codec2Client::Component> &comp, nsecs_t timestamp) - : component(comp), lastQueuedTimestampNs(timestamp) {} + Queue(const std::shared_ptr<Codec2Client::Component> &comp) + : component(comp), lastQueuedTimestampNs(0) {} Queue(const Queue &) = delete; Queue &operator =(const Queue &) = delete; diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp index 4a31953a80..78ddd6d569 100644 --- a/media/codec2/sfplugin/CCodec.cpp +++ b/media/codec2/sfplugin/CCodec.cpp @@ -1286,7 +1286,8 @@ void CCodec::start() { { Mutexed<Config>::Locked config(mConfig); inputFormat = config->mInputFormat; - outputFormat = config->mOutputFormat; + // start triggers format dup + outputFormat = config->mOutputFormat = config->mOutputFormat->dup(); if (config->mInputSurface) { err2 = config->mInputSurface->start(); } @@ -1295,6 +1296,8 @@ void CCodec::start() { mCallback->onError(err2, ACTION_CODE_FATAL); return; } + // We're not starting after flush. + (void)mSentConfigAfterResume.test_and_set(); err2 = mChannel->start(inputFormat, outputFormat); if (err2 != OK) { mCallback->onError(err2, ACTION_CODE_FATAL); @@ -1523,18 +1526,26 @@ void CCodec::flush() { } void CCodec::signalResume() { - auto setResuming = [this] { + std::shared_ptr<Codec2Client::Component> comp; + auto setResuming = [this, &comp] { Mutexed<State>::Locked state(mState); if (state->get() != FLUSHED) { return UNKNOWN_ERROR; } state->set(RESUMING); + comp = state->comp; return OK; }; if (tryAndReportOnError(setResuming) != OK) { return; } + mSentConfigAfterResume.clear(); + { + Mutexed<Config>::Locked config(mConfig); + config->queryConfiguration(comp); + } + (void)mChannel->start(nullptr, nullptr); { @@ -1730,7 +1741,7 @@ void CCodec::onMessageReceived(const sp<AMessage> &msg) { // handle configuration changes in work done Mutexed<Config>::Locked config(mConfig); - bool changed = false; + bool changed = !mSentConfigAfterResume.test_and_set(); Config::Watcher<C2StreamInitDataInfo::output> initData = config->watch<C2StreamInitDataInfo::output>(); if (!work->worklets.empty() @@ -1762,7 +1773,9 @@ void CCodec::onMessageReceived(const sp<AMessage> &msg) { ++stream; } - changed = config->updateConfiguration(updates, config->mOutputDomain); + if (config->updateConfiguration(updates, config->mOutputDomain)) { + changed = true; + } // copy standard infos to graphic buffers if not already present (otherwise, we // may overwrite the actual intermediate value with a final value) diff --git a/media/codec2/sfplugin/CCodec.h b/media/codec2/sfplugin/CCodec.h index b0b3c4f175..a580d1d20c 100644 --- a/media/codec2/sfplugin/CCodec.h +++ b/media/codec2/sfplugin/CCodec.h @@ -17,6 +17,7 @@ #ifndef C_CODEC_H_ #define C_CODEC_H_ +#include <atomic> #include <chrono> #include <list> #include <memory> @@ -175,6 +176,7 @@ private: typedef CCodecConfig Config; Mutexed<Config> mConfig; Mutexed<std::list<std::unique_ptr<C2Work>>> mWorkDoneQueue; + std::atomic_flag mSentConfigAfterResume; friend class CCodecCallbackImpl; diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp index 2efb9871e4..4ee6c1cd4f 100644 --- a/media/codec2/sfplugin/CCodecBufferChannel.cpp +++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp @@ -1072,7 +1072,7 @@ status_t CCodecBufferChannel::start( } else { output->buffers.reset(new LinearOutputBuffers(mName)); } - output->buffers->setFormat(outputFormat->dup()); + output->buffers->setFormat(outputFormat); // Try to set output surface to created block pool if given. @@ -1276,6 +1276,24 @@ bool CCodecBufferChannel::handleWork( std::unique_ptr<C2Work> work, const sp<AMessage> &outputFormat, const C2StreamInitDataInfo::output *initData) { + if (outputFormat != nullptr) { + Mutexed<Output>::Locked output(mOutput); + ALOGD("[%s] onWorkDone: output format changed to %s", + mName, outputFormat->debugString().c_str()); + output->buffers->setFormat(outputFormat); + + AString mediaType; + if (outputFormat->findString(KEY_MIME, &mediaType) + && mediaType == MIMETYPE_AUDIO_RAW) { + int32_t channelCount; + int32_t sampleRate; + if (outputFormat->findInt32(KEY_CHANNEL_COUNT, &channelCount) + && outputFormat->findInt32(KEY_SAMPLE_RATE, &sampleRate)) { + output->buffers->updateSkipCutBuffer(sampleRate, channelCount); + } + } + } + if ((work->input.ordinal.frameIndex - mFirstValidFrameIndex.load()).peek() < 0) { // Discard frames from previous generation. ALOGD("[%s] Discard frames from previous generation.", mName); @@ -1453,24 +1471,6 @@ bool CCodecBufferChannel::handleWork( } } - if (outputFormat != nullptr) { - Mutexed<Output>::Locked output(mOutput); - ALOGD("[%s] onWorkDone: output format changed to %s", - mName, outputFormat->debugString().c_str()); - output->buffers->setFormat(outputFormat); - - AString mediaType; - if (outputFormat->findString(KEY_MIME, &mediaType) - && mediaType == MIMETYPE_AUDIO_RAW) { - int32_t channelCount; - int32_t sampleRate; - if (outputFormat->findInt32(KEY_CHANNEL_COUNT, &channelCount) - && outputFormat->findInt32(KEY_SAMPLE_RATE, &sampleRate)) { - output->buffers->updateSkipCutBuffer(sampleRate, channelCount); - } - } - } - int32_t flags = 0; if (worklet->output.flags & C2FrameData::FLAG_END_OF_STREAM) { flags |= MediaCodec::BUFFER_FLAG_EOS; diff --git a/media/codec2/sfplugin/CCodecBuffers.cpp b/media/codec2/sfplugin/CCodecBuffers.cpp index 26c702ddc0..ed8b832478 100644 --- a/media/codec2/sfplugin/CCodecBuffers.cpp +++ b/media/codec2/sfplugin/CCodecBuffers.cpp @@ -878,9 +878,10 @@ void OutputBuffersArray::realloc(const std::shared_ptr<C2Buffer> &c2buffer) { switch (c2buffer->data().type()) { case C2BufferData::LINEAR: { uint32_t size = kLinearBufferSize; - const C2ConstLinearBlock &block = c2buffer->data().linearBlocks().front(); - if (block.size() < kMaxLinearBufferSize / 2) { - size = block.size() * 2; + const std::vector<C2ConstLinearBlock> &linear_blocks = c2buffer->data().linearBlocks(); + const uint32_t block_size = linear_blocks.front().size(); + if (block_size < kMaxLinearBufferSize / 2) { + size = block_size * 2; } else { size = kMaxLinearBufferSize; } diff --git a/media/extractors/midi/Android.bp b/media/extractors/midi/Android.bp index 7d42e703f3..91ce78eb9d 100644 --- a/media/extractors/midi/Android.bp +++ b/media/extractors/midi/Android.bp @@ -14,7 +14,9 @@ cc_library_shared { static_libs: [ "libmedia_midiiowrapper", "libsonivox", - "libstagefright_foundation" + "libstagefright_foundation", + "libwatchdog", + "libbase", ], name: "libmidiextractor", relative_install_path: "extractors", @@ -35,5 +37,4 @@ cc_library_shared { "signed-integer-overflow", ], }, - } diff --git a/media/extractors/midi/MidiExtractor.cpp b/media/extractors/midi/MidiExtractor.cpp index 9f4f9e69b4..d0efb2f652 100644 --- a/media/extractors/midi/MidiExtractor.cpp +++ b/media/extractors/midi/MidiExtractor.cpp @@ -26,6 +26,7 @@ #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MediaErrors.h> #include <libsonivox/eas_reverb.h> +#include <watchdog/Watchdog.h> namespace android { @@ -116,6 +117,7 @@ media_status_t MidiSource::read( MediaBufferHelper **outBuffer, const ReadOptions *options) { ALOGV("MidiSource::read"); + MediaBufferHelper *buffer; // process an optional seek request int64_t seekTimeUs; @@ -139,6 +141,8 @@ status_t MidiSource::init() } // MidiEngine +using namespace std::chrono_literals; +static constexpr auto kTimeout = 10s; MidiEngine::MidiEngine(CDataSource *dataSource, AMediaFormat *fileMetadata, @@ -147,6 +151,8 @@ MidiEngine::MidiEngine(CDataSource *dataSource, mEasHandle(NULL), mEasConfig(NULL), mIsInitialized(false) { + Watchdog watchdog(kTimeout); + mIoWrapper = new MidiIoWrapper(dataSource); // spin up a new EAS engine EAS_I32 temp; @@ -186,6 +192,8 @@ MidiEngine::MidiEngine(CDataSource *dataSource, } MidiEngine::~MidiEngine() { + Watchdog watchdog(kTimeout); + if (mEasHandle) { EAS_CloseFile(mEasData, mEasHandle); } @@ -217,12 +225,16 @@ status_t MidiEngine::releaseBuffers() { } status_t MidiEngine::seekTo(int64_t positionUs) { + Watchdog watchdog(kTimeout); + ALOGV("seekTo %lld", (long long)positionUs); EAS_RESULT result = EAS_Locate(mEasData, mEasHandle, positionUs / 1000, false); return result == EAS_SUCCESS ? OK : UNKNOWN_ERROR; } MediaBufferHelper* MidiEngine::readBuffer() { + Watchdog watchdog(kTimeout); + EAS_STATE state; EAS_State(mEasData, mEasHandle, &state); if ((state == EAS_STATE_STOPPED) || (state == EAS_STATE_ERROR)) { diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp index 9d5890c42c..485c0cc9ef 100755 --- a/media/extractors/mp4/MPEG4Extractor.cpp +++ b/media/extractors/mp4/MPEG4Extractor.cpp @@ -1060,6 +1060,8 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { // drop it now to reduce our footprint free(mLastTrack->mTx3gBuffer); mLastTrack->mTx3gBuffer = NULL; + mLastTrack->mTx3gFilled = 0; + mLastTrack->mTx3gSize = 0; } } else if (chunk_type == FOURCC("moov")) { @@ -2621,6 +2623,10 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { // if those apps are compensating for it, we'd break them with such a change // + if (mLastTrack->mTx3gBuffer == NULL) { + mLastTrack->mTx3gSize = 0; + mLastTrack->mTx3gFilled = 0; + } if (mLastTrack->mTx3gSize - mLastTrack->mTx3gFilled < chunk_size) { size_t growth = kTx3gGrowth; if (growth < chunk_size) { @@ -4993,8 +4999,11 @@ status_t MPEG4Source::parseChunk(off64_t *offset) { } status_t MPEG4Source::parseSampleAuxiliaryInformationSizes( - off64_t offset, off64_t /* size */) { + off64_t offset, off64_t size) { ALOGV("parseSampleAuxiliaryInformationSizes"); + if (size < 9) { + return -EINVAL; + } // 14496-12 8.7.12 uint8_t version; if (mDataSource->readAt( @@ -5007,25 +5016,32 @@ status_t MPEG4Source::parseSampleAuxiliaryInformationSizes( return ERROR_UNSUPPORTED; } offset++; + size--; uint32_t flags; if (!mDataSource->getUInt24(offset, &flags)) { return ERROR_IO; } offset += 3; + size -= 3; if (flags & 1) { + if (size < 13) { + return -EINVAL; + } uint32_t tmp; if (!mDataSource->getUInt32(offset, &tmp)) { return ERROR_MALFORMED; } mCurrentAuxInfoType = tmp; offset += 4; + size -= 4; if (!mDataSource->getUInt32(offset, &tmp)) { return ERROR_MALFORMED; } mCurrentAuxInfoTypeParameter = tmp; offset += 4; + size -= 4; } uint8_t defsize; @@ -5034,6 +5050,7 @@ status_t MPEG4Source::parseSampleAuxiliaryInformationSizes( } mCurrentDefaultSampleInfoSize = defsize; offset++; + size--; uint32_t smplcnt; if (!mDataSource->getUInt32(offset, &smplcnt)) { @@ -5041,11 +5058,16 @@ status_t MPEG4Source::parseSampleAuxiliaryInformationSizes( } mCurrentSampleInfoCount = smplcnt; offset += 4; - + size -= 4; if (mCurrentDefaultSampleInfoSize != 0) { ALOGV("@@@@ using default sample info size of %d", mCurrentDefaultSampleInfoSize); return OK; } + if(smplcnt > size) { + ALOGW("b/124525515 - smplcnt(%u) > size(%ld)", (unsigned int)smplcnt, (unsigned long)size); + android_errorWriteLog(0x534e4554, "124525515"); + return -EINVAL; + } if (smplcnt > mCurrentSampleInfoAllocSize) { uint8_t * newPtr = (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt); if (newPtr == NULL) { @@ -5061,26 +5083,32 @@ status_t MPEG4Source::parseSampleAuxiliaryInformationSizes( } status_t MPEG4Source::parseSampleAuxiliaryInformationOffsets( - off64_t offset, off64_t /* size */) { + off64_t offset, off64_t size) { ALOGV("parseSampleAuxiliaryInformationOffsets"); + if (size < 8) { + return -EINVAL; + } // 14496-12 8.7.13 uint8_t version; if (mDataSource->readAt(offset, &version, sizeof(version)) != 1) { return ERROR_IO; } offset++; + size--; uint32_t flags; if (!mDataSource->getUInt24(offset, &flags)) { return ERROR_IO; } offset += 3; + size -= 3; uint32_t entrycount; if (!mDataSource->getUInt32(offset, &entrycount)) { return ERROR_IO; } offset += 4; + size -= 4; if (entrycount == 0) { return OK; } @@ -5106,19 +5134,31 @@ status_t MPEG4Source::parseSampleAuxiliaryInformationOffsets( for (size_t i = 0; i < entrycount; i++) { if (version == 0) { + if (size < 4) { + ALOGW("b/124526959"); + android_errorWriteLog(0x534e4554, "124526959"); + return -EINVAL; + } uint32_t tmp; if (!mDataSource->getUInt32(offset, &tmp)) { return ERROR_IO; } mCurrentSampleInfoOffsets[i] = tmp; offset += 4; + size -= 4; } else { + if (size < 8) { + ALOGW("b/124526959"); + android_errorWriteLog(0x534e4554, "124526959"); + return -EINVAL; + } uint64_t tmp; if (!mDataSource->getUInt64(offset, &tmp)) { return ERROR_IO; } mCurrentSampleInfoOffsets[i] = tmp; offset += 8; + size -= 8; } } @@ -5440,16 +5480,12 @@ status_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) { // apply some sanity (vs strict legality) checks // - // clamp the count of entries in the trun box, to avoid spending forever parsing - // this box. Clamping (vs error) lets us play *something*. - // 1 million is about 400 msecs on a Pixel3, should be no more than a couple seconds - // on the slowest devices. - static constexpr uint32_t kMaxTrunSampleCount = 1000000; + static constexpr uint32_t kMaxTrunSampleCount = 10000; if (sampleCount > kMaxTrunSampleCount) { - ALOGW("b/123389881 clamp sampleCount(%u) @ kMaxTrunSampleCount(%u)", + ALOGW("b/123389881 sampleCount(%u) > kMaxTrunSampleCount(%u)", sampleCount, kMaxTrunSampleCount); android_errorWriteLog(0x534e4554, "124389881 count"); - + return -EINVAL; } } @@ -5493,7 +5529,12 @@ status_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) { tmp.duration = sampleDuration; tmp.compositionOffset = sampleCtsOffset; memset(tmp.iv, 0, sizeof(tmp.iv)); - mCurrentSamples.add(tmp); + if (mCurrentSamples.add(tmp) < 0) { + ALOGW("b/123389881 failed saving sample(n=%zu)", mCurrentSamples.size()); + android_errorWriteLog(0x534e4554, "124389881 allocation"); + mCurrentSamples.clear(); + return NO_MEMORY; + } dataOffset += sampleSize; } diff --git a/media/extractors/mp4/SampleTable.cpp b/media/extractors/mp4/SampleTable.cpp index bf29bf1eac..e7e8901bf1 100644 --- a/media/extractors/mp4/SampleTable.cpp +++ b/media/extractors/mp4/SampleTable.cpp @@ -391,20 +391,11 @@ status_t SampleTable::setTimeToSampleParams( } mTimeToSampleCount = U32_AT(&header[4]); - if (mTimeToSampleCount > UINT32_MAX / (2 * sizeof(uint32_t))) { - // Choose this bound because - // 1) 2 * sizeof(uint32_t) is the amount of memory needed for one - // time-to-sample entry in the time-to-sample table. - // 2) mTimeToSampleCount is the number of entries of the time-to-sample - // table. - // 3) We hope that the table size does not exceed UINT32_MAX. + if (mTimeToSampleCount > (data_size - 8) / (2 * sizeof(uint32_t))) { ALOGE("Time-to-sample table size too large."); return ERROR_OUT_OF_RANGE; } - // Note: At this point, we know that mTimeToSampleCount * 2 will not - // overflow because of the above condition. - uint64_t allocSize = (uint64_t)mTimeToSampleCount * 2 * sizeof(uint32_t); mTotalSize += allocSize; if (mTotalSize > kMaxTotalSize) { @@ -540,6 +531,12 @@ status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) } uint64_t allocSize = (uint64_t)numSyncSamples * sizeof(uint32_t); + if (allocSize > data_size - 8) { + ALOGW("b/124771364 - allocSize(%lu) > size(%lu)", + (unsigned long)allocSize, (unsigned long)(data_size - 8)); + android_errorWriteLog(0x534e4554, "124771364"); + return ERROR_MALFORMED; + } if (allocSize > kMaxTotalSize) { ALOGE("Sync sample table size too large."); return ERROR_OUT_OF_RANGE; diff --git a/media/libaaudio/src/binding/IAAudioService.cpp b/media/libaaudio/src/binding/IAAudioService.cpp index 97ad2b02a0..e017b3a122 100644 --- a/media/libaaudio/src/binding/IAAudioService.cpp +++ b/media/libaaudio/src/binding/IAAudioService.cpp @@ -237,12 +237,12 @@ IMPLEMENT_META_INTERFACE(AAudioService, "IAAudioService"); status_t BnAAudioService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { - aaudio_handle_t streamHandle; + aaudio_handle_t streamHandle = 0; aaudio::AAudioStreamRequest request; aaudio::AAudioStreamConfiguration configuration; - pid_t tid; - int64_t nanoseconds; - aaudio_result_t result; + pid_t tid = 0; + int64_t nanoseconds = 0; + aaudio_result_t result = AAUDIO_OK; status_t status = NO_ERROR; ALOGV("BnAAudioService::onTransact(%i) %i", code, flags); @@ -285,7 +285,11 @@ status_t BnAAudioService::onTransact(uint32_t code, const Parcel& data, case CLOSE_STREAM: { CHECK_INTERFACE(IAAudioService, data, reply); - data.readInt32(&streamHandle); + status = data.readInt32(&streamHandle); + if (status != NO_ERROR) { + ALOGE("BnAAudioService::%s(CLOSE_STREAM) streamHandle failed!", __func__); + return status; + } result = closeStream(streamHandle); //ALOGD("BnAAudioService::onTransact CLOSE_STREAM 0x%08X, result = %d", // streamHandle, result); @@ -297,6 +301,7 @@ status_t BnAAudioService::onTransact(uint32_t code, const Parcel& data, CHECK_INTERFACE(IAAudioService, data, reply); status = data.readInt32(&streamHandle); if (status != NO_ERROR) { + ALOGE("BnAAudioService::%s(GET_STREAM_DESCRIPTION) streamHandle failed!", __func__); return status; } aaudio::AudioEndpointParcelable parcelable; @@ -313,7 +318,11 @@ status_t BnAAudioService::onTransact(uint32_t code, const Parcel& data, case START_STREAM: { CHECK_INTERFACE(IAAudioService, data, reply); - data.readInt32(&streamHandle); + status = data.readInt32(&streamHandle); + if (status != NO_ERROR) { + ALOGE("BnAAudioService::%s(START_STREAM) streamHandle failed!", __func__); + return status; + } result = startStream(streamHandle); ALOGV("BnAAudioService::onTransact START_STREAM 0x%08X, result = %d", streamHandle, result); @@ -323,7 +332,11 @@ status_t BnAAudioService::onTransact(uint32_t code, const Parcel& data, case PAUSE_STREAM: { CHECK_INTERFACE(IAAudioService, data, reply); - data.readInt32(&streamHandle); + status = data.readInt32(&streamHandle); + if (status != NO_ERROR) { + ALOGE("BnAAudioService::%s(PAUSE_STREAM) streamHandle failed!", __func__); + return status; + } result = pauseStream(streamHandle); ALOGV("BnAAudioService::onTransact PAUSE_STREAM 0x%08X, result = %d", streamHandle, result); @@ -333,7 +346,11 @@ status_t BnAAudioService::onTransact(uint32_t code, const Parcel& data, case STOP_STREAM: { CHECK_INTERFACE(IAAudioService, data, reply); - data.readInt32(&streamHandle); + status = data.readInt32(&streamHandle); + if (status != NO_ERROR) { + ALOGE("BnAAudioService::%s(STOP_STREAM) streamHandle failed!", __func__); + return status; + } result = stopStream(streamHandle); ALOGV("BnAAudioService::onTransact STOP_STREAM 0x%08X, result = %d", streamHandle, result); @@ -343,7 +360,11 @@ status_t BnAAudioService::onTransact(uint32_t code, const Parcel& data, case FLUSH_STREAM: { CHECK_INTERFACE(IAAudioService, data, reply); - data.readInt32(&streamHandle); + status = data.readInt32(&streamHandle); + if (status != NO_ERROR) { + ALOGE("BnAAudioService::%s(FLUSH_STREAM) streamHandle failed!", __func__); + return status; + } result = flushStream(streamHandle); ALOGV("BnAAudioService::onTransact FLUSH_STREAM 0x%08X, result = %d", streamHandle, result); @@ -353,20 +374,40 @@ status_t BnAAudioService::onTransact(uint32_t code, const Parcel& data, case REGISTER_AUDIO_THREAD: { CHECK_INTERFACE(IAAudioService, data, reply); - data.readInt32(&streamHandle); - data.readInt32(&tid); - data.readInt64(&nanoseconds); + status = data.readInt32(&streamHandle); + if (status != NO_ERROR) { + ALOGE("BnAAudioService::%s(REGISTER_AUDIO_THREAD) streamHandle failed!", __func__); + return status; + } + status = data.readInt32(&tid); + if (status != NO_ERROR) { + ALOGE("BnAAudioService::%s(REGISTER_AUDIO_THREAD) tid failed!", __func__); + return status; + } + status = data.readInt64(&nanoseconds); + if (status != NO_ERROR) { + ALOGE("BnAAudioService::%s(REGISTER_AUDIO_THREAD) nanoseconds failed!", __func__); + return status; + } result = registerAudioThread(streamHandle, tid, nanoseconds); - ALOGV("BnAAudioService::onTransact REGISTER_AUDIO_THREAD 0x%08X, result = %d", - streamHandle, result); + ALOGV("BnAAudioService::%s(REGISTER_AUDIO_THREAD) 0x%08X, result = %d", + __func__, streamHandle, result); reply->writeInt32(result); return NO_ERROR; } break; case UNREGISTER_AUDIO_THREAD: { CHECK_INTERFACE(IAAudioService, data, reply); - data.readInt32(&streamHandle); - data.readInt32(&tid); + status = data.readInt32(&streamHandle); + if (status != NO_ERROR) { + ALOGE("BnAAudioService::%s(UNREGISTER_AUDIO_THREAD) streamHandle failed!", __func__); + return status; + } + status = data.readInt32(&tid); + if (status != NO_ERROR) { + ALOGE("BnAAudioService::%s(UNREGISTER_AUDIO_THREAD) tid failed!", __func__); + return status; + } result = unregisterAudioThread(streamHandle, tid); ALOGV("BnAAudioService::onTransact UNREGISTER_AUDIO_THREAD 0x%08X, result = %d", streamHandle, result); diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp index a1b04caa92..271e18655e 100644 --- a/media/libaudioclient/AudioRecord.cpp +++ b/media/libaudioclient/AudioRecord.cpp @@ -884,7 +884,6 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, const struct timespec *r { // previous and new IAudioRecord sequence numbers are used to detect track re-creation uint32_t oldSequence = 0; - uint32_t newSequence; Proxy::Buffer buffer; status_t status = NO_ERROR; @@ -902,7 +901,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, const struct timespec *r // start of lock scope AutoMutex lock(mLock); - newSequence = mSequence; + uint32_t newSequence = mSequence; // did previous obtainBuffer() fail due to media server death or voluntary invalidation? if (status == DEAD_OBJECT) { // re-create track, unless someone else has already done so @@ -939,6 +938,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, const struct timespec *r audioBuffer->frameCount = buffer.mFrameCount; audioBuffer->size = buffer.mFrameCount * mFrameSize; audioBuffer->raw = buffer.mRaw; + audioBuffer->sequence = oldSequence; if (nonContig != NULL) { *nonContig = buffer.mNonContig; } @@ -959,6 +959,12 @@ void AudioRecord::releaseBuffer(const Buffer* audioBuffer) buffer.mRaw = audioBuffer->raw; AutoMutex lock(mLock); + if (audioBuffer->sequence != mSequence) { + // This Buffer came from a different IAudioRecord instance, so ignore the releaseBuffer + ALOGD("%s is no-op due to IAudioRecord sequence mismatch %u != %u", + __func__, audioBuffer->sequence, mSequence); + return; + } mInOverrun = false; mProxy->releaseBuffer(&buffer); diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp index 4a80cd3baa..9a66d48a90 100644 --- a/media/libaudioclient/AudioTrack.cpp +++ b/media/libaudioclient/AudioTrack.cpp @@ -1665,7 +1665,6 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, const struct timespec *re { // previous and new IAudioTrack sequence numbers are used to detect track re-creation uint32_t oldSequence = 0; - uint32_t newSequence; Proxy::Buffer buffer; status_t status = NO_ERROR; @@ -1682,7 +1681,7 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, const struct timespec *re { // start of lock scope AutoMutex lock(mLock); - newSequence = mSequence; + uint32_t newSequence = mSequence; // did previous obtainBuffer() fail due to media server death or voluntary invalidation? if (status == DEAD_OBJECT) { // re-create track, unless someone else has already done so @@ -1729,6 +1728,7 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, const struct timespec *re audioBuffer->frameCount = buffer.mFrameCount; audioBuffer->size = buffer.mFrameCount * mFrameSize; audioBuffer->raw = buffer.mRaw; + audioBuffer->sequence = oldSequence; if (nonContig != NULL) { *nonContig = buffer.mNonContig; } @@ -1752,6 +1752,12 @@ void AudioTrack::releaseBuffer(const Buffer* audioBuffer) buffer.mRaw = audioBuffer->raw; AutoMutex lock(mLock); + if (audioBuffer->sequence != mSequence) { + // This Buffer came from a different IAudioTrack instance, so ignore the releaseBuffer + ALOGD("%s is no-op due to IAudioTrack sequence mismatch %u != %u", + __func__, audioBuffer->sequence, mSequence); + return; + } mReleased += stepCount; mInUnderrun = false; mProxy->releaseBuffer(&buffer); diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp index 9d47fa7157..d55b094629 100644 --- a/media/libaudioclient/IAudioPolicyService.cpp +++ b/media/libaudioclient/IAudioPolicyService.cpp @@ -1370,7 +1370,8 @@ status_t BnAudioPolicyService::onTransact( case GET_OFFLOAD_FORMATS_A2DP: case LIST_AUDIO_VOLUME_GROUPS: case GET_VOLUME_GROUP_FOR_ATTRIBUTES: - case SET_RTT_ENABLED: { + case SET_RTT_ENABLED: + case SET_ALLOWED_CAPTURE_POLICY: { if (!isServiceUid(IPCThreadState::self()->getCallingUid())) { ALOGW("%s: transaction %d received from PID %d unauthorized UID %d", __func__, code, IPCThreadState::self()->getCallingPid(), diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h index a3c0fe4ac5..574302b869 100644 --- a/media/libaudioclient/include/media/AudioRecord.h +++ b/media/libaudioclient/include/media/AudioRecord.h @@ -92,6 +92,11 @@ public: int8_t* i8; // unsigned 8-bit, offset by 0x80 // input to obtainBuffer(): unused, output: pointer to buffer }; + + uint32_t sequence; // IAudioRecord instance sequence number, as of obtainBuffer(). + // It is set by obtainBuffer() and confirmed by releaseBuffer(). + // Not "user-serviceable". + // TODO Consider sp<IMemory> instead, or in addition to this. }; /* As a convenience, if a callback is supplied, a handler thread @@ -420,14 +425,17 @@ public: * frameCount number of frames requested * size ignored * raw ignored + * sequence ignored * After error return: * frameCount 0 * size 0 * raw undefined + * sequence undefined * After successful return: * frameCount actual number of frames available, <= number requested * size actual number of bytes available * raw pointer to the buffer + * sequence IAudioRecord instance sequence number, as of obtainBuffer() */ status_t obtainBuffer(Buffer* audioBuffer, int32_t waitCount, diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h index df5eabc5cc..c607918b96 100644 --- a/media/libaudioclient/include/media/AudioTrack.h +++ b/media/libaudioclient/include/media/AudioTrack.h @@ -107,6 +107,11 @@ public: int16_t* i16; // signed 16-bit int8_t* i8; // unsigned 8-bit, offset by 0x80 }; // input to obtainBuffer(): unused, output: pointer to buffer + + uint32_t sequence; // IAudioTrack instance sequence number, as of obtainBuffer(). + // It is set by obtainBuffer() and confirmed by releaseBuffer(). + // Not "user-serviceable". + // TODO Consider sp<IMemory> instead, or in addition to this. }; /* As a convenience, if a callback is supplied, a handler thread @@ -692,14 +697,17 @@ public: * frameCount number of [empty slots for] frames requested * size ignored * raw ignored + * sequence ignored * After error return: * frameCount 0 * size 0 * raw undefined + * sequence undefined * After successful return: * frameCount actual number of [empty slots for] frames available, <= number requested * size actual number of bytes available * raw pointer to the buffer + * sequence IAudioTrack instance sequence number, as of obtainBuffer() */ status_t obtainBuffer(Buffer* audioBuffer, int32_t waitCount, size_t *nonContig = NULL); diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp index 917080511f..7eab230bb7 100644 --- a/media/libstagefright/Android.bp +++ b/media/libstagefright/Android.bp @@ -129,7 +129,6 @@ cc_library { "CameraSource.cpp", "CameraSourceTimeLapse.cpp", "DataConverter.cpp", - "DataSourceBase.cpp", "DataSourceFactory.cpp", "DataURISource.cpp", "ClearFileSource.cpp", @@ -267,7 +266,6 @@ cc_library_static { srcs: [ "ClearFileSource.cpp", "DataURISource.cpp", - "DataSourceBase.cpp", "HTTPBase.cpp", "HevcUtils.cpp", "MediaClock.cpp", diff --git a/media/libstagefright/DataSourceBase.cpp b/media/libstagefright/DataSourceBase.cpp deleted file mode 100644 index 8f47ee56cb..0000000000 --- a/media/libstagefright/DataSourceBase.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -//#define LOG_NDEBUG 0 -#define LOG_TAG "DataSourceBase" - -#include <media/DataSourceBase.h> -#include <media/stagefright/foundation/ByteUtils.h> -#include <media/stagefright/MediaErrors.h> -#include <utils/String8.h> - -namespace android { - -bool DataSourceBase::getUInt16(off64_t offset, uint16_t *x) { - *x = 0; - - uint8_t byte[2]; - if (readAt(offset, byte, 2) != 2) { - return false; - } - - *x = (byte[0] << 8) | byte[1]; - - return true; -} - -bool DataSourceBase::getUInt24(off64_t offset, uint32_t *x) { - *x = 0; - - uint8_t byte[3]; - if (readAt(offset, byte, 3) != 3) { - return false; - } - - *x = (byte[0] << 16) | (byte[1] << 8) | byte[2]; - - return true; -} - -bool DataSourceBase::getUInt32(off64_t offset, uint32_t *x) { - *x = 0; - - uint32_t tmp; - if (readAt(offset, &tmp, 4) != 4) { - return false; - } - - *x = ntohl(tmp); - - return true; -} - -bool DataSourceBase::getUInt64(off64_t offset, uint64_t *x) { - *x = 0; - - uint64_t tmp; - if (readAt(offset, &tmp, 8) != 8) { - return false; - } - - *x = ntoh64(tmp); - - return true; -} - -bool DataSourceBase::getUInt16Var(off64_t offset, uint16_t *x, size_t size) { - if (size == 2) { - return getUInt16(offset, x); - } - if (size == 1) { - uint8_t tmp; - if (readAt(offset, &tmp, 1) == 1) { - *x = tmp; - return true; - } - } - return false; -} - -bool DataSourceBase::getUInt32Var(off64_t offset, uint32_t *x, size_t size) { - if (size == 4) { - return getUInt32(offset, x); - } - if (size == 2) { - uint16_t tmp; - if (getUInt16(offset, &tmp)) { - *x = tmp; - return true; - } - } - return false; -} - -bool DataSourceBase::getUInt64Var(off64_t offset, uint64_t *x, size_t size) { - if (size == 8) { - return getUInt64(offset, x); - } - if (size == 4) { - uint32_t tmp; - if (getUInt32(offset, &tmp)) { - *x = tmp; - return true; - } - } - return false; -} - -status_t DataSourceBase::getSize(off64_t *size) { - *size = 0; - - return ERROR_UNSUPPORTED; -} - -bool DataSourceBase::getUri(char *uriString __unused, size_t bufferSize __unused) { - return false; -} - -} // namespace android diff --git a/media/libstagefright/foundation/OpusHeader.cpp b/media/libstagefright/foundation/OpusHeader.cpp index 513e41f4a9..f5687e0d60 100644 --- a/media/libstagefright/foundation/OpusHeader.cpp +++ b/media/libstagefright/foundation/OpusHeader.cpp @@ -292,6 +292,10 @@ bool GetOpusHeaderBuffers(const uint8_t *data, size_t data_size, *opusHeadSize = data_size; return true; } else if (memcmp(AOPUS_CSD_MARKER_PREFIX, data, AOPUS_CSD_MARKER_PREFIX_SIZE) == 0) { + if (data_size < AOPUS_UNIFIED_CSD_MINSIZE || data_size > AOPUS_UNIFIED_CSD_MAXSIZE) { + ALOGD("Unexpected size for unified opus csd %zu", data_size); + return false; + } size_t i = 0; bool found = false; while (i <= data_size - AOPUS_MARKER_SIZE - AOPUS_LENGTH_SIZE) { diff --git a/media/libstagefright/include/media/stagefright/DataSourceBase.h b/media/libstagefright/include/media/stagefright/DataSourceBase.h index af5b83d919..c607c91658 100644 --- a/media/libstagefright/include/media/stagefright/DataSourceBase.h +++ b/media/libstagefright/include/media/stagefright/DataSourceBase.h @@ -18,6 +18,8 @@ #define DATA_SOURCE_BASE_H_ +#include <media/stagefright/foundation/ByteUtils.h> +#include <media/stagefright/MediaErrors.h> #include <sys/types.h> #include <utils/Errors.h> @@ -45,20 +47,106 @@ public: virtual ssize_t readAt(off64_t offset, void *data, size_t size) = 0; // Convenience methods: - bool getUInt16(off64_t offset, uint16_t *x); - bool getUInt24(off64_t offset, uint32_t *x); // 3 byte int, returned as a 32-bit int - bool getUInt32(off64_t offset, uint32_t *x); - bool getUInt64(off64_t offset, uint64_t *x); + bool getUInt16(off64_t offset, uint16_t *x) { + *x = 0; + + uint8_t byte[2]; + if (readAt(offset, byte, 2) != 2) { + return false; + } + + *x = (byte[0] << 8) | byte[1]; + + return true; + } + // 3 byte int, returned as a 32-bit int + bool getUInt24(off64_t offset, uint32_t *x) { + *x = 0; + + uint8_t byte[3]; + if (readAt(offset, byte, 3) != 3) { + return false; + } + + *x = (byte[0] << 16) | (byte[1] << 8) | byte[2]; + + return true; + } + bool getUInt32(off64_t offset, uint32_t *x) { + *x = 0; + + uint32_t tmp; + if (readAt(offset, &tmp, 4) != 4) { + return false; + } + + *x = ntohl(tmp); + + return true; + } + bool getUInt64(off64_t offset, uint64_t *x) { + *x = 0; + + uint64_t tmp; + if (readAt(offset, &tmp, 8) != 8) { + return false; + } + + *x = ntoh64(tmp); + + return true; + } // read either int<N> or int<2N> into a uint<2N>_t, size is the int size in bytes. - bool getUInt16Var(off64_t offset, uint16_t *x, size_t size); - bool getUInt32Var(off64_t offset, uint32_t *x, size_t size); - bool getUInt64Var(off64_t offset, uint64_t *x, size_t size); + bool getUInt16Var(off64_t offset, uint16_t *x, size_t size) { + if (size == 2) { + return getUInt16(offset, x); + } + if (size == 1) { + uint8_t tmp; + if (readAt(offset, &tmp, 1) == 1) { + *x = tmp; + return true; + } + } + return false; + } + bool getUInt32Var(off64_t offset, uint32_t *x, size_t size) { + if (size == 4) { + return getUInt32(offset, x); + } + if (size == 2) { + uint16_t tmp; + if (getUInt16(offset, &tmp)) { + *x = tmp; + return true; + } + } + return false; + } + bool getUInt64Var(off64_t offset, uint64_t *x, size_t size) { + if (size == 8) { + return getUInt64(offset, x); + } + if (size == 4) { + uint32_t tmp; + if (getUInt32(offset, &tmp)) { + *x = tmp; + return true; + } + } + return false; + } // May return ERROR_UNSUPPORTED. - virtual status_t getSize(off64_t *size); + virtual status_t getSize(off64_t *size) { + *size = 0; + return ERROR_UNSUPPORTED; + } - virtual bool getUri(char *uriString, size_t bufferSize); + virtual bool getUri(char * /*uriString*/, size_t /*bufferSize*/) { + return false; + } virtual uint32_t flags() { return 0; diff --git a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp index 1e434cbcea..9df3508d85 100644 --- a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp +++ b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp @@ -338,6 +338,12 @@ ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::addPacket( ABitReader bits(buffer->data() + offset, buffer->size() - offset); unsigned auxSize = bits.getBits(mAuxiliaryDataSizeLength); + if (buffer->size() < auxSize) { + ALOGE("b/123940919 auxSize %u", auxSize); + android_errorWriteLog(0x534e4554, "123940919"); + queue->erase(queue->begin()); + return MALFORMED_PACKET; + } offset += (mAuxiliaryDataSizeLength + auxSize + 7) / 8; } @@ -346,6 +352,12 @@ ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::addPacket( it != headers.end(); ++it) { const AUHeader &header = *it; + if (buffer->size() < header.mSize) { + ALOGE("b/123940919 AU_size %u", header.mSize); + android_errorWriteLog(0x534e4554, "123940919"); + queue->erase(queue->begin()); + return MALFORMED_PACKET; + } if (buffer->size() < offset + header.mSize) { return MALFORMED_PACKET; } diff --git a/media/libwatchdog/Android.bp b/media/libwatchdog/Android.bp new file mode 100644 index 0000000000..2bdf17262c --- /dev/null +++ b/media/libwatchdog/Android.bp @@ -0,0 +1,35 @@ +// Copyright 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +cc_library { + name: "libwatchdog", + srcs: [ + "Watchdog.cpp", + ], + export_include_dirs: ["include"], + shared_libs: [ + "liblog", + ], + static_libs: [ + "libbase", + ], + target: { + windows: { + enabled: false, + }, + darwin: { + enabled: false, + }, + }, +} diff --git a/media/libwatchdog/Watchdog.cpp b/media/libwatchdog/Watchdog.cpp new file mode 100644 index 0000000000..bb012b9429 --- /dev/null +++ b/media/libwatchdog/Watchdog.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "Watchdog" + +#include <watchdog/Watchdog.h> + +#include <android-base/logging.h> +#include <android-base/threads.h> +#include <signal.h> +#include <time.h> +#include <cstring> +#include <utils/Log.h> + +namespace android { + +Watchdog::Watchdog(::std::chrono::steady_clock::duration timeout) { + // Create the timer. + struct sigevent sev; + sev.sigev_notify = SIGEV_THREAD_ID; + sev.sigev_notify_thread_id = base::GetThreadId(); + sev.sigev_signo = SIGABRT; + sev.sigev_value.sival_ptr = &mTimerId; + int err = timer_create(CLOCK_MONOTONIC, &sev, &mTimerId); + if (err != 0) { + PLOG(FATAL) << "Failed to create timer"; + } + + // Start the timer. + struct itimerspec spec; + memset(&spec, 0, sizeof(spec)); + auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(timeout); + LOG_ALWAYS_FATAL_IF(timeout.count() <= 0, "Duration must be positive"); + spec.it_value.tv_sec = ns.count() / 1000000000; + spec.it_value.tv_nsec = ns.count() % 1000000000; + err = timer_settime(mTimerId, 0, &spec, nullptr); + if (err != 0) { + PLOG(FATAL) << "Failed to start timer"; + } +} + +Watchdog::~Watchdog() { + // Delete the timer. + int err = timer_delete(mTimerId); + if (err != 0) { + PLOG(FATAL) << "Failed to delete timer"; + } +} + +} // namespace android diff --git a/media/libwatchdog/include/watchdog/Watchdog.h b/media/libwatchdog/include/watchdog/Watchdog.h new file mode 100644 index 0000000000..2819f8a270 --- /dev/null +++ b/media/libwatchdog/include/watchdog/Watchdog.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_WATCHDOG_H +#define ANDROID_WATCHDOG_H + +#include <chrono> +#include <time.h> + +namespace android { + +/* + * An RAII-style object, which would crash the process if a timeout expires + * before the object is destroyed. + * The calling thread would be sent a SIGABORT, which would typically result in + * a stack trace. + * + * Sample usage: + * { + * Watchdog watchdog(std::chrono::milliseconds(10)); + * DoSomething(); + * } + * // If we got here, the function completed in time. + */ +class Watchdog final { +public: + Watchdog(std::chrono::steady_clock::duration timeout); + ~Watchdog(); + +private: + timer_t mTimerId; +}; + +} // namespace android + +#endif // ANDROID_WATCHDOG_H diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp index ca8cb785e9..dd69496160 100644 --- a/media/mtp/MtpServer.cpp +++ b/media/mtp/MtpServer.cpp @@ -44,6 +44,7 @@ #include "MtpStringBuffer.h" namespace android { +static const int SN_EVENT_LOG_ID = 0x534e4554; static const MtpOperationCode kSupportedOperationCodes[] = { MTP_OPERATION_GET_DEVICE_INFO, @@ -961,6 +962,17 @@ MtpResponseCode MtpServer::doSendObjectInfo() { if (!parseDateTime(modified, modifiedTime)) modifiedTime = 0; + if ((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0) || + (strchr(name, '/') != NULL)) { + char errMsg[80]; + + snprintf(errMsg, sizeof(errMsg), "Invalid name: %s", (const char *) name); + ALOGE("%s (b/130656917)", errMsg); + android_errorWriteWithInfoLog(SN_EVENT_LOG_ID, "130656917", -1, errMsg, + strlen(errMsg)); + + return MTP_RESPONSE_INVALID_PARAMETER; + } if (path[path.size() - 1] != '/') path.append("/"); path.append(name); diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp index a3cabd877a..9c7a630c0f 100644 --- a/media/ndk/Android.bp +++ b/media/ndk/Android.bp @@ -110,10 +110,6 @@ cc_library_shared { symbol_file: "libmediandk.map.txt", versions: ["29"], }, - - // Bug: http://b/124522995 libmediandk has linker errors when built with - // coverage - native_coverage: false, } llndk_library { diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index ec1e982160..6425590893 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -5535,7 +5535,10 @@ uint32_t AudioPolicyManager::setOutputDevices(const sp<SwAudioOutputDescriptor>& patchBuilder.addSink(filteredDevice); } - installPatch(__func__, patchHandle, outputDesc.get(), patchBuilder.patch(), delayMs); + // Add half reported latency to delayMs when muteWaitMs is null in order + // to avoid disordered sequence of muting volume and changing devices. + installPatch(__func__, patchHandle, outputDesc.get(), patchBuilder.patch(), + muteWaitMs == 0 ? (delayMs + (outputDesc->latency() / 2)) : delayMs); } // update stream volumes according to new device diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp index 5660d5e243..12984d0a12 100644 --- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp @@ -997,11 +997,6 @@ status_t AudioPolicyService::setAllowedCapturePolicy(uid_t uid, audio_flags_mask ALOGV("%s() mAudioPolicyManager == NULL", __func__); return NO_INIT; } - uint_t callingUid = IPCThreadState::self()->getCallingUid(); - if (uid != callingUid) { - ALOGD("%s() uid invalid %d != %d", __func__, uid, callingUid); - return PERMISSION_DENIED; - } return mAudioPolicyManager->setAllowedCapturePolicy(uid, capturePolicy); } diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 87deba2115..95e4e6eb74 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -121,6 +121,8 @@ static void setLogLevel(int level) { // ---------------------------------------------------------------------------- static const String16 sManageCameraPermission("android.permission.MANAGE_CAMERA"); +static const String16 sCameraOpenCloseListenerPermission( + "android.permission.CAMERA_OPEN_CLOSE_LISTENER"); // Matches with PERCEPTIBLE_APP_ADJ in ProcessList.java static constexpr int32_t kVendorClientScore = 200; @@ -1827,7 +1829,11 @@ Status CameraService::addListenerHelper(const sp<ICameraServiceListener>& listen } auto clientUid = CameraThreadState::getCallingUid(); - sp<ServiceListener> serviceListener = new ServiceListener(this, listener, clientUid); + auto clientPid = CameraThreadState::getCallingPid(); + bool openCloseCallbackAllowed = checkPermission(sCameraOpenCloseListenerPermission, + clientPid, clientUid); + sp<ServiceListener> serviceListener = new ServiceListener(this, listener, + clientUid, clientPid, openCloseCallbackAllowed); auto ret = serviceListener->initialize(); if (ret != NO_ERROR) { String8 msg = String8::format("Failed to initialize service listener: %s (%d)", @@ -2537,6 +2543,9 @@ status_t CameraService::BasicClient::startCameraOps() { sCameraService->mUidPolicy->registerMonitorUid(mClientUid); + // Notify listeners of camera open/close status + sCameraService->updateOpenCloseStatus(mCameraIdStr, true/*open*/, mClientPackageName); + return OK; } @@ -2577,6 +2586,9 @@ status_t CameraService::BasicClient::finishCameraOps() { sCameraService->mUidPolicy->unregisterMonitorUid(mClientUid); + // Notify listeners of camera open/close status + sCameraService->updateOpenCloseStatus(mCameraIdStr, false/*open*/, mClientPackageName); + return OK; } @@ -3352,6 +3364,29 @@ void CameraService::updateStatus(StatusInternal status, const String8& cameraId, }); } +void CameraService::updateOpenCloseStatus(const String8& cameraId, bool open, + const String16& clientPackageName) { + Mutex::Autolock lock(mStatusListenerLock); + + for (const auto& it : mListenerList) { + if (!it.second->isOpenCloseCallbackAllowed()) { + continue; + } + + binder::Status ret; + String16 cameraId64(cameraId); + if (open) { + ret = it.second->getListener()->onCameraOpened(cameraId64, clientPackageName); + } else { + ret = it.second->getListener()->onCameraClosed(cameraId64); + } + if (!ret.isOk()) { + ALOGE("%s: Failed to trigger onCameraOpened/onCameraClosed callback: %d", __FUNCTION__, + ret.exceptionCode()); + } + } +} + template<class Func> void CameraService::CameraState::updateStatus(StatusInternal status, const String8& cameraId, diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index 22842a1cc3..bcaca9ffcb 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -817,7 +817,9 @@ private: class ServiceListener : public virtual IBinder::DeathRecipient { public: ServiceListener(sp<CameraService> parent, sp<hardware::ICameraServiceListener> listener, - int uid) : mParent(parent), mListener(listener), mListenerUid(uid) {} + int uid, int pid, bool openCloseCallbackAllowed) : mParent(parent), + mListener(listener), mListenerUid(uid), mListenerPid(pid), + mOpenCloseCallbackAllowed(openCloseCallbackAllowed) {} status_t initialize() { return IInterface::asBinder(mListener)->linkToDeath(this); @@ -831,12 +833,16 @@ private: } int getListenerUid() { return mListenerUid; } + int getListenerPid() { return mListenerPid; } sp<hardware::ICameraServiceListener> getListener() { return mListener; } + bool isOpenCloseCallbackAllowed() { return mOpenCloseCallbackAllowed; } private: wp<CameraService> mParent; sp<hardware::ICameraServiceListener> mListener; int mListenerUid; + int mListenerPid; + bool mOpenCloseCallbackAllowed = false; }; // Guarded by mStatusListenerMutex @@ -859,6 +865,13 @@ private: void updateStatus(StatusInternal status, const String8& cameraId); + /** + * Update the opened/closed status of the given camera id. + * + * This method acqiures mStatusListenerLock. + */ + void updateOpenCloseStatus(const String8& cameraId, bool open, const String16& packageName); + // flashlight control sp<CameraFlashlight> mFlashlight; // guard mTorchStatusMap diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp index 4227a3b9de..93e18cfee3 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.cpp +++ b/services/camera/libcameraservice/device3/Camera3Device.cpp @@ -3529,6 +3529,8 @@ void Camera3Device::sendCaptureResult(CameraMetadata &pendingMetadata, frameNumber); return; } + nsecs_t sensorTimestamp = timestamp.data.i64[0]; + for (auto& physicalMetadata : captureResult.mPhysicalMetadatas) { camera_metadata_entry timestamp = physicalMetadata.mPhysicalCameraMetadata.find(ANDROID_SENSOR_TIMESTAMP); @@ -3583,7 +3585,7 @@ void Camera3Device::sendCaptureResult(CameraMetadata &pendingMetadata, CameraMetadata(m.mPhysicalCameraMetadata)); } mTagMonitor.monitorMetadata(TagMonitor::RESULT, - frameNumber, timestamp.data.i64[0], captureResult.mMetadata, + frameNumber, sensorTimestamp, captureResult.mMetadata, monitoredPhysicalMetadata); insertResultLocked(&captureResult, frameNumber); diff --git a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h index 0f6be79be0..b9e58574c6 100644 --- a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h +++ b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h @@ -54,6 +54,15 @@ struct H2BCameraServiceListener : // TODO: no implementation yet. return binder::Status::ok(); } + virtual binder::Status onCameraOpened(const ::android::String16& /*cameraId*/, + const ::android::String16& /*clientPackageId*/) { + // empty implementation + return binder::Status::ok(); + } + virtual binder::Status onCameraClosed(const ::android::String16& /*cameraId*/) { + // empty implementation + return binder::Status::ok(); + } }; } // implementation diff --git a/services/mediacodec/Android.bp b/services/mediacodec/Android.bp index 99a6d6b807..2f3cad9737 100644 --- a/services/mediacodec/Android.bp +++ b/services/mediacodec/Android.bp @@ -64,5 +64,8 @@ prebuilt_etc { src: "seccomp_policy/mediacodec-x86.policy", }, }, - required: ["crash_dump.policy"], + required: [ + "crash_dump.policy", + "code_coverage.policy", + ], } diff --git a/services/mediacodec/Android.mk b/services/mediacodec/Android.mk index ecc84087b3..15bc5035b6 100644 --- a/services/mediacodec/Android.mk +++ b/services/mediacodec/Android.mk @@ -72,7 +72,7 @@ include $(CLEAR_VARS) LOCAL_MODULE := mediacodec.policy LOCAL_MODULE_CLASS := ETC LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/seccomp_policy -LOCAL_REQUIRED_MODULES := crash_dump.policy +LOCAL_REQUIRED_MODULES := crash_dump.policy code_coverage.policy # mediacodec runs in 32-bit combatibility mode. For 64 bit architectures, # use the 32 bit policy ifdef TARGET_2ND_ARCH diff --git a/services/mediacodec/seccomp_policy/mediacodec-arm.policy b/services/mediacodec/seccomp_policy/mediacodec-arm.policy index 3870a11680..835f8bbec6 100644 --- a/services/mediacodec/seccomp_policy/mediacodec-arm.policy +++ b/services/mediacodec/seccomp_policy/mediacodec-arm.policy @@ -59,3 +59,5 @@ getdents64: 1 getrandom: 1 @include /system/etc/seccomp_policy/crash_dump.arm.policy + +@include /system/etc/seccomp_policy/code_coverage.arm.policy diff --git a/services/mediacodec/seccomp_policy/mediacodec-x86.policy b/services/mediacodec/seccomp_policy/mediacodec-x86.policy index d9c4045f82..a9d32d611e 100644 --- a/services/mediacodec/seccomp_policy/mediacodec-x86.policy +++ b/services/mediacodec/seccomp_policy/mediacodec-x86.policy @@ -69,3 +69,4 @@ getpid: 1 gettid: 1 @include /system/etc/seccomp_policy/crash_dump.x86.policy +@include /system/etc/seccomp_policy/code_coverage.x86.policy diff --git a/services/mediacodec/seccomp_policy/mediaswcodec-arm.policy b/services/mediacodec/seccomp_policy/mediaswcodec-arm.policy index 9042cd77b2..93b485243f 100644 --- a/services/mediacodec/seccomp_policy/mediaswcodec-arm.policy +++ b/services/mediacodec/seccomp_policy/mediaswcodec-arm.policy @@ -84,3 +84,5 @@ geteuid32: 1 getgid32: 1 getegid32: 1 getgroups32: 1 + +@include /system/etc/seccomp_policy/code_coverage.arm.policy diff --git a/services/mediacodec/seccomp_policy/mediaswcodec-arm64.policy b/services/mediacodec/seccomp_policy/mediaswcodec-arm64.policy index 4faf8b20c1..bb05770839 100644 --- a/services/mediacodec/seccomp_policy/mediaswcodec-arm64.policy +++ b/services/mediacodec/seccomp_policy/mediaswcodec-arm64.policy @@ -79,3 +79,4 @@ getgid: 1 getegid: 1 getgroups: 1 +@include /system/etc/seccomp_policy/code_coverage.arm64.policy diff --git a/services/mediaextractor/Android.bp b/services/mediaextractor/Android.bp index b812244170..0c701d7b80 100644 --- a/services/mediaextractor/Android.bp +++ b/services/mediaextractor/Android.bp @@ -66,6 +66,9 @@ prebuilt_etc { src: "seccomp_policy/mediaextractor-x86_64.policy", }, }, - required: ["crash_dump.policy"], + required: [ + "crash_dump.policy", + "code_coverage.policy", + ], } diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy b/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy index 964acf421b..118072ec65 100644 --- a/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy +++ b/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy @@ -41,6 +41,9 @@ getegid32: 1 getgroups32: 1 nanosleep: 1 getrandom: 1 +timer_create: 1 +timer_settime: 1 +timer_delete: 1 # for dynamically loading extractors pread64: 1 @@ -50,3 +53,4 @@ readlinkat: 1 _llseek: 1 @include /system/etc/seccomp_policy/crash_dump.arm.policy +@include /system/etc/seccomp_policy/code_coverage.arm.policy diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-arm64.policy b/services/mediaextractor/seccomp_policy/mediaextractor-arm64.policy index e6c676c5dd..481e29e253 100644 --- a/services/mediaextractor/seccomp_policy/mediaextractor-arm64.policy +++ b/services/mediaextractor/seccomp_policy/mediaextractor-arm64.policy @@ -30,6 +30,9 @@ rt_sigreturn: 1 getrlimit: 1 nanosleep: 1 getrandom: 1 +timer_create: 1 +timer_settime: 1 +timer_delete: 1 # for FileSource readlinkat: 1 @@ -44,3 +47,4 @@ mremap: 1 sched_yield: 1 @include /system/etc/seccomp_policy/crash_dump.arm64.policy +@include /system/etc/seccomp_policy/code_coverage.arm64.policy diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy b/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy index 56ad8dfbe8..15fb24e5ea 100644 --- a/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy +++ b/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy @@ -39,6 +39,9 @@ getegid32: 1 getgroups32: 1 nanosleep: 1 getrandom: 1 +timer_create: 1 +timer_settime: 1 +timer_delete: 1 # for dynamically loading extractors getdents64: 1 @@ -57,3 +60,4 @@ getpid: 1 gettid: 1 @include /system/etc/seccomp_policy/crash_dump.x86.policy +@include /system/etc/seccomp_policy/code_coverage.x86.policy diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy b/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy index 607a03ef04..4f2646c9cd 100644 --- a/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy +++ b/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy @@ -34,6 +34,9 @@ sched_setscheduler: 1 getrlimit: 1 nanosleep: 1 getrandom: 1 +timer_create: 1 +timer_settime: 1 +timer_delete: 1 # for dynamically loading extractors getdents64: 1 @@ -51,3 +54,4 @@ getpid: 1 gettid: 1 @include /system/etc/seccomp_policy/crash_dump.x86_64.policy +@include /system/etc/seccomp_policy/code_coverage.x86_64.policy diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp index 377d30bcde..51afdcd82e 100644 --- a/services/soundtrigger/SoundTriggerHwService.cpp +++ b/services/soundtrigger/SoundTriggerHwService.cpp @@ -40,6 +40,32 @@ #define HW_MODULE_PREFIX "primary" namespace android { +namespace { + +// Given an IMemory, returns a copy of its content along with its size. +// Returns nullptr on failure or if input is nullptr. +std::pair<std::unique_ptr<uint8_t[]>, + size_t> CopyToArray(const sp<IMemory>& mem) { + if (mem == nullptr) { + return std::make_pair(nullptr, 0); + } + + const size_t size = mem->size(); + if (size == 0) { + return std::make_pair(nullptr, 0); + } + + std::unique_ptr<uint8_t[]> ar = std::make_unique<uint8_t[]>(size); + if (ar == nullptr) { + return std::make_pair(nullptr, 0); + } + + memcpy(ar.get(), mem->pointer(), size); + return std::make_pair(std::move(ar), size); +} + +} + SoundTriggerHwService::SoundTriggerHwService() : BnSoundTriggerHwService(), mNextUniqueId(1), @@ -557,8 +583,13 @@ status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelM return NO_INIT; } - struct sound_trigger_sound_model *sound_model = - (struct sound_trigger_sound_model *)modelMemory->pointer(); + auto immutableMemory = CopyToArray(modelMemory); + if (immutableMemory.first == nullptr) { + return NO_MEMORY; + } + + struct sound_trigger_sound_model* sound_model = + (struct sound_trigger_sound_model*) immutableMemory.first.get(); size_t structSize; if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) { @@ -568,9 +599,10 @@ status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelM } if (sound_model->data_offset < structSize || - sound_model->data_size > (UINT_MAX - sound_model->data_offset) || - modelMemory->size() < sound_model->data_offset || - sound_model->data_size > (modelMemory->size() - sound_model->data_offset)) { + sound_model->data_size > (UINT_MAX - sound_model->data_offset) || + immutableMemory.second < sound_model->data_offset || + sound_model->data_size > + (immutableMemory.second - sound_model->data_offset)) { android_errorWriteLog(0x534e4554, "30148546"); ALOGE("loadSoundModel() data_size is too big"); return BAD_VALUE; @@ -651,13 +683,19 @@ status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t ha return NO_INIT; } - struct sound_trigger_recognition_config *config = - (struct sound_trigger_recognition_config *)dataMemory->pointer(); + auto immutableMemory = CopyToArray(dataMemory); + if (immutableMemory.first == nullptr) { + return NO_MEMORY; + } + + struct sound_trigger_recognition_config* config = + (struct sound_trigger_recognition_config*) immutableMemory.first.get(); if (config->data_offset < sizeof(struct sound_trigger_recognition_config) || - config->data_size > (UINT_MAX - config->data_offset) || - dataMemory->size() < config->data_offset || - config->data_size > (dataMemory->size() - config->data_offset)) { + config->data_size > (UINT_MAX - config->data_offset) || + immutableMemory.second < config->data_offset || + config->data_size > + (immutableMemory.second - config->data_offset)) { ALOGE("startRecognition() data_size is too big"); return BAD_VALUE; } |