-Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
+Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved.
Except as noted, this software is licensed under Apache License, Version 2.
Please, see the LICENSE file for Apache License terms and conditions.
\ No newline at end of file
--- /dev/null
+# partial-update-app-ui
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#ifndef __FIRMWAREUPDATEUI_H__
#define __FIRMWAREUPDATEUI_H__
+#include <stdio.h>
#include <app.h>
#include <Elementary.h>
#include <system_settings.h>
#include <glib.h>
#include <update_control.h>
#include <notification.h>
+#include <app_alarm.h>
+#include <curl/curl.h>
+#include <system_info.h>
+#include <json-glib/json-glib.h>
#ifdef LOG_TAG
#undef LOG_TAG
Evas_Object *label;
} appdata_s;
-typedef enum
-{
- FOTA_OPERATION_DOWNLOAD = 0,
- FOTA_OPERATION_INSTALL,
-}fota_operation;
-
#define RED "\033[0;31m"
#define YELLOW "\033[0;33m"
#define DCOLOR "\033[0;m"
#define LOGW(fmt, arg...) dlog_print(DLOG_WARN, LOG_TAG, "%s (%d) %s : " fmt, __FILE__, __LINE__, __FUNCTION__, ##arg)
#define UPDATE_TITLE "Software Update"
-#define DOWNLOAD_TITLE "Software Download"
-#define FOTA_MODE_DOWNLOAD "fota-plug"
#define FOTA_MODE_INSTALL "fota-install"
-#define FOTA_MODE_UNPLUG "fota-unplug"
#define FOTA_MODE_REBOOT "fota-reboot"
#define UPDATE_SUCCESS "00"
+#define REG_INTERVAL "regular_interval"
+#define MAX_ATTEMPT "max_attempt"
+#define REQ_CON_TIMEOUT 5L
+#define REQ_TIMEOUT 7L
+#define UPDATE_URL "http://107.109.223.60/delta.tar.gz"
-extern void fota_show_install_popup(Evas_Object* nf, char *title, char* cmd);
-extern void fota_show_download_popup(Evas_Object* nf, char *title, char* cmd);
-extern void fota_show_result_popup(Evas_Object *nf,fota_operation e_oper, bool status, int error);
+char g_post_msg[PATH_MAX];
+char g_img_url[PATH_MAX];
+int read_attempts();
+void write_attempts(int attempts);
+int read_json_attribute(const char *attribute);
+void launch_update_at_regular_interval(void);
+void fota_show_install_popup(Evas_Object* nf);
+void fota_show_result_popup(Evas_Object *nf, bool status, int error);
+void download_software_update(Evas_Object *nf);
+void createUpdateStatusFile();
+bool updateStatusFileExists();
+void removeUpdateStatusFile();
#endif /* __FIRMWAREUPDATEUI_H__ */
profile = iot-headed-5.5
# C/CPP Sources
-USER_SRCS = src/firmware-update-ui.c src/interaction.c
+USER_SRCS = src/firmware-update-ui.c src/interaction.c src/download.c src/utils.c
# EDC Sources
USER_EDCS =
# PO Sources
-USER_POS =
+USER_POS = res/po/en_US.po res/po/ko_KR.po
# User Defines
USER_DEFS = TIZEN_DEPRECATION DEPRECATION_WARNING
--- /dev/null
+{"regular_interval":1,"max_attempt":3}
\ No newline at end of file
--- /dev/null
+# This PO file is automatically generated by PO File Editor of Tizen Studio
+# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES CAN BE OVERWRITTEN
+
+msgid "IDS_SOFTWARE_UPDATE_UNAVAILABLE_TEXT"
+msgstr "Software update unavailable. Please contact the service center."
+
+msgid "IDS_SOFTWARE_UPDATE_FAIL_TEXT"
+msgstr "Software update failed."
+
+msgid "IDS_SOFTWARE_UPDATE_CURRENT_VERSION"
+msgstr "Current Version : "
+
+msgid "IDS_SOFTWARE_UPDATE_SUCCESS_TEXT"
+msgstr "Software update has been completed successfully."
+
+msgid "IDS_SOFTWARE_UPDATE_NOTI_TEXT"
+msgstr "Software update is available. Click to update"
+
+msgid "IDS_SOFTWARE_UPDATE_TEXT"
+msgstr "An update is ready to start. Please restart your device to complete. Do you want to restart your device now?"
+
+msgid "IDS_SOFTWARE_UPDATE_TITLE"
+msgstr "Software Update"
+
+msgid "IDS_SOFTWARE_OK_BUTTON"
+msgstr "OK"
+
+msgid "IDS_SOFTWARE_NOT_NOW_BUTTON"
+msgstr "Not Now"
+
+msgid "IDS_SOFTWARE_NOW_BUTTON"
+msgstr "Now"
--- /dev/null
+# This PO file is automatically generated by PO File Editor of Tizen Studio
+# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES CAN BE OVERWRITTEN
+
+msgid "IDS_SOFTWARE_UPDATE_UNAVAILABLE_TEXT"
+msgstr "업데이트를 할 수 없습니다. 서비스 센터에 연락하세요."
+
+msgid "IDS_SOFTWARE_UPDATE_FAIL_TEXT"
+msgstr "업데이트가 실패하였습니다."
+
+msgid "IDS_SOFTWARE_UPDATE_CURRENT_VERSION"
+msgstr "현재 버전 : "
+
+msgid "IDS_SOFTWARE_UPDATE_SUCCESS_TEXT"
+msgstr "업데이트가 성공적으로 완료되었습니다."
+
+msgid "IDS_SOFTWARE_UPDATE_NOTI_TEXT"
+msgstr "업데이트를 할수 있습니다 . 업데이트하려면 클릭하세요"
+
+msgid "IDS_SOFTWARE_UPDATE_TEXT"
+msgstr "업데이트를 시작할 준비가 되었습니다 . 완료하려면 기기를 다시 시작하세요 지금 다시 시작하시겠습니까 ?"
+
+msgid "IDS_SOFTWARE_UPDATE_TITLE"
+msgstr "소프트웨어 업데이트"
+
+msgid "IDS_SOFTWARE_OK_BUTTON"
+msgstr "확인"
+
+msgid "IDS_SOFTWARE_NOT_NOW_BUTTON"
+msgstr "지금은 아닙니다"
+
+msgid "IDS_SOFTWARE_NOW_BUTTON"
+msgstr "지금"
--- /dev/null
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * 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 "firmware-update-ui.h"
+
+static bool g_write_cb;
+
+static size_t _write_function(void *ptr, size_t size, size_t nmemb, struct url_data *data)
+{
+ g_write_cb = true;
+ char *token = NULL, *image_url = NULL;
+
+ char* url_response = (char*)ptr;
+ LOGI("size=%zu nmemb=%zu data=%s", size, nmemb, url_response);
+
+ while ((token = strsep(&url_response, "\""))) {
+ if (strstr(token, "tar.gz")) {
+ image_url = strdup(token);
+ break;
+ }
+ }
+ snprintf(g_img_url, sizeof(g_img_url), "%s", image_url);
+ LOGI("Update Image download url =%s", g_img_url);
+
+ return size * nmemb;
+}
+
+static void get_source_device_metadata(void)
+{
+ LOGI(" Inside get_source_device_metadata");
+ char *device_type;
+ system_info_get_platform_string("http://tizen.org/system/device_type", &device_type);
+
+ char *device_model;
+ system_info_get_platform_string("http://tizen.org/system/model_name", &device_model);
+
+ char *vendor_name;
+ system_info_get_platform_string("http://tizen.org/system/manufacturer", &vendor_name);
+
+ char *source_version;
+ system_info_get_platform_string("http://tizen.org/system/build.release", &source_version);
+
+ LOGI("Device type = %s",device_type);
+ LOGI("Device model = %s",device_model);
+ LOGI("Vendor name = %s",vendor_name);
+ LOGI("Source version = %s",source_version);
+
+ snprintf(g_post_msg, sizeof(g_post_msg), "{\"deviceType\":\"%s\",\"deviceModel\" : \"%s\",\"vendorName\": \"%s\",\"imageType\": \"all\",\"architecture\": \"arm32\",\"sourceVersion\": \"tizen-unified_%s\"}"
+ ,device_type, device_model, vendor_name, source_version);
+ LOGI("Post Message = %s",g_post_msg);
+ free(device_type);
+ free(device_model);
+ free(vendor_name);
+ free(source_version);
+
+ return;
+}
+
+static bool get_delta_image_url(char* url, char* post_data) {
+ LOGI("Server url = %s", url);
+ LOGI("post message = %s", post_data);
+ CURL *curl;
+ CURLcode res;
+
+ g_write_cb = false;
+ curl_global_init(CURL_GLOBAL_ALL);
+ curl = curl_easy_init();
+ if (curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_POST, 1L);
+
+ struct curl_slist *headers = NULL;
+ headers = curl_slist_append(headers, "Accept: application/json");
+ headers = curl_slist_append(headers, "Content-type: application/json");
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
+
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(post_data));
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, _write_function);
+ curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, REQ_CON_TIMEOUT);
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT, REQ_TIMEOUT);
+
+ res = curl_easy_perform(curl);
+ LOGI("return of curl_easy_perform API = %d", res);
+ if(res != CURLE_OK) {
+ LOGE("curl_easy_perform() failed: %s", curl_easy_strerror(res));
+ }
+ if(!g_write_cb) {
+ LOGE("Unable to get server response to recieve delta image URL");
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+ return false;
+ }
+ curl_easy_cleanup(curl);
+ }
+ curl_global_cleanup();
+ return true;
+}
+
+static bool download_delta_image(char *url)
+{
+ CURL *curl;
+ FILE *fp;
+ CURLcode res;
+ char out_filename[FILENAME_MAX];
+
+ char *shared_data_path = app_get_shared_data_path();
+ snprintf(out_filename, sizeof(out_filename), "%sdelta.tar.gz",shared_data_path);
+ LOGI("Delta image path = %s",out_filename);
+
+ curl_global_init(CURL_GLOBAL_ALL);
+ curl = curl_easy_init();
+ if (curl)
+ {
+ fp = fopen(out_filename,"wb");
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
+
+ res = curl_easy_perform(curl);
+ LOGI("return of curl_easy_perform API = %d", res);
+ if(res != CURLE_OK) {
+ LOGE("curl_easy_perform() failed: %s", curl_easy_strerror(res));
+ fclose(fp);
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+ return false;
+ }
+ LOGI("Delta image downloaded at path = %s",out_filename);
+ curl_easy_cleanup(curl);
+ fclose(fp);
+ }
+ curl_global_cleanup();
+ return true;
+}
+
+void download_software_update(Evas_Object *nf)
+{
+ LOGI("Inside download_software_update");
+ bool schedule_launch = FALSE; // Flag to set app launch after regular interval
+ int max_attempt;
+
+ max_attempt = read_json_attribute(MAX_ATTEMPT);
+ if(!max_attempt)
+ return;
+
+ int current_attempt = read_attempts();
+ if(current_attempt > max_attempt) // Check if maximum fail attempts exceeded
+ {
+ LOGI("Maximum Attempts exceeded for Software Update");
+ fota_show_result_popup(nf, FALSE, 0);
+ }
+ else
+ {
+ get_source_device_metadata();
+ bool ret = true; //get_delta_image_url(UPDATE_URL, g_post_msg);
+ if(!ret)
+ schedule_launch = TRUE;
+ else
+ {
+ ret = download_delta_image(UPDATE_URL);//g_img_url);
+ if(!ret)
+ schedule_launch = TRUE;
+ else
+ fota_show_install_popup(nf); // Launch UI popup if update pkg downloaded
+ }
+ }
+
+ if(schedule_launch)
+ {
+ launch_update_at_regular_interval();
+ ui_app_exit();
+ }
+}
\ No newline at end of file
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
evas_object_show(ad->nf);
// elm_naviframe_prev_btn_auto_pushed_set(ad->nf, EINA_TRUE);
elm_object_content_set(ad->conform, ad->nf);
-
- evas_object_show(ad->win);
}
static bool
app_create(void *data)
{
appdata_s *ad = data;
-
+ LOGI("Inside App Create");
create_base_gui(ad);
return true;
static void
app_control(app_control_h app_control, void *data)
{
+ LOGI("Inside app_control");
int ret = 0;
- char *value = NULL, *shared_path = NULL;
+ char *value = NULL;
appdata_s *ad = data;
- gchar *download_cmd;
notification_h notify = notification_load_by_tag(LOG_TAG);
if(notify) {
notification_free(notify);
}
- /* Will be triggered if update image attached for download */
- LOGI("Inside app_control");
- ret = app_control_get_extra_data(app_control, FOTA_MODE_DOWNLOAD, &value);
- if (ret == APP_CONTROL_ERROR_NONE) {
- LOGI("App-control %s : %s", FOTA_MODE_DOWNLOAD, value);
- shared_path = app_get_shared_data_path();
- LOGI("Shared path : %s", shared_path);
-
- download_cmd = g_strjoin(" ", "cp", value, shared_path, NULL);
- if(shared_path) free(shared_path);
- LOGI("Download command in App-control %s", download_cmd);
-
- fota_show_download_popup(ad->nf, UPDATE_TITLE, download_cmd);
-
- } else if (ret != APP_CONTROL_ERROR_KEY_NOT_FOUND) {
- LOGE("App-control %s Error : %d", FOTA_MODE_DOWNLOAD, ret);
- }
-
- /* Will be triggered if update image is ready to install */
+ /* Will be triggered if app launched by Notification */
ret = app_control_get_extra_data(app_control, FOTA_MODE_INSTALL, &value);
- if (ret == APP_CONTROL_ERROR_NONE) {
- LOGI("App-control %s : %s", FOTA_MODE_INSTALL, value);
-
- shared_path = app_get_shared_data_path();
- LOGI("Shared path : %s", shared_path);
- download_cmd = g_strjoin(" ", "cp", value, shared_path, NULL);
- if(shared_path) free(shared_path);
- LOGI("Download command in App-control %s", download_cmd);
-
- fota_show_install_popup(ad->nf, UPDATE_TITLE, download_cmd);
-
- } else if (ret != APP_CONTROL_ERROR_KEY_NOT_FOUND) {
- LOGE("App-control %s Error : %d", FOTA_MODE_INSTALL, ret);
+ if (ret == APP_CONTROL_ERROR_NONE)
+ {
+ LOGI("App-control %s ", FOTA_MODE_INSTALL);
+ fota_show_install_popup(ad->nf);
}
-
- /* Will be triggered if external storage device is unplugged and UI app terminates */
- ret = app_control_get_extra_data(app_control, FOTA_MODE_UNPLUG, &value);
- if (ret == APP_CONTROL_ERROR_NONE) {
- LOGI("App-control %s : %s", FOTA_MODE_UNPLUG, value);
- ui_app_exit();
-
- } else if (ret != APP_CONTROL_ERROR_KEY_NOT_FOUND) {
- LOGE("App-control %s Error : %d", FOTA_MODE_UNPLUG, ret);
- }
-
- /* Will be triggered if update image is ready to install */
- ret = app_control_get_extra_data(app_control, FOTA_MODE_REBOOT, &value);
- if (ret == APP_CONTROL_ERROR_NONE) {
+ /* Will be triggered if app launched after reboot of install update */
+/* else if (app_control_get_extra_data(app_control, FOTA_MODE_REBOOT, &value) == APP_CONTROL_ERROR_NONE )
+ {
LOGI("App-control %s : %s", FOTA_MODE_REBOOT, value);
/* fota-reboot sends value=00 in case of RO/RW update success */
- if (strncmp(value, UPDATE_SUCCESS, strlen(UPDATE_SUCCESS)) == 0) {
- fota_show_result_popup(ad->nf, FOTA_OPERATION_INSTALL, TRUE, APP_CONTROL_ERROR_NONE);
- } else {
+/* if (strncmp(value, UPDATE_SUCCESS, strlen(UPDATE_SUCCESS)) == 0)
+ {
+ LOGI("Update Firmware Success");
+ fota_show_result_popup(ad->nf, TRUE, APP_CONTROL_ERROR_NONE);
+ }
+ else
+ {
int error = atoi(value);
LOGI("Update Firmware error %s : %d", value, error);
- fota_show_result_popup(ad->nf, FOTA_OPERATION_INSTALL, FALSE, error);
+ fota_show_result_popup(ad->nf, FALSE, error);
+ }
+ }*/
+ else /* Normal Launch of app after reboot or by scheduling */
+ {
+ if(updateStatusFileExists() )
+ {
+ LOGI("Update Status File Exists");
+ removeUpdateStatusFile();
+ int value;
+ update_control_property_e property = UPDATE_CONTROL_PROPERTY_RESULT;
+ int status = update_control_get_property(property,(void **)&value);
+ LOGI("Update Status from API update_control_get_property: %d",status);
+ if(status == UPDATE_CONTROL_ERROR_NONE)
+ {
+ LOGI("Update Status File Exists value: %d",value);
+ if(value == -1)
+ {
+ LOGI("Firmware update failed");
+ fota_show_result_popup(ad->nf, FALSE,0);
+ }
+ else
+ {
+ LOGI("Firmware update successful");
+ fota_show_result_popup(ad->nf, TRUE, APP_CONTROL_ERROR_NONE);
+ }
+ }
+ else
+ {
+ LOGI("Update Status Could not be fetched");
+ download_software_update(ad->nf); // Resume normal launch of app.
+ }
+ }
+ else
+ {
+ download_software_update(ad->nf);
}
-
- } else if (ret != APP_CONTROL_ERROR_KEY_NOT_FOUND) {
- LOGE("App-control %s Error : %d", FOTA_MODE_REBOOT, ret);
}
-
}
static void
/* Take necessary actions when application becomes visible. */
}
-static void
-app_terminate(void *data)
+static void app_terminate(void *data)
{
/* Release all resources. */
}
-static void
-ui_app_lang_changed(app_event_info_h event_info, void *user_data)
+static void ui_app_lang_changed(app_event_info_h event_info, void *user_data)
{
/*APP_EVENT_LANGUAGE_CHANGED*/
}
}
-static void
-ui_app_orient_changed(app_event_info_h event_info, void *user_data)
+static void ui_app_orient_changed(app_event_info_h event_info, void *user_data)
{
/*APP_EVENT_DEVICE_ORIENTATION_CHANGED*/
return;
}
-static void
-ui_app_region_changed(app_event_info_h event_info, void *user_data)
+static void ui_app_region_changed(app_event_info_h event_info, void *user_data)
{
/*APP_EVENT_REGION_FORMAT_CHANGED*/
}
-static void
-ui_app_low_battery(app_event_info_h event_info, void *user_data)
+static void ui_app_low_battery(app_event_info_h event_info, void *user_data)
{
/*APP_EVENT_LOW_BATTERY*/
}
-static void
-ui_app_low_memory(app_event_info_h event_info, void *user_data)
+static void ui_app_low_memory(app_event_info_h event_info, void *user_data)
{
/*APP_EVENT_LOW_MEMORY*/
}
-int
-main(int argc, char *argv[])
+int main(int argc, char *argv[])
{
appdata_s ad = {0,};
int ret = 0;
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "firmware-update-ui.h"
-static char path[PATH_MAX];
-static char cmd_version[PATH_MAX];
-static char cmd_dwnload[PATH_MAX];
-
static void
_popup_block_clicked_cb(void *data, Evas_Object *obj, void *event_info)
{
if (pkgname)
app_control_set_app_id(service, pkgname);
- LOGI("Value = %s", argument);
+ LOGI("Operation = %s", operation);
if (operation && argument)
app_control_add_extra_data(service, operation, argument);
app_control_destroy(service);
}
-static char* fota_get_update_image_version()
-{
-
- bool flag_image = FALSE;
- char *image_path = NULL, *directory = NULL, *version = NULL, *token = NULL;
- char *cmd = cmd_version;
- LOGI("cmd : %s", cmd);
-
- while ((token = strsep(&cmd, " "))) {
- if (strstr(token, "delta.tar")) {
- image_path = strdup(token);
- break;
- }
- }
- LOGI("Update image path : %s", image_path);
- if(!image_path)
- return NULL;
-
- snprintf(path, sizeof(path), "%s", image_path);
-
- while ((token = strsep(&image_path, "/"))) {
- if (strncmp(token, "delta.tar", strlen("delta.tar")) == 0) {
- flag_image = TRUE;
- break;
- }
- directory = strdup(token);
- }
- LOGI("Image directory : %s", directory);
- if(!directory || !flag_image) {
- free(image_path);
- return NULL;
- }
-
- while ((token = strsep(&directory, "-"))) {
- version = strdup(token);
- }
- LOGI("Update image version : %s", version);
- if(!version) {
- free(image_path);
- free(directory);
- return NULL;
- }
-
- free(directory);
- free(image_path);
- return version;
-}
-
-void fota_show_result_popup(Evas_Object *nf,fota_operation e_oper, bool status, int error)
+void fota_show_result_popup(Evas_Object *nf, bool status, int error)
{
LOGI("Inside fota_show_result_popup");
char title[PATH_MAX], text[PATH_MAX];
elm_popup_align_set(popup, ELM_NOTIFY_ALIGN_FILL, 0.5);
evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
- if (e_oper == FOTA_OPERATION_DOWNLOAD ) {
- snprintf(title, sizeof(title), "%s Failed",DOWNLOAD_TITLE);
- snprintf(text, sizeof(text), "%s failed.<br>[error:%d]",DOWNLOAD_TITLE, error);
-
- } else if (e_oper == FOTA_OPERATION_INSTALL && status) {
- snprintf(title, sizeof(title), "%s Succeeded",UPDATE_TITLE);
- snprintf(text, sizeof(text), "Software update is successfully done!");
+ if (status)
+ {
+ LOGI("Update success after Reboot");
+ char *source_version;
+ system_info_get_platform_string("http://tizen.org/system/build.release", &source_version);
+ snprintf(title, sizeof(title), "%s",_("IDS_SOFTWARE_UPDATE_TITLE"));
+ snprintf(text, sizeof(text), "%s<br>%s %s",_("IDS_SOFTWARE_UPDATE_SUCCESS_TEXT"), _("IDS_SOFTWARE_UPDATE_CURRENT_VERSION"),source_version);
- } else if (e_oper == FOTA_OPERATION_INSTALL && !status) {
- snprintf(title, sizeof(title), "%s Failed",UPDATE_TITLE);
- snprintf(text, sizeof(text), "%s failed.<br>[error:%d]<br>Please contact the service center",UPDATE_TITLE, error);
+ free(source_version);
+ write_attempts(0);
+ }
+ else
+ {
+ int current_attempt = read_attempts();
+ int max_attempts = read_json_attribute(MAX_ATTEMPT);
+ if(current_attempt < max_attempts)
+ {
+ LOGI("Update failed after Reboot, Launch after regular interval");
+ snprintf(title, sizeof(title), "%s",_("IDS_SOFTWARE_UPDATE_TITLE"));
+ snprintf(text, sizeof(text), "%s",_("IDS_SOFTWARE_UPDATE_FAIL_TEXT"));
+ write_attempts(current_attempt+1);
+ launch_update_at_regular_interval();
+ }
+ else
+ {
+ LOGI("Update failed, Maximum Attempts exceeded for Software Update");
+ snprintf(title, sizeof(title), "%s",_("IDS_SOFTWARE_UPDATE_TITLE"));
+ snprintf(text, sizeof(text), "%s",_("IDS_SOFTWARE_UPDATE_UNAVAILABLE_TEXT"));
+ write_attempts(current_attempt+1);
+ }
}
elm_object_part_text_set(popup, "title,text", title);
elm_object_text_set(popup,text);
evas_object_smart_callback_add(popup, "dismissed", _popup_hide_finished_cb, NULL);
evas_object_smart_callback_add(popup, "block,clicked", _popup_block_clicked_cb, NULL);
- /* Ok button */
+ /* OK button */
Evas_Object *btn1 = elm_button_add(popup);
- elm_object_text_set(btn1, "OK");
+ elm_object_text_set(btn1, _("IDS_SOFTWARE_OK_BUTTON"));
elm_object_part_content_set(popup, "button1", btn1);
evas_object_smart_callback_add(btn1, "clicked", _app_terminate_request_cb, nf);
{
LOGI("Inside _send_notification_install_update_cb");
Evas_Object *popup = data;
- //elm_popup_dismiss(popup);
- //evas_object_del(popup);
notification_h notify = notification_create(NOTIFICATION_TYPE_ONGOING);
if (!notify) {
return;
}
- notification_set_text(notify, NOTIFICATION_TEXT_TYPE_TITLE, UPDATE_TITLE, NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
- notification_set_text(notify, NOTIFICATION_TEXT_TYPE_CONTENT, "Software update is available. Click to update", NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
+ notification_set_text(notify, NOTIFICATION_TEXT_TYPE_TITLE, _("IDS_SOFTWARE_UPDATE_TITLE"), NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
+ notification_set_text(notify, NOTIFICATION_TEXT_TYPE_CONTENT, _("IDS_SOFTWARE_UPDATE_NOTI_TEXT"), NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
notification_set_layout(notify, NOTIFICATION_LY_ONGOING_EVENT);
notification_set_tag(notify, LOG_TAG);
- LOGI("Image path in _send_notification_install_update_cb = %s",path);
-
/* Relaunch App to install update when user clicks notification */
- notification_launch_cb(notify, FOTA_MODE_INSTALL, path, PACKAGE);
+ notification_launch_cb(notify, FOTA_MODE_INSTALL, "/", PACKAGE);
notification_post(notify);
elm_popup_dismiss(popup);
LOGI("Inside _install_update_cb");
Evas_Object *nf = data;
- char title[PATH_MAX];
- snprintf(title, sizeof(title), "Updating. Don't turn off your device");
-
- Evas_Object *popup = elm_popup_add(nf);
- elm_object_style_set(popup, "transparent");
- elm_popup_align_set(popup, ELM_NOTIFY_ALIGN_FILL, 0.5);
- evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
- elm_object_part_text_set(popup, "title,text", title);
-
- eext_object_event_callback_add(popup, EEXT_CALLBACK_BACK, _popup_hide_cb, NULL);
- evas_object_smart_callback_add(popup, "dismissed", _popup_hide_finished_cb, NULL);
- evas_object_smart_callback_add(popup, "block,clicked", _popup_block_clicked_cb, NULL);
- evas_object_show(popup);
-
Evas_Object *prev_popup = evas_object_data_get(obj, "install-popup");
if (prev_popup) {
evas_object_del(prev_popup);
LOGI("Start Update");
/* Install update-image downloaded at shared location on device */
int ret = update_control_initialize();
+
if(ret != UPDATE_CONTROL_ERROR_NONE) {
LOGE("update_control_initialize API Failed, error : %d", ret);
- fota_show_result_popup(nf, FOTA_OPERATION_INSTALL, FALSE, ret);
+ fota_show_result_popup(nf, FALSE, ret);
}
+ LOGI("Update control Initialized");
ret = update_control_do_update();
if(ret != UPDATE_CONTROL_ERROR_NONE) {
LOGE("update_control_do_update API Failed, error : %d", ret);
- fota_show_result_popup(nf, FOTA_OPERATION_INSTALL, FALSE, ret);
+ fota_show_result_popup(nf, FALSE, ret);
}
+ createUpdateStatusFile();
+ LOGI("Update control Do Update Complete");
ret = update_control_deinitialize();
if(ret != UPDATE_CONTROL_ERROR_NONE) {
LOGE("update_control_deinitialize API Failed, error : %d", ret);
- fota_show_result_popup(nf, FOTA_OPERATION_INSTALL, FALSE, ret);
- }
-}
-
-static void
-_send_notification_download_image_cb(void *data, Evas_Object *obj, void *event_info)
-{
- LOGI("Inside _send_notification_download_image_cb");
- Evas_Object *popup = data;
-
- notification_h notify = notification_create(NOTIFICATION_TYPE_ONGOING);
- if (!notify) {
- LOGE("notification_create(NOTIFICATION_TYPE_ONGOING) failed.");
- return;
- }
-
- notification_set_text(notify, NOTIFICATION_TEXT_TYPE_TITLE, "SoftwareUpdate", NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
- notification_set_text(notify, NOTIFICATION_TEXT_TYPE_CONTENT, "Software update is available. Click to update", NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
-
- notification_set_layout(notify, NOTIFICATION_LY_ONGOING_EVENT);
- notification_set_tag(notify, LOG_TAG);
-
- LOGI("Image path in _send_notification_download_image_cb = %s",path);
- /* Relaunch App to download update-image when user clicks notification */
- notification_launch_cb(notify, FOTA_MODE_DOWNLOAD, path, PACKAGE);
-
- notification_post(notify);
-
- elm_popup_dismiss(popup);
- ui_app_exit();
-}
-
-static void
-_download_image_cb(void *data, Evas_Object *obj, void *event_info)
-{
- LOGI("Inside _download_image_cb");
- Evas_Object *nf = data;
- Evas_Object *prev_popup = evas_object_data_get(obj, "download-popup");
-
- /* Copy update-image from attached USB to shared location on device */
- LOGI("Download Command = %s", cmd_dwnload);
- int ret = system(cmd_dwnload);
- LOGI("System command return : %d", ret);
-
- if (ret == -1 || WEXITSTATUS(ret) != 0) {
- fota_show_result_popup(nf, FOTA_OPERATION_DOWNLOAD, FALSE, ret);
- } else {
- fota_show_install_popup(nf, UPDATE_TITLE, cmd_dwnload);
- }
- if (prev_popup) {
- evas_object_del(prev_popup);
- }
- elm_popup_dismiss(nf);
-}
-
-void fota_show_install_popup(Evas_Object *nf, char *title, char* cmd)
-{
- char buf[PATH_MAX] = {0};
- snprintf(cmd_version, PATH_MAX, "%s", cmd);
- snprintf(cmd_dwnload, PATH_MAX, "%s", cmd);
-
- char *version = fota_get_update_image_version();
- if(!version)
- {
- LOGE("Invalid update image version : %s", version);
- fota_show_result_popup(nf, FOTA_OPERATION_INSTALL, FALSE, FALSE);
- } else {
- snprintf(buf, sizeof(buf), "Software Updates ready to install<br>-Version: %s", version);
- free(version);
- LOGI("Inside fota_show_install_popup");
-
- Evas_Object *popup = elm_popup_add(nf);
- elm_object_style_set(popup, "transparent");
- elm_popup_align_set(popup, ELM_NOTIFY_ALIGN_FILL, 0.5);
- evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
- elm_object_part_text_set(popup, "title,text", title);
- elm_object_text_set(popup,buf);
-
- eext_object_event_callback_add(popup, EEXT_CALLBACK_BACK, _popup_hide_cb, NULL);
- evas_object_smart_callback_add(popup, "dismissed", _popup_hide_finished_cb, NULL);
- evas_object_smart_callback_add(popup, "block,clicked", _popup_block_clicked_cb, NULL);
-
- /* Not Now button */
- Evas_Object *btn1 = elm_button_add(popup);
- elm_object_style_set(btn1, "border");
- elm_object_text_set(btn1, "Not Now");
- elm_object_part_content_set(popup, "button1", btn1);
- evas_object_smart_callback_add(btn1, "clicked", _send_notification_install_update_cb, popup);
-
- /* Install button */
- Evas_Object *btn2 = elm_button_add(popup);
- elm_object_text_set(btn2, "Install");
- elm_object_part_content_set(popup, "button2", btn2);
- evas_object_data_set(btn2, "install-popup", popup);
- evas_object_smart_callback_add(btn2, "clicked", _install_update_cb, nf);
- evas_object_show(popup);
+ fota_show_result_popup(nf, FALSE, ret);
}
+ LOGI("Update control Deinitialize Done");
}
-void fota_show_download_popup(Evas_Object *nf, char *title, char* cmd)
+void fota_show_install_popup(Evas_Object *nf)
{
+ LOGI("Inside fota_show_install_popup %s", _("IDS_SOFTWARE_UPDATE_TITLE"));
char buf[PATH_MAX] = {0};
- snprintf(cmd_version, PATH_MAX, "%s", cmd);
- snprintf(cmd_dwnload, PATH_MAX, "%s", cmd);
-
- char *version = fota_get_update_image_version();
- if(!version)
- {
- LOGE("Invalid update image version : %s", version);
-
- /* Need to check if show popup for wrong image path */
- fota_show_result_popup(nf, FOTA_OPERATION_DOWNLOAD, FALSE, FALSE);
- } else {
- snprintf(buf, sizeof(buf), "Updated software is now available<br>-Version: %s", version);
- free(version);
- LOGI("Inside fota_show_download_popup");
-
- Evas_Object *popup = elm_popup_add(nf);
- elm_object_style_set(popup, "transparent");
- elm_popup_align_set(popup, ELM_NOTIFY_ALIGN_FILL, 0.5);
- evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
- elm_object_part_text_set(popup, "title,text", title);
- elm_object_text_set(popup,buf);
+ snprintf(buf, sizeof(buf), "%s", _("IDS_SOFTWARE_UPDATE_TEXT"));
- eext_object_event_callback_add(popup, EEXT_CALLBACK_BACK, _popup_hide_cb, NULL);
- evas_object_smart_callback_add(popup, "dismissed", _popup_hide_finished_cb, NULL);
- evas_object_smart_callback_add(popup, "block,clicked", _popup_block_clicked_cb, NULL);
-
- /* Not Now button */
- Evas_Object *btn1 = elm_button_add(popup);
- elm_object_style_set(btn1, "border");
- elm_object_text_set(btn1, "Not Now");
- elm_object_part_content_set(popup, "button1", btn1);
- evas_object_smart_callback_add(btn1, "clicked", _send_notification_download_image_cb, popup);
+ Evas_Object *popup = elm_popup_add(nf);
+ elm_object_style_set(popup, "transparent");
+ elm_popup_align_set(popup, ELM_NOTIFY_ALIGN_FILL, 0.5);
+ evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_object_part_text_set(popup, "title,text", _("IDS_SOFTWARE_UPDATE_TITLE"));
+ elm_object_text_set(popup,buf);
- /* Download button */
- Evas_Object *btn2 = elm_button_add(popup);
- //elm_object_style_set(btn2, "popup");
- elm_object_text_set(btn2, "Download");
- elm_object_part_content_set(popup, "button2", btn2);
- evas_object_data_set(btn2, "download-popup", popup);
- evas_object_smart_callback_add(btn2, "clicked", _download_image_cb, nf);
+ eext_object_event_callback_add(popup, EEXT_CALLBACK_BACK, _popup_hide_cb, NULL);
+ evas_object_smart_callback_add(popup, "dismissed", _popup_hide_finished_cb, NULL);
+ evas_object_smart_callback_add(popup, "block,clicked", _popup_block_clicked_cb, NULL);
- evas_object_show(popup);
- }
+ /* Not Now button */
+ Evas_Object *btn1 = elm_button_add(popup);
+ elm_object_style_set(btn1, "border");
+ elm_object_text_set(btn1, _("IDS_SOFTWARE_NOT_NOW_BUTTON"));
+ elm_object_part_content_set(popup, "button1", btn1);
+ evas_object_smart_callback_add(btn1, "clicked", _send_notification_install_update_cb, popup);
+
+ /* Now button */
+ Evas_Object *btn2 = elm_button_add(popup);
+ elm_object_text_set(btn2, _("IDS_SOFTWARE_NOW_BUTTON"));
+ elm_object_part_content_set(popup, "button2", btn2);
+ evas_object_data_set(btn2, "install-popup", popup);
+ evas_object_smart_callback_add(btn2, "clicked", _install_update_cb, nf);
+ evas_object_show(popup);
}
--- /dev/null
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * 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 "firmware-update-ui.h"
+
+int read_attempts()
+{
+ char attempt_file_path[FILENAME_MAX];
+ char buffer[FILENAME_MAX];
+ int attempt = 0, flag = 0;
+ char *attempt_char = NULL;
+
+ char *data_path = app_get_data_path();
+ snprintf(attempt_file_path, sizeof(attempt_file_path), "%sattempt.txt",data_path);
+ LOGI("Attempt File path = %s",attempt_file_path);
+ if(data_path)
+ free(data_path);
+
+ FILE *fp = fopen (attempt_file_path, "r");
+ if(!fp)
+ {
+ LOGI("Creating Attempt Count file");
+ fp = fopen (attempt_file_path, "w");
+ fprintf(fp, "attempt=%d\n", ++attempt);
+ fclose(fp);
+ }
+ else
+ {
+ while(fgets(buffer, sizeof(buffer), fp)) {
+
+ char* token = strtok(&buffer, "=");
+ while (token)
+ {
+ if (strstr(token, "attempt")) {
+ token = strtok(NULL, " ");
+ attempt_char = strdup(token);
+ flag = 1;
+ break;
+ }
+ }
+ if(flag)
+ break;
+ }
+ fclose(fp);
+
+ attempt = atoi(attempt_char);
+ if(attempt_char)
+ free(attempt_char);
+
+ if(!attempt) /* Software Update attempt after last Success update */
+ write_attempts(++attempt);
+ }
+
+ LOGI("Current Attempt = %d", attempt);
+ return attempt;
+}
+
+void write_attempts(int attempts)
+{
+ LOGI("Increment Attempt = %d", attempts);
+ char attempt_file_path[FILENAME_MAX];
+
+ char *data_path = app_get_data_path();
+ snprintf(attempt_file_path, sizeof(attempt_file_path), "%sattempt.txt",data_path);
+ if(data_path)
+ free(data_path);
+
+ FILE *fp = fopen (attempt_file_path, "w");
+ fprintf(fp, "attempt=%d\n", attempts);
+ fclose(fp);
+}
+
+void createUpdateStatusFile()
+{
+ char updatestatus_file_path[FILENAME_MAX];
+ char *data_path = app_get_data_path();
+ snprintf(updatestatus_file_path, sizeof(updatestatus_file_path), "%supdatestart.txt",data_path);
+ FILE *fp = fopen (updatestatus_file_path, "r");
+ if(!fp)
+ {
+ LOGI("[Upgrade Status] Creating update Status file");
+ fp = fopen (updatestatus_file_path, "w");
+ fclose(fp);
+ }
+ LOGI("[Upgrade Status] update Status file must be created");
+}
+
+bool updateStatusFileExists()
+{
+ char updatestatus_file_path[FILENAME_MAX];
+ char *data_path = app_get_data_path();
+ snprintf(updatestatus_file_path, sizeof(updatestatus_file_path), "%supdatestart.txt",data_path);
+ FILE *fp = fopen (updatestatus_file_path, "r");
+ if(!fp)
+ {
+ LOGI("[Upgrade Status] File Not Found Upgrade process was not initiated.");
+ return false;
+ }
+ else
+ {
+ LOGI("[Upgrade Status] File Found Upgarde process was initiated");
+ fclose(fp);
+ return true;
+ }
+}
+
+void removeUpdateStatusFile()
+{
+ char updatestatus_file_path[FILENAME_MAX];
+ char *data_path = app_get_data_path();
+ snprintf(updatestatus_file_path, sizeof(updatestatus_file_path), "%supdatestart.txt",data_path);
+ remove (updatestatus_file_path);
+ LOGI("[Upgrade Status] File removed successfully");
+}
+void launch_update_at_regular_interval()
+{
+ LOGI("Inside Launch update App at regular interval");
+ int ret;
+ int alarm_id;
+
+ app_control_h app_control = NULL;
+ ret = app_control_create(&app_control);
+ if (ret != APP_CONTROL_ERROR_NONE) {
+ LOGI("app_control_create API failed. Err = %d", ret);
+ return;
+ }
+ app_control_set_operation(app_control, APP_CONTROL_OPERATION_DEFAULT);
+ app_control_set_app_id(app_control, PACKAGE);
+
+ int reg_interval = read_json_attribute(REG_INTERVAL);
+ struct tm date;
+ alarm_get_current_time(&date);
+ date.tm_min += reg_interval;
+ ret = alarm_schedule_once_at_date(app_control, &date, &alarm_id);
+ if (ret != APP_CONTROL_ERROR_NONE) {
+ LOGI("alarm_schedule_once_at_date API failed. Err = %d", ret);
+ return;
+ }
+}
+
+int read_json_attribute(const char *attribute)
+{
+ char json_file_path[FILENAME_MAX];
+ GError *error = NULL;
+ int value;
+
+ char *res_path = app_get_resource_path();
+ snprintf(json_file_path, sizeof(json_file_path), "%sconfig.json",res_path);
+ LOGI("Json File path = %s",json_file_path);
+ if(res_path)
+ free(res_path);
+
+ JsonParser *parser = json_parser_new();
+ json_parser_load_from_file (parser, json_file_path, &error);
+ if (error)
+ {
+ LOGE("Unable to parse `%s': %s\n", json_file_path, error->message);
+ g_error_free (error);
+ g_object_unref (parser);
+ return 0;
+ }
+
+ JsonNode *root = json_parser_get_root(parser);
+ JsonObject *pObject = json_node_get_object(root);
+
+ value = json_object_get_int_member(pObject, attribute);
+ LOGE("Value of %s = %d", attribute, value);
+ g_object_unref (parser);
+
+ return value;
+}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<manifest xmlns="http://tizen.org/ns/packages" api-version="5.5" package="org.tizen.firmware-update-ui" version="1.0.0">
<profile name="tizeniot"/>
- <ui-application appid="org.tizen.firmware-update-ui" exec="firmware-update-ui" launch_mode="single" multiple="false" nodisplay="false" taskmanage="false" type="capp">
+ <ui-application appid="org.tizen.firmware-update-ui" exec="firmware-update-ui" launch_mode="single" multiple="false" nodisplay="false" taskmanage="false" type="capp" on-boot="true">
<label>firmware-update-ui</label>
<metadata key="tizen-fota-manager" value="client"/>
</ui-application>
<privilege>http://tizen.org/privilege/updatecontrol.admin</privilege>
<privilege>http://tizen.org/privilege/notification</privilege>
<privilege>http://tizen.org/privilege/datasharing</privilege>
+ <privilege>http://tizen.org/privilege/internet</privilege>
<privilege>http://tizen.org/privilege/externalstorage.appdata</privilege>
+ <privilege>http://tizen.org/privilege/mediastorage</privilege>
<privilege>http://tizen.org/privilege/externalstorage</privilege>
+ <privilege>http://tizen.org/privilege/message.read</privilege>
+ <privilege>http://tizen.org/privilege/alarm.get</privilege>
+ <privilege>http://tizen.org/privilege/alarm.set</privilege>
+ <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
+ <privilege>http://tizen.org/privilege/download</privilege>
+ <privilege>http://tizen.org/privilege/network.get</privilege>
+ <privilege>http://tizen.org/privilege/peripheralio</privilege>
</privileges>
</manifest>