Merge "VolumeShaper: Log to mediametrics" into main
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 645a3d4..c9d2f1a 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -2428,27 +2428,27 @@
* </ul></p>
*
* <p>Flash strength level to use in capture mode i.e. when the applications control
- * flash with either SINGLE or TORCH mode.</p>
+ * flash with either <code>SINGLE</code> or <code>TORCH</code> mode.</p>
* <p>Use ACAMERA_FLASH_SINGLE_STRENGTH_MAX_LEVEL and
* ACAMERA_FLASH_TORCH_STRENGTH_MAX_LEVEL to check whether the device supports
* flash strength control or not.
- * If the values of android.flash.info.singleStrengthMaxLevel and
+ * If the values of ACAMERA_FLASH_SINGLE_STRENGTH_MAX_LEVEL and
* ACAMERA_FLASH_TORCH_STRENGTH_MAX_LEVEL are greater than 1,
* then the device supports manual flash strength control.</p>
- * <p>If the ACAMERA_FLASH_MODE <code>==</code> TORCH the value must be >= 1
+ * <p>If the ACAMERA_FLASH_MODE <code>==</code> <code>TORCH</code> the value must be >= 1
* and <= ACAMERA_FLASH_TORCH_STRENGTH_MAX_LEVEL.
* If the application doesn't set the key and
* ACAMERA_FLASH_TORCH_STRENGTH_MAX_LEVEL > 1,
* then the flash will be fired at the default level set by HAL in
* ACAMERA_FLASH_TORCH_STRENGTH_DEFAULT_LEVEL.
- * If the ACAMERA_FLASH_MODE <code>==</code> SINGLE, then the value must be >= 1
+ * If the ACAMERA_FLASH_MODE <code>==</code> <code>SINGLE</code>, then the value must be >= 1
* and <= ACAMERA_FLASH_SINGLE_STRENGTH_MAX_LEVEL.
* If the application does not set this key and
* ACAMERA_FLASH_SINGLE_STRENGTH_MAX_LEVEL > 1,
* then the flash will be fired at the default level set by HAL
* in ACAMERA_FLASH_SINGLE_STRENGTH_DEFAULT_LEVEL.
- * If ACAMERA_CONTROL_AE_MODE is set to any of ON_AUTO_FLASH, ON_ALWAYS_FLASH,
- * ON_AUTO_FLASH_REDEYE, ON_EXTERNAL_FLASH values, then the strengthLevel will be ignored.</p>
+ * If ACAMERA_CONTROL_AE_MODE is set to any of <code>ON_AUTO_FLASH</code>, <code>ON_ALWAYS_FLASH</code>,
+ * <code>ON_AUTO_FLASH_REDEYE</code>, <code>ON_EXTERNAL_FLASH</code> values, then the strengthLevel will be ignored.</p>
*
* @see ACAMERA_CONTROL_AE_MODE
* @see ACAMERA_FLASH_MODE
@@ -2460,7 +2460,7 @@
ACAMERA_FLASH_STRENGTH_LEVEL = // int32
ACAMERA_FLASH_START + 6,
/**
- * <p>Maximum flash brightness level for manual flash control in SINGLE mode.</p>
+ * <p>Maximum flash brightness level for manual flash control in <code>SINGLE</code> mode.</p>
*
* <p>Type: int32</p>
*
@@ -2470,7 +2470,7 @@
* </ul></p>
*
* <p>Maximum flash brightness level in camera capture mode and
- * ACAMERA_FLASH_MODE set to SINGLE.
+ * ACAMERA_FLASH_MODE set to <code>SINGLE</code>.
* Value will be > 1 if the manual flash strength control feature is supported,
* otherwise the value will be equal to 1.
* Note that this level is just a number of supported levels (the granularity of control).
@@ -2481,7 +2481,7 @@
ACAMERA_FLASH_SINGLE_STRENGTH_MAX_LEVEL = // int32
ACAMERA_FLASH_START + 7,
/**
- * <p>Default flash brightness level for manual flash control in SINGLE mode.</p>
+ * <p>Default flash brightness level for manual flash control in <code>SINGLE</code> mode.</p>
*
* <p>Type: int32</p>
*
@@ -2500,7 +2500,7 @@
ACAMERA_FLASH_SINGLE_STRENGTH_DEFAULT_LEVEL = // int32
ACAMERA_FLASH_START + 8,
/**
- * <p>Maximum flash brightness level for manual flash control in TORCH mode</p>
+ * <p>Maximum flash brightness level for manual flash control in <code>TORCH</code> mode</p>
*
* <p>Type: int32</p>
*
@@ -2510,7 +2510,7 @@
* </ul></p>
*
* <p>Maximum flash brightness level in camera capture mode and
- * ACAMERA_FLASH_MODE set to TORCH.
+ * ACAMERA_FLASH_MODE set to <code>TORCH</code>.
* Value will be > 1 if the manual flash strength control feature is supported,
* otherwise the value will be equal to 1.</p>
* <p>Note that this level is just a number of supported levels(the granularity of control).
@@ -2527,7 +2527,7 @@
ACAMERA_FLASH_TORCH_STRENGTH_MAX_LEVEL = // int32
ACAMERA_FLASH_START + 9,
/**
- * <p>Default flash brightness level for manual flash control in TORCH mode</p>
+ * <p>Default flash brightness level for manual flash control in <code>TORCH</code> mode</p>
*
* <p>Type: int32</p>
*
@@ -5875,10 +5875,16 @@
* <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
* </ul></p>
*
- * <p>If TRUE, all images produced by the camera device in the RAW image formats will
- * have lens shading correction already applied to it. If FALSE, the images will
- * not be adjusted for lens shading correction.
- * See android.request.maxNumOutputRaw for a list of RAW image formats.</p>
+ * <p>If <code>true</code>, all images produced by the camera device in the <code>RAW</code> image formats will have
+ * at least some lens shading correction already applied to it. If <code>false</code>, the images will
+ * not be adjusted for lens shading correction. See android.request.maxNumOutputRaw for a
+ * list of RAW image formats.</p>
+ * <p>When <code>true</code>, the <code>lensShadingCorrectionMap</code> key may still have values greater than 1.0,
+ * and those will need to be applied to any captured RAW frames for them to match the shading
+ * correction of processed buffers such as <code>YUV</code> or <code>JPEG</code> images. This may occur, for
+ * example, when some basic fixed lens shading correction is applied by hardware to RAW data,
+ * and additional correction is done dynamically in the camera processing pipeline after
+ * demosaicing.</p>
* <p>This key will be <code>null</code> for all devices do not report this information.
* Devices with RAW capability will always report this information in this key.</p>
*/
diff --git a/media/codec2/components/avc/C2SoftAvcDec.h b/media/codec2/components/avc/C2SoftAvcDec.h
index 36a463e..6165455 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.h
+++ b/media/codec2/components/avc/C2SoftAvcDec.h
@@ -173,7 +173,7 @@
VuiColorAspects()
: primaries(2), transfer(2), coeffs(2), fullRange(0) { }
- bool operator==(const VuiColorAspects &o) {
+ bool operator==(const VuiColorAspects &o) const {
return primaries == o.primaries && transfer == o.transfer && coeffs == o.coeffs
&& fullRange == o.fullRange;
}
diff --git a/media/codec2/components/dav1d/C2SoftDav1dDec.h b/media/codec2/components/dav1d/C2SoftDav1dDec.h
index 6008325..c5c1214 100644
--- a/media/codec2/components/dav1d/C2SoftDav1dDec.h
+++ b/media/codec2/components/dav1d/C2SoftDav1dDec.h
@@ -91,7 +91,7 @@
coeffs(C2Color::MATRIX_UNSPECIFIED),
fullRange(C2Color::RANGE_UNSPECIFIED) {}
- bool operator==(const VuiColorAspects& o) {
+ bool operator==(const VuiColorAspects& o) const {
return primaries == o.primaries && transfer == o.transfer && coeffs == o.coeffs &&
fullRange == o.fullRange;
}
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.h b/media/codec2/components/gav1/C2SoftGav1Dec.h
index 0e09fcc..e5d10e0 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.h
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.h
@@ -84,7 +84,7 @@
coeffs(C2Color::MATRIX_UNSPECIFIED),
fullRange(C2Color::RANGE_UNSPECIFIED) { }
- bool operator==(const VuiColorAspects &o) {
+ bool operator==(const VuiColorAspects &o) const {
return primaries == o.primaries && transfer == o.transfer && coeffs == o.coeffs
&& fullRange == o.fullRange;
}
diff --git a/media/codec2/components/hevc/C2SoftHevcDec.h b/media/codec2/components/hevc/C2SoftHevcDec.h
index 6abf69e..ff6d371 100644
--- a/media/codec2/components/hevc/C2SoftHevcDec.h
+++ b/media/codec2/components/hevc/C2SoftHevcDec.h
@@ -132,7 +132,7 @@
VuiColorAspects()
: primaries(2), transfer(2), coeffs(2), fullRange(0) { }
- bool operator==(const VuiColorAspects &o) {
+ bool operator==(const VuiColorAspects &o) const {
return primaries == o.primaries && transfer == o.transfer && coeffs == o.coeffs
&& fullRange == o.fullRange;
}
diff --git a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h
index 3965bcc..a7bee90 100644
--- a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h
+++ b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h
@@ -172,7 +172,7 @@
VuiColorAspects()
: primaries(2), transfer(2), coeffs(2), fullRange(0) { }
- bool operator==(const VuiColorAspects &o) {
+ bool operator==(const VuiColorAspects &o) const {
return primaries == o.primaries && transfer == o.transfer && coeffs == o.coeffs
&& fullRange == o.fullRange;
}
diff --git a/media/codec2/hal/common/Android.bp b/media/codec2/hal/common/Android.bp
index 4c9da33..0638363 100644
--- a/media/codec2/hal/common/Android.bp
+++ b/media/codec2/hal/common/Android.bp
@@ -28,13 +28,9 @@
"liblog",
"libstagefright_foundation",
"server_configurable_flags",
+ "libaconfig_storage_read_api_cc",
],
-
static_libs: ["aconfig_mediacodec_flags_c_lib"],
-
- defaults: [
- "aconfig_lib_cc_static_link.defaults",
- ],
}
cc_library_static {
@@ -57,6 +53,7 @@
shared_libs: [
"libbase",
"server_configurable_flags",
+ "libaconfig_storage_read_api_cc",
],
static_libs: ["aconfig_mediacodec_flags_c_lib"],
@@ -71,5 +68,6 @@
shared_libs: [
"libbase",
"server_configurable_flags",
+ "libaconfig_storage_read_api_cc",
],
}
diff --git a/media/codec2/sfplugin/Android.bp b/media/codec2/sfplugin/Android.bp
index 7076bac..3c8c1b7 100644
--- a/media/codec2/sfplugin/Android.bp
+++ b/media/codec2/sfplugin/Android.bp
@@ -84,6 +84,7 @@
"libui",
"libutils",
"server_configurable_flags",
+ "libaconfig_storage_read_api_cc",
],
export_shared_lib_headers: [
@@ -91,10 +92,6 @@
"libcodec2_client",
],
- defaults: [
- "aconfig_lib_cc_static_link.defaults",
- ],
-
sanitize: {
cfi: true,
misc_undefined: [
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index dc06ee6..327c3fd 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -180,7 +180,6 @@
// public dependency for implementing Codec 2 components
cc_defaults {
name: "libcodec2-impl-defaults",
- cpp_std: "gnu++17",
defaults: [
"libcodec2_hal_selection",
diff --git a/media/codec2/vndk/C2Fence.cpp b/media/codec2/vndk/C2Fence.cpp
index 5d50fc3..3438406 100644
--- a/media/codec2/vndk/C2Fence.cpp
+++ b/media/codec2/vndk/C2Fence.cpp
@@ -533,8 +533,7 @@
break;
default:
ALOGV("Unsupported fence type %d", type);
- // If this is malformed-handle close the handle here.
- (void) native_handle_close(handle);
+ // Nothing else to do. The handle is owned by the caller.
// return a null-fence in this case
break;
}
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
index daabdb7..e5373f3 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
@@ -65,9 +65,9 @@
{5, 3, -1, 3, 5}}}; /* Rock Preset */
static const std::vector<Equalizer::Preset> kEqPresets = {
- {0, "Normal"}, {1, "Classical"}, {2, "Dance"}, {3, "Flat"}, {4, "Folk"},
- {5, "Heavy Metal"}, {6, "Hip Hop"}, {7, "Jazz"}, {8, "Pop"}, {9, "Rock"}};
-
+ {-1, "Custom"}, {0, "Normal"}, {1, "Classical"}, {2, "Dance"},
+ {3, "Flat"}, {4, "Folk"}, {5, "Heavy Metal"}, {6, "Hip Hop"},
+ {7, "Jazz"}, {8, "Pop"}, {9, "Rock"}};
const std::vector<Range::EqualizerRange> kEqRanges = {
MAKE_RANGE(Equalizer, preset, 0, MAX_NUM_PRESETS - 1),
diff --git a/media/liberror/include/error/BinderResult.h b/media/liberror/include/error/BinderResult.h
new file mode 100644
index 0000000..1f1211c
--- /dev/null
+++ b/media/liberror/include/error/BinderResult.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <binder/Status.h>
+#include <error/expected_utils.h>
+#include <utils/Errors.h>
+
+namespace android {
+namespace error {
+
+/**
+ * A convenience short-hand for base::expected, where the error type is a binder::Status, for use
+ * when implementing binder services.
+ * Clients need to link against libbinder, since this library is header only.
+ */
+template <typename T>
+using BinderResult = base::expected<T, binder::Status>;
+
+inline base::unexpected<binder::Status> unexpectedExceptionCode(int32_t exceptionCode,
+ const char* s) {
+ return base::unexpected{binder::Status::fromExceptionCode(exceptionCode, s)};
+}
+
+inline base::unexpected<binder::Status> unexpectedServiceException(int32_t serviceSpecificCode,
+ const char* s) {
+ return base::unexpected{binder::Status::fromServiceSpecificError(serviceSpecificCode, s)};
+}
+
+} // namespace error
+} // namespace android
+
+inline std::string errorToString(const ::android::binder::Status& status) {
+ return std::string{status.toString8().c_str()};
+}
diff --git a/media/liberror/include/error/BinderStatusMatcher.h b/media/liberror/include/error/BinderStatusMatcher.h
new file mode 100644
index 0000000..11d9e65
--- /dev/null
+++ b/media/liberror/include/error/BinderStatusMatcher.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <ostream>
+
+#include <binder/Status.h>
+
+namespace android::error {
+
+class BinderStatusMatcher {
+ public:
+ using is_gtest_matcher = void;
+
+ explicit BinderStatusMatcher(binder::Status status) : status_(std::move(status)) {}
+
+ static BinderStatusMatcher hasException(binder::Status::Exception ex) {
+ return BinderStatusMatcher(binder::Status::fromExceptionCode(ex));
+ }
+
+ static BinderStatusMatcher isOk() { return BinderStatusMatcher(binder::Status::ok()); }
+
+ bool MatchAndExplain(const binder::Status& value,
+ ::testing::MatchResultListener* listener) const {
+ if (status_.exceptionCode() == value.exceptionCode() &&
+ status_.transactionError() == value.transactionError() &&
+ status_.serviceSpecificErrorCode() == value.serviceSpecificErrorCode()) {
+ return true;
+ }
+ *listener << "received binder status: " << value;
+ return false;
+ }
+
+ void DescribeTo(std::ostream* os) const { *os << "contains binder status " << status_; }
+
+ void DescribeNegationTo(std::ostream* os) const {
+ *os << "does not contain binder status " << status_;
+ }
+
+ private:
+ const binder::Status status_;
+};
+} // namespace android::error
diff --git a/media/liberror/include/error/ExpectedMatchers.h b/media/liberror/include/error/ExpectedMatchers.h
new file mode 100644
index 0000000..b81adbf
--- /dev/null
+++ b/media/liberror/include/error/ExpectedMatchers.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <ostream>
+#include <type_traits>
+
+namespace android::error {
+
+/**
+ * Example Usage:
+ * Given a function with signature
+ * Result<T, U> foo()
+ * Matchers can be used as follows:
+ * EXPECT_THAT(foo(), IsOkAnd(Eq(T{})));
+ * EXPECT_THAT(foo(), IsErrorAnd(Eq(U{})));
+ */
+template <typename ExpectedT>
+class IsOkAndImpl : public ::testing::MatcherInterface<ExpectedT> {
+ public:
+ using ValueT = std::remove_reference_t<ExpectedT>::value_type;
+
+ template <typename InnerMatcher>
+ explicit IsOkAndImpl(InnerMatcher innerMatcher)
+ : inner_matcher_(::testing::SafeMatcherCast<const ValueT&>(
+ std::forward<InnerMatcher>(innerMatcher))) {}
+
+ bool MatchAndExplain(ExpectedT val, ::testing::MatchResultListener* listener) const {
+ if (!val.has_value()) {
+ *listener << "which has error " << ::testing::PrintToString(val.error());
+ return false;
+ }
+ const auto res = inner_matcher_.MatchAndExplain(val.value(), listener);
+ if (!res) {
+ *listener << "which has value " << ::testing::PrintToString(val.value());
+ }
+ return res;
+ }
+
+ void DescribeTo(std::ostream* os) const {
+ *os << "contains expected value which ";
+ inner_matcher_.DescribeTo(os);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const {
+ *os << "does not contain expected, or contains expected value which ";
+ inner_matcher_.DescribeNegationTo(os);
+ }
+
+ private:
+ ::testing::Matcher<const ValueT&> inner_matcher_;
+};
+
+template <typename InnerMatcher>
+class IsOkAnd {
+ public:
+ explicit IsOkAnd(InnerMatcher innerMatcher) : inner_matcher_(std::move(innerMatcher)) {}
+
+ template <typename T>
+ operator ::testing::Matcher<T>() const {
+ return ::testing::Matcher<T>{new IsOkAndImpl<const T&>(inner_matcher_)};
+ }
+
+ private:
+ InnerMatcher inner_matcher_;
+};
+
+template <typename ExpectedT>
+class IsErrorAndImpl : public ::testing::MatcherInterface<ExpectedT> {
+ public:
+ using ErrorT = typename std::remove_reference_t<ExpectedT>::error_type;
+
+ template <typename InnerMatcher>
+ explicit IsErrorAndImpl(InnerMatcher innerMatcher)
+ : inner_matcher_(::testing::SafeMatcherCast<const ErrorT&>(
+ std::forward<InnerMatcher>(innerMatcher))) {}
+
+ bool MatchAndExplain(ExpectedT val, ::testing::MatchResultListener* listener) const {
+ if (val.has_value()) {
+ *listener << "which has value " << ::testing::PrintToString(val.value());
+ return false;
+ }
+
+ const auto res = inner_matcher_.MatchAndExplain(val.error(), listener);
+ if (!res) {
+ *listener << "which has error " << ::testing::PrintToString(val.error());
+ }
+ return res;
+ }
+
+ void DescribeTo(std::ostream* os) const {
+ *os << "contains error value which ";
+ inner_matcher_.DescribeTo(os);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const {
+ *os << "does not contain error value, or contains error value which ";
+ inner_matcher_.DescribeNegationTo(os);
+ }
+
+ private:
+ ::testing::Matcher<const ErrorT&> inner_matcher_;
+};
+
+template <typename InnerMatcher>
+class IsErrorAnd {
+ public:
+ explicit IsErrorAnd(InnerMatcher innerMatcher) : inner_matcher_(std::move(innerMatcher)) {}
+
+ template <typename T>
+ operator ::testing::Matcher<T>() const {
+ return ::testing::Matcher<T>{new IsErrorAndImpl<const T&>(inner_matcher_)};
+ }
+
+ private:
+ InnerMatcher inner_matcher_;
+};
+
+} // namespace android::error
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 5b6848c..ac178aa 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -315,13 +315,10 @@
"libaudioclient_aidl_conversion",
"packagemanager_aidl-cpp",
"server_configurable_flags",
+ "libaconfig_storage_read_api_cc",
"aconfig_mediacodec_flags_c_lib",
],
- defaults: [
- "aconfig_lib_cc_static_link.defaults",
- ],
-
static_libs: [
"android.media.codec-aconfig-cc",
"libstagefright_esds",
diff --git a/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp
index 9f46a74..b29429a 100644
--- a/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp
+++ b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp
@@ -21,105 +21,256 @@
#include <media/stagefright/MPEG2TSWriter.h>
#include <media/stagefright/MPEG4Writer.h>
#include <media/stagefright/OggWriter.h>
-
-#include "MediaMimeTypes.h"
-
#include <webm/WebmWriter.h>
namespace android {
-std::string genMimeType(FuzzedDataProvider *dataProvider) {
- uint8_t idx = dataProvider->ConsumeIntegralInRange<uint8_t>(0, kMimeTypes.size() - 1);
- return std::string(kMimeTypes[idx]);
-}
-sp<IMediaExtractor> genMediaExtractor(FuzzedDataProvider *dataProvider, std::string mimeType,
- uint16_t maxDataAmount) {
- uint32_t dataBlobSize = dataProvider->ConsumeIntegralInRange<uint16_t>(0, maxDataAmount);
- std::vector<uint8_t> data = dataProvider->ConsumeBytes<uint8_t>(dataBlobSize);
- // data:[<mediatype>][;base64],<data>
- std::string uri("data:");
- uri += mimeType;
- // Currently libstagefright only accepts base64 uris
- uri += ";base64,";
- android::AString out;
- android::encodeBase64(data.data(), data.size(), &out);
- uri += out.c_str();
-
- sp<DataSource> source =
- DataSourceFactory::getInstance()->CreateFromURI(NULL /* httpService */, uri.c_str());
-
- if (source == NULL) {
- return NULL;
- }
-
- return MediaExtractorFactory::Create(source);
-}
-
-sp<MediaSource> genMediaSource(FuzzedDataProvider *dataProvider, uint16_t maxMediaBlobSize) {
- std::string mime = genMimeType(dataProvider);
- sp<IMediaExtractor> extractor = genMediaExtractor(dataProvider, mime, maxMediaBlobSize);
-
- if (extractor == NULL) {
- return NULL;
- }
-
- for (size_t i = 0; i < extractor->countTracks(); ++i) {
- sp<MetaData> meta = extractor->getTrackMetaData(i);
-
- std::string trackMime = dataProvider->PickValueInArray(kTestedMimeTypes);
- if (!strcasecmp(mime.c_str(), trackMime.c_str())) {
- sp<IMediaSource> track = extractor->getTrack(i);
- if (track == NULL) {
- return NULL;
- }
- return new CallbackMediaSource(track);
- }
- }
-
- return NULL;
-}
-
-sp<MediaWriter> createWriter(int fd, StandardWriters writerType, sp<MetaData> fileMeta) {
+sp<MediaWriter> createWriter(int fd, StandardWriters writerType, sp<MetaData> writerMeta,
+ FuzzedDataProvider* fdp) {
sp<MediaWriter> writer;
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyRealTimeRecording, fdp->ConsumeBool());
+ }
+
switch (writerType) {
- case OGG:
- writer = new OggWriter(fd);
- fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_OGG);
- break;
case AAC:
- writer = new AACWriter(fd);
- fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AAC_ADIF);
+ writer = sp<AACWriter>::make(fd);
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AAC_ADIF);
+ }
break;
case AAC_ADTS:
- writer = new AACWriter(fd);
- fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AAC_ADTS);
- break;
- case WEBM:
- writer = new WebmWriter(fd);
- fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_WEBM);
- break;
- case MPEG4:
- writer = new MPEG4Writer(fd);
- fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_MPEG_4);
+ writer = sp<AACWriter>::make(fd);
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AAC_ADTS);
+ }
break;
case AMR_NB:
- writer = new AMRWriter(fd);
- fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_NB);
+ writer = sp<AMRWriter>::make(fd);
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_NB);
+ }
break;
case AMR_WB:
- writer = new AMRWriter(fd);
- fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_WB);
+ writer = sp<AMRWriter>::make(fd);
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_WB);
+ }
break;
case MPEG2TS:
- writer = new MPEG2TSWriter(fd);
- fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_MPEG2TS);
+ writer = sp<MPEG2TSWriter>::make(fd);
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_MPEG2TS);
+ }
break;
- default:
- return nullptr;
+ case MPEG4:
+ writer = sp<MPEG4Writer>::make(fd);
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_MPEG_4);
+ } else if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_HEIF);
+ } else if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_THREE_GPP);
+ }
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKey2ByteNalLength, fdp->ConsumeBool());
+ }
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyTimeScale,
+ fdp->ConsumeIntegralInRange<int32_t>(600, 96000));
+ }
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKey4BitTrackIds, fdp->ConsumeBool());
+ }
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt64(kKeyTrackTimeStatus, fdp->ConsumeIntegral<int64_t>());
+ }
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyRotation, fdp->ConsumeIntegralInRange<uint8_t>(0, 3) * 90);
+ }
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt64(kKeyTime, fdp->ConsumeIntegral<int64_t>());
+ }
+ break;
+ case OGG:
+ writer = sp<OggWriter>::make(fd);
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_OGG);
+ }
+ break;
+ case WEBM:
+ writer = sp<WebmWriter>::make(fd);
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_WEBM);
+ }
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyTimeScale,
+ fdp->ConsumeIntegralInRange<int32_t>(600, 96000));
+ }
+ break;
}
- if (writer != nullptr) {
- fileMeta->setInt32(kKeyRealTimeRecording, false);
- }
+
return writer;
}
+
+sp<FuzzSource> createSource(StandardWriters writerType, FuzzedDataProvider* fdp) {
+ sp<MetaData> meta = sp<MetaData>::make();
+
+ switch (writerType) {
+ case AAC:
+ case AAC_ADTS:
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
+ meta->setInt32(kKeyChannelCount, fdp->ConsumeIntegralInRange<uint8_t>(1, 7));
+ meta->setInt32(kKeySampleRate, fdp->PickValueInArray<uint32_t>(kSampleRateTable));
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyAACProfile, fdp->ConsumeIntegral<int32_t>());
+ }
+ break;
+ case AMR_NB:
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
+ meta->setInt32(kKeyChannelCount, 1);
+ meta->setInt32(kKeySampleRate, 8000);
+ break;
+ case AMR_WB:
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
+ meta->setInt32(kKeyChannelCount, 1);
+ meta->setInt32(kKeySampleRate, 16000);
+ break;
+ case MPEG2TS:
+ if (fdp->ConsumeBool()) {
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
+ meta->setInt32(kKeyChannelCount, fdp->ConsumeIntegral<int32_t>());
+ meta->setInt32(kKeySampleRate, fdp->PickValueInArray<uint32_t>(kSampleRateTable));
+ } else {
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+ // The +1s ensure a minimum height and width of 1.
+ meta->setInt32(kKeyWidth, fdp->ConsumeIntegral<uint16_t>() + 1);
+ meta->setInt32(kKeyHeight, fdp->ConsumeIntegral<uint16_t>() + 1);
+ }
+ break;
+ case MPEG4: {
+ auto mime = fdp->PickValueInArray<std::string>(kMpeg4MimeTypes);
+ meta->setCString(kKeyMIMEType, mime.c_str());
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyBackgroundMode, fdp->ConsumeBool());
+ }
+
+ if (!strncasecmp(mime.c_str(), "audio/", 6)) {
+ meta->setInt32(kKeyChannelCount, fdp->ConsumeIntegral<int32_t>());
+ meta->setInt32(kKeySampleRate, fdp->PickValueInArray<uint32_t>(kSampleRateTable));
+
+ } else {
+ // The +1s ensure a minimum height and width of 1.
+ meta->setInt32(kKeyWidth, fdp->ConsumeIntegral<uint16_t>() + 1);
+ meta->setInt32(kKeyHeight, fdp->ConsumeIntegral<uint16_t>() + 1);
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyDisplayWidth, fdp->ConsumeIntegral<uint16_t>());
+ }
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyDisplayHeight, fdp->ConsumeIntegral<uint16_t>());
+ }
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyTileWidth, fdp->ConsumeIntegral<uint16_t>());
+ }
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyTileHeight, fdp->ConsumeIntegral<uint16_t>());
+ }
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyGridRows, fdp->ConsumeIntegral<uint8_t>());
+ }
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyGridCols, fdp->ConsumeIntegral<uint8_t>());
+ }
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyTemporalLayerCount, fdp->ConsumeIntegral<int32_t>());
+ }
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeySARWidth, fdp->ConsumeIntegral<uint16_t>());
+ }
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeySARHeight, fdp->ConsumeIntegral<uint16_t>());
+ }
+ }
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyBitRate, fdp->ConsumeIntegral<int32_t>());
+ }
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyMaxBitRate, fdp->ConsumeIntegral<int32_t>());
+ }
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyTrackIsDefault, fdp->ConsumeBool());
+ }
+ break;
+ }
+ case OGG:
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_OPUS);
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyChannelCount, fdp->ConsumeIntegral<int32_t>());
+ }
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeySampleRate, fdp->PickValueInArray<uint32_t>(kSampleRateTable));
+ }
+ break;
+ case WEBM:
+ if (fdp->ConsumeBool()) {
+ if (fdp->ConsumeBool()) {
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP8);
+ } else {
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP9);
+ }
+
+ if (fdp->ConsumeBool()) {
+ // The +1s ensure a minimum height and width of 1.
+ meta->setInt32(kKeyWidth, fdp->ConsumeIntegral<uint16_t>() + 1);
+ meta->setInt32(kKeyHeight, fdp->ConsumeIntegral<uint16_t>() + 1);
+ }
+ } else {
+ if (fdp->ConsumeBool()) {
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
+ } else {
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_OPUS);
+ }
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyChannelCount, fdp->ConsumeIntegral<int32_t>());
+ }
+ meta->setInt32(kKeySampleRate, fdp->PickValueInArray<uint32_t>(kSampleRateTable));
+ }
+
+ break;
+ }
+
+ return sp<FuzzSource>::make(meta, fdp);
+}
} // namespace android
diff --git a/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.h b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.h
index 6856ac0..ad1218b 100644
--- a/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.h
+++ b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.h
@@ -15,20 +15,52 @@
*/
#pragma once
-#include <datasource/DataSourceFactory.h>
+
#include <fuzzer/FuzzedDataProvider.h>
-#include <android/IMediaExtractor.h>
-#include <media/IMediaHTTPService.h>
-#include <media/mediarecorder.h>
-#include <media/stagefright/CallbackMediaSource.h>
+
+#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaExtractorFactory.h>
#include <media/stagefright/MediaWriter.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/foundation/base64.h>
-#include <utils/StrongPointer.h>
namespace android {
+class FuzzSource : public MediaSource {
+ public:
+ FuzzSource(sp<MetaData> meta, FuzzedDataProvider* fdp) : mMetaData(meta), mFdp(fdp) {}
+
+ status_t start(MetaData*) { return OK; }
+
+ virtual status_t stop() { return OK; }
+
+ status_t read(MediaBufferBase** buffer, const ReadOptions*) {
+ // Ensuring that mBuffer has at least two bytes to avoid check failure
+ // in MPEG2TSWriter::SourceInfo::onMessageReceived().
+ if (mFdp->remaining_bytes() > 2) {
+ auto size = mFdp->ConsumeIntegralInRange<uint8_t>(2, INT8_MAX);
+ mBuffer = mFdp->ConsumeBytes<uint8_t>(size);
+ MediaBufferBase* mbb = new MediaBuffer(mBuffer.data(), mBuffer.size());
+
+ size_t length = mFdp->ConsumeIntegralInRange<size_t>(2, mbb->size());
+ size_t offset = mFdp->ConsumeIntegralInRange<size_t>(0, mbb->size() - length);
+ mbb->set_range(offset, length);
+
+ mbb->meta_data().setInt32(kKeyIsEndOfStream, mFdp->ConsumeBool());
+ mbb->meta_data().setInt64(kKeyTime, mFdp->ConsumeIntegral<uint32_t>() / 2);
+ *buffer = mbb;
+
+ return OK;
+ }
+
+ return ERROR_END_OF_STREAM;
+ }
+
+ sp<MetaData> getFormat() { return mMetaData; }
+
+ private:
+ sp<MetaData> mMetaData = nullptr;
+ FuzzedDataProvider* mFdp = nullptr;
+ std::vector<uint8_t> mBuffer;
+};
+
enum StandardWriters {
OGG,
AAC,
@@ -42,54 +74,22 @@
kMaxValue = MPEG2TS,
};
-static std::string kTestedMimeTypes[] = {"audio/3gpp",
- "audio/amr-wb",
- "audio/vorbis",
- "audio/opus",
- "audio/mp4a-latm",
- "audio/mpeg",
- "audio/mpeg-L1",
- "audio/mpeg-L2",
- "audio/midi",
- "audio/qcelp",
- "audio/g711-alaw",
- "audio/g711-mlaw",
- "audio/flac",
- "audio/aac-adts",
- "audio/gsm",
- "audio/ac3",
- "audio/eac3",
- "audio/eac3-joc",
- "audio/ac4",
- "audio/scrambled",
- "audio/alac",
- "audio/x-ms-wma",
- "audio/x-adpcm-ms",
- "audio/x-adpcm-dvi-ima",
- "video/avc",
- "video/hevc",
- "video/mp4v-es",
- "video/3gpp",
- "video/x-vnd.on2.vp8",
- "video/x-vnd.on2.vp9",
- "video/av01",
- "video/mpeg2",
- "video/dolby-vision",
- "video/scrambled",
- "video/divx",
- "video/divx3",
- "video/xvid",
- "video/x-motion-jpeg",
- "text/3gpp-tt",
- "application/x-subrip",
- "text/vtt",
- "text/cea-608",
- "text/cea-708",
- "application/x-id3v4"};
+static const uint32_t kSampleRateTable[] = {
+ 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000,
+};
+static const std::string kMpeg4MimeTypes[] = {
+ MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC, MEDIA_MIMETYPE_IMAGE_AVIF,
-std::string genMimeType(FuzzedDataProvider *dataProvider);
-sp<IMediaExtractor> genMediaExtractor(FuzzedDataProvider *dataProvider, uint16_t dataAmount);
-sp<MediaSource> genMediaSource(FuzzedDataProvider *dataProvider, uint16_t maxMediaBlobSize);
+ MEDIA_MIMETYPE_VIDEO_AV1, MEDIA_MIMETYPE_VIDEO_AVC,
+ MEDIA_MIMETYPE_VIDEO_HEVC, MEDIA_MIMETYPE_VIDEO_MPEG4,
+ MEDIA_MIMETYPE_VIDEO_H263, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION,
-sp<MediaWriter> createWriter(int32_t fd, StandardWriters writerType, sp<MetaData> fileMeta);
+ MEDIA_MIMETYPE_AUDIO_AMR_NB, MEDIA_MIMETYPE_AUDIO_AMR_WB,
+ MEDIA_MIMETYPE_AUDIO_AAC,
+};
+
+sp<MediaWriter> createWriter(int32_t fd, StandardWriters writerType, sp<MetaData> writerMeta,
+ FuzzedDataProvider* fdp);
+
+sp<FuzzSource> createSource(StandardWriters writerType, FuzzedDataProvider* fdp);
} // namespace android
diff --git a/media/libstagefright/tests/fuzzers/WriterFuzzer.cpp b/media/libstagefright/tests/fuzzers/WriterFuzzer.cpp
index 97d1160..cd0a866 100644
--- a/media/libstagefright/tests/fuzzers/WriterFuzzer.cpp
+++ b/media/libstagefright/tests/fuzzers/WriterFuzzer.cpp
@@ -13,216 +13,49 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-// Authors: corbin.souffrant@leviathansecurity.com
-// dylan.katz@leviathansecurity.com
-
-#include <android-base/file.h>
-#include <android/content/AttributionSourceState.h>
-#include <ctype.h>
-#include <media/mediarecorder.h>
-#include <media/stagefright/MPEG4Writer.h>
-#include <media/stagefright/MediaDefs.h>
-#include <stdlib.h>
-#include <utils/StrongPointer.h>
-#include <utils/Vector.h>
-
-#include <functional>
-#include <string>
#include "FuzzerMediaUtility.h"
-#include "fuzzer/FuzzedDataProvider.h"
-
-static constexpr uint16_t kMaxOperations = 5000;
-static constexpr uint8_t kMaxPackageNameLen = 50;
-// For other strings in mpeg we want a higher limit.
-static constexpr uint16_t kMaxMPEGStrLen = 1000;
-static constexpr uint16_t kMaxMediaBlobSize = 1000;
namespace android {
-using android::content::AttributionSourceState;
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ FuzzedDataProvider fdp(data, size);
-std::string getFourCC(FuzzedDataProvider *fdp) {
- std::string fourCC = fdp->ConsumeRandomLengthString(4);
- // Replace any existing nulls
- for (size_t pos = 0; pos < fourCC.length(); pos++) {
- if (fourCC.at(pos) == '\0') {
- fourCC.replace(pos, 1, "a");
- }
+ // memfd_create() creates an anonymous file and returns a file
+ // descriptor that refers to it. MFD_ALLOW_SEALING allows sealing
+ // operations on this file.
+ int32_t fd = memfd_create("WriterFuzzer", MFD_ALLOW_SEALING);
+ if (fd == -1) {
+ ALOGE("memfd_create() failed: %s", strerror(errno));
+ return 0;
}
- // If our string is too short, fill the remainder with "a"s.
- while (fourCC.length() < 4) {
- fourCC += 'a';
- }
- return fourCC;
-}
+ StandardWriters writerType = fdp.ConsumeEnum<StandardWriters>();
+ sp<MetaData> writerMeta = sp<MetaData>::make();
-typedef std::vector<std::function<void(FuzzedDataProvider*,
- sp<MediaWriter>, sp<MetaData>, int tmpFileFd)>> OperationVec;
-typedef std::vector<std::function<void(FuzzedDataProvider*, MPEG4Writer*)>> MPEG4OperationVec;
-static const OperationVec operations = {
- [](FuzzedDataProvider*, sp<MediaWriter> mediaWriter, sp<MetaData>, int) {
- mediaWriter->pause();
- },
- [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int tmpFd) {
- bool valid_fd = dataProvider->ConsumeBool();
- int fd = -1;
- if (valid_fd) {
- fd = tmpFd;
- }
- // Args don't seem to be used
- Vector<String16> args;
- mediaWriter->dump(fd, args);
- },
- [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int tmpFd) {
- bool valid_fd = dataProvider->ConsumeBool();
- int fd = -1;
- if (valid_fd) {
- fd = tmpFd;
- }
- mediaWriter->setNextFd(fd);
- },
- [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int) {
- mediaWriter->setCaptureRate(dataProvider->ConsumeFloatingPoint<float>());
- },
- [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int) {
- mediaWriter->setMaxFileDuration(dataProvider->ConsumeIntegral<int64_t>());
- },
- [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int) {
- mediaWriter->setStartTimeOffsetMs(dataProvider->ConsumeIntegral<int>());
-
- // Likely won't do much, but might as well as do a quick check
- // while we're here.
- mediaWriter->getStartTimeOffsetMs();
- },
- [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int) {
- mediaWriter->setMaxFileDuration(dataProvider->ConsumeIntegral<int64_t>());
- },
- [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int) {
- mediaWriter->setMaxFileDuration(dataProvider->ConsumeIntegral<int64_t>());
- },
-};
-
-static const MPEG4OperationVec mpeg4Operations = {
- [](FuzzedDataProvider*, MPEG4Writer *mediaWriter) { mediaWriter->notifyApproachingLimit(); },
- // Lower level write methods.
- // High-level startBox/endBox/etc are all called elsewhere,
- [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
- uint8_t val = dataProvider->ConsumeIntegral<uint8_t>();
- mediaWriter->writeInt8(val);
- },
- [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
- uint16_t val = dataProvider->ConsumeIntegral<uint16_t>();
- mediaWriter->writeInt16(val);
- },
- [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
- uint32_t val = dataProvider->ConsumeIntegral<uint32_t>();
- mediaWriter->writeInt32(val);
- },
- [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
- uint64_t val = dataProvider->ConsumeIntegral<uint64_t>();
- mediaWriter->writeInt64(val);
- },
- [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
- std::string strVal = dataProvider->ConsumeRandomLengthString(kMaxMPEGStrLen);
- mediaWriter->writeCString(strVal.c_str());
- },
- [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
- std::string fourCC = getFourCC(dataProvider);
- mediaWriter->writeFourcc(fourCC.c_str());
- },
-
- // Misc setters
- [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
- uint32_t layers = dataProvider->ConsumeIntegral<uint32_t>();
- mediaWriter->setTemporalLayerCount(layers);
- },
- [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
- uint32_t duration = dataProvider->ConsumeIntegral<uint32_t>();
- mediaWriter->setInterleaveDuration(duration);
- },
- [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
- int lat = dataProvider->ConsumeIntegral<int>();
- int lon = dataProvider->ConsumeIntegral<int>();
- mediaWriter->setGeoData(lat, lon);
- },
-};
-
-// Not all writers can always add new sources, so we'll need additional checks.
-void addSource(FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter) {
- sp<MediaSource> mediaSource = genMediaSource(dataProvider, kMaxMediaBlobSize);
- if (mediaSource == NULL) {
- // There's a static check preventing NULLs in addSource.
- return;
- }
- mediaWriter->addSource(mediaSource);
-}
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- FuzzedDataProvider dataProvider(data, size);
- TemporaryFile tf;
- sp<MetaData> fileMeta = new MetaData;
- StandardWriters writerType = dataProvider.ConsumeEnum<StandardWriters>();
- sp<MediaWriter> writer = createWriter(tf.fd, writerType, fileMeta);
-
- AttributionSourceState attributionSource;
- attributionSource.packageName = dataProvider.ConsumeRandomLengthString(kMaxPackageNameLen);
- attributionSource.uid = dataProvider.ConsumeIntegral<int32_t>();
- attributionSource.pid = dataProvider.ConsumeIntegral<int32_t>();
- attributionSource.token = sp<BBinder>::make();
- sp<MediaRecorder> mr = new MediaRecorder(attributionSource);
- writer->setListener(mr);
-
- uint8_t baseOpLen = operations.size();
- uint8_t totalLen = baseOpLen;
- uint8_t maxSources;
- // Different writers support different amounts of sources.
- switch (writerType) {
- case StandardWriters::AAC:
- case StandardWriters::AAC_ADTS:
- case StandardWriters::AMR_NB:
- case StandardWriters::AMR_WB:
- case StandardWriters::OGG:
- maxSources = 1;
- break;
- case StandardWriters::WEBM:
- maxSources = 2;
- break;
- default:
- maxSources = UINT8_MAX;
- break;
- }
- // Initialize some number of sources and add them to our writer.
- uint8_t sourceCount = dataProvider.ConsumeIntegralInRange<uint8_t>(0, maxSources);
- for (uint8_t i = 0; i < sourceCount; i++) {
- addSource(&dataProvider, writer);
+ sp<MediaWriter> writer = createWriter(fd, writerType, writerMeta, &fdp);
+ if (writer == nullptr) {
+ close(fd);
+ return 0;
}
- // Increase our range if additional operations are implemented.
- // Currently only MPEG4 has additiona public operations on their writer.
- if (writerType == StandardWriters::MPEG4) {
- totalLen += mpeg4Operations.size();
+ if (writerType == StandardWriters::WEBM) {
+ // This range is set to avoid CHECK failure in WEBMWriter::reset() -> EbmlVoid::EBmlVoid().
+ writer->setMaxFileSize(fdp.ConsumeIntegralInRange<int64_t>(5 * 1024 * 1024, INT64_MAX));
+ } else {
+ writer->setMaxFileSize(fdp.ConsumeIntegral<int64_t>());
}
+ writer->setMaxFileDuration(fdp.ConsumeIntegral<int64_t>());
+ writer->setCaptureRate(fdp.ConsumeFloatingPoint<float>());
- // Many operations require the writer to be started.
- writer->start(fileMeta.get());
- for (size_t ops_run = 0; dataProvider.remaining_bytes() > 0 && ops_run < kMaxOperations - 1;
- ops_run++) {
- uint8_t op = dataProvider.ConsumeIntegralInRange<uint8_t>(0, totalLen - 1);
- if (op < baseOpLen) {
- operations[op](&dataProvider, writer, fileMeta, tf.fd);
- } else if (writerType == StandardWriters::MPEG4) {
- mpeg4Operations[op - baseOpLen](&dataProvider, (MPEG4Writer*)writer.get());
- } else {
- // Here just in case, will error out.
- operations[op](&dataProvider, writer, fileMeta, tf.fd);
- }
- }
+ sp<MediaSource> source = createSource(writerType, &fdp);
+ writer->addSource(source);
+ writer->start(writerMeta.get());
+ writer->pause();
writer->stop();
- writer.clear();
- writer = nullptr;
+ close(fd);
+
return 0;
}
} // namespace android
diff --git a/services/audiopolicy/permission/NativePermissionController.cpp b/services/audiopolicy/permission/NativePermissionController.cpp
index 9fcf22d..8659f2c 100644
--- a/services/audiopolicy/permission/NativePermissionController.cpp
+++ b/services/audiopolicy/permission/NativePermissionController.cpp
@@ -24,9 +24,9 @@
#include <cutils/android_filesystem_config.h>
#include <utils/Errors.h>
-using ::android::base::unexpected;
using ::android::binder::Status;
-using ::android::error::Result;
+using ::android::error::BinderResult;
+using ::android::error::unexpectedExceptionCode;
namespace com::android::media::permission {
static std::optional<std::string> getFixedPackageName(uid_t uid) {
@@ -103,23 +103,31 @@
// -- End Binder methods
-Result<std::vector<std::string>> NativePermissionController::getPackagesForUid(uid_t uid) const {
+BinderResult<std::vector<std::string>> NativePermissionController::getPackagesForUid(
+ uid_t uid) const {
uid = uid % AID_USER_OFFSET;
const auto fixed_package_opt = getFixedPackageName(uid);
if (fixed_package_opt.has_value()) {
- return Result<std::vector<std::string>>{std::in_place_t{}, {fixed_package_opt.value()}};
+ return BinderResult<std::vector<std::string>>{std::in_place_t{},
+ {fixed_package_opt.value()}};
}
std::lock_guard l{m_};
- if (!is_package_populated_) return unexpected{::android::NO_INIT};
+ if (!is_package_populated_) {
+ return unexpectedExceptionCode(
+ Status::EX_ILLEGAL_STATE,
+ "NPC::getPackagesForUid: controller never populated by system_server");
+ }
const auto cursor = package_map_.find(uid);
if (cursor != package_map_.end()) {
return cursor->second;
} else {
- return unexpected{::android::BAD_VALUE};
+ return unexpectedExceptionCode(
+ Status::EX_ILLEGAL_ARGUMENT,
+ ("NPC::getPackagesForUid: uid not found: " + std::to_string(uid)).c_str());
}
}
-Result<bool> NativePermissionController::validateUidPackagePair(
+BinderResult<bool> NativePermissionController::validateUidPackagePair(
uid_t uid, const std::string& packageName) const {
uid = uid % AID_USER_OFFSET;
const auto fixed_package_opt = getFixedPackageName(uid);
@@ -127,20 +135,27 @@
return packageName == fixed_package_opt.value();
}
std::lock_guard l{m_};
- if (!is_package_populated_) return unexpected{::android::NO_INIT};
+ if (!is_package_populated_) {
+ return unexpectedExceptionCode(
+ Status::EX_ILLEGAL_STATE,
+ "NPC::validatedUidPackagePair: controller never populated by system_server");
+ }
const auto cursor = package_map_.find(uid);
return (cursor != package_map_.end()) &&
(std::find(cursor->second.begin(), cursor->second.end(), packageName) !=
cursor->second.end());
}
-Result<bool> NativePermissionController::checkPermission(PermissionEnum perm, uid_t uid) const {
+BinderResult<bool> NativePermissionController::checkPermission(PermissionEnum perm,
+ uid_t uid) const {
std::lock_guard l{m_};
const auto& uids = permission_map_[static_cast<size_t>(perm)];
if (!uids.empty()) {
return std::binary_search(uids.begin(), uids.end(), uid);
} else {
- return unexpected{::android::NO_INIT};
+ return unexpectedExceptionCode(
+ Status::EX_ILLEGAL_STATE,
+ "NPC::checkPermission: controller never populated by system_server");
}
}
diff --git a/services/audiopolicy/permission/ValidatedAttributionSourceState.cpp b/services/audiopolicy/permission/ValidatedAttributionSourceState.cpp
index 2c32289..f313422 100644
--- a/services/audiopolicy/permission/ValidatedAttributionSourceState.cpp
+++ b/services/audiopolicy/permission/ValidatedAttributionSourceState.cpp
@@ -20,31 +20,39 @@
#include <error/expected_utils.h>
#include <utils/Log.h>
+using ::android::binder::Status;
+using ::android::error::BinderResult;
+using ::android::error::unexpectedExceptionCode;
+
namespace com::android::media::permission {
-using ::android::base::unexpected;
-
-Result<ValidatedAttributionSourceState> ValidatedAttributionSourceState::createFromBinderContext(
- AttributionSourceState attr, const IPermissionProvider& provider) {
+BinderResult<ValidatedAttributionSourceState>
+ValidatedAttributionSourceState::createFromBinderContext(AttributionSourceState attr,
+ const IPermissionProvider& provider) {
attr.pid = ::android::IPCThreadState::self()->getCallingPid();
attr.uid = ::android::IPCThreadState::self()->getCallingUid();
return createFromTrustedUidNoPackage(std::move(attr), provider);
}
-Result<ValidatedAttributionSourceState>
+BinderResult<ValidatedAttributionSourceState>
ValidatedAttributionSourceState::createFromTrustedUidNoPackage(
AttributionSourceState attr, const IPermissionProvider& provider) {
if (attr.packageName.has_value() && attr.packageName->size() != 0) {
if (VALUE_OR_RETURN(provider.validateUidPackagePair(attr.uid, attr.packageName.value()))) {
return ValidatedAttributionSourceState{std::move(attr)};
} else {
- return unexpected{::android::PERMISSION_DENIED};
+ return unexpectedExceptionCode(Status::EX_SECURITY,
+ attr.toString()
+ .insert(0, ": invalid attr ")
+ .insert(0, __PRETTY_FUNCTION__)
+ .c_str());
}
} else {
// For APIs which don't appropriately pass attribution sources or packages, we need
// to populate the package name with our best guess.
const auto packageNames = VALUE_OR_RETURN(provider.getPackagesForUid(attr.uid));
- LOG_ALWAYS_FATAL_IF(packageNames.empty());
+ LOG_ALWAYS_FATAL_IF(packageNames.empty(), "%s BUG: empty package list from controller",
+ __PRETTY_FUNCTION__);
attr.packageName = std::move(packageNames[0]);
return ValidatedAttributionSourceState{std::move(attr)};
}
diff --git a/services/audiopolicy/permission/include/media/IPermissionProvider.h b/services/audiopolicy/permission/include/media/IPermissionProvider.h
index 27a61ea..8d90543 100644
--- a/services/audiopolicy/permission/include/media/IPermissionProvider.h
+++ b/services/audiopolicy/permission/include/media/IPermissionProvider.h
@@ -22,7 +22,7 @@
#include <vector>
#include <com/android/media/permission/PermissionEnum.h>
-#include <error/Result.h>
+#include <error/BinderResult.h>
namespace com::android::media::permission {
@@ -31,19 +31,20 @@
// Get all package names which run under a certain app-id. Returns non-empty.
// Not user specific, since packages are across users. Special app-ids (system,
// shell, etc.) are handled. Fails if the provider does not know about the
- // app-id.
- virtual ::android::error::Result<std::vector<std::string>> getPackagesForUid(
+ // app-id or if the provider has not been initialized.
+ virtual ::android::error::BinderResult<std::vector<std::string>> getPackagesForUid(
uid_t uid) const = 0;
// True iff the provided package name runs under the app-id of uid.
// Special app-ids (system, shell, etc.) are handled.
- // Fails if the provider does not know about the app-id.
- virtual ::android::error::Result<bool> validateUidPackagePair(
+ // Fails if the provider does not know about the app-id or if the provider has not been
+ // initialized.
+ virtual ::android::error::BinderResult<bool> validateUidPackagePair(
uid_t uid, const std::string& packageName) const = 0;
// True iff the uid holds the permission (user aware).
// Fails with NO_INIT if cache hasn't been populated.
- virtual ::android::error::Result<bool> checkPermission(PermissionEnum permission,
- uid_t uid) const = 0;
+ virtual ::android::error::BinderResult<bool> checkPermission(PermissionEnum permission,
+ uid_t uid) const = 0;
virtual ~IPermissionProvider() = default;
};
} // namespace com::android::media::permission
diff --git a/services/audiopolicy/permission/include/media/NativePermissionController.h b/services/audiopolicy/permission/include/media/NativePermissionController.h
index d464023..a81c7a2 100644
--- a/services/audiopolicy/permission/include/media/NativePermissionController.h
+++ b/services/audiopolicy/permission/include/media/NativePermissionController.h
@@ -24,6 +24,7 @@
#include <android-base/thread_annotations.h>
#include <com/android/media/permission/BnNativePermissionController.h>
+#include <error/BinderResult.h>
namespace com::android::media::permission {
@@ -36,11 +37,12 @@
Status populatePermissionState(PermissionEnum permission, const std::vector<int>& uids) final;
// end binder methods
- ::android::error::Result<std::vector<std::string>> getPackagesForUid(uid_t uid) const final;
- ::android::error::Result<bool> validateUidPackagePair(
+ ::android::error::BinderResult<std::vector<std::string>> getPackagesForUid(
+ uid_t uid) const final;
+ ::android::error::BinderResult<bool> validateUidPackagePair(
uid_t uid, const std::string& packageName) const final;
- ::android::error::Result<bool> checkPermission(PermissionEnum permission,
- uid_t uid) const final;
+ ::android::error::BinderResult<bool> checkPermission(PermissionEnum permission,
+ uid_t uid) const final;
private:
mutable std::mutex m_;
diff --git a/services/audiopolicy/permission/include/media/ValidatedAttributionSourceState.h b/services/audiopolicy/permission/include/media/ValidatedAttributionSourceState.h
index 8d9da05..46f7d0a 100644
--- a/services/audiopolicy/permission/include/media/ValidatedAttributionSourceState.h
+++ b/services/audiopolicy/permission/include/media/ValidatedAttributionSourceState.h
@@ -17,22 +17,22 @@
#pragma once
#include <android/content/AttributionSourceState.h>
-#include <error/Result.h>
+#include <error/BinderResult.h>
#include "IPermissionProvider.h"
namespace com::android::media::permission {
using ::android::content::AttributionSourceState;
-using ::android::error::Result;
class ValidatedAttributionSourceState {
public:
/**
* Validates an attribution source from within the context of a binder transaction.
- * Overwrites the uid/pid and validates the packageName
+ * Overwrites the uid/pid and validates the packageName.
+ * Returns EX_SECURITY on package validation fail.
*/
- static Result<ValidatedAttributionSourceState> createFromBinderContext(
+ static ::android::error::BinderResult<ValidatedAttributionSourceState> createFromBinderContext(
AttributionSourceState attr, const IPermissionProvider& provider);
/**
@@ -47,9 +47,10 @@
* Create a ValidatedAttribubtionSourceState in cases where the uid/pid is trusted, but the
* packages have not been validated. Proper use of the previous two methods should avoid the
* necessity of this, but it is useful for migration purposes as well as testing this class.
+ * Returns EX_SECURITY on package validation fail.
*/
- static Result<ValidatedAttributionSourceState> createFromTrustedUidNoPackage(
- AttributionSourceState attr, const IPermissionProvider& provider);
+ static ::android::error::BinderResult<ValidatedAttributionSourceState>
+ createFromTrustedUidNoPackage(AttributionSourceState attr, const IPermissionProvider& provider);
operator AttributionSourceState() const { return state_; }
diff --git a/services/audiopolicy/permission/tests/NativePermissionControllerTest.cpp b/services/audiopolicy/permission/tests/NativePermissionControllerTest.cpp
index 3f6b787..f2423c1 100644
--- a/services/audiopolicy/permission/tests/NativePermissionControllerTest.cpp
+++ b/services/audiopolicy/permission/tests/NativePermissionControllerTest.cpp
@@ -19,14 +19,22 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
-#include <android-base/expected.h>
+#include <error/BinderStatusMatcher.h>
+#include <error/ExpectedMatchers.h>
-using ::android::base::unexpected;
-using ::android::binder::Status;
+using android::binder::Status::EX_ILLEGAL_ARGUMENT;
+using android::binder::Status::EX_ILLEGAL_STATE;
+using android::error::BinderStatusMatcher;
+using android::error::IsErrorAnd;
+using android::error::IsOkAnd;
using com::android::media::permission::NativePermissionController;
using com::android::media::permission::PermissionEnum;
using com::android::media::permission::UidPackageState;
+using ::testing::ElementsAre;
+using ::testing::IsFalse;
+using ::testing::IsTrue;
+
class NativePermissionControllerTest : public ::testing::Test {
protected:
android::sp<NativePermissionController> holder_ =
@@ -40,50 +48,37 @@
return out;
}
-static std::vector<std::string> makeVector(const char* one) {
- return {one};
-}
-
-static std::vector<std::string> makeVector(const char* one, const char* two) {
- return {one, two};
-}
-
-#define UNWRAP_EQ(expr, desired_expr) \
- do { \
- auto tmp_ = (expr); \
- EXPECT_TRUE(tmp_.has_value()); \
- if (tmp_.has_value()) EXPECT_EQ(*tmp_, desired_expr); \
- } while (0)
-
// --- Tests for non-populated ----
TEST_F(NativePermissionControllerTest, getPackagesForUid_NotPopulated) {
// Verify errors are returned
- EXPECT_EQ(controller_.getPackagesForUid(10000), unexpected{android::NO_INIT});
- EXPECT_EQ(controller_.getPackagesForUid(10001), unexpected{android::NO_INIT});
+ EXPECT_THAT(controller_.getPackagesForUid(10000),
+ IsErrorAnd(BinderStatusMatcher::hasException(EX_ILLEGAL_STATE)));
+ EXPECT_THAT(controller_.getPackagesForUid(10001),
+ IsErrorAnd(BinderStatusMatcher::hasException(EX_ILLEGAL_STATE)));
// fixed uids should work
- UNWRAP_EQ(controller_.getPackagesForUid(1000), makeVector("system"));
+ EXPECT_THAT(controller_.getPackagesForUid(1000), IsOkAnd(ElementsAre(std::string{"system"})));
}
TEST_F(NativePermissionControllerTest, validateUidPackagePair_NotPopulated) {
// Verify errors are returned
- EXPECT_EQ(controller_.validateUidPackagePair(10000, "com.package"),
- unexpected{android::NO_INIT});
+ EXPECT_THAT(controller_.validateUidPackagePair(10000, "com.package"),
+ IsErrorAnd(BinderStatusMatcher::hasException(EX_ILLEGAL_STATE)));
// fixed uids should work
- UNWRAP_EQ(controller_.validateUidPackagePair(1000, "system"), true);
+ EXPECT_THAT(controller_.validateUidPackagePair(1000, "system"), IsOkAnd(IsTrue()));
}
+
// --- Tests for populatePackagesForUids ----
TEST_F(NativePermissionControllerTest, populatePackages_EmptyInput) {
std::vector<UidPackageState> input;
// succeeds
- EXPECT_TRUE(controller_.populatePackagesForUids(input).isOk());
+ EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
// Verify unknown uid behavior
- const auto res1 = controller_.getPackagesForUid(10000);
- ASSERT_FALSE(res1.has_value());
- EXPECT_EQ(res1.error(), ::android::BAD_VALUE);
+ EXPECT_THAT(controller_.getPackagesForUid(10000),
+ IsErrorAnd(BinderStatusMatcher::hasException(EX_ILLEGAL_ARGUMENT)));
}
TEST_F(NativePermissionControllerTest, populatePackages_ValidInput) {
@@ -92,11 +87,11 @@
createState(10001, {"com.example2.app1"}),
};
- EXPECT_TRUE(controller_.populatePackagesForUids(input).isOk());
+ EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
- UNWRAP_EQ(controller_.getPackagesForUid(10000),
- makeVector("com.example.app1", "com.example.app2"));
- UNWRAP_EQ(controller_.getPackagesForUid(10001), makeVector("com.example2.app1"));
+ EXPECT_THAT(controller_.getPackagesForUid(10000),
+ IsOkAnd(ElementsAre("com.example.app1", "com.example.app2")));
+ EXPECT_THAT(controller_.getPackagesForUid(10001), IsOkAnd(ElementsAre("com.example2.app1")));
}
// --- Tests for updatePackagesForUid ---
@@ -107,14 +102,14 @@
};
UidPackageState newState = createState(12000, {"com.example.other"});
- EXPECT_TRUE(controller_.populatePackagesForUids(input).isOk());
- EXPECT_TRUE(controller_.updatePackagesForUid(newState).isOk());
+ EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
+ EXPECT_THAT(controller_.updatePackagesForUid(newState), BinderStatusMatcher::isOk());
// Verify the results: only the updated package should be changed
- UNWRAP_EQ(controller_.getPackagesForUid(10000),
- makeVector("com.example.app1", "com.example.app2"));
- UNWRAP_EQ(controller_.getPackagesForUid(10001), makeVector("com.example2.app1"));
- UNWRAP_EQ(controller_.getPackagesForUid(12000), makeVector("com.example.other"));
+ EXPECT_THAT(controller_.getPackagesForUid(10000),
+ IsOkAnd(ElementsAre("com.example.app1", "com.example.app2")));
+ EXPECT_THAT(controller_.getPackagesForUid(10001), IsOkAnd(ElementsAre("com.example2.app1")));
+ EXPECT_THAT(controller_.getPackagesForUid(12000), IsOkAnd(ElementsAre("com.example.other")));
}
TEST_F(NativePermissionControllerTest, updatePackages_ExistingUid) {
@@ -123,14 +118,14 @@
createState(10001, {"com.example2.app1"}),
};
- EXPECT_TRUE(controller_.populatePackagesForUids(input).isOk());
+ EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
// Update packages for existing uid
UidPackageState newState = createState(10000, {"com.example.other", "com.example.new"});
- EXPECT_TRUE(controller_.updatePackagesForUid(newState).isOk());
+ EXPECT_THAT(controller_.updatePackagesForUid(newState), BinderStatusMatcher::isOk());
// Verify update
- UNWRAP_EQ(controller_.getPackagesForUid(10000),
- makeVector("com.example.other", "com.example.new"));
+ EXPECT_THAT(controller_.getPackagesForUid(10000),
+ IsOkAnd(ElementsAre("com.example.other", "com.example.new")));
}
TEST_F(NativePermissionControllerTest, updatePackages_EmptyRemovesEntry) {
@@ -138,15 +133,14 @@
createState(10000, {"com.example.app1"}),
};
- EXPECT_TRUE(controller_.populatePackagesForUids(input).isOk());
+ EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
UidPackageState newState{}; // Empty package list
newState.uid = 10000;
- EXPECT_TRUE(controller_.updatePackagesForUid(newState).isOk());
+ EXPECT_THAT(controller_.updatePackagesForUid(newState), BinderStatusMatcher::isOk());
// getPackages for unknown UID should error out
- const auto res = controller_.getPackagesForUid(10000);
- ASSERT_FALSE(res.has_value());
- EXPECT_EQ(res.error(), ::android::BAD_VALUE);
+ EXPECT_THAT(controller_.getPackagesForUid(10000),
+ IsErrorAnd(BinderStatusMatcher::hasException(EX_ILLEGAL_ARGUMENT)));
}
TEST_F(NativePermissionControllerTest, validateUidPackagePair_ValidPair) {
@@ -154,9 +148,9 @@
createState(10000, {"com.example.app1", "com.example.app2"}),
};
- EXPECT_TRUE(controller_.populatePackagesForUids(input).isOk());
+ EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
- UNWRAP_EQ(controller_.validateUidPackagePair(10000, "com.example.app1"), true);
+ EXPECT_THAT(controller_.validateUidPackagePair(10000, "com.example.app1"), IsOkAnd(IsTrue()));
}
TEST_F(NativePermissionControllerTest, validateUidPackagePair_InvalidPackage) {
@@ -164,9 +158,9 @@
createState(10000, {"com.example.app1", "com.example.app2"}),
};
- EXPECT_TRUE(controller_.populatePackagesForUids(input).isOk());
+ EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
- UNWRAP_EQ(controller_.validateUidPackagePair(10000, "com.example.other"), false);
+ EXPECT_THAT(controller_.validateUidPackagePair(10000, "com.example.other"), IsOkAnd(IsFalse()));
}
TEST_F(NativePermissionControllerTest, validateUidPackagePair_UnknownUid) {
@@ -174,45 +168,44 @@
createState(10000, {"com.example.app1", "com.example.app2"}),
};
- EXPECT_TRUE(controller_.populatePackagesForUids(input).isOk());
+ EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
- UNWRAP_EQ(controller_.validateUidPackagePair(12000, "any.package"), false);
+ EXPECT_THAT(controller_.validateUidPackagePair(12000, "any.package"), IsOkAnd(IsFalse()));
}
TEST_F(NativePermissionControllerTest, populatePermissionState_InvalidPermission) {
- EXPECT_EQ(controller_.populatePermissionState(PermissionEnum::ENUM_SIZE, {}).exceptionCode(),
- Status::EX_ILLEGAL_ARGUMENT);
- EXPECT_EQ(controller_
- .populatePermissionState(
- static_cast<PermissionEnum>(
- static_cast<int>(PermissionEnum::ENUM_SIZE) + 1),
- {})
- .exceptionCode(),
- Status::EX_ILLEGAL_ARGUMENT);
+ EXPECT_THAT(controller_.populatePermissionState(PermissionEnum::ENUM_SIZE, {}),
+ BinderStatusMatcher::hasException(EX_ILLEGAL_ARGUMENT));
+ EXPECT_THAT(
+ controller_.populatePermissionState(
+ static_cast<PermissionEnum>(static_cast<int>(PermissionEnum::ENUM_SIZE) + 1),
+ {}),
+ BinderStatusMatcher::hasException(EX_ILLEGAL_ARGUMENT));
}
TEST_F(NativePermissionControllerTest, populatePermissionState_HoldsPermission) {
// Unsorted
std::vector<int> uids{3, 1, 2, 4, 5};
- EXPECT_TRUE(
- controller_.populatePermissionState(PermissionEnum::MODIFY_AUDIO_ROUTING, uids).isOk());
+ EXPECT_THAT(controller_.populatePermissionState(PermissionEnum::MODIFY_AUDIO_ROUTING, uids),
+ BinderStatusMatcher::isOk());
- EXPECT_TRUE(*controller_.checkPermission(PermissionEnum::MODIFY_AUDIO_ROUTING, 3));
+ EXPECT_THAT(controller_.checkPermission(PermissionEnum::MODIFY_AUDIO_ROUTING, 3),
+ IsOkAnd(IsTrue()));
}
TEST_F(NativePermissionControllerTest, populatePermissionState_DoesNotHoldPermission) {
// Unsorted
std::vector<int> uids{3, 1, 2, 4, 5};
- EXPECT_TRUE(
- controller_.populatePermissionState(PermissionEnum::MODIFY_AUDIO_ROUTING, uids).isOk());
+ EXPECT_THAT(controller_.populatePermissionState(PermissionEnum::MODIFY_AUDIO_ROUTING, uids),
+ BinderStatusMatcher::isOk());
- EXPECT_FALSE(*controller_.checkPermission(PermissionEnum::MODIFY_AUDIO_ROUTING, 6));
+ EXPECT_THAT(controller_.checkPermission(PermissionEnum::MODIFY_AUDIO_ROUTING, 6),
+ IsOkAnd(IsFalse()));
}
TEST_F(NativePermissionControllerTest, populatePermissionState_NotInitialized) {
- const auto res = controller_.checkPermission(PermissionEnum::MODIFY_AUDIO_ROUTING, 3);
- ASSERT_FALSE(res.has_value());
- EXPECT_EQ(res.error(), ::android::NO_INIT);
+ EXPECT_THAT(controller_.checkPermission(PermissionEnum::MODIFY_AUDIO_ROUTING, 3),
+ IsErrorAnd(BinderStatusMatcher::hasException(EX_ILLEGAL_STATE)));
}
diff --git a/services/audiopolicy/permission/tests/ValidatedAttributionSourceStateTest.cpp b/services/audiopolicy/permission/tests/ValidatedAttributionSourceStateTest.cpp
index efc318b..0dd8814 100644
--- a/services/audiopolicy/permission/tests/ValidatedAttributionSourceStateTest.cpp
+++ b/services/audiopolicy/permission/tests/ValidatedAttributionSourceStateTest.cpp
@@ -20,24 +20,35 @@
#include <gtest/gtest.h>
#include <android-base/expected.h>
+#include <error/ExpectedMatchers.h>
#include <media/IPermissionProvider.h>
+#include "error/BinderStatusMatcher.h"
using ::android::base::unexpected;
using ::android::binder::Status;
+using ::android::binder::Status::EX_ILLEGAL_ARGUMENT;
+using ::android::binder::Status::EX_ILLEGAL_STATE;
+using ::android::binder::Status::EX_SECURITY;
using ::android::content::AttributionSourceState;
-using ::android::error::Result;
+using ::android::error::BinderResult;
+using ::android::error::BinderStatusMatcher;
+using ::android::error::IsErrorAnd;
+using ::android::error::IsOkAnd;
using ::com::android::media::permission::IPermissionProvider;
using ::com::android::media::permission::PermissionEnum;
using ::com::android::media::permission::ValidatedAttributionSourceState;
+
+using ::testing::Eq;
using ::testing::Return;
class MockPermissionProvider : public IPermissionProvider {
public:
- MOCK_METHOD(Result<std::vector<std::string>>, getPackagesForUid, (uid_t uid),
+ MOCK_METHOD(BinderResult<std::vector<std::string>>, getPackagesForUid, (uid_t uid),
(override, const));
- MOCK_METHOD(Result<bool>, validateUidPackagePair, (uid_t uid, const std::string&),
+ MOCK_METHOD(BinderResult<bool>, validateUidPackagePair, (uid_t uid, const std::string&),
(override, const));
- MOCK_METHOD(Result<bool>, checkPermission, (PermissionEnum perm, uid_t), (override, const));
+ MOCK_METHOD(BinderResult<bool>, checkPermission, (PermissionEnum perm, uid_t),
+ (override, const));
};
class ValidatedAttributionSourceStateTest : public ::testing::Test {
@@ -47,21 +58,14 @@
const std::vector<std::string> mPackageList{"com.package1", "com.package2"};
};
-#define UNWRAP_EQ(expr, desired_expr) \
- do { \
- auto tmp_ = (expr); \
- EXPECT_TRUE(tmp_.has_value()); \
- if (tmp_.has_value()) EXPECT_EQ(*tmp_, desired_expr); \
- } while (0)
-
TEST_F(ValidatedAttributionSourceStateTest, providedPackageValid) {
const std::string package = "com.package1";
EXPECT_CALL(mMockProvider, validateUidPackagePair(mUid, package)).WillOnce(Return(true));
AttributionSourceState attr;
attr.uid = mUid;
attr.packageName = package;
- UNWRAP_EQ(ValidatedAttributionSourceState::createFromTrustedUidNoPackage(attr, mMockProvider),
- attr);
+ EXPECT_THAT(ValidatedAttributionSourceState::createFromTrustedUidNoPackage(attr, mMockProvider),
+ IsOkAnd(Eq(attr)));
}
TEST_F(ValidatedAttributionSourceStateTest, providedPackageInvalid) {
@@ -70,10 +74,8 @@
AttributionSourceState attr;
attr.uid = mUid;
attr.packageName = package;
- const auto res =
- ValidatedAttributionSourceState::createFromTrustedUidNoPackage(attr, mMockProvider);
- ASSERT_FALSE(res.has_value());
- EXPECT_EQ(res.error(), ::android::PERMISSION_DENIED);
+ EXPECT_THAT(ValidatedAttributionSourceState::createFromTrustedUidNoPackage(attr, mMockProvider),
+ IsErrorAnd(BinderStatusMatcher::hasException(EX_SECURITY)));
}
TEST_F(ValidatedAttributionSourceStateTest, packageLookup_whenMissingPackage) {
@@ -83,8 +85,8 @@
AttributionSourceState expectedAttr;
expectedAttr.uid = mUid;
expectedAttr.packageName = "com.package1";
- UNWRAP_EQ(ValidatedAttributionSourceState::createFromTrustedUidNoPackage(attr, mMockProvider),
- expectedAttr);
+ EXPECT_THAT(ValidatedAttributionSourceState::createFromTrustedUidNoPackage(attr, mMockProvider),
+ IsOkAnd(Eq(expectedAttr)));
}
TEST_F(ValidatedAttributionSourceStateTest, packageLookup_whenEmptyPackage) {
@@ -95,33 +97,29 @@
AttributionSourceState expectedAttr;
expectedAttr.uid = mUid;
expectedAttr.packageName = "com.package1";
- UNWRAP_EQ(ValidatedAttributionSourceState::createFromTrustedUidNoPackage(attr, mMockProvider),
- expectedAttr);
+ EXPECT_THAT(ValidatedAttributionSourceState::createFromTrustedUidNoPackage(attr, mMockProvider),
+ IsOkAnd(Eq(expectedAttr)));
}
TEST_F(ValidatedAttributionSourceStateTest, controllerNotInitialized) {
EXPECT_CALL(mMockProvider, getPackagesForUid(mUid))
- .WillOnce(Return(unexpected{::android::NO_INIT}));
+ .WillOnce(Return(unexpected{Status::fromExceptionCode(EX_ILLEGAL_STATE)}));
AttributionSourceState attr;
attr.uid = mUid;
attr.packageName = std::string{};
AttributionSourceState expectedAttr;
expectedAttr.uid = mUid;
expectedAttr.packageName = "com.package1";
- const auto res =
- ValidatedAttributionSourceState::createFromTrustedUidNoPackage(attr, mMockProvider);
- ASSERT_FALSE(res.has_value());
- EXPECT_EQ(res.error(), ::android::NO_INIT);
+ EXPECT_THAT(ValidatedAttributionSourceState::createFromTrustedUidNoPackage(attr, mMockProvider),
+ IsErrorAnd(BinderStatusMatcher::hasException(EX_ILLEGAL_STATE)));
}
TEST_F(ValidatedAttributionSourceStateTest, uidNotFound) {
EXPECT_CALL(mMockProvider, getPackagesForUid(mUid))
- .WillOnce(Return(unexpected{::android::BAD_VALUE}));
+ .WillOnce(Return(unexpected{Status::fromExceptionCode(EX_ILLEGAL_ARGUMENT)}));
AttributionSourceState attr;
attr.uid = mUid;
attr.packageName = std::string{};
- const auto res =
- ValidatedAttributionSourceState::createFromTrustedUidNoPackage(attr, mMockProvider);
- ASSERT_FALSE(res.has_value());
- EXPECT_EQ(res.error(), ::android::BAD_VALUE);
+ EXPECT_THAT(ValidatedAttributionSourceState::createFromTrustedUidNoPackage(attr, mMockProvider),
+ IsErrorAnd(BinderStatusMatcher::hasException(EX_ILLEGAL_ARGUMENT)));
}
diff --git a/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp b/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp
index c6793a9..c7b4297 100644
--- a/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp
+++ b/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp
@@ -17,6 +17,7 @@
*****************************************************************************
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
*/
+#include <binder/IPCThreadState.h>
#include <fuzzer/FuzzedDataProvider.h>
#include <media/MediaMetricsItem.h>
#include <mediametricsservice/AudioTypes.h>
@@ -26,210 +27,158 @@
#include <string.h>
#include <utils/Log.h>
#include <algorithm>
+#include <set>
using namespace android;
+static constexpr size_t STATSD_LOG_LINES_MAX = 48;
+static unsigned long long kPackedCallingUid = (unsigned long long)AID_SYSTEM << 32;
+constexpr int8_t kMaxBytes = 100;
+constexpr int8_t kMinBytes = 0;
+constexpr size_t kMaxItemLength = 16;
// low water mark
constexpr size_t kLogItemsLowWater = 1;
// high water mark
constexpr size_t kLogItemsHighWater = 2;
-constexpr size_t kMaxItemLength = 16;
-constexpr size_t kMaxApis = 64;
+
+/*
+ * Concatenating strings to generate keys in such a way that the
+ * lambda function inside AudioAnalytics() added in the 'mAction' object is covered
+ */
+
+std::string keyMediaValues[] = {
+ "metrics.manager",
+ "mediadrm",
+ "audio.device.a2dp",
+ AMEDIAMETRICS_KEY_AUDIO_MIDI,
+ AMEDIAMETRICS_KEY_PREFIX_AUDIO_SPATIALIZER "*",
+ AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*",
+ AMEDIAMETRICS_KEY_AUDIO_FLINGER,
+ AMEDIAMETRICS_KEY_AUDIO_POLICY,
+ AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*",
+ AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*",
+ AMEDIAMETRICS_KEY_PREFIX_AUDIO_STREAM "*",
+ AMEDIAMETRICS_KEY_PREFIX_AUDIO_DEVICE
+ "postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent",
+};
+
+std::string keyMediaAction[] = {
+ "createAudioPatch",
+ "connected",
+ AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE,
+ AMEDIAMETRICS_PROP_EVENT_VALUE_TIMEOUT,
+ AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR,
+ AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM,
+ AMEDIAMETRICS_PROP_EVENT_VALUE_DEVICECLOSED,
+ AMEDIAMETRICS_PROP_EVENT_VALUE_SETVOICEVOLUME,
+ AMEDIAMETRICS_PROP_EVENT_VALUE_SETMODE,
+ AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP,
+};
class MediaMetricsServiceFuzzer {
- public:
- void invokeStartsWith(const uint8_t *data, size_t size);
- void invokeInstantiate(const uint8_t *data, size_t size);
- void invokePackageInstallerCheck(const uint8_t *data, size_t size);
- void invokeItemManipulation(const uint8_t *data, size_t size);
- void invokeItemExpansion(const uint8_t *data, size_t size);
- void invokeTimeMachineStorage(const uint8_t *data, size_t size);
- void invokeTransactionLog(const uint8_t *data, size_t size);
- void invokeAnalyticsAction(const uint8_t *data, size_t size);
- void invokeAudioAnalytics(const uint8_t *data, size_t size);
- void invokeTimedAction(const uint8_t *data, size_t size);
- void process(const uint8_t *data, size_t size);
+ public:
+ MediaMetricsServiceFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){};
+ void process();
+ void invokeStartsWith();
+ void invokeInstantiate();
+ void invokePackageInstallerCheck();
+ void invokeTimeMachineStorage();
+ void invokeTransactionLog();
+ void invokeAnalyticsAction();
+ void invokeAudioAnalytics();
+ void invokeTimedAction();
+ void setKeyValues(std::shared_ptr<mediametrics::Item>& item, std::string keyValue);
+ std::shared_ptr<mediametrics::Item> CreateItem();
+ sp<MediaMetricsService> mMediaMetricsService;
+ FuzzedDataProvider mFdp;
std::atomic_int mValue = 0;
};
-void MediaMetricsServiceFuzzer::invokeStartsWith(const uint8_t *data, size_t size) {
- FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
- while (fdp.remaining_bytes()) {
- android::mediametrics::startsWith(fdp.ConsumeRandomLengthString(),
- fdp.ConsumeRandomLengthString());
- }
+void MediaMetricsServiceFuzzer::setKeyValues(std::shared_ptr<mediametrics::Item>& item,
+ std::string keyValue) {
+ auto invokeActionAPIs = mFdp.PickValueInArray<const std::function<void()>>({
+ [&]() { item->setInt32(keyValue.c_str(), mFdp.ConsumeIntegral<int32_t>()); },
+ [&]() { item->addInt32(keyValue.c_str(), mFdp.ConsumeIntegral<int32_t>()); },
+ [&]() { item->setInt64(keyValue.c_str(), mFdp.ConsumeIntegral<int64_t>()); },
+ [&]() { item->addInt64(keyValue.c_str(), mFdp.ConsumeIntegral<int64_t>()); },
+ [&]() { item->setDouble(keyValue.c_str(), mFdp.ConsumeFloatingPoint<double>()); },
+ [&]() { item->addDouble(keyValue.c_str(), mFdp.ConsumeFloatingPoint<double>()); },
+ [&]() { item->setTimestamp(mFdp.ConsumeIntegral<int64_t>()); },
+ [&]() {
+ std::string value = mFdp.ConsumeBool()
+ ? mFdp.ConsumeRandomLengthString(kMaxBytes)
+ : mFdp.PickValueInArray<std::string>(keyMediaAction);
+ item->setCString(keyValue.c_str(), value.c_str());
+ },
+ [&]() {
+ item->setRate(keyValue.c_str(), mFdp.ConsumeIntegral<int64_t>(),
+ mFdp.ConsumeIntegral<int64_t>());
+ },
+ [&]() {
+ mediametrics::LogItem<1> itemTemp(mFdp.ConsumeRandomLengthString(kMaxBytes));
+ itemTemp.setPid(mFdp.ConsumeIntegral<int16_t>())
+ .setUid(mFdp.ConsumeIntegral<int16_t>());
+
+ int32_t i = mFdp.ConsumeIntegral<int32_t>();
+ itemTemp.set(std::to_string(i).c_str(), (int32_t)i);
+ itemTemp.updateHeader();
+ (void)item->readFromByteString(itemTemp.getBuffer(), itemTemp.getLength());
+ },
+
+ });
+ invokeActionAPIs();
}
-void MediaMetricsServiceFuzzer::invokeInstantiate(const uint8_t *data, size_t size) {
- FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
- sp mediaMetricsService = new MediaMetricsService();
-
- while (fdp.remaining_bytes()) {
- std::unique_ptr<mediametrics::Item> random_key(
- mediametrics::Item::create(fdp.ConsumeRandomLengthString()));
- mediaMetricsService->submit(random_key.get());
- random_key->setInt32(fdp.ConsumeRandomLengthString().c_str(),
- fdp.ConsumeIntegral<int32_t>());
- mediaMetricsService->submit(random_key.get());
-
- std::unique_ptr<mediametrics::Item> audiotrack_key(
- mediametrics::Item::create("audiotrack"));
- mediaMetricsService->submit(audiotrack_key.get());
- audiotrack_key->addInt32(fdp.ConsumeRandomLengthString().c_str(),
- fdp.ConsumeIntegral<int32_t>());
- mediaMetricsService->submit(audiotrack_key.get());
+std::shared_ptr<mediametrics::Item> MediaMetricsServiceFuzzer::CreateItem() {
+ std::string key;
+ if (mFdp.ConsumeBool()) {
+ key = mFdp.ConsumeRandomLengthString(kMaxItemLength);
+ } else {
+ key = mFdp.PickValueInArray<std::string>(keyMediaValues);
}
-}
-void MediaMetricsServiceFuzzer::invokePackageInstallerCheck(const uint8_t *data, size_t size) {
- FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
- while (fdp.remaining_bytes()) {
- MediaMetricsService::useUidForPackage(fdp.ConsumeRandomLengthString().c_str(),
- fdp.ConsumeRandomLengthString().c_str());
- }
-}
-
-void MediaMetricsServiceFuzzer::invokeItemManipulation(const uint8_t *data, size_t size) {
- FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
-
- mediametrics::Item item(fdp.ConsumeRandomLengthString().c_str());
- while (fdp.remaining_bytes()) {
- const uint8_t action = fdp.ConsumeIntegralInRange<uint8_t>(0, 16);
- const std::string key = fdp.ConsumeRandomLengthString();
- if (fdp.remaining_bytes() < 1 || key.length() < 1) {
- break;
+ std::shared_ptr<mediametrics::Item> item = std::make_shared<mediametrics::Item>(key.c_str());
+ size_t numKeys = mFdp.ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes);
+ std::set<std::string> keySet;
+ for (size_t i = 0; i < numKeys; ++i) {
+ std::string keyValue;
+ if (mFdp.ConsumeBool()) {
+ keyValue = mFdp.ConsumeRandomLengthString(kMaxBytes);
+ } else {
+ keyValue = mFdp.PickValueInArray<std::string>(
+ {AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_STATE, "logSessionIkeyd"});
}
- switch (action) {
- case 0: {
- item.setInt32(key.c_str(), fdp.ConsumeIntegral<int32_t>());
- break;
- }
- case 1: {
- item.addInt32(key.c_str(), fdp.ConsumeIntegral<int32_t>());
- break;
- }
- case 2: {
- int32_t i32 = 0;
- item.getInt32(key.c_str(), &i32);
- break;
- }
- case 3: {
- item.setInt64(key.c_str(), fdp.ConsumeIntegral<int64_t>());
- break;
- }
- case 4: {
- item.addInt64(key.c_str(), fdp.ConsumeIntegral<int64_t>());
- break;
- }
- case 5: {
- int64_t i64 = 0;
- item.getInt64(key.c_str(), &i64);
- break;
- }
- case 6: {
- item.setDouble(key.c_str(), fdp.ConsumeFloatingPoint<double>());
- break;
- }
- case 7: {
- item.addDouble(key.c_str(), fdp.ConsumeFloatingPoint<double>());
- break;
- }
- case 8: {
- double d = 0;
- item.getDouble(key.c_str(), &d);
- break;
- }
- case 9: {
- item.setCString(key.c_str(), fdp.ConsumeRandomLengthString().c_str());
- break;
- }
- case 10: {
- char *s = nullptr;
- item.getCString(key.c_str(), &s);
- if (s) free(s);
- break;
- }
- case 11: {
- std::string s;
- item.getString(key.c_str(), &s);
- break;
- }
- case 12: {
- item.setRate(key.c_str(), fdp.ConsumeIntegral<int64_t>(),
- fdp.ConsumeIntegral<int64_t>());
- break;
- }
- case 13: {
- int64_t b = 0, h = 0;
- double d = 0;
- item.getRate(key.c_str(), &b, &h, &d);
- break;
- }
- case 14: {
- (void)item.filter(key.c_str());
- break;
- }
- case 15: {
- const char *arr[1] = {""};
- arr[0] = const_cast<char *>(key.c_str());
- (void)item.filterNot(1, arr);
- break;
- }
- case 16: {
- (void)item.toString().c_str();
- break;
- }
+ if (keySet.find(keyValue) == keySet.end()) {
+ setKeyValues(item, keyValue);
+ keySet.insert(keyValue);
}
}
-
- Parcel p;
- mediametrics::Item item2;
-
- (void)item.writeToParcel(&p);
- p.setDataPosition(0); // rewind for reading
- (void)item2.readFromParcel(p);
-
- char *byteData = nullptr;
- size_t length = 0;
- (void)item.writeToByteString(&byteData, &length);
- (void)item2.readFromByteString(byteData, length);
- if (byteData) {
- free(byteData);
- }
-
- sp mediaMetricsService = new MediaMetricsService();
- mediaMetricsService->submit(&item2);
+ return item;
}
-void MediaMetricsServiceFuzzer::invokeItemExpansion(const uint8_t *data, size_t size) {
- FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
-
- mediametrics::LogItem<1> item("FuzzItem");
- item.setPid(fdp.ConsumeIntegral<int16_t>()).setUid(fdp.ConsumeIntegral<int16_t>());
-
- while (fdp.remaining_bytes()) {
- int32_t i = fdp.ConsumeIntegral<int32_t>();
- item.set(std::to_string(i).c_str(), (int32_t)i);
- }
- item.updateHeader();
-
- mediametrics::Item item2;
- (void)item2.readFromByteString(item.getBuffer(), item.getLength());
-
- sp mediaMetricsService = new MediaMetricsService();
- mediaMetricsService->submit(&item2);
+void MediaMetricsServiceFuzzer::invokeStartsWith() {
+ android::mediametrics::startsWith(mFdp.ConsumeRandomLengthString(kMaxBytes),
+ mFdp.ConsumeRandomLengthString(kMaxBytes));
}
-void MediaMetricsServiceFuzzer::invokeTimeMachineStorage(const uint8_t *data, size_t size) {
- FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+void MediaMetricsServiceFuzzer::invokeInstantiate() {
+ auto item = CreateItem();
+ mMediaMetricsService->submit(item.get());
+}
- auto item = std::make_shared<mediametrics::Item>("FuzzKey");
- int32_t i32 = fdp.ConsumeIntegral<int32_t>();
- int64_t i64 = fdp.ConsumeIntegral<int64_t>();
- double d = fdp.ConsumeFloatingPoint<double>();
- std::string str = fdp.ConsumeRandomLengthString();
- std::pair<int64_t, int64_t> pair(fdp.ConsumeIntegral<int64_t>(),
- fdp.ConsumeIntegral<int64_t>());
+void MediaMetricsServiceFuzzer::invokePackageInstallerCheck() {
+ MediaMetricsService::useUidForPackage(mFdp.ConsumeRandomLengthString(kMaxBytes).c_str(),
+ mFdp.ConsumeRandomLengthString(kMaxBytes).c_str());
+}
+
+void MediaMetricsServiceFuzzer::invokeTimeMachineStorage() {
+ auto item = CreateItem();
+ int32_t i32 = mFdp.ConsumeIntegral<int32_t>();
+ int64_t i64 = mFdp.ConsumeIntegral<int64_t>();
+ double d = mFdp.ConsumeFloatingPoint<double>();
+ std::string str = mFdp.ConsumeRandomLengthString(kMaxBytes);
+ std::pair<int64_t, int64_t> pair(mFdp.ConsumeIntegral<int64_t>(),
+ mFdp.ConsumeIntegral<int64_t>());
(*item).set("i32", i32).set("i64", i64).set("double", d).set("string", str).set("rate", pair);
android::mediametrics::TimeMachine timeMachine;
@@ -253,124 +202,89 @@
timeMachine.get("Key.string", &str, -1);
}
-void MediaMetricsServiceFuzzer::invokeTransactionLog(const uint8_t *data, size_t size) {
- FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
-
- auto item = std::make_shared<mediametrics::Item>("Key1");
- (*item)
- .set("one", fdp.ConsumeIntegral<int32_t>())
- .set("two", fdp.ConsumeIntegral<int32_t>())
- .setTimestamp(fdp.ConsumeIntegral<int32_t>());
+void MediaMetricsServiceFuzzer::invokeTransactionLog() {
+ auto item = CreateItem();
android::mediametrics::TransactionLog transactionLog(
kLogItemsLowWater, kLogItemsHighWater); // keep at most 2 items
transactionLog.size();
transactionLog.put(item);
- transactionLog.size();
-
- auto item2 = std::make_shared<mediametrics::Item>("Key2");
- (*item2)
- .set("three", fdp.ConsumeIntegral<int32_t>())
- .set("[Key1]three", fdp.ConsumeIntegral<int32_t>())
- .setTimestamp(fdp.ConsumeIntegral<int32_t>());
-
- transactionLog.put(item2);
- transactionLog.size();
-
- auto item3 = std::make_shared<mediametrics::Item>("Key3");
- (*item3)
- .set("six", fdp.ConsumeIntegral<int32_t>())
- .set("[Key1]four", fdp.ConsumeIntegral<int32_t>()) // affects Key1
- .set("[Key1]five", fdp.ConsumeIntegral<int32_t>()) // affects key1
- .setTimestamp(fdp.ConsumeIntegral<int32_t>());
-
- transactionLog.put(item3);
- transactionLog.size();
}
-void MediaMetricsServiceFuzzer::invokeAnalyticsAction(const uint8_t *data, size_t size) {
- FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
-
+void MediaMetricsServiceFuzzer::invokeAnalyticsAction() {
mediametrics::AnalyticsActions analyticsActions;
bool action = false;
- while (fdp.remaining_bytes()) {
- analyticsActions.addAction(
- (fdp.ConsumeRandomLengthString() + std::string(".event")).c_str(),
- fdp.ConsumeRandomLengthString(),
+ analyticsActions.addAction(
+ (mFdp.ConsumeRandomLengthString(kMaxBytes) + std::string(".event")).c_str(),
+ mFdp.ConsumeRandomLengthString(kMaxBytes),
std::make_shared<mediametrics::AnalyticsActions::Function>(
- [&](const std::shared_ptr<const android::mediametrics::Item> &) {
- action = true;
- }));
- }
+ [&](const std::shared_ptr<const android::mediametrics::Item>&) {
+ action = true;
+ }));
- FuzzedDataProvider fdp2 = FuzzedDataProvider(data, size);
- size_t apiCount = 0;
- while (fdp2.remaining_bytes() && ++apiCount <= kMaxApis) {
- // make a test item
- auto item = std::make_shared<mediametrics::Item>(
- fdp2.ConsumeRandomLengthString(kMaxItemLength).c_str());
- (*item).set("event", fdp2.ConsumeRandomLengthString().c_str());
+ // make a test item
+ auto item = CreateItem();
+ (*item).set("event", mFdp.ConsumeRandomLengthString(kMaxBytes).c_str());
- // get the actions and execute them
- auto actions = analyticsActions.getActionsForItem(item);
- for (const auto &action : actions) {
- action->operator()(item);
+ // get the actions and execute them
+ auto actions = analyticsActions.getActionsForItem(item);
+ for (const auto& action : actions) {
+ action->operator()(item);
}
- }
}
-void MediaMetricsServiceFuzzer::invokeAudioAnalytics(const uint8_t *data, size_t size) {
- FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+void MediaMetricsServiceFuzzer::invokeAudioAnalytics() {
+ int32_t maxLogLine = mFdp.ConsumeIntegralInRange<int32_t>(0, STATSD_LOG_LINES_MAX);
std::shared_ptr<android::mediametrics::StatsdLog> statsdLog =
- std::make_shared<android::mediametrics::StatsdLog>(10);
+ std::make_shared<android::mediametrics::StatsdLog>(maxLogLine);
android::mediametrics::AudioAnalytics audioAnalytics{statsdLog};
- while (fdp.remaining_bytes()) {
- auto item = std::make_shared<mediametrics::Item>(fdp.ConsumeRandomLengthString().c_str());
- int32_t transactionUid = fdp.ConsumeIntegral<int32_t>(); // arbitrary
- (*item)
- .set(fdp.ConsumeRandomLengthString().c_str(), fdp.ConsumeIntegral<int32_t>())
- .set(fdp.ConsumeRandomLengthString().c_str(), fdp.ConsumeIntegral<int32_t>())
- .set(AMEDIAMETRICS_PROP_ALLOWUID, transactionUid)
- .setUid(transactionUid)
- .setTimestamp(fdp.ConsumeIntegral<int32_t>());
- audioAnalytics.submit(item, fdp.ConsumeBool());
+ auto item = CreateItem();
+ Parcel parcel;
+ item->writeToParcel(&parcel);
+ parcel.setDataPosition(0);
+ if (mFdp.ConsumeBool()) {
+ item->readFromParcel(parcel);
}
-
- audioAnalytics.dump(1000);
+ audioAnalytics.submit(item, mFdp.ConsumeBool());
}
-void MediaMetricsServiceFuzzer::invokeTimedAction(const uint8_t *data, size_t size) {
- FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+void MediaMetricsServiceFuzzer::invokeTimedAction() {
android::mediametrics::TimedAction timedAction;
+ timedAction.postIn(std::chrono::seconds(mFdp.ConsumeIntegral<uint32_t>()),
+ [this] { ++mValue; });
+ timedAction.size();
+}
- while (fdp.remaining_bytes()) {
- timedAction.postIn(std::chrono::seconds(fdp.ConsumeIntegral<int32_t>()),
- [this] { ++mValue; });
- timedAction.size();
+void MediaMetricsServiceFuzzer::process() {
+ mMediaMetricsService = sp<MediaMetricsService>::make();
+
+ if (mFdp.ConsumeBool()) {
+ IPCThreadState::self()->restoreCallingIdentity(kPackedCallingUid);
+ } else {
+ IPCThreadState::self()->restoreCallingIdentity(mFdp.ConsumeIntegral<size_t>());
+ }
+ while (mFdp.remaining_bytes()) {
+ auto invokeAPIs = mFdp.PickValueInArray<const std::function<void()>>({
+ [&]() { invokeStartsWith(); },
+ [&]() { invokeInstantiate(); },
+ [&]() { invokePackageInstallerCheck(); },
+ [&]() { invokeTimeMachineStorage(); },
+ [&]() { invokeTransactionLog(); },
+ [&]() { invokeAudioAnalytics(); },
+ [&]() { invokeTimedAction(); },
+ });
+ invokeAPIs();
}
}
-void MediaMetricsServiceFuzzer::process(const uint8_t *data, size_t size) {
- invokeStartsWith(data, size);
- invokeInstantiate(data, size);
- invokePackageInstallerCheck(data, size);
- invokeItemManipulation(data, size);
- invokeItemExpansion(data, size);
- invokeTimeMachineStorage(data, size);
- invokeTransactionLog(data, size);
- invokeAnalyticsAction(data, size);
- invokeAudioAnalytics(data, size);
- invokeTimedAction(data, size);
-}
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if (size < 1) {
return 0;
}
- MediaMetricsServiceFuzzer mediaMetricsServiceFuzzer;
- mediaMetricsServiceFuzzer.process(data, size);
+ MediaMetricsServiceFuzzer mediaMetricsServiceFuzzer(data, size);
+ mediaMetricsServiceFuzzer.process();
return 0;
}