CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(diagnostics LANGUAGES C)
SET(target ${PROJECT_NAME})
-SET(dependency "glib-2.0 gio-unix-2.0 dlog dumpsys capi-system-info")
+SET(dependency "glib-2.0 gio-unix-2.0 dlog dumpsys dumpsys-system bugreport capi-system-info bundle aul")
# ADD_DEFINITIONS(-Wall -Werror -Wextra)
# Options
# cmocka tasts and coverage
option(ENABLE_COVERAGE "Measure the coverage and generate report" OFF)
-option(ENABLE_TESTS "Run unit tests after build" ON)
-if(ENABLE_TESTS OR ENABLE_COVERAGE)
+option(ENABLE_TESTS "Run unit tests after build" OFF)
+if(ENABLE_TESTS)
FIND_PACKAGE(CMocka CONFIG REQUIRED)
enable_testing()
include(CTest)
INCLUDE_DIRECTORIES(${LIBCMOCKA_INCLUDE_DIR})
ADD_SUBDIRECTORY(src/test)
-endif(ENABLE_TESTS OR ENABLE_COVERAGE)
+endif(ENABLE_TESTS)
/**
* @ingroup CAPI_SYSTEM_FRAMEWORK
* @defgroup CAPI_SYSTEM_DIAGNOSTICS_MODULE Diagnostics
- * @brief The @ref CAPI_SYSTEM_DIAGNOSTICS_MODULE API provides functions to receive crash reports and request logs from other apps.
+ * @brief The @ref CAPI_SYSTEM_DIAGNOSTICS_MODULE API provides functions to send and receive diagnostic events and data from other applications/services.
*
* @section CAPI_SYSTEM_DIAGNOSTICS_MODULE_HEADER Required Header
* \#include <diagnostics.h>
*
* @section CAPI_SYSTEM_DIAGNOSTICS_MODULE_OVERVIEW Overview
- * This @ref CAPI_SYSTEM_DIAGNOSTICS_MODULE API allows applications to receive notification about newly created crash report,
- * as well as request other apps to dump their logs in real time. Moreover, functions for reading crash and log contents are provided.
+ * This @ref CAPI_SYSTEM_DIAGNOSTICS_MODULE API allows applications to exchange diagnostic information.
+ *
+ * Client - a program using this API. In case of applications, client ID is set to the application ID, but services must set their ID explicitly using diagnostics_set_client_id().
+ *
+ * Provider - a client that sends diagnostic events or serves diagnostic data.
+ *
+ * Subscriber - a client that subscribes to diagnostic events or requests diagnostic data.
+ *
+ * Event - simple signal sent to all subscribed clients. \n
+ * Event may be sent with additional data (bundle). \n
+ * There is a diagnostic context associated with the event, which holds information about sender (client ID), event name and event data.
+ *
+ * Data - any data, logs or files sent by providers via this API (dumpsys underneath). \n
+ * Subscribers may specify additional parameters when requesting diagnostic data. Based on this parameters, providers send appropriate data.
+ *
+ * Bugreport - diagnostic report created on demand with diagnostics_request_bugreport(). \n
+ * Bugreport may be process-specific (when pid argument is given) or system-specific (when pid <= 0).
*
* @section CAPI_SYSTEM_DIAGNOSTICS_MODULE_FEATURE Realted Features
*
* This API is related with the following feature:\n
* - %http://tizen.org/feature/diagnostics\n
*
- * It is recommended to design feature related codes in your application for reliability.\n
+ * It is recommended to use features in your application for reliability. \n
*
- * You can check if a device supports the related features for this API by using @ref CAPI_SYSTEM_SYSTEM_INFO_MODULE,thereby controlling the procedure of your application.\n
+ * You can check if the device supports the related features for this API by using System Information, and control your application's actions accordingly. \n
*
- * To ensure your application is only running on the device with specific features, please define the features in your manifest file using the manifest editor in the SDK.\n
+ * To ensure your application is running only on devices with specific features, please define the features in your manifest file using the manifest editor in the SDK.
*
- * More details on featuring your application can be found from <a href="https://docs.tizen.org/application/tizen-studio/native-tools/manifest-text-editor#feature-element"><b>Feature Element</b>.</a>
+ * More details on using features in your application can be found in the <a href="https://developer.tizen.org/development/tizen-studio/native-tools/configuring-your-app/manifest-text-editor#feature"><b>feature element description</b></a>.
*/
#include <stdio.h>
#include <tizen.h>
+#include <bundle.h>
#ifdef __cplusplus
extern "C" {
} diagnostics_error_e;
/**
- * @brief Notification callback fired when new bug report arrives.
+ * @brief Notification callback fired when new diagnostics event arrives.
* @since_tizen 6.0
- * @remarks @a ctx should be released with diagnostics_destroy()
+ * @remarks @a ctx should be released with diagnostics_destroy().
*
* @param[in] ctx Diagnostics context handle
* @param[in] user_data The user data passed from the callback registration function
typedef void(*diagnostics_notification_cb)(diagnostics_ctx_h ctx, void *user_data);
/**
- * @brief Sets the callback for bug report notification.
+ * @brief Request callback fired when someone requests diagnostics data.
+ * @since_tizen 6.5
+ * @remarks @a data should be released with diagnostics_data_destroy().
+ *
+ * @param[in] data Diagnostics data handle
+ * @param[in] params Array of request's parameters \n
+ * This array is owned by @a data, so it is available until @a data is released \n
+ * @a params are the same as passed to diagnostics_request_client_data() or diagnostics_get_data()
+ * @param[in] params_size Number of parameters
+ * @param[in] ctx Diagnostics context handling an event that the request is related to \n
+ * @a ctx is available when data has been requested with diagnostics_get_data() \n
+ * @a ctx is NULL when data has been requested with diagnostics_request_client_data() \n
+ * This parameter allows diagnostics client to find diagnostics data related to the specific event
+ * @param[in] user_data The user data passed from the callback registration function
+ */
+typedef void (*diagnostics_request_cb)(diagnostics_data_h data, char **params, int params_size, diagnostics_ctx_h ctx, void *user_data);
+
+/**
+ * @brief Sets the callback for diagnostics event notification.
* @since_tizen 6.0
+ * @remarks This function is dedicated to diagnostic information subscribers.
*
* @param[in] callback A callback function to set
* @param[in] user_data The user data to be passed to the callback function
* @retval #DIAGNOSTICS_ERROR_NOT_SUPPORTED Not supported
* @retval #DIAGNOSTICS_ERROR_INVALID_PARAMETER Provided parameter is invalid
* @retval #DIAGNOSTICS_ERROR_RESOURCE_BUSY Callback already registered
- * @retval #DIAGNOSTICS_ERROR_IO_ERROR Internal error occured
+ * @retval #DIAGNOSTICS_ERROR_IO_ERROR Internal error occurred
+ *
+ * @code
+ * #include <diagnostics.h>
+ *
+ * static void notification_handler(diagnostics_ctx_h ctx, void *user_data)
+ * {
+ * // Process diagnostics event
+ *
+ * diagnostics_destroy(ctx);
+ * }
+ *
+ * static GMainLoop *mainloop = NULL;
+ *
+ * int main(int argc, char **argv)
+ * {
+ * diagnostics_set_notification_cb(notification_handler, NULL);
+ * diagnostics_subscribe_event("ConnectionBroken", "org.tizen.someapp");
+ *
+ * mainloop = g_main_loop_new(NULL, FALSE);
+ * g_main_loop_run(mainloop);
+ * }
+ *
+ * @endcode
*/
int diagnostics_set_notification_cb(diagnostics_notification_cb callback, void *user_data);
/**
- * @brief Unsets the callback for bug report notification.
+ * @brief Unsets the callback for diagnostics event notification.
* @since_tizen 6.0
- *
+ * @remarks This function is dedicated to diagnostic information subscribers. \n
+ * It clears all the events added with diagnostics_subscribe_event().
+ *
* @return 0 on success, otherwise a negative error value
* @retval #DIAGNOSTICS_ERROR_NONE Success
* @retval #DIAGNOSTICS_ERROR_NOT_SUPPORTED Not supported
- * @retval #DIAGNOSTICS_ERROR_IO_ERROR Internal error occured
+ * @retval #DIAGNOSTICS_ERROR_IO_ERROR Internal error occurred
*/
int diagnostics_unset_notification_cb(void);
/**
* @platform
- * @brief Requests client to dump data.
+ * @brief Subscribes to an event sent by diagnostics client.
+ * @since_tizen 6.5
+ * @privlevel platform
+ * @privilege
+ * @remarks This function is dedicated to diagnostic information subscribers. \n
+ * It is permitted only to an app signed by platform level certificates.
+ *
+ * @param[in] event_name Event name \n
+ * Its length is limited to 255 characters + null terminator
+ * @param[in] client_id The ID of the diagnostics client (event sender) \n
+ * Its length is limited to 255 characters + null terminator
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #DIAGNOSTICS_ERROR_NONE Success
+ * @retval #DIAGNOSTICS_ERROR_NOT_SUPPORTED Not supported
+ * @retval #DIAGNOSTICS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #DIAGNOSTICS_ERROR_INVALID_PARAMETER Provided parameter is invalid
+ * @retval #DIAGNOSTICS_ERROR_IO_ERROR Internal error occurred
+ * @retval #DIAGNOSTICS_ERROR_OUT_OF_MEMORY Out of memory
+ */
+int diagnostics_subscribe_event(const char *event_name, const char *client_id);
+
+/**
+ * @platform
+ * @brief Sets the callback for diagnostics data request.
+ * @since_tizen 6.5
+ * @privlevel platform
+ * @privilege
+ * @remarks This function is dedicated to diagnostic information providers. \n
+ * It is permitted only to an app signed by platform level certificates.
+ *
+ * @param[in] callback A callback function to set
+ * @param[in] user_data The user data to be passed to the callback function
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #DIAGNOSTICS_ERROR_NONE Success
+ * @retval #DIAGNOSTICS_ERROR_NOT_SUPPORTED Not supported
+ * @retval #DIAGNOSTICS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #DIAGNOSTICS_ERROR_INVALID_PARAMETER Provided parameter is invalid or the caller ID not set (required for system services only)
+ * @retval #DIAGNOSTICS_ERROR_RESOURCE_BUSY Callback already registered
+ * @retval #DIAGNOSTICS_ERROR_IO_ERROR Internal error occurred
+ *
+ * @code
+ * #include <diagnostics.h>
+ *
+ * static void data_request_cb(diagnostics_data_h data, char **params, int params_size, diagnostics_ctx_h ctx, void *user_data)
+ * {
+ * const char *buf = "Some data";
+ * size_t bytes_written;
+ *
+ * diagnostics_data_write(data, buf, sizeof(buf)/sizeof(char), &bytes_written);
+ *
+ * diagnostics_data_destroy(data);
+ * }
+ *
+ * static GMainLoop *mainloop = NULL;
+ *
+ * int main(int argc, char **argv)
+ * {
+ * diagnostics_data_h data;
+ *
+ * // This is required for services only, not applications
+ * diagnostics_set_client_id("diagnostics-client");
+ *
+ * diagnostics_set_data_request_cb(data_request_cb, NULL);
+ *
+ * mainloop = g_main_loop_new(NULL, FALSE);
+ * g_main_loop_run(mainloop);
+ * }
+ *
+ * @endcode
+ */
+int diagnostics_set_data_request_cb(diagnostics_request_cb callback, void *user_data);
+
+/**
+ * @platform
+ * @brief Unsets the callback for diagnostics data request.
+ * @since_tizen 6.5
+ * @privlevel platform
+ * @privilege
+ * @remarks This function is dedicated to diagnostic information providers. \n
+ * It is permitted only to an app signed by platform level certificates.
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #DIAGNOSTICS_ERROR_NONE Success
+ * @retval #DIAGNOSTICS_ERROR_NOT_SUPPORTED Not supported
+ * @retval #DIAGNOSTICS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #DIAGNOSTICS_ERROR_IO_ERROR Internal error occurred
+ */
+int diagnostics_unset_data_request_cb(void);
+
+/**
+ * @platform
+ * @brief Requests diagnostics client to dump data.
* @since_tizen 6.0
* @privlevel platform
* @privilege
- * @remarks @a data should be released with diagnostics_data_destroy().
- * This function is permitted only to an app signed by platform level certificates.
+ * @remarks This function is dedicated to diagnostic information subscribers. \n
+ * It is permitted only to an app signed by platform level certificates. \n
+ * @a data should be released with diagnostics_data_destroy().
*
- * @param[in] client_id An id of app or service to request
- * @param[in] params Array of parameters
+ * @param[in] client_id An ID of application or service to request
+ * @param[in] params Array of parameters \n
+ * Refer to specific diagnostics client's documentation for available parameters
* @param[in] params_size Number of parameters
* @param[out] data Dumpsys data handle
*
* @retval #DIAGNOSTICS_ERROR_NOT_SUPPORTED Not supported
* @retval #DIAGNOSTICS_ERROR_PERMISSION_DENIED Permission denied
* @retval #DIAGNOSTICS_ERROR_INVALID_PARAMETER Provided parameter is invalid
- * @retval #DIAGNOSTICS_ERROR_IO_ERROR Internal error occured
+ * @retval #DIAGNOSTICS_ERROR_IO_ERROR Internal error occurred
* @retval #DIAGNOSTICS_ERROR_OUT_OF_MEMORY Not enough memory to create data handle
+ *
+ * @code
+ * #include <diagnostics.h>
+ *
+ * int main(int argc, char **argv)
+ * {
+ * diagnostics_data_h data;
+ * const char *params[] = {"foo", "bar", "baz"};
+ * char buf[1000];
+ * size_t bytes_read;
+ *
+ * diagnostics_request_client_data("diagnostics-client", params, sizeof(params)/sizeof(char*), &data);
+ *
+ * while (true) {
+ * diagnostics_data_read(data, buf, sizeof(buf)/sizeof(char), -1, &bytes_read);
+ * if (bytes_read == 0) // Reached EOF
+ * break;
+ *
+ * // Process the chunk of data
+ * }
+ *
+ * diagnostics_data_destroy(data);
+ * }
+ *
+ * @endcode
*/
int diagnostics_request_client_data(const char *client_id, const char **params, int params_size, diagnostics_data_h *data);
+/**
+ * @platform
+ * @brief Requests diagnostics context's provider to dump data.
+ * @since_tizen 6.0
+ * @privlevel platform
+ * @privilege
+ * @remarks This function is dedicated to diagnostic information subscribers. \n
+ * It is permitted only to an app signed by platform level certificates. \n
+ * @a data should be released with diagnostics_data_destroy(). \n
+ * The difference between this function and diagnostics_request_client_data() is that
+ * this function sends back the whole context to the context's provider to help it find the data specific to the generated event.
+ *
+ * @param[in] ctx Diagnostics context handle
+ * @param[in] params Array of parameters \n
+ * Refer to specific diagnostics client's documentation for available parameters
+ * @param[in] params_size Number of parameters
+ * @param[out] data Diagnostics data handle
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #DIAGNOSTICS_ERROR_NONE Success
+ * @retval #DIAGNOSTICS_ERROR_NOT_SUPPORTED Not supported
+ * @retval #DIAGNOSTICS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #DIAGNOSTICS_ERROR_INVALID_PARAMETER Provided parameter is invalid
+ * @retval #DIAGNOSTICS_ERROR_IO_ERROR Internal error occurred
+ * @retval #DIAGNOSTICS_ERROR_OUT_OF_MEMORY Not enough memory to create data handle
+ *
+ * @code
+ *
+ * void notification_handler(diagnostics_ctx_h ctx, void *user_data)
+ * {
+ * diagnostics_data_h data;
+ * const char *params[] = {"foo", "bar", "baz"};
+ *
+ * // Request more data from the client that the event came from
+ * diagnostics_get_data(ctx, params, sizeof(params)/sizeof(char*), &data);
+ *
+ * // Read data
+ *
+ * diagnostics_data_destroy(data);
+ * diagnostics_destroy(ctx);
+ * }
+ *
+ * @endcode
+ */
+int diagnostics_get_data(diagnostics_ctx_h ctx, const char **params, int params_size, diagnostics_data_h *data);
+
+/**
+ * @brief Gets a file descriptor for diagnostics data.
+ * @since_tizen 6.5
+ * @remarks This function provides a file descriptor to read/write diagnostic data in a custom way
+ * instead of using our diagnostics_data_read() and diagnostics_data_write() functions. \n
+ * Moreover, keep in mind that reading is allowed for diagnostic data subscribers and writing is allowed for providers.
+ * @param[in] data Diagnostics data handle
+ * @param[in,out] fd A file descriptor related to diagnostics data
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #DIAGNOSTICS_ERROR_NONE Success
+ * @retval #DIAGNOSTICS_ERROR_NOT_SUPPORTED Not supported
+ * @retval #DIAGNOSTICS_ERROR_INVALID_PARAMETER Provided parameter is invalid
+ */
+int diagnostics_data_get_fd(diagnostics_data_h data, int *fd);
+
/**
* @brief Reads diagnostics data.
* @since_tizen 6.0
- * @remarks @a data should be released with diagnostics_data_destroy().
- * This function is intended for use in loop until EOF is reached.
- * EOF is when @a bytes_read == 0 and function returns #DIAGNOSTICS_ERROR_NONE.
+ * @remarks This function is dedicated to diagnostic information subscribers. \n
+ * It is intended for use in loop until EOF is reached. EOF is when @a bytes_read == 0 and function returns #DIAGNOSTICS_ERROR_NONE.
+ *
* @param[in] data Diagnostics data handle
* @param[in,out] buf Buffer to store read data \n
- * Provided buffer must be large enough to contain @a count number of bytes
+ * Provided buffer must be large enough to contain a @a count number of bytes
* @param[in] count Number of bytes to read
* @param[in] timeout_ms Timeout [ms] for reading requested number of bytes (timeout_ms <= 0 means to wait forever)
- * @param[out] bytes_read Real number of read bytes
+ * @param[out] bytes_read Real number of bytes read
*
* @return 0 on success, otherwise a negative error value
* @retval #DIAGNOSTICS_ERROR_NONE Success
* @retval #DIAGNOSTICS_ERROR_NOT_SUPPORTED Not supported
* @retval #DIAGNOSTICS_ERROR_INVALID_PARAMETER Provided parameter is invalid
- * @retval #DIAGNOSTICS_ERROR_TIMED_OUT Timeout occured
+ * @retval #DIAGNOSTICS_ERROR_TIMED_OUT Timeout occurred
* @retval #DIAGNOSTICS_ERROR_TRY_AGAIN Try again
- * @retval #DIAGNOSTICS_ERROR_IO_ERROR Internal error occured while trying to read data, result is unspecified and *bytes_read is not updated
+ * @retval #DIAGNOSTICS_ERROR_IO_ERROR Internal error occurred while trying to read data, result is unspecified and *bytes_read is not updated
*/
int diagnostics_data_read(diagnostics_data_h data, void *buf, size_t count, int timeout_ms, size_t *bytes_read);
/**
- * @brief Frees diagnostics data.
- * @since_tizen 6.0
+ * @brief Writes diagnostics data.
+ * @since_tizen 6.5
+ * @remarks This function is dedicated to diagnostic information providers. \n
+ * Data is being written to the special file descriptor and then copied to the diagnostic information subscriber's endpoint.
*
* @param[in] data Diagnostics data handle
+ * @param[in] buf Buffer with data to write \n
+ * Provided buffer must be of size not less than a @a count number of bytes
+ * @param[in] count Number of bytes to write
+ * @param[out] bytes_written Real number of bytes written
*
* @return 0 on success, otherwise a negative error value
* @retval #DIAGNOSTICS_ERROR_NONE Success
* @retval #DIAGNOSTICS_ERROR_NOT_SUPPORTED Not supported
* @retval #DIAGNOSTICS_ERROR_INVALID_PARAMETER Provided parameter is invalid
+ * @retval #DIAGNOSTICS_ERROR_TRY_AGAIN Try again
+ * @retval #DIAGNOSTICS_ERROR_IO_ERROR Internal error occurred while trying to write data, result is unspecified and *bytes_written is not updated
*/
-int diagnostics_data_destroy(diagnostics_data_h data);
+int diagnostics_data_write(diagnostics_data_h data, const void *buf, size_t count, size_t *bytes_written);
+
+/**
+ * @platform
+ * @brief Sends diagnostics event.
+ * @since_tizen 6.5
+ * @privlevel platform
+ * @privilege
+ * @remarks This function is dedicated to diagnostic information providers. \n
+ * It is permitted only to an app signed by platform level certificates.
+ *
+ * @param[in] event_name Diagnostics event name
+ * @param[in] event_data Event data or NULL.
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #DIAGNOSTICS_ERROR_NONE Success
+ * @retval #DIAGNOSTICS_ERROR_NOT_SUPPORTED Not supported
+ * @retval #DIAGNOSTICS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #DIAGNOSTICS_ERROR_INVALID_PARAMETER Provided parameter is invalid or the caller ID not set (required for system services only)
+ * @retval #DIAGNOSTICS_ERROR_IO_ERROR Internal error occurred
+ *
+ * @code
+ *
+ * int main(int argc, char *argv[])
+ * {
+ * bundle *event_data = bundle_create();
+ *
+ * // This is required for services only, not applications
+ * diagnostics_set_client_id("diagnostics-client");
+ *
+ * bundle_add_str(event_data, "somekey", "somevalue");
+ * diagnostics_send_event("ConnectionBroken", event_data);
+ *
+ * bundle_free(event_data);
+ * }
+ *
+ * @endcode
+ */
+int diagnostics_send_event(const char *event_name, bundle *event_data);
/**
- * @brief Gets diagnostics context provider's id.
+ * @brief Gets diagnostics client ID (event sender).
* @since_tizen 6.0
- * @remarks @a client_id should be released with free().
+ * @remarks This function is dedicated to diagnostic information subscribers. \n
+ * @a client_id should be released with free().
*
* @param[in] ctx Diagnostics context handle
- * @param[out] client_id An id of the context provider
+ * @param[out] client_id ID of the diagnostics client
*
* @return 0 on success, otherwise a negative error value
* @retval #DIAGNOSTICS_ERROR_NONE Success
* @retval #DIAGNOSTICS_ERROR_NOT_SUPPORTED Not supported
* @retval #DIAGNOSTICS_ERROR_INVALID_PARAMETER Provided parameter is invalid
+ *
+ * @code
+ *
+ * void notification_handler(diagnostics_ctx_h ctx, void *user_data)
+ * {
+ * char *client_id;
+ *
+ * diagnostics_get_client_id(ctx, &client_id);
+ *
+ * // Process diagnostics event
+ *
+ * free(client_id);
+ * diagnostics_destroy(ctx);
+ * }
+ *
+ * @endcode
*/
int diagnostics_get_client_id(diagnostics_ctx_h ctx, char **client_id);
+/**
+ * @brief Gets diagnostics event name.
+ * @since_tizen 6.5
+ * @remarks This function is dedicated to diagnostic information subscribers. \n
+ * @a event_name should be released with free().
+ *
+ * @param[in] ctx Diagnostics context handle
+ * @param[out] event_name Name of the diagnostics event
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #DIAGNOSTICS_ERROR_NONE Success
+ * @retval #DIAGNOSTICS_ERROR_NOT_SUPPORTED Not supported
+ * @retval #DIAGNOSTICS_ERROR_INVALID_PARAMETER Provided parameter is invalid
+ *
+ * @code
+ *
+ * void notification_handler(diagnostics_ctx_h ctx, void *user_data)
+ * {
+ * char *event_name;
+ *
+ * diagnostics_get_event_name(ctx, &event_name);
+ *
+ * // Process diagnostics event
+ *
+ * free(event_name);
+ * diagnostics_destroy(ctx);
+ * }
+ *
+ * @endcode
+ */
+int diagnostics_get_event_name(diagnostics_ctx_h ctx, char **event_name);
+
+/**
+ * @brief Gets diagnostics event data.
+ * @since_tizen 6.5
+ * @remarks This function is dedicated to diagnostic information subscribers. \n
+ * @a event_data should be released with bundle_free().
+ *
+ * @param[in] ctx Diagnostics context handle
+ * @param[out] event_data Data that came with the diagnostics event (may be NULL when no data has been provided)
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #DIAGNOSTICS_ERROR_NONE Success
+ * @retval #DIAGNOSTICS_ERROR_NOT_SUPPORTED Diagnostics feature is missing or the function has been called by application, not system service
+ * @retval #DIAGNOSTICS_ERROR_INVALID_PARAMETER Provided parameter is invalid
+ *
+ * @code
+ *
+ * void notification_handler(diagnostics_ctx_h ctx, void *user_data)
+ * {
+ * bundle *event_data;
+ *
+ * diagnostics_get_event_data(ctx, &event_data);
+ *
+ * // Process diagnostics event
+ *
+ * bundle_free(event_data);
+ * diagnostics_destroy(ctx);
+ * }
+ *
+ * @endcode
+ */
+int diagnostics_get_event_data(diagnostics_ctx_h ctx, bundle **event_data);
+
+/**
+ * @brief Sets the diagnostics client ID.
+ * @since_tizen 6.5
+ * @remarks This function is dedicated to diagnostic information providers. \n
+ * As services do not have any name associated with them, ID must be set explicitly with this function before calling any of the following functions: \n
+ * diagnostics_set_data_request_cb() \n
+ * diagnostics_send_event() \n
+ * diagnostics_request_bugreport() \n
+ * For applications, client ID is set to the application ID and cannot be changed.
+ *
+ * @param[in] client_id Diagnostics client ID to set.
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #DIAGNOSTICS_ERROR_NONE Success
+ * @retval #DIAGNOSTICS_ERROR_NOT_SUPPORTED Not supported
+ * @retval #DIAGNOSTICS_ERROR_INVALID_PARAMETER Provided parameter is invalid
+ * @retval #DIAGNOSTICS_ERROR_RESOURCE_BUSY Client ID has already been set, not possible to change
+ * @retval #DIAGNOSTICS_ERROR_IO_ERROR Internal error occurred
+ */
+int diagnostics_set_client_id(const char *client_id);
+
/**
* @platform
- * @brief Gets report data.
- * @since_tizen 6.0
+ * @brief Requests bugreport creation.
+ * @since_tizen 6.5
* @privlevel platform
- * @privilege
- * @remarks @a data should be released with diagnostics_data_destroy().
- * This function is permitted only to an app signed by platform level certificates.
+ * @privilege http://tizen.org/privilege/bugreport.admin
+ * @remarks This function is dedicated to diagnostic information subscribers. \n
+ * To get bugreport's content, user must subscribe to 'BugreportCreated' diagnostics event, which is sent by crash-service after creating the report.
*
- * @param[in] ctx Diagnostics context handle
- * @param[in] params Array of parameters \n
- * Refer to context provider's documentation for available parameters
- * @param[in] params_size Number of parameters
- * @param[out] data Diagnostics data handle
+ * @param[in] pid ID of a process that should be livedumped. When @a pid <= 0, system-wide bugreport is created.
*
* @return 0 on success, otherwise a negative error value
* @retval #DIAGNOSTICS_ERROR_NONE Success
* @retval #DIAGNOSTICS_ERROR_NOT_SUPPORTED Not supported
* @retval #DIAGNOSTICS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #DIAGNOSTICS_ERROR_INVALID_PARAMETER Provided parameter is invalid or the caller ID not set (required for system services only)
+ * @retval #DIAGNOSTICS_ERROR_IO_ERROR Internal error occurred
+ */
+int diagnostics_request_bugreport(int pid);
+
+/**
+ * @brief Frees diagnostics data.
+ * @since_tizen 6.0
+ *
+ * @param[in] data Diagnostics data handle
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #DIAGNOSTICS_ERROR_NONE Success
+ * @retval #DIAGNOSTICS_ERROR_NOT_SUPPORTED Not supported
* @retval #DIAGNOSTICS_ERROR_INVALID_PARAMETER Provided parameter is invalid
- * @retval #DIAGNOSTICS_ERROR_IO_ERROR Internal error occured
- * @retval #DIAGNOSTICS_ERROR_OUT_OF_MEMORY Not enough memory to create data handle
*/
-int diagnostics_get_data(diagnostics_ctx_h ctx, const char **params, int params_size, diagnostics_data_h *data);
+int diagnostics_data_destroy(diagnostics_data_h data);
/**
* @brief Frees diagnostics context.
BuildRequires: pkgconfig(gio-unix-2.0)
BuildRequires: pkgconfig(dlog)
BuildRequires: pkgconfig(dumpsys)
+BuildRequires: pkgconfig(dumpsys-system)
+BuildRequires: pkgconfig(bugreport)
BuildRequires: pkgconfig(capi-system-info)
+BuildRequires: pkgconfig(bundle)
+BuildRequires: pkgconfig(aul)
BuildRequires: glib2-devel
%if 0%{?gcov:1}
BuildRequires: lcov
# Build
ADD_LIBRARY(${target} SHARED ${SOURCES})
-SET_TARGET_PROPERTIES(${target} PROPERTIES COMPILE_FLAGS "${EXTRA_CFLAGS} -fPIE")
+SET_TARGET_PROPERTIES(${target} PROPERTIES COMPILE_FLAGS "${EXTRA_CFLAGS} -fPIC")
SET_TARGET_PROPERTIES(${target} PROPERTIES LINK_FLAGS "-pie")
SET_TARGET_PROPERTIES(${target} PROPERTIES SOVERSION ${MAJORVER})
SET_TARGET_PROPERTIES(${target} PROPERTIES VERSION ${FULLVER})
ADD_LIBRARY(${target}_static STATIC ${SOURCES})
TARGET_INCLUDE_DIRECTORIES(${target}_static PRIVATE ${CMAKE_SOURCE_DIR}/src/library)
-TARGET_COMPILE_OPTIONS(${target}_static BEFORE PRIVATE -include ../test/test_diagnostics_add_function_defs.h)
+# TARGET_COMPILE_OPTIONS(${target}_static BEFORE PRIVATE -include ../test/test_diagnostics_add_function_defs.h)
TARGET_COMPILE_DEFINITIONS(${target}_static PUBLIC -DUNIT_TEST)
if(ENABLE_COVERAGE)
TARGET_COMPILE_OPTIONS(${target}_static PUBLIC -g -fprofile-arcs -ftest-coverage)
#include "dbus.h"
#include "log.h"
-static int subscription_id = 0;
-
static GDBusConnection *dbus_connect()
{
GDBusConnection *conn;
return conn;
}
-int dbus_subscribe(void (*signal_handler)(GDBusConnection *,
+int dbus_subscribe(const char *interface_name,
+ const char *object_path,
+ const char *member_name,
+ void (*signal_handler)(GDBusConnection *,
const gchar *,
const gchar *,
const gchar *,
ret = g_dbus_connection_signal_subscribe(conn,
NULL,
- NULL,
- DBUS_MEMBER_CRASH,
- NULL,
+ interface_name,
+ member_name,
+ object_path,
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
signal_handler,
NULL,
NULL);
if (ret == FALSE) {
- _E("Unable to subscribe to crash signal");
+ _E("g_dbus_connection_signal_subscribe() failed");
return -EIO;
}
- subscription_id = ret;
-
- return 0;
+ return ret;
}
-void dbus_unsubscribe(void)
+void dbus_unsubscribe(int subscription_id)
{
GDBusConnection *conn = dbus_connect();
if (!conn)
return;
- if (subscription_id)
+ if (subscription_id > 0)
g_dbus_connection_signal_unsubscribe(conn, subscription_id);
-
- subscription_id = 0;
}
-int dbus_get_file_from_report(const char *report_path, const int entry, int *fd)
+int dbus_send_signal(const char *interface_name,
+ const char *object_path,
+ const char *signal_name,
+ GVariant *parameters)
{
- GDBusConnection *conn = dbus_connect();
- GDBusMessage *message = NULL;
- GDBusMessage *reply = NULL;
- GVariant *parameters = NULL;
- GUnixFDList *fd_list = NULL;
- GError *error = NULL;
- int fd_out = -1;
+ GError *err = NULL;
+ gchar *parameters_str = parameters ? g_variant_print(parameters, TRUE) : NULL;
int ret = -1;
+ GDBusConnection *conn = dbus_connect();
if (!conn)
- goto finish;
-
- message = g_dbus_message_new_method_call(DBUS_BUS_NAME,
- DBUS_OBJECT_PATH,
- DBUS_INTERFACE_NAME,
- DBUS_METHOD_GET_FILE);
- parameters = g_variant_new("(si)", report_path, entry);
- g_dbus_message_set_body(message, parameters);
-
- reply = g_dbus_connection_send_message_with_reply_sync(conn,
- message,
- G_DBUS_SEND_MESSAGE_FLAGS_NONE,
- 10000,
- NULL,
- NULL,
- &error);
-
- // _D("MESSAGE: \n%s", g_dbus_message_print(message, 4));
- // _D("REPLY: \n%s", g_dbus_message_print(reply, 4));
-
- if (reply != NULL && g_dbus_message_get_message_type(reply) == G_DBUS_MESSAGE_TYPE_ERROR)
- g_dbus_message_to_gerror(reply, &error);
-
- if (error != NULL) {
- _E("Send message error: %s\n", error ? error->message : "unknown error");
- ret = error->code == G_DBUS_ERROR_ACCESS_DENIED ? -EACCES : -1;
- goto finish;
- }
-
- fd_list = g_dbus_message_get_unix_fd_list(reply);
- if (!fd_list) {
- _E("Method call get_file() haven't returned file descriptor");
+ goto cleanup;
+
+ ret = g_dbus_connection_emit_signal(conn, /* connection */
+ NULL, /* destination_bus_name */
+ object_path, /* object_path */
+ interface_name, /* interface_name */
+ signal_name, /* signal_name */
+ parameters, /* parameters */
+ &err); /* error */
+ if (ret == FALSE) {
+ _E("g_dbus_connection_emit_signal() failed: %s", err->message);
+ g_error_free(err);
ret = -1;
- goto finish;
+ goto cleanup;
}
- fd_out = g_unix_fd_list_get(fd_list, 0, &error);
- if (fd_out == -1 || error) {
- _E("g_unix_fd_list_get() failed: %s", error ? error->message : "");
- ret = -1;
- goto finish;
- }
+ _D("Sent signal\n"
+ " interface_name: %s\n"
+ " object_path: %s\n"
+ " signal_name: %s\n"
+ " parameters: %s\n",
+ interface_name, object_path, signal_name, parameters_str);
ret = 0;
-finish:
- *fd = fd_out;
- if (parameters)
- g_variant_unref(parameters);
- if (message)
- g_object_unref(message);
- if (reply)
- g_object_unref(reply);
- if (error)
- g_error_free(error);
+cleanup:
+ g_free(parameters_str);
return ret;
}
-
-struct dbus_signal_s *dbus_signal_create(const gchar *sender_name,
- const gchar *object_path,
- const gchar *interface_name,
- const gchar *signal_name,
- GVariant *parameters)
-{
- struct dbus_signal_s *signal;
-
- signal = calloc(1, sizeof(struct dbus_signal_s));
- if (!signal) {
- _E("Unable to allocate memory");
- return NULL;
- }
-
- signal->sender_name = g_strdup(sender_name);
- signal->object_path = g_strdup(object_path);
- signal->interface_name = g_strdup(interface_name);
- signal->signal_name = g_strdup(signal_name);
- signal->parameters = parameters;
- g_variant_ref(signal->parameters);
-
- return signal;
-}
-
-void dbus_signal_cleanup(struct dbus_signal_s *signal)
-{
- if (!signal)
- return;
-
- g_free(signal->sender_name);
- g_free(signal->object_path);
- g_free(signal->interface_name);
- g_free(signal->signal_name);
- g_variant_unref(signal->parameters);
- free(signal);
-}
#ifndef __DBUS_H__
#define __DBUS_H__
-#define DBUS_MEMBER_CRASH "ProcessCrashedEx"
-#define DBUS_SENDER_CRASH "org.tizen.system.crash"
-
-#define DBUS_BUS_NAME "org.tizen.system.diagnostics"
-#define DBUS_OBJECT_PATH "/Org/Tizen/System/Diagnostics"
-#define DBUS_INTERFACE_NAME DBUS_BUS_NAME
-#define DBUS_METHOD_GET_FILE "get_file"
+#define DBUS_EVENT_INTERFACE_NAME "org.tizen.system.diagnostics.event"
+#define DBUS_EVENT_OBJECT_PATH "/Org/Tizen/System/Diagnostics/Event"
#include <gio/gio.h>
-#include <gio/gunixfdlist.h>
#include <glib.h>
-struct dbus_signal_s {
- gchar *sender_name;
- gchar *object_path;
- gchar *interface_name;
- gchar *signal_name;
- GVariant *parameters;
-};
-
-int dbus_subscribe(void (*signal_handler)(GDBusConnection *,
+int dbus_subscribe(const char *interface_name,
+ const char *object_path,
+ const char *member_name,
+ void (*signal_handler)(GDBusConnection *,
const gchar *,
const gchar *,
const gchar *,
const gchar *,
GVariant *,
gpointer));
-void dbus_unsubscribe(void);
-int dbus_get_file_from_report(const char *report_path, const int entry, int *fd);
-struct dbus_signal_s *dbus_signal_create(const gchar *sender_name,
- const gchar *object_path,
- const gchar *interface_name,
- const gchar *signal_name,
- GVariant *parameters);
-void dbus_signal_cleanup(struct dbus_signal_s *signal);
+void dbus_unsubscribe(int subscription_id);
+
+int dbus_send_signal(const char *interface_name,
+ const char *object_path,
+ const char *signal_name,
+ GVariant *parameters);
#endif /* __DBUS_H__ */
#include <gio/gio.h>
#include <glib.h>
#include <libdumpsys.h>
+#include <dumpsys-system.h>
+#include <libbugreport.h>
#include <poll.h>
+#include <bundle.h>
+#include <aul.h>
+#include <limits.h>
#include "log.h"
#include "signal.h"
#include "dbus.h"
#ifndef STATIC
-#define STATIC
- static
+#define STATIC static
#endif
#define DIAGNOSTICS_FEATURE "http://tizen.org/feature/diagnostics"
#define FEATURE_FALSE 0
#define FEATURE_TRUE 1
-STATIC struct _diagnostics_cb_info_s {
- diagnostics_notification_cb cb;
- void *user_data;
-} cb_info = {
- NULL,
- NULL
-};
+#define MAX_EVENT_NAME_LEN 255
+#define MAX_CLIENT_ID_LEN 255
+#define MAX_INT_DIGITS 11
struct _diagnostics_ctx_s {
char *client_id;
- struct dbus_signal_s *signal;
- signal_type_e signal_type;
+ char *event_name;
+ bundle *event_data;
};
struct _diagnostics_data_s {
int fd;
+ char **params;
+ int params_size;
+};
+
+struct _diagnostics_event_s {
+ char *event_name;
+ char *client_id;
+ int subscription_id;
+};
+
+STATIC struct _diagnostics_notification_cb_info_s {
+ diagnostics_notification_cb cb;
+ void *user_data;
+ struct _diagnostics_event_s **events;
+ int events_count;
+} notification_cb_info = {
+ NULL,
+ NULL,
+ NULL,
+ 0
};
+STATIC struct _dumpsys_cb_info_s {
+ diagnostics_request_cb cb;
+ void *user_data;
+ void *handler;
+} dumpsys_cb_info = {
+ NULL,
+ NULL,
+ NULL
+};
+
+enum _ctx_params {
+ CTX_PARAM_MAGIC_TOKEN = -5,
+ CTX_PARAM_CLIENT_ID = -4,
+ CTX_PARAM_EVENT_NAME = -3,
+ CTX_PARAM_EVENT_DATA_RAW = -2,
+ CTX_PARAM_EVENT_DATA_LEN = -1,
+ CTX_PARAM_LEN = 5
+};
+
+/*
+ * This magic_token is just a random string
+ * and is used to split user parameters and auto-added
+ * context parameters in dumpsys dump request
+ */
+STATIC char *magic_token = "4IJJSPh1CqITvhgm9KAg";
+
+STATIC char app_id[MAX_CLIENT_ID_LEN + 1] = {0, };
+STATIC char service_name[MAX_CLIENT_ID_LEN + 1] = {0, };
+
STATIC int diagnostics_feature = FEATURE_UNKNOWN;
STATIC bool __is_feature_supported(void)
return (diagnostics_feature == FEATURE_TRUE ? true : false);
}
-STATIC struct _diagnostics_ctx_s *diagnostics_create(struct dbus_signal_s *signal)
+STATIC bool is_app()
{
- RETV_IF(signal == NULL, NULL);
+ int ret;
- struct _diagnostics_ctx_s *ctx;
+ if (app_id[0])
+ return true;
+
+ ret = aul_app_get_appid_bypid(getpid(), app_id, sizeof(app_id));
+ if (ret)
+ return false;
+
+ return true;
+}
+
+STATIC char *get_client_id()
+{
+ if (is_app())
+ return app_id;
+
+ if (service_name[0])
+ return service_name;
+
+ _E("Client ID not set, first call diagnostics_set_client_id()");
+ return NULL;
+}
+
+STATIC void diagnostics_event_destroy(struct _diagnostics_event_s *event)
+{
+ free(event->event_name);
+ free(event->client_id);
+ free(event);
+}
+
+STATIC struct _diagnostics_ctx_s *diagnostics_create(const char *client_id, const char *event_name, bundle *event_data)
+{
+ RETV_IF(client_id == NULL, NULL);
+ RETV_IF(event_name == NULL, NULL);
+
+ struct _diagnostics_ctx_s *ctx = NULL;
ctx = calloc(1, sizeof(struct _diagnostics_ctx_s));
if (!ctx) {
return NULL;
}
- if (signal->signal_name && strcmp(signal->signal_name, DBUS_MEMBER_CRASH) == 0) {
- ctx->client_id = DBUS_SENDER_CRASH;
- ctx->signal_type = signal_is_valid_crash(signal) ? SIG_TYPE_CRASH : SIG_TYPE_INVALID;
- } else {
- _E("Unknown signal name");
- free(ctx);
+ ctx->client_id = strndup(client_id, MAX_CLIENT_ID_LEN);
+ if (!ctx->client_id) {
+ _E("Unable to allocate memory");
+ diagnostics_destroy(ctx);
+ return NULL;
+ }
+
+ ctx->event_name = strndup(event_name, MAX_EVENT_NAME_LEN);
+ if (!ctx->event_name) {
+ _E("Unable to allocate memory");
+ diagnostics_destroy(ctx);
+ return NULL;
+ }
+
+ ctx->event_data = event_data;
+
+ return ctx;
+}
+
+STATIC struct _diagnostics_ctx_s *diagnostics_create_from_params(char **params, int params_size)
+{
+ if (params == NULL || params_size < CTX_PARAM_LEN)
+ return NULL;
+
+ struct _diagnostics_ctx_s *ctx = NULL;
+ bundle *event_data = NULL;
+ int event_data_len = 0;
+
+ if (strncmp(params[params_size + CTX_PARAM_MAGIC_TOKEN], magic_token, strlen(magic_token)) != 0)
+ return NULL;
+
+ errno = 0;
+ event_data_len = (int) strtol(params[params_size + CTX_PARAM_EVENT_DATA_LEN], NULL, 10);
+ if (event_data_len < 0 || errno != 0) {
+ _E("Unable to convert raw bundle size to int");
+ return NULL;
+ }
+
+ if (event_data_len > 0) {
+ event_data = bundle_decode((const bundle_raw *) params[params_size + CTX_PARAM_EVENT_DATA_RAW], event_data_len);
+ if (!event_data) {
+ _E("Unable to decode bundle");
+ return NULL;
+ }
+ }
+
+ ctx = diagnostics_create(params[params_size + CTX_PARAM_CLIENT_ID], params[params_size + CTX_PARAM_EVENT_NAME], event_data);
+ if (!ctx) {
+ _E("Unable to create ctx");
+ bundle_free(event_data);
return NULL;
}
- ctx->signal = signal;
return ctx;
}
-STATIC struct _diagnostics_data_s *diagnostics_data_create(int fd)
+STATIC struct _diagnostics_data_s *diagnostics_data_create(int fd, char **params, int params_size)
{
RETV_IF(fd < 0, NULL);
+ RETV_IF(params == NULL && params_size != 0, NULL);
+ RETV_IF(params_size < 0, NULL);
struct _diagnostics_data_s *data;
}
data->fd = fd;
+
+ data->params = calloc(params_size, sizeof(char*));
+ if (!data->params) {
+ _E("Unable to allocate memory");
+ free(data);
+ return NULL;
+ }
+
+ for (int i = 0; i < params_size; i++) {
+ data->params[i] = strdup(params[i]);
+ if (!data->params[i]) {
+ _E("Unable to allocate memory");
+ diagnostics_data_destroy(data);
+ return NULL;
+ }
+ data->params_size = i + 1;
+ }
+
return data;
}
STATIC void signal_handler(GDBusConnection *connection,
- const gchar *sender_name,
- const gchar *object_path,
- const gchar *interface_name,
- const gchar *signal_name,
- GVariant *parameters,
- gpointer user_data)
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
{
struct _diagnostics_ctx_s *ctx;
- struct dbus_signal_s *signal;
-
- _D("signal_handler");
- _D("parameters: %s", g_variant_print(parameters, TRUE));
-
- if (!cb_info.cb) {
+ struct _diagnostics_event_s *event = NULL;
+ bundle *event_data = NULL;
+ char *event_data_raw = NULL;
+ char *client_id = NULL;
+ int event_data_len;
+
+ _D("Received signal\n"
+ " sender: %s\n"
+ " objpath: %s\n"
+ " interface: %s\n"
+ " member: %s\n"
+ " parameters: %s\n",
+ sender_name, object_path, interface_name, signal_name, g_variant_print(parameters, TRUE));
+
+ if (!notification_cb_info.cb) {
_E("No user cb set");
return;
}
- _D("dbus_signal_create");
- signal = dbus_signal_create(sender_name,
- object_path,
- interface_name,
- signal_name,
- parameters);
- if (!signal) {
- _E("Unable to create signal structure");
- return;
+ g_variant_get(parameters, "(ssi)", &client_id, &event_data_raw, &event_data_len);
+
+ /* Check if the event comes from the right client */
+ for (int i = 0; i < notification_cb_info.events_count; i++) {
+ if (strncmp(notification_cb_info.events[i]->event_name, signal_name, MAX_EVENT_NAME_LEN) == 0 &&
+ strncmp(notification_cb_info.events[i]->client_id, client_id, MAX_CLIENT_ID_LEN) == 0) {
+
+ event = notification_cb_info.events[i];
+ break;
+ }
+ }
+
+ if (!event) {
+ _W("Cannot find (event_name, client_id) pair in subscribed events, ignoring event");
+ goto cleanup;
+ }
+
+ if (strlen(event_data_raw) > 0) {
+ event_data = bundle_decode((const bundle_raw *) event_data_raw, event_data_len);
+ if (!event_data) {
+ _E("Unable to decode bundle");
+ goto cleanup;
+ }
}
- _D("diagnostics_create");
- ctx = diagnostics_create(signal);
+ ctx = diagnostics_create(event->client_id, event->event_name, event_data);
if (!ctx) {
_E("Unable to create diagnostics context");
- dbus_signal_cleanup(signal);
- return;
+ bundle_free(event_data);
+ goto cleanup;
}
- _D("Fireing user cb!");
- cb_info.cb(ctx, cb_info.user_data);
+ _D("Fireing notification cb");
+ notification_cb_info.cb(ctx, notification_cb_info.user_data);
+
+cleanup:
+ free(client_id);
+ free(event_data_raw);
}
int diagnostics_set_notification_cb(diagnostics_notification_cb callback, void *user_data)
RETVM_IF(__is_feature_supported() == false, DIAGNOSTICS_ERROR_NOT_SUPPORTED, "Diagnostics feature is not supported");
RETV_IF(callback == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
+ if (notification_cb_info.cb) {
+ _E("Notification callback has already been set");
+ return DIAGNOSTICS_ERROR_RESOURCE_BUSY;
+ }
+
+ notification_cb_info.cb = callback;
+ notification_cb_info.user_data = user_data;
+
+ return DIAGNOSTICS_ERROR_NONE;
+}
+
+int diagnostics_unset_notification_cb(void)
+{
+ RETVM_IF(__is_feature_supported() == false, DIAGNOSTICS_ERROR_NOT_SUPPORTED, "Diagnostics feature is not supported");
+
+ for (int i = 0; i < notification_cb_info.events_count; i++) {
+ dbus_unsubscribe(notification_cb_info.events[i]->subscription_id);
+ diagnostics_event_destroy(notification_cb_info.events[i]);
+ }
+ free(notification_cb_info.events);
+
+ notification_cb_info.cb = NULL;
+ notification_cb_info.user_data = NULL;
+ notification_cb_info.events = NULL;
+ notification_cb_info.events_count = 0;
+
+ return DIAGNOSTICS_ERROR_NONE;
+}
+
+int diagnostics_send_event(const char *event_name, bundle *event_data)
+{
+ RETVM_IF(__is_feature_supported() == false, DIAGNOSTICS_ERROR_NOT_SUPPORTED, "Diagnostics feature is not supported");
+ RETV_IF(event_name == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
+
+ char *client_id;
+ GVariant *parameters = NULL;
+ bundle_raw *event_data_raw = NULL;
+ int event_data_len = 0;
+ int ret;
+
+ client_id = get_client_id();
+ if (!client_id)
+ return DIAGNOSTICS_ERROR_INVALID_PARAMETER;
+
+ if (event_data) {
+ ret = bundle_encode(event_data, &event_data_raw, &event_data_len);
+ if (ret) {
+ _E("Unable to encode bundle: %d", ret);
+ return DIAGNOSTICS_ERROR_IO_ERROR;
+ }
+ }
+
+ parameters = g_variant_new("(ssi)", client_id, event_data_raw ? (char *) event_data_raw : "", event_data_len);
+ free(event_data_raw);
+
+ ret = dbus_send_signal(DBUS_EVENT_INTERFACE_NAME, DBUS_EVENT_OBJECT_PATH, event_name, parameters);
+ if (ret) {
+ _E("Unable to send dbus signal: %d", ret);
+ return DIAGNOSTICS_ERROR_IO_ERROR;
+ }
+
+ return DIAGNOSTICS_ERROR_NONE;
+}
+
+int diagnostics_subscribe_event(const char *event_name, const char *client_id)
+{
+ RETVM_IF(__is_feature_supported() == false, DIAGNOSTICS_ERROR_NOT_SUPPORTED, "Diagnostics feature is not supported");
+ RETV_IF(event_name == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
+ RETV_IF(client_id == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
+
+ struct _diagnostics_event_s *event;
int ret;
- _D("diagnostics_set_notification_cb()");
+ /* Create new event structure */
+ event = calloc(1, sizeof(struct _diagnostics_event_s));
+ if (!event) {
+ _E("Unable to allocate memory");
+ return DIAGNOSTICS_ERROR_OUT_OF_MEMORY;
+ }
+
+ event->client_id = strndup(client_id, MAX_CLIENT_ID_LEN);
+ if (!event->client_id) {
+ _E("Unable to allocate memory");
+ diagnostics_event_destroy(event);
+ return DIAGNOSTICS_ERROR_OUT_OF_MEMORY;
+ }
+
+ event->event_name = strndup(event_name, MAX_EVENT_NAME_LEN);
+ if (!event->event_name) {
+ _E("Unable to allocate memory");
+ diagnostics_event_destroy(event);
+ return DIAGNOSTICS_ERROR_OUT_OF_MEMORY;
+ }
+
+ /* Add event to registered events */
+ notification_cb_info.events = realloc(notification_cb_info.events,
+ (notification_cb_info.events_count + 1) * sizeof(struct _diagnostics_event_s *));
+ if (!notification_cb_info.events) {
+ _E("Unable to allocate memory");
+ diagnostics_event_destroy(event);
+ return DIAGNOSTICS_ERROR_OUT_OF_MEMORY;
+ }
+
+ notification_cb_info.events[notification_cb_info.events_count++] = event;
+
+ ret = dbus_subscribe(DBUS_EVENT_INTERFACE_NAME, DBUS_EVENT_OBJECT_PATH, event_name, signal_handler);
+ if (ret <= 0) {
+ _E("Unable to subscribe to dbus signal: %d", ret);
+ diagnostics_event_destroy(event);
+ notification_cb_info.events_count--;
+ return DIAGNOSTICS_ERROR_IO_ERROR;
+ }
+
+ event->subscription_id = ret;
+
+ return DIAGNOSTICS_ERROR_NONE;
+}
+
+STATIC int dumpsys_handler(const int fd, const int argc, char **argv)
+{
+ struct _diagnostics_data_s *data;
+ struct _diagnostics_ctx_s *ctx = NULL;
+
+ _D("dumpsys_handler");
+ _D("argc: %d", argc);
+ for (int i = 0; i < argc; i++)
+ _D("argv[%d]: %s", i, argv[i]);
- if (cb_info.cb) {
- _E("Callback has already been set");
+ if (!dumpsys_cb_info.cb) {
+ _E("No data request cb set");
+ return -1;
+ }
+
+ /* Create ctx if is shipped with dumpsys parameters (last 5) */
+ ctx = diagnostics_create_from_params(argv, argc);
+
+ data = diagnostics_data_create(fd, argv, ctx ? argc - CTX_PARAM_LEN : argc);
+ if (data == NULL) {
+ _E("Unable to create diagnostics_data");
+ return -1;
+ }
+
+ _D("Fireing dumpsys cb");
+ dumpsys_cb_info.cb(data, data->params, data->params_size, ctx, dumpsys_cb_info.user_data);
+
+ return 0;
+}
+
+int diagnostics_set_data_request_cb(diagnostics_request_cb callback, void *user_data)
+{
+ RETVM_IF(__is_feature_supported() == false, DIAGNOSTICS_ERROR_NOT_SUPPORTED, "Diagnostics feature is not supported");
+ RETV_IF(callback == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
+
+ char *client_id;
+ int ret;
+
+ if (dumpsys_cb_info.cb) {
+ _E("Data request callback has already been set");
return DIAGNOSTICS_ERROR_RESOURCE_BUSY;
}
- ret = dbus_subscribe(signal_handler);
+ client_id = get_client_id();
+ if (!client_id)
+ return DIAGNOSTICS_ERROR_INVALID_PARAMETER;
+
+ ret = dumpsys_system_register_dump_cb(dumpsys_handler, client_id, &dumpsys_cb_info.handler);
if (ret) {
- _E("Unable to subscribe to dbus signals");
+ _E("dumpsys_system_register_dump_cb failed: %d", ret);
return DIAGNOSTICS_ERROR_IO_ERROR;
}
- cb_info.cb = callback;
- cb_info.user_data = user_data;
+ dumpsys_cb_info.cb = callback;
+ dumpsys_cb_info.user_data = user_data;
return DIAGNOSTICS_ERROR_NONE;
}
-int diagnostics_unset_notification_cb(void)
+int diagnostics_unset_data_request_cb(void)
{
RETVM_IF(__is_feature_supported() == false, DIAGNOSTICS_ERROR_NOT_SUPPORTED, "Diagnostics feature is not supported");
- _D("diagnostics_unset_notification_cb()");
+ int ret = dumpsys_system_unregister_dump_cb(dumpsys_cb_info.handler);
+ if (ret) {
+ _E("dumpsys_system_unregister_dump_cb failed: %d", ret);
+ return DIAGNOSTICS_ERROR_IO_ERROR;
+ }
- cb_info.cb = NULL;
- cb_info.user_data = NULL;
+ dumpsys_cb_info.cb = NULL;
+ dumpsys_cb_info.user_data = NULL;
+ dumpsys_cb_info.handler = NULL;
- dbus_unsubscribe();
return DIAGNOSTICS_ERROR_NONE;
}
-int diagnostics_request_client_data(const char *client_id, const char **params, int params_size, diagnostics_data_h *data)
+STATIC int _diagnostics_request_client_data(const char *client_id, const char **params, int params_size, diagnostics_data_h *data, struct _diagnostics_ctx_s *ctx)
{
RETVM_IF(__is_feature_supported() == false, DIAGNOSTICS_ERROR_NOT_SUPPORTED, "Diagnostics feature is not supported");
RETV_IF(client_id == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
+ RETV_IF(params == NULL && params_size != 0, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
RETV_IF(params_size < 0, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
RETV_IF(data == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
+ const char *params_empty[] = {0};
+ char **_params = NULL;
+ int _params_size;
+ bundle_raw *event_data_raw = NULL;
+ int event_data_len = 0;
+ char len_str[MAX_INT_DIGITS];
int fd = -1;
int ret;
- ret = dumpsys_dump(client_id, params_size, params, &fd);
+ if (ctx) {
+ /* We are going to append 5 more parameters to store ctx:
+ *
+ * magic_token
+ * ctx->client_id
+ * ctx->event_name
+ * event_data_raw
+ * event_data_len
+ *
+ */
+
+ _params_size = params_size + CTX_PARAM_LEN;
+
+ _params = calloc(_params_size, sizeof(char *));
+ if (!_params) {
+ _E("Unable to allocate memory");
+ return DIAGNOSTICS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (ctx->event_data) {
+ ret = bundle_encode(ctx->event_data, &event_data_raw, &event_data_len);
+ if (ret) {
+ _E("Unable to encode bundle: %d", ret);
+ free(_params);
+ return DIAGNOSTICS_ERROR_IO_ERROR;
+ }
+ }
+
+ ret = snprintf(len_str, MAX_INT_DIGITS, "%d", event_data_len);
+ if (ret < 0) {
+ _E("snprintf() failed: %d", ret);
+ return DIAGNOSTICS_ERROR_IO_ERROR;
+ }
+
+ for (int i = 0; i < params_size; i++)
+ _params[i] = (char *) params[i];
+
+ _params[_params_size + CTX_PARAM_MAGIC_TOKEN] = magic_token;
+ _params[_params_size + CTX_PARAM_CLIENT_ID] = ctx->client_id;
+ _params[_params_size + CTX_PARAM_EVENT_NAME] = ctx->event_name;
+ _params[_params_size + CTX_PARAM_EVENT_DATA_RAW] = event_data_raw ? (char *) event_data_raw : "";
+ _params[_params_size + CTX_PARAM_EVENT_DATA_LEN] = len_str;
+
+ _D("_params_size: %d", _params_size);
+ for (int i = 0; i < _params_size; i++)
+ _D("_params[%d]: %s", i, _params[i]);
+
+ } else {
+ _params = (char **) (params ? params : params_empty);
+ _params_size = params_size;
+ }
+
+ ret = dumpsys_dump(client_id, _params_size, (const char **) _params, &fd);
+
+ if (ctx) {
+ free(event_data_raw);
+ free(_params);
+ }
+
if (ret != DIAGNOSTICS_ERROR_NONE) {
_E("dumpsys_dump() failed: %d", ret);
if (ret == TIZEN_ERROR_PERMISSION_DENIED)
return DIAGNOSTICS_ERROR_IO_ERROR;
}
- *data = diagnostics_data_create(fd);
+ *data = diagnostics_data_create(fd, (char **) params, params_size);
if (*data == NULL) {
_E("Unable to create diagnostics_data");
return DIAGNOSTICS_ERROR_OUT_OF_MEMORY;
return DIAGNOSTICS_ERROR_NONE;
}
+int diagnostics_request_client_data(const char *client_id, const char **params, int params_size, diagnostics_data_h *data)
+{
+ return _diagnostics_request_client_data(client_id, params, params_size, data, NULL);
+}
+
+int diagnostics_get_data(diagnostics_ctx_h ctx, const char **params, int params_size, diagnostics_data_h *data)
+{
+ RETV_IF(ctx == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
+
+ return _diagnostics_request_client_data(((struct _diagnostics_ctx_s *)ctx)->client_id, params, params_size, data, ctx);
+}
+
+int diagnostics_data_get_fd(diagnostics_data_h data, int *fd)
+{
+ RETVM_IF(__is_feature_supported() == false, DIAGNOSTICS_ERROR_NOT_SUPPORTED, "Diagnostics feature is not supported");
+ RETV_IF(data == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
+ RETV_IF(fd == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
+
+ *fd = ((struct _diagnostics_data_s *)data)->fd;
+
+ return DIAGNOSTICS_ERROR_NONE;
+}
+
int diagnostics_data_read(diagnostics_data_h data, void *buf, size_t count, int timeout_ms, size_t *bytes_read)
{
RETVM_IF(__is_feature_supported() == false, DIAGNOSTICS_ERROR_NOT_SUPPORTED, "Diagnostics feature is not supported");
struct pollfd poll_fd;
int ready;
- int ret;
+ int ret, e;
poll_fd.fd = ((struct _diagnostics_data_s *)data)->fd;
poll_fd.events = POLLIN;
if (poll_fd.revents & POLLIN) {
ret = read(poll_fd.fd, buf, count);
if (ret < 0) {
+ e = errno;
_E("read() failed: %m, fd: %d", poll_fd.fd);
- if (errno == EAGAIN)
+ if (e == EAGAIN)
return DIAGNOSTICS_ERROR_TRY_AGAIN;
return DIAGNOSTICS_ERROR_IO_ERROR;
}
return DIAGNOSTICS_ERROR_IO_ERROR;
}
+int diagnostics_data_write(diagnostics_data_h data, const void *buf, size_t count, size_t *bytes_written)
+{
+ RETVM_IF(__is_feature_supported() == false, DIAGNOSTICS_ERROR_NOT_SUPPORTED, "Diagnostics feature is not supported");
+ RETV_IF(data == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
+ RETV_IF(buf == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
+ RETV_IF(bytes_written == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
+
+ struct _diagnostics_data_s *_data = (struct _diagnostics_data_s *) data;
+ int ret, e;
+
+ ret = write(_data->fd, buf, count);
+ if (ret < 0) {
+ e = errno;
+ _E("write() failed: %m, fd: %d", _data->fd);
+ if (e == EAGAIN)
+ return DIAGNOSTICS_ERROR_TRY_AGAIN;
+ return DIAGNOSTICS_ERROR_IO_ERROR;
+ }
+ *bytes_written = ret;
+
+ return DIAGNOSTICS_ERROR_NONE;
+}
+
int diagnostics_get_client_id(diagnostics_ctx_h ctx, char **client_id)
{
RETVM_IF(__is_feature_supported() == false, DIAGNOSTICS_ERROR_NOT_SUPPORTED, "Diagnostics feature is not supported");
RETV_IF(ctx == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
RETV_IF(client_id == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
- *client_id = strdup(((struct _diagnostics_ctx_s *)ctx)->client_id);
+ *client_id = strndup(((struct _diagnostics_ctx_s *)ctx)->client_id, MAX_CLIENT_ID_LEN);
return DIAGNOSTICS_ERROR_NONE;
}
-STATIC int get_report_path(diagnostics_ctx_h ctx, const char **path, size_t *len)
+int diagnostics_get_event_name(diagnostics_ctx_h ctx, char **event_name)
{
+ RETVM_IF(__is_feature_supported() == false, DIAGNOSTICS_ERROR_NOT_SUPPORTED, "Diagnostics feature is not supported");
RETV_IF(ctx == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
- RETV_IF(path == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
- RETV_IF(((struct _diagnostics_ctx_s *)ctx)->signal_type != SIG_TYPE_CRASH, DIAGNOSTICS_ERROR_NOT_SUPPORTED);
-
- GVariant *val;
+ RETV_IF(event_name == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
- val = g_variant_get_child_value(((struct _diagnostics_ctx_s *)ctx)->signal->parameters, SIG_CRASH_REPORTPATH);
- *path = g_variant_get_string(val, (gsize *)len);
+ *event_name = strndup(((struct _diagnostics_ctx_s *)ctx)->event_name, MAX_EVENT_NAME_LEN);
return DIAGNOSTICS_ERROR_NONE;
}
-int diagnostics_get_data(diagnostics_ctx_h ctx, const char **params, int params_size, diagnostics_data_h *data)
+int diagnostics_get_event_data(diagnostics_ctx_h ctx, bundle **event_data)
{
RETVM_IF(__is_feature_supported() == false, DIAGNOSTICS_ERROR_NOT_SUPPORTED, "Diagnostics feature is not supported");
RETV_IF(ctx == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
- RETV_IF(params_size < 0, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
- RETV_IF(data == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
- RETV_IF(((struct _diagnostics_ctx_s *)ctx)->signal_type != SIG_TYPE_CRASH, DIAGNOSTICS_ERROR_NOT_SUPPORTED);
+ RETV_IF(event_data == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
- const char *report_path;
- size_t len;
- int report_id;
- int fd;
- int ret;
+ *event_data = bundle_dup(((struct _diagnostics_ctx_s *)ctx)->event_data);
- /*
- * TODO: Make this suitable for supporting other clients, not just crash-worker
- */
+ return DIAGNOSTICS_ERROR_NONE;
+}
- ret = get_report_path(((struct _diagnostics_ctx_s *)ctx), &report_path, &len);
- if (ret) {
- _E("diagnostics_get_report_path() failed: %d", ret);
- return DIAGNOSTICS_ERROR_IO_ERROR;
- }
+int diagnostics_set_client_id(const char *client_id)
+{
+ RETVM_IF(__is_feature_supported() == false, DIAGNOSTICS_ERROR_NOT_SUPPORTED, "Diagnostics feature is not supported");
+ RETV_IF(client_id == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
- if (params_size < 1)
- return DIAGNOSTICS_ERROR_NOT_SUPPORTED;
+ int ret;
- if (strcmp(params[0], "cs_full") == 0)
- report_id = 0;
- else if (strcmp(params[0], "cs_info_json") == 0)
- report_id = 1;
- else {
- _E("Unsupported parameter: %s", params[0]);
- return DIAGNOSTICS_ERROR_NOT_SUPPORTED;
+ if (is_app()) {
+ _E("Setting client ID is only possible for system services, not apps");
+ return DIAGNOSTICS_ERROR_RESOURCE_BUSY;
}
- ret = dbus_get_file_from_report(report_path, report_id, &fd);
- if (ret) {
- _E("dbus_get_file_from_report() failed: %d", ret);
- if (ret == -EACCES)
- return DIAGNOSTICS_ERROR_PERMISSION_DENIED;
- return DIAGNOSTICS_ERROR_IO_ERROR;
+ if (service_name[0]) {
+ _E("Client ID is already set to: '%s', it is not possible to change it during runtime", service_name);
+ return DIAGNOSTICS_ERROR_RESOURCE_BUSY;
}
- *data = diagnostics_data_create(fd);
- if (*data == NULL) {
- _E("Unable to create diagnostics_data");
- close(fd);
- return DIAGNOSTICS_ERROR_OUT_OF_MEMORY;
+ ret = snprintf(service_name, MAX_CLIENT_ID_LEN, "%s", client_id);
+ if (ret < 0) {
+ _E("snprintf() failed: %d", ret);
+ return DIAGNOSTICS_ERROR_IO_ERROR;
}
return DIAGNOSTICS_ERROR_NONE;
}
-int diagnostics_destroy(diagnostics_ctx_h ctx)
+int diagnostics_request_bugreport(int pid)
{
- RETV_IF(ctx == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
+ RETVM_IF(__is_feature_supported() == false, DIAGNOSTICS_ERROR_NOT_SUPPORTED, "Diagnostics feature is not supported");
+
+ char reason[256 + MAX_CLIENT_ID_LEN];
+ char report_path[PATH_MAX];
+ char *client_id;
+ int ret;
+
+ client_id = get_client_id();
+ if (!client_id)
+ return DIAGNOSTICS_ERROR_INVALID_PARAMETER;
- dbus_signal_cleanup(((struct _diagnostics_ctx_s *)ctx)->signal);
- free(ctx);
+ ret = snprintf(reason, sizeof(reason),
+ "Diagnostics API requested bugreport.\n"
+ "PID (requested): %d\n"
+ "Client ID (requester): %s\n",
+ pid, client_id);
+
+ if (ret < 0) {
+ _E("Unable to set reason: %m");
+ return DIAGNOSTICS_ERROR_IO_ERROR;
+ }
+
+ /*
+ * TODO: livedump_pid() should be changed to return
+ * TIZEN_ERROR_PERMISSION_DENIED in case of missing permission
+ * TIZEN_ERROR_INVALID_PARAMETER in case of no such process
+ */
+ ret = livedump_pid(pid > 0 ? pid : 0, reason, report_path, PATH_MAX);
+ if (ret == false)
+ return DIAGNOSTICS_ERROR_IO_ERROR;
return DIAGNOSTICS_ERROR_NONE;
}
{
RETV_IF(data == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
- close(((struct _diagnostics_data_s *)data)->fd);
- free(data);
+ struct _diagnostics_data_s *_data = (struct _diagnostics_data_s *) data;
+ close(_data->fd);
+
+ for (int i = 0; i < _data->params_size; i++)
+ free(_data->params[i]);
+
+ free(_data->params);
+ free(_data);
+
+ return DIAGNOSTICS_ERROR_NONE;
+}
+
+int diagnostics_destroy(diagnostics_ctx_h ctx)
+{
+ RETV_IF(ctx == NULL, DIAGNOSTICS_ERROR_INVALID_PARAMETER);
+
+ struct _diagnostics_ctx_s *_ctx = (struct _diagnostics_ctx_s *) ctx;
+
+ free(_ctx->client_id);
+ free(_ctx->event_name);
+ bundle_free(_ctx->event_data);
+ free(_ctx);
return DIAGNOSTICS_ERROR_NONE;
}
+++ /dev/null
-/*
-* Copyright (c) 2020 Samsung Electronics Co., Ltd.
-*
-* 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.
-*/
-
-#include "signal.h"
-#include "log.h"
-#include "dbus.h"
-
-#include <gio/gio.h>
-#include <glib.h>
-
-int signal_is_valid_crash(struct dbus_signal_s *signal)
-{
- GVariant *extra;
-
- RETV_IF(signal == NULL, FALSE);
- RETV_IF(g_variant_n_children(signal->parameters) != SIG_CRASH_SIZE, FALSE);
-
- extra = g_variant_get_child_value(signal->parameters, SIG_CRASH_EX);
- RETV_IF(g_variant_is_container(extra) == FALSE, FALSE);
-
- return TRUE;
-}
+++ /dev/null
-/*
-* Copyright (c) 2020 Samsung Electronics Co., Ltd.
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-
-#ifndef __SIGNAL_H__
-#define __SIGNAL_H__
-
-#define SIG_CRASH_SIZE 8
-#define SIG_CRASH_CMDNAME 0
-#define SIG_CRASH_CMDPATH 1
-#define SIG_CRASH_APPID 2
-#define SIG_CRASH_PKGID 3
-#define SIG_CRASH_REPORTPATH 4
-#define SIG_CRASH_PID 5
-#define SIG_CRASH_TID 6
-#define SIG_CRASH_EX 7
-#define SIG_CRASH_EX_SYSSIGNAL "sys.signal"
-#define SIG_CRASH_EX_SYSTIDCOMM "sys.tid.comm"
-#define SIG_CRASH_EX_ARMPC "arm.pc"
-#define SIG_CRASH_EX_ARMLR "arm.lr"
-
-struct dbus_signal_s;
-
-typedef enum {
- SIG_TYPE_CRASH,
- /* SIG_TYPE_CRASH_LEGACY ? */
- SIG_TYPE_INVALID
-} signal_type_e;
-
-int signal_is_valid_crash(struct dbus_signal_s *signal);
-
-#endif /* __SIGNAL_H__ */