#include "common/pkgmgr_signal.h"
+#include <manifest_parser/utils/logging.h>
+
+#include <aul.h>
+#include <bundle_cpp.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <systemd/sd-login.h>
+#include <tzplatform_config.h>
+
#include <cassert>
#include <map>
+#include <vector>
-#include "common/utils/logging.h"
-
-// Redefine this value as it is not exported by pkgmgr
-// this should probably be in public interface because of
-// otherwise there is no way to return errorcode
-#define PKGMGR_INSTALLER_ERROR_KEY_STR "error"
+#include "common/utils/pkgmgr_query.h"
namespace {
-namespace ci=common_installer;
+namespace ci = common_installer;
-const std::map<ci::RequestType,const char *> kEventStr = {
+const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
+const std::map<ci::RequestType, const char*> kEventStr = {
{ci::RequestType::Install, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
- {ci::RequestType::Recovery, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
- {ci::RequestType::Reinstall, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
+ {ci::RequestType::Recovery, PKGMGR_INSTALLER_UNINSTALL_EVENT_STR},
+ {ci::RequestType::RecoveryUpdate, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
+ {ci::RequestType::Reinstall, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
{ci::RequestType::Uninstall, PKGMGR_INSTALLER_UNINSTALL_EVENT_STR},
- {ci::RequestType::Unknown, PKGMGR_INSTALLER_INSTALL_EVENT_STR}, //not needed
- {ci::RequestType::Update, PKGMGR_INSTALLER_UPGRADE_EVENT_STR}
+ {ci::RequestType::PartialUninstall, PKGMGR_INSTALLER_UNINSTALL_EVENT_STR},
+ {ci::RequestType::Update, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
+ {ci::RequestType::ReadonlyUpdateInstall, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
+ {ci::RequestType::ReadonlyUpdateUninstall,
+ PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
+ {ci::RequestType::Delta, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
+ {ci::RequestType::Move, PKGMGR_INSTALLER_MOVE_EVENT_STR},
+ {ci::RequestType::MountInstall, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
+ {ci::RequestType::MountUpdate, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
+ {ci::RequestType::ManifestDirectInstall, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
+ {ci::RequestType::ManifestDirectUpdate, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
+ {ci::RequestType::ManifestPartialInstall, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
+ {ci::RequestType::ManifestPartialUpdate, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
+ {ci::RequestType::DisablePkg, PKGMGR_INSTALLER_UNINSTALL_EVENT_STR},
+ {ci::RequestType::EnablePkg, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
+ {ci::RequestType::MigrateExtImg, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
+ {ci::RequestType::Unknown, PKGMGR_INSTALLER_UNKNOWN_EVENT_STR}
};
} // namespace
namespace common_installer {
-PkgmgrSignal::State PkgmgrSignal::state_ = PkgmgrSignal::State::NOT_SENT;
-PkgmgrSignal::PkgmgrSignal(pkgmgr_installer* pi, RequestType req_type)
- : pi_(pi), request_type_(req_type) {
+PkgmgrSignal::PkgmgrSignal(pkgmgr_installer* pi)
+ : pi_(pi), state_(State::NOT_SENT), request_type_(RequestType::Unknown),
+ error_message_sent_(false), is_upgrade_(false) {
+ uid_ = pkgmgr_installer_get_uid(pi_);
+ request_mode_ = GetRequestMode(uid_);
}
bool PkgmgrSignal::SendStarted(
const std::string& type, const std::string& pkgid) {
- if (state_ != State::NOT_SENT) {
+ if (state_ != State::NOT_SENT)
return false;
- }
+
+ if (!SetupUserList(pkgid))
+ LOG(WARNING) << "Failed to setup user list";
auto key = kEventStr.find(request_type_);
- if (!SendSignal(PKGMGR_INSTALLER_START_KEY_STR, key->second, type, pkgid)) {
+ if (key == kEventStr.end())
return false;
+
+ if (strcmp(key->second, PKGMGR_INSTALLER_UPGRADE_EVENT_STR) == 0)
+ is_upgrade_ = true;
+
+ pkgmgr_installer_set_is_upgrade(pi_, is_upgrade_ ? 1 : 0);
+
+ if (!SendSignal(PKGMGR_INSTALLER_START_KEY_STR, key->second, type, pkgid))
+ return false;
+
+ for (auto l : user_list_) {
+ key = kEventStr.find(l.second);
+ if (key == kEventStr.end())
+ continue;
+ SendSignal(l.first, PKGMGR_INSTALLER_START_KEY_STR, key->second, type,
+ pkgid);
}
+
state_ = State::STARTED;
+
+ // workaround for pkgmgr client to know all appids which are uninstalled
+ if (request_type_ == ci::RequestType::Uninstall) {
+ if (!SendAppids(type, pkgid))
+ return false;
+ for (auto l : user_list_)
+ SendAppids(l.first, type, pkgid);
+ }
+
return true;
}
bool PkgmgrSignal::SendProgress(int progress,
const std::string& type, const std::string& pkgid) {
- if (state_ != State::STARTED) {
+ if (state_ != State::STARTED)
+ return false;
+
+ if (!SendSignal(PKGMGR_INSTALLER_INSTALL_PERCENT_KEY_STR,
+ std::to_string(progress).c_str(), type, pkgid))
return false;
+ for (auto l : user_list_) {
+ // ignore error case
+ SendSignal(l.first, PKGMGR_INSTALLER_INSTALL_PERCENT_KEY_STR,
+ std::to_string(progress).c_str(), type, pkgid);
}
- return SendSignal(PKGMGR_INSTALLER_INSTALL_PERCENT_KEY_STR,
- std::to_string(progress).c_str(), type, pkgid);
+ return true;
}
bool PkgmgrSignal::SendFinished(
Step::Status result, const std::string& type, const std::string& pkgid) {
- if (state_ != State::STARTED) {
+ if (state_ != State::STARTED)
return false;
- }
- if (result != Step::Status::OK) {
+
+ pkgmgr_installer_set_is_upgrade(pi_, is_upgrade_ ? 1 : 0);
+
+ if (result != Step::Status::OK && !error_message_sent_) {
if (!SendSignal(
PKGMGR_INSTALLER_ERROR_KEY_STR,
- std::to_string(static_cast<int>(result)).c_str(), type, pkgid)) {
+ std::to_string(static_cast<int>(result)).c_str(), type, pkgid))
return false;
- }
+
+ for (auto l : user_list_)
+ SendSignal(l.first,
+ PKGMGR_INSTALLER_ERROR_KEY_STR,
+ std::to_string(static_cast<int>(result)).c_str(), type, pkgid);
}
+
if (!SendSignal(
- PKGMGR_INSTALLER_END_KEY_STR, GetResultKey(result), type, pkgid)) {
+ PKGMGR_INSTALLER_END_KEY_STR, GetResultKey(result), type, pkgid))
return false;
- }
+
+ for (auto l : user_list_)
+ SendSignal(l.first,
+ PKGMGR_INSTALLER_END_KEY_STR, GetResultKey(result), type, pkgid);
+
state_ = State::FINISHED;
return true;
}
+bool PkgmgrSignal::SendError(
+ Step::Status result,
+ const std::string& error_message,
+ const std::string& type,
+ const std::string& pkgid) {
+ if (state_ != State::STARTED)
+ return false;
+
+ pkgmgr_installer_set_is_upgrade(pi_, is_upgrade_ ? 1 : 0);
+
+ std::string error_value = std::to_string(static_cast<int>(result));
+ if (!error_message.empty())
+ error_value = error_value + ":" + error_message;
+
+ LOG(ERROR) << "PkgmgrSignal error_value: (" << error_value << ")";
+ error_message_sent_ = true;
+ if (!SendSignal(
+ PKGMGR_INSTALLER_ERROR_KEY_STR,
+ error_value.c_str(),
+ type,
+ pkgid))
+ return false;
+ for (auto l : user_list_)
+ SendSignal(l.first,
+ PKGMGR_INSTALLER_ERROR_KEY_STR,
+ error_value.c_str(),
+ type,
+ pkgid);
+ return true;
+}
+
+void PkgmgrSignal::SetRequestType(RequestType req_type) {
+ request_type_ = req_type;
+}
+
bool PkgmgrSignal::SendSignal(
const char* key,
const char* value,
const std::string& type,
const std::string& pkgid) const {
+
+ uid_t uid = pkgmgr_installer_get_uid(pi_);
+ tizen_base::Bundle b({
+ { AUL_K_PKGID, pkgid },
+ { AUL_K_PACKAGETYPE, type },
+ { AUL_K_PKG_EVENT_NAME, key },
+ { AUL_K_PKG_EVENT_RESULT, value }
+ });
+
+ int ret = aul_package_pre_event_send(uid, b.GetHandle());
+ if (ret != 0)
+ LOG(ERROR) << "aul_package_pre_event_send() is failed";
+
// send pkgmgr signal
if (pkgmgr_installer_send_signal(
pi_,
return true;
}
+bool PkgmgrSignal::SendSignal(
+ uid_t uid,
+ const char* key,
+ const char* value,
+ const std::string& type,
+ const std::string& pkgid) const {
+
+ tizen_base::Bundle b({
+ { AUL_K_PKGID, pkgid },
+ { AUL_K_PACKAGETYPE, type},
+ { AUL_K_PKG_EVENT_NAME, key},
+ { AUL_K_PKG_EVENT_RESULT, value}
+ });
+
+ int ret = aul_package_pre_event_send(uid, b.GetHandle());
+ if (ret != 0)
+ LOG(ERROR) << "aul_package_pre_event_send() is failed";
+
+ // send pkgmgr signal
+ if (pkgmgr_installer_send_signal_for_uid(
+ pi_,
+ uid,
+ !type.empty() ? type.c_str(): "",
+ !pkgid.empty() ? pkgid.c_str() : "",
+ key,
+ value)) {
+ LOG(ERROR) << "Fail to send pkgmgr signal";
+ return false;
+ }
+
+ LOG(DEBUG) << "Success to send pkgmgr signal"
+ << " USER=" << uid
+ << " PKGID=" << pkgid
+ << " KEY=" << key
+ << " VALUE=" << value;
+ return true;
+}
+
const char* PkgmgrSignal::GetResultKey(Step::Status result) const {
switch (result) {
case Step::Status::OK:
}
}
+bool PkgmgrSignal::SendAppids(const std::string& type,
+ const std::string& pkgid) const {
+ std::vector<std::string> appids;
+ ci::PkgQueryInterface pkg_query(pkgid, pkgmgr_installer_get_uid(pi_));
+ if (!pkg_query.AppidsForPkgId(&appids))
+ return true;
+ for (auto& appid : appids) {
+ if (pkgmgr_installer_send_app_uninstall_signal(pi_, type.c_str(),
+ pkgid.c_str(),
+ appid.c_str()))
+ return false;
+ }
+ return true;
+}
+
+bool PkgmgrSignal::SendAppids(uid_t uid,
+ const std::string& type,
+ const std::string& pkgid) const {
+ std::vector<std::string> appids;
+ ci::PkgQueryInterface pkg_query(pkgid, pkgmgr_installer_get_uid(pi_));
+ if (!pkg_query.AppidsForPkgId(&appids))
+ return true;
+ for (auto& appid : appids) {
+ if (pkgmgr_installer_send_app_uninstall_signal_for_uid(
+ pi_, uid, type.c_str(), pkgid.c_str(), appid.c_str()))
+ return false;
+ }
+ return true;
+}
+
+bool PkgmgrSignal::SetupUserList(const std::string& pkgid) {
+ uid_t* uids = nullptr;
+ int n = sd_get_uids(&uids);
+
+ if (n < 0)
+ return false;
+ ci::PkgQueryInterface pkg_query_for_global(pkgid, kGlobalUserUid);
+ for (int i = 0; i < n; i++) {
+ ci::PkgQueryInterface pkg_query(pkgid, uids[i]);
+ switch (request_mode_) {
+ case RequestMode::GLOBAL:
+ // if user pkg is installed, installer will not send signal to user.
+ if (pkg_query.IsPackageInstalled(ci::RequestMode::USER))
+ continue;
+ else
+ user_list_.emplace_back(uids[i], request_type_);
+ break;
+ case RequestMode::USER:
+ if (uid_ != uids[i])
+ continue;
+ user_list_.emplace_back(uids[i], request_type_);
+ break;
+ default:
+ user_list_.emplace_back(uids[i], request_type_);
+ break;
+ }
+ }
+
+ if (uids)
+ free(uids);
+
+ return true;
+}
+
} // namespace common_installer