MediaMetrics: Add standard error codes
Standard error strings are added to the accepted constants.
Added mapping method from status_t to string and back.
Test: atest mediametrics_tests
Bug: 199763036
Change-Id: Iae25729b342384f1981c082661d7829f6c33f0b6
diff --git a/media/libmediametrics/MediaMetricsItem.cpp b/media/libmediametrics/MediaMetricsItem.cpp
index d597a4d..1c71f5c 100644
--- a/media/libmediametrics/MediaMetricsItem.cpp
+++ b/media/libmediametrics/MediaMetricsItem.cpp
@@ -23,6 +23,7 @@
#include <mutex>
#include <set>
+#include <unordered_map>
#include <binder/Parcel.h>
#include <cutils/properties.h>
@@ -51,6 +52,32 @@
// the service is off.
#define SVC_TRIES 2
+static const std::unordered_map<std::string, int32_t>& getErrorStringMap() {
+ // DO NOT MODIFY VALUES (OK to add new ones).
+ // This may be found in frameworks/av/media/libmediametrics/include/MediaMetricsConstants.h
+ static std::unordered_map<std::string, int32_t> map{
+ {"", NO_ERROR},
+ {AMEDIAMETRICS_PROP_ERROR_VALUE_ARGUMENT, BAD_VALUE},
+ {AMEDIAMETRICS_PROP_ERROR_VALUE_IO, DEAD_OBJECT},
+ {AMEDIAMETRICS_PROP_ERROR_VALUE_MEMORY, NO_MEMORY},
+ {AMEDIAMETRICS_PROP_ERROR_VALUE_SECURITY, PERMISSION_DENIED},
+ {AMEDIAMETRICS_PROP_ERROR_VALUE_STATE, INVALID_OPERATION},
+ {AMEDIAMETRICS_PROP_ERROR_VALUE_TIMEOUT, WOULD_BLOCK},
+ {AMEDIAMETRICS_PROP_ERROR_VALUE_UNKNOWN, UNKNOWN_ERROR},
+ };
+ return map;
+}
+
+status_t errorStringToStatus(const char *error) {
+ const auto& map = getErrorStringMap();
+ if (error == nullptr || error == "") return NO_ERROR;
+ auto it = map.find(error);
+ if (it != map.end()) {
+ return it->second;
+ }
+ return UNKNOWN_ERROR;
+}
+
mediametrics::Item* mediametrics::Item::convert(mediametrics_handle_t handle) {
mediametrics::Item *item = (android::mediametrics::Item *) handle;
return item;
diff --git a/media/libmediametrics/include/MediaMetricsConstants.h b/media/libmediametrics/include/MediaMetricsConstants.h
index a09a673..5d0eca0 100644
--- a/media/libmediametrics/include/MediaMetricsConstants.h
+++ b/media/libmediametrics/include/MediaMetricsConstants.h
@@ -115,6 +115,19 @@
#define AMEDIAMETRICS_PROP_DIRECTION "direction" // string AAudio input or output
#define AMEDIAMETRICS_PROP_DURATIONNS "durationNs" // int64 duration time span
#define AMEDIAMETRICS_PROP_ENCODING "encoding" // string value of format
+
+// Error statistics
+#define AMEDIAMETRICS_PROP_ERROR "error#" // string, empty or one of
+ // AMEDIAMETRICS_PROP_ERROR_VALUE_*
+ // Used for error categorization.
+#define AMEDIAMETRICS_PROP_ERRORSUBCODE "errorSubCode#" // int32, specific code for error
+ // used in conjunction with error#.
+#define AMEDIAMETRICS_PROP_ERRORMESSAGE "errorMessage#" // string, supplemental to error.
+ // Arbitrary information treated as
+ // informational, may be logcat msg,
+ // or an exception with stack trace.
+ // Treated as "debug" information.
+
#define AMEDIAMETRICS_PROP_EVENT "event#" // string value (often func name)
#define AMEDIAMETRICS_PROP_EXECUTIONTIMENS "executionTimeNs" // time to execute the event
@@ -215,4 +228,62 @@
#define AMEDIAMETRICS_PROP_CALLERNAME_VALUE_TONEGENERATOR "tonegenerator" // dial tones
#define AMEDIAMETRICS_PROP_CALLERNAME_VALUE_UNKNOWN "unknown" // callerName not set
+// MediaMetrics errors are expected to cover the following sources:
+// https://docs.oracle.com/javase/7/docs/api/java/lang/RuntimeException.html
+// https://docs.oracle.com/javase/7/docs/api/java/lang/Exception.html
+// https://cs.android.com/android/platform/superproject/+/master:frameworks/native/libs/binder/include/binder/Status.h;drc=88e25c0861499ee3ab885814dddc097ab234cb7b;l=57
+// https://cs.android.com/android/platform/superproject/+/master:frameworks/base/media/java/android/media/AudioSystem.java;drc=3ac246c43294d7f7012bdcb0ccb7bae1aa695bd4;l=785
+// https://cs.android.com/android/platform/superproject/+/master:frameworks/av/media/libaaudio/include/aaudio/AAudio.h;drc=cfd3a6fa3aaaf712a890dc02452b38ef401083b8;l=120
+
+// Error category:
+// An empty error string indicates no error.
+
+// Error category: argument
+// IllegalArgumentException
+// NullPointerException
+// BAD_VALUE
+// Out of range, out of bounds.
+#define AMEDIAMETRICS_PROP_ERROR_VALUE_ARGUMENT "argument"
+
+// Error category: io
+// IOException
+// android.os.DeadObjectException, android.os.RemoteException
+// DEAD_OBJECT
+// FAILED_TRANSACTION
+// IO_ERROR
+// file or ioctl failure
+// Service, rpc, binder, or socket failure.
+// Hardware or device failure.
+#define AMEDIAMETRICS_PROP_ERROR_VALUE_IO "io"
+
+// Error category: outOfMemory
+// OutOfMemoryException
+// NO_MEMORY
+#define AMEDIAMETRICS_PROP_ERROR_VALUE_MEMORY "memory"
+
+// Error category: security
+// SecurityException
+// PERMISSION_DENIED
+#define AMEDIAMETRICS_PROP_ERROR_VALUE_SECURITY "security"
+
+// Error category: state
+// IllegalStateException
+// UnsupportedOperationException
+// INVALID_OPERATION
+// NO_INIT
+// Functionality not implemented (argument may or may not be correct).
+// Call unexpected or out of order.
+#define AMEDIAMETRICS_PROP_ERROR_VALUE_STATE "state"
+
+// Error category: timeout
+// TimeoutException
+// WOULD_BLOCK
+#define AMEDIAMETRICS_PROP_ERROR_VALUE_TIMEOUT "timeout"
+
+// Error category: unknown
+// Exception (Java specified not listed above, or custom app/service)
+// UNKNOWN_ERROR
+// Catch-all bucket for errors not listed above.
+#define AMEDIAMETRICS_PROP_ERROR_VALUE_UNKNOWN "unknown"
+
#endif // ANDROID_MEDIA_MEDIAMETRICSCONSTANTS_H
diff --git a/media/libmediametrics/include/media/MediaMetricsItem.h b/media/libmediametrics/include/media/MediaMetricsItem.h
index 428992c..30a2955 100644
--- a/media/libmediametrics/include/media/MediaMetricsItem.h
+++ b/media/libmediametrics/include/media/MediaMetricsItem.h
@@ -105,6 +105,36 @@
};
/*
+ * Helper for error conversions
+ */
+
+static inline constexpr const char* statusToErrorString(status_t status) {
+ switch (status) {
+ case NO_ERROR:
+ return "";
+ case BAD_VALUE:
+ return AMEDIAMETRICS_PROP_ERROR_VALUE_ARGUMENT;
+ case DEAD_OBJECT:
+ case FAILED_TRANSACTION:
+ return AMEDIAMETRICS_PROP_ERROR_VALUE_IO;
+ case NO_MEMORY:
+ return AMEDIAMETRICS_PROP_ERROR_VALUE_MEMORY;
+ case PERMISSION_DENIED:
+ return AMEDIAMETRICS_PROP_ERROR_VALUE_SECURITY;
+ case NO_INIT:
+ case INVALID_OPERATION:
+ return AMEDIAMETRICS_PROP_ERROR_VALUE_STATE;
+ case WOULD_BLOCK:
+ return AMEDIAMETRICS_PROP_ERROR_VALUE_TIMEOUT;
+ case UNKNOWN_ERROR:
+ default:
+ return AMEDIAMETRICS_PROP_ERROR_VALUE_UNKNOWN;
+ }
+}
+
+status_t errorStringToStatus(const char *error);
+
+/*
* Time printing
*
* kPrintFormatLong time string is 19 characters (including null termination).
diff --git a/services/mediametrics/tests/mediametrics_tests.cpp b/services/mediametrics/tests/mediametrics_tests.cpp
index 69ec947..cd6af9f 100644
--- a/services/mediametrics/tests/mediametrics_tests.cpp
+++ b/services/mediametrics/tests/mediametrics_tests.cpp
@@ -1225,3 +1225,29 @@
ASSERT_EQ(id, validateId.validateId(id));
}
}
+
+TEST(mediametrics_tests, ErrorConversion) {
+ constexpr status_t errors[] = {
+ NO_ERROR,
+ BAD_VALUE,
+ DEAD_OBJECT,
+ NO_MEMORY,
+ PERMISSION_DENIED,
+ INVALID_OPERATION,
+ WOULD_BLOCK,
+ UNKNOWN_ERROR,
+ };
+
+ auto roundTrip = [](status_t status) {
+ return android::mediametrics::errorStringToStatus(
+ android::mediametrics::statusToErrorString(status));
+ };
+
+ // Primary status error categories.
+ for (const auto error : errors) {
+ ASSERT_EQ(error, roundTrip(error));
+ }
+
+ // Status errors specially considered.
+ ASSERT_EQ(DEAD_OBJECT, roundTrip(FAILED_TRANSACTION));
+}