Merge branch 'tizen_4.0' into tizen_5.0 36/219536/3
authorPiotr Kosko/Native/Web API (PLT) /SRPOL/Engineer/Samsung Electronics <p.kosko@samsung.com>
Thu, 5 Dec 2019 14:18:12 +0000 (15:18 +0100)
committerPiotr Kosko/Native/Web API (PLT) /SRPOL/Engineer/Samsung Electronics <p.kosko@samsung.com>
Thu, 5 Dec 2019 14:53:10 +0000 (15:53 +0100)
Change-Id: I6272ee91b469df02a70c0ddea192ef9cc46b0123

1  2 
packaging/webapi-plugins.spec
src/application/application_manager.cc
src/application/application_utils.cc
src/common/platform_enum.h
src/mediacontroller/mediacontroller_client.cc
src/mediacontroller/mediacontroller_client.h
src/mediacontroller/mediacontroller_instance.cc
src/mediacontroller/mediacontroller_server.cc
src/mediacontroller/mediacontroller_types.cc
src/mediacontroller/mediacontroller_types.h

@@@ -8,7 -8,7 +8,7 @@@
  %define crosswalk_extensions_path %{_libdir}/%{crosswalk_extensions}
  
  Name:       webapi-plugins
- Version:    2.43
 -Version:    2.39
++Version:    2.44
  Release:    0
  License:    Apache-2.0 and BSD-3-Clause and MIT
  Group:      Development/Libraries
@@@ -480,182 -534,111 +480,183 @@@ void ApplicationManager::LaunchAppContr
          return;
        }
  
 -      int ret = app_control_set_launch_mode(app_control_ptr.get(), launch_mode);
 -      if (APP_CONTROL_ERROR_NONE != ret) {
 -        LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Setting launch mode failed."),
 -                          &response->get<picojson::object>(),
 -                          ("Setting launch mode failed: %d (%s)", ret, get_error_message(ret)));
 -        return;
 +      picojson::value return_value = picojson::value(picojson::object());
 +      picojson::object& return_value_obj = return_value.get<picojson::object>();
 +      return_value_obj.insert(
 +          std::make_pair(kListenerId, picojson::value(callback_data->reply_callback_id)));
 +
 +      if (APP_CONTROL_RESULT_SUCCEEDED == result) {
 +        LoggerD("App started");
 +        return_value_obj.insert(std::make_pair("data", picojson::value(picojson::array())));
 +        if (!ApplicationUtils::ServiceToApplicationControlDataArray(
 +                reply, &return_value_obj.find("data")->second.get<picojson::array>())) {
 +          return_value_obj.erase("data");
 +        }
 +        ReportSuccess(return_value_obj);
 +      } else {
 +        ReportError(return_value_obj);
        }
 -    }
  
 -    app_control_reply_cb callback = nullptr;
 -    struct ReplayCallbackData {
 -      ApplicationInstance* app_instance;
 -      std::string reply_callback;
 +      Instance::PostMessage(callback_data->instance, return_value.serialize().c_str());
 +      delete callback_data;
      };
 +  }
  
 -    ReplayCallbackData* user_data = nullptr;
 -
 -    if (!reply_callback.empty()) {
 -      user_data = new ReplayCallbackData();
 -      user_data->app_instance = &this->instance_;
 -      user_data->reply_callback = reply_callback;
 -
 -      callback = [](app_control_h request, app_control_h reply, app_control_result_e result,
 -                    void* user_data) {
 -        LoggerD("send_launch_request callback");
 -
 -        picojson::value return_value = picojson::value(picojson::object());
 -        picojson::object& return_value_obj = return_value.get<picojson::object>();
 -        ReplayCallbackData* reply_callback = static_cast<ReplayCallbackData*>(user_data);
 -
 -        if (APP_CONTROL_RESULT_SUCCEEDED == result) {
 -          const std::string data = "data";
 -          return_value_obj.insert(std::make_pair(data, picojson::value(picojson::array())));
 -          if (!ApplicationUtils::ServiceToApplicationControlDataArray(
 -                  reply, &return_value_obj.find(data)->second.get<picojson::array>())) {
 -            return_value_obj.erase(data);
 -          }
 -          ReportSuccess(return_value_obj);
 -        } else {
 -          ReportError(return_value_obj);
 -        }
 +  app_control_result_cb result_callback = [](app_control_h launch_request,
 +                                             app_control_error_e launch_result, void* user_data) {
 +    ScopeLogger("LaunchAppControl result_callback");
  
 -        return_value_obj.insert(
 -            std::make_pair("listenerId", picojson::value(reply_callback->reply_callback)));
 -        Instance::PostMessage(reply_callback->app_instance, return_value.serialize().c_str());
 -        delete reply_callback;
 -      };
 +    LaunchAppControlCallbackData* callback_data =
 +        static_cast<LaunchAppControlCallbackData*>(user_data);
 +
 +    auto result = ApplicationUtils::TranslateAppControlError(launch_result);
 +
 +    if (result.IsError()) {
 +      LogAndReportError(result, &(callback_data->response->get<picojson::object>()));
 +    } else {
 +      ReportSuccess(callback_data->response->get<picojson::object>());
      }
  
 -    const int retry_count = 3;
 +    Instance::PostMessage(callback_data->instance, callback_data->response->serialize().c_str());
  
 -    int retry = 0;
 -    int ret = 0;
 +    if (result.IsError() || (callback_data->reply_callback_id).empty()) {
 +      delete callback_data;
 +    }
 +  };
  
 -    while (retry < retry_count) {
 -      LoggerD("Calling launch request. Attempt number: %d", retry);
 +  /*
 +   * TODO: Observe how often app_control_send_launch_request_async tries to launch the application.
 +   * Previous implementation, using synchronous app_control_send_launch_request,
 +   * tries to launch the application 3 times, before reporting an error.
 +   * New implementation, using app_control_send_launch_request_async makes only one attempt.
 +   * If problems, such as failed application start occur, multiple attempts may solve the problem.
 +   */
-   auto launch_result =
-       ApplicationUtils::TranslateAppControlError(static_cast<app_control_error_e>(app_control_send_launch_request_async(
++  auto launch_result = ApplicationUtils::TranslateAppControlError(
++      static_cast<app_control_error_e>(app_control_send_launch_request_async(
 +          app_control_ptr.get(), result_callback, reply_callback, launch_app_user_data)));
 +
 +  if (launch_result.IsError()) {
 +    delete launch_app_user_data;
 +    AsyncResponse(launch_result, &response);
 +  } else {
 +    LoggerD("App launched");
 +  }
 +}
  
 -      ret = app_control_send_launch_request(app_control_ptr.get(), callback, user_data);
 -      LoggerD("App control launch request returned: %d, %s", ret, get_error_message(ret));
 -      if (APP_CONTROL_ERROR_NONE == ret) {
 -        break;
 -      }
 +namespace {
  
 -      // delay 300ms for each retry
 -      struct timespec sleep_time = {0, 300L * 1000L * 1000L};
 -      nanosleep(&sleep_time, nullptr);
 -      ++retry;
 -    }
 +PlatformResult TranslateLaunchError(app_control_error_e return_code) {
 +  ScopeLogger();
 +
 +  auto result = ApplicationUtils::TranslateAppControlError(return_code);
 +  if (ErrorCode::SECURITY_ERR == result.error_code()) {
 +    result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error.");
 +  }
 +
 +  return result;
 +}
 +
 +PlatformResult PrepareAppControlForLaunch(const picojson::value& args, app_control_h* app_control) {
 +  ScopeLogger();
 +
 +  const auto& app_id = args.get("id");
 +  if (!app_id.is<std::string>()) {
 +    return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
 +  }
 +  const auto app_id_str = app_id.get<std::string>();
 +
 +  app_control_h tmp_app_control = nullptr;
 +  int result = app_control_create(&tmp_app_control);
 +  if (APP_CONTROL_ERROR_NONE != result) {
 +    LoggerD("app_control_create() failed: %d (%s)", result, get_error_message(result));
 +    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred.");
 +  }
 +
 +  std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)>
 +      app_control_ptr(tmp_app_control, &app_control_destroy);
 +
 +  if (!app_id_str.empty()) {
 +    LoggerD("app_id: %s", app_id_str.c_str());
 +
 +    int ret = app_control_set_app_id(app_control_ptr.get(), app_id_str.c_str());
  
      if (APP_CONTROL_ERROR_NONE != ret) {
 -      delete user_data;
 -
 -      switch (ret) {
 -        case APP_CONTROL_ERROR_INVALID_PARAMETER:
 -          LogAndReportError(
 -              PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter returned."),
 -              &response->get<picojson::object>(),
 -              ("app_control_send_launch_request returns APP_CONTROL_ERROR_INVALID_PARAMETER"));
 -          return;
 -        case APP_CONTROL_ERROR_OUT_OF_MEMORY:
 -          LogAndReportError(
 -              PlatformResult(ErrorCode::UNKNOWN_ERR, "Out of memory."),
 -              &response->get<picojson::object>(),
 -              ("app_control_send_launch_request returns APP_CONTROL_ERROR_OUT_OF_MEMORY"));
 -          return;
 -        case APP_CONTROL_ERROR_LAUNCH_REJECTED:
 -        case APP_CONTROL_ERROR_APP_NOT_FOUND:
 -          LogAndReportError(
 -              PlatformResult(ErrorCode::NOT_FOUND_ERR, "No matched application found."),
 -              &response->get<picojson::object>(),
 -              ("app_control_send_launch_request returns APP_CONTROL_ERROR_APP_NOT_FOUND"));
 -          return;
 -        default:
 -          LogAndReportError(
 -              PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."),
 -              &response->get<picojson::object>(),
 -              ("app_control_send_launch_request returns: %d (%s)", ret, get_error_message(ret)));
 -          return;
 -      }
 +      LoggerE("Failed to set app id: %d (%s)", ret, get_error_message(ret));
 +      return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
      }
 -    ReportSuccess(response->get<picojson::object>());
 +  }
 +
 +  *app_control = app_control_ptr.release();
 +
 +  return PlatformResult(ErrorCode::NO_ERROR);
 +}
 +
 +}  // namespace
 +void ApplicationManager::Launch(const picojson::value& args) {
 +  ScopeLogger();
 +
 +  int callback_id = -1;
 +  const auto& callback = args.get(kCallbackId);
 +  if (callback.is<double>()) {
 +    callback_id = static_cast<int>(callback.get<double>());
 +  }
 +
 +  std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
 +  picojson::object& response_obj = response->get<picojson::object>();
 +  response_obj.insert(
 +      std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
 +
 +  app_control_h app_control = nullptr;
 +  auto prepare_app_control_result = PrepareAppControlForLaunch(args, &app_control);
 +  if (prepare_app_control_result.IsError()) {
 +    AsyncResponse(LogAndCreateResult(prepare_app_control_result), &response);
 +    return;
 +  }
 +
 +  std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)>
 +      app_control_ptr(app_control, &app_control_destroy);
 +
 +  struct LaunchCallbackData {
 +    ApplicationInstance* instance;
 +    std::shared_ptr<picojson::value> response;
 +  }* launch_user_data = new (std::nothrow) LaunchCallbackData{&this->instance_, response};
 +
 +  app_control_result_cb result_callback = [](app_control_h launch_request,
 +                                             app_control_error_e launch_result, void* user_data) {
 +    ScopeLogger("Launch result_callback");
 +
 +    LaunchCallbackData* callback_data = static_cast<LaunchCallbackData*>(user_data);
 +
 +    auto result = TranslateLaunchError(launch_result);
 +
 +    if (result.IsError()) {
 +      LogAndReportError(result, &(callback_data->response->get<picojson::object>()));
 +    } else {
 +      ReportSuccess(callback_data->response->get<picojson::object>());
 +    }
 +
 +    Instance::PostMessage(callback_data->instance, callback_data->response->serialize().c_str());
 +
 +    delete callback_data;
    };
  
 -  launch(response);
 -  Instance::PostMessage(&this->instance_, response->serialize().c_str());
 +  /*
 +   * TODO: Observe how often app_control_send_launch_request_async tries to launch the application.
 +   * Previous implementation, using synchronous app_control_send_launch_request,
 +   * tries to launch the application 3 times, before reporting an error.
 +   * New implementation, using app_control_send_launch_request_async makes only one attempt.
 +   * If problems, such as failed application start occur, multiple attempts may solve the problem.
 +   */
-   auto launch_result = TranslateLaunchError(static_cast<app_control_error_e>(app_control_send_launch_request_async(
-       app_control_ptr.get(), result_callback, nullptr, launch_user_data)));
++  auto launch_result =
++      TranslateLaunchError(static_cast<app_control_error_e>(app_control_send_launch_request_async(
++          app_control_ptr.get(), result_callback, nullptr, launch_user_data)));
 +
 +  if (launch_result.IsError()) {
 +    delete launch_user_data;
 +    AsyncResponse(launch_result, &response);
 +  } else {
 +    LoggerD("App launched");
 +  }
  }
  
  // internal impl of app_control_foreach_app_matched() for handling APP_CONTROL_ERROR_APP_NOT_FOUND
@@@ -383,37 -265,21 +383,38 @@@ PlatformResult ApplicationUtils::Applic
    const std::string& key = it_key->second.get<std::string>();
    const picojson::array& value = it_value->second.get<picojson::array>();
  
 -  const size_t size = value.size();
 -  const char** arr = new const char*[size];
 -  size_t i = 0;
 +  std::vector<const char*> value_data;
  
 -  for (auto iter = value.begin(); iter != value.end(); ++iter, ++i) {
 -    arr[i] = iter->get<std::string>().c_str();
 +  for (auto& v : value) {
 +    value_data.push_back(v.get<std::string>().c_str());
    }
  
 -  if (1 == size) {
 -    app_control_add_extra_data(app_control, key.c_str(), arr[0]);
 +  int result = APP_CONTROL_ERROR_NONE;
 +  /*
 +   * Native applications handle single extra data objects and arrays in a different ways,
 +   * hence they have to be packed with different native API functions.
 +   */
 +  if (1 == value_data.size()) {
 +    result = app_control_add_extra_data(app_control, key.c_str(), value_data[0]);
    } else {
-     result = app_control_add_extra_data_array(app_control, key.c_str(), value_data.data(), value_data.size());
 -    app_control_add_extra_data_array(app_control, key.c_str(), arr, size);
++    result = app_control_add_extra_data_array(app_control, key.c_str(), value_data.data(),
++                                              value_data.size());
 +  }
 +
 +  if (APP_CONTROL_ERROR_INVALID_PARAMETER == result) {
 +    if (0 == key.length()) {
 +      LoggerD("app_control_add_extra_data_array failed: zero-length key");
 +      return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
 +                            "Invalid AppControlData key: key length is 0.");
 +    }
 +    LoggerD("app_control_add_extra_data_array failed: invalid parameter passed");
 +    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
 +                          "Invalid AppControlData value, associated with key: " + key);
 +  } else if (APP_CONTROL_ERROR_KEY_REJECTED == result) {
 +    LoggerD("app_control_add_extra_data_array failed: key rejected");
 +    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid AppControlData's key: " + key);
    }
  
 -  delete[] arr;
    return PlatformResult(ErrorCode::NO_ERROR);
  }
  
index 6c62695,0000000..a7e22ca
mode 100644,000000..100644
--- /dev/null
@@@ -1,81 -1,0 +1,77 @@@
- #include <string>
 +/*
 + * Copyright (c) 2019 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.
 + */
 +
 +#ifndef COMMON_PLATFORM_ENUM_H_
 +#define COMMON_PLATFORM_ENUM_H_
 +
 +#include "platform_result.h"
 +
- #include <initializer_list>
++#include <initializer_list>
 +#include <map>
++#include <string>
 +#include <vector>
- template<typename NativeEnumType>
- class PlatformEnum
- {
- using MapType = std::map<std::string, NativeEnumType>;
- using RevMapType = std::map<NativeEnumType, std::string>;
- using MapTypeConstIter = typename MapType::const_iterator;
 +
 +namespace common {
 +
++template <typename NativeEnumType>
++class PlatformEnum {
++  using MapType = std::map<std::string, NativeEnumType>;
++  using RevMapType = std::map<NativeEnumType, std::string>;
 +
- public:
-   PlatformEnum(std::initializer_list<std::pair<const std::string, NativeEnumType>> m) : mapping_(m) {
-     for (auto it: mapping_) {
++  using MapTypeConstIter = typename MapType::const_iterator;
 +
- private:
++ public:
++  PlatformEnum(std::initializer_list<std::pair<const std::string, NativeEnumType>> m)
++      : mapping_(m) {
++    for (auto it : mapping_) {
 +      rev_mapping_[it.second] = it.first;
 +    }
 +  }
 +
 +  PlatformResult getName(NativeEnumType value, std::string* name) const {
 +    auto it = rev_mapping_.find(value);
 +    if (it != rev_mapping_.end()) {
 +      *name = it->second;
 +      return PlatformResult(ErrorCode::NO_ERROR);
 +    }
 +    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "enum value not registered");
 +  }
 +
 +  PlatformResult getValue(std::string name, NativeEnumType* value) const {
 +    auto it = mapping_.find(name);
 +    if (it != mapping_.end()) {
 +      *value = it->second;
 +      return PlatformResult(ErrorCode::NO_ERROR);
 +    }
 +    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "enum name not registered");
 +  }
 +
 +  MapTypeConstIter begin() const {
 +    return mapping_.cbegin();
 +  }
 +
 +  MapTypeConstIter end() const {
 +    return mapping_.cend();
 +  }
 +
- } // common
- #endif // COMMON_PLATFORM_ENUM_H_
++ private:
 +  MapType mapping_;
 +  RevMapType rev_mapping_;
 +};
 +
++}  // common
 +
++#endif  // COMMON_PLATFORM_ENUM_H_
@@@ -41,12 -38,6 +41,12 @@@ MediaControllerClient::MediaControllerC
  MediaControllerClient::~MediaControllerClient() {
    ScopeLogger();
  
-     LoggerE("Failed to unset cmd reply callback. Error code: %d; Error message: %s",
-             ret, get_error_message(ret));
 +  int ret = mc_client_unset_cmd_reply_received_cb(handle_);
 +  if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
++    LoggerE("Failed to unset cmd reply callback. Error code: %d; Error message: %s", ret,
++            get_error_message(ret));
 +  }
 +
    if (nullptr != server_status_listener_ && !UnsetServerStatusChangeListener()) {
      LoggerE("Failed to unset server status change listener");
    }
@@@ -69,13 -60,6 +69,14 @@@ PlatformResult MediaControllerClient::I
          ("mc_client_create() error: %d, message: %s", ret, get_error_message(ret)));
    }
  
-     return LogAndCreateResult(
-         ErrorCode::UNKNOWN_ERR, "Unable to register cmd reply received callback",
-         ("mc_client_set_cmd_reply_received_cb() error: %d, message: %s", ret, get_error_message(ret)));
 +  ret = mc_client_set_cmd_reply_received_cb(handle_, OnCommandReply, this);
 +  if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
++    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
++                              "Unable to register cmd reply received callback",
++                              ("mc_client_set_cmd_reply_received_cb() error: %d, message: %s", ret,
++                               get_error_message(ret)));
 +  }
 +
    return PlatformResult(ErrorCode::NO_ERROR);
  }
  
@@@ -471,8 -457,8 +472,7 @@@ void MediaControllerClient::OnMetadataU
  PlatformResult MediaControllerClient::SendCommand(const std::string& server_name,
                                                    const std::string& command,
                                                    const picojson::value& data,
-                                                   const JsonCallback& reply_cb,
-                                                   char** request_id) {
 -                                                  const std::string& reply_id,
 -                                                  const JsonCallback& reply_cb) {
++                                                  const JsonCallback& reply_cb, char** request_id) {
    ScopeLogger();
    bundle* bundle = bundle_create();
    SCOPE_EXIT {
          ("bundle_add(data) error: %d, message: %s", ret, get_error_message(ret)));
    }
  
-   ret = mc_client_send_custom_cmd(handle_, server_name.c_str(), command.c_str(), bundle, request_id);
 -  ret = mc_client_send_custom_command(handle_, server_name.c_str(), command.c_str(), bundle,
 -                                      OnCommandReply, this);
++  ret =
++      mc_client_send_custom_cmd(handle_, server_name.c_str(), command.c_str(), bundle, request_id);
    if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
      return LogAndCreateResult(
          ErrorCode::UNKNOWN_ERR, "Error sending custom command",
@@@ -66,8 -66,8 +66,8 @@@ class MediaControllerClient 
  
    static void OnServerStatusUpdate(const char* server_name, mc_server_state_e state,
                                     void* user_data);
-   static void OnCommandReply(const char* server_name, const char* request_id,
-                              int result_code, bundle* bundle, void* user_data);
 -  static void OnCommandReply(const char* server_name, int result_code, bundle* bundle,
 -                             void* user_data);
++  static void OnCommandReply(const char* server_name, const char* request_id, int result_code,
++                             bundle* bundle, void* user_data);
    static void OnPlaybackUpdate(const char* server_name, mc_playback_h playback, void* user_data);
    static void OnShuffleModeUpdate(const char* server_name, mc_shuffle_mode_e mode, void* user_data);
    static void OnRepeatModeUpdate(const char* server_name, mc_repeat_mode_e mode, void* user_data);
@@@ -19,9 -19,8 +19,9 @@@
  #include "common/logger.h"
  #include "common/picojson.h"
  #include "common/platform_result.h"
++#include "common/scope_exit.h"
  #include "common/task-queue.h"
  #include "common/tools.h"
- #include "common/scope_exit.h"
  
  #include "mediacontroller/mediacontroller_types.h"
  
@@@ -318,18 -317,11 +318,16 @@@ void MediaControllerInstance::MediaCont
    }
  
    CHECK_EXIST(args, "clientName", out)
 -  CHECK_EXIST(args, "replyId", out)
 +  CHECK_EXIST(args, "requestId", out)
    CHECK_EXIST(args, "data", out)
  
-   auto result = server_->CommandReply(
-     args.get("clientName").get<std::string>(),
-     args.get("requestId").get<std::string>(),
-     args.get("data"));
 -  server_->CommandReply(args.get("clientName").get<std::string>(), args.get("replyId").to_str(),
 -                        args.get("data"));
++  auto result = server_->CommandReply(args.get("clientName").get<std::string>(),
++                                      args.get("requestId").get<std::string>(), args.get("data"));
 +
 +  if (!result) {
 +    LogAndReportError(result, &out);
 +    return;
 +  }
  
    ReportSuccess(out);
  }
@@@ -608,17 -602,10 +606,14 @@@ void MediaControllerInstance::MediaCont
      Instance::PostMessage(this, reply->serialize().c_str());
    };
  
 -  PlatformResult result = client_->SendCommand(
 -      args.get("name").get<std::string>(), args.get("command").get<std::string>(), args.get("data"),
 -      args.get("replyId").to_str(), reply_cb);
 +  char* request_id = nullptr;
 +  SCOPE_EXIT {
 +    free(request_id);
 +  };
 +
-   PlatformResult result = client_->SendCommand(
-       args.get("name").get<std::string>(),
-       args.get("command").get<std::string>(),
-       args.get("data"),
-       reply_cb,
-       &request_id);
++  PlatformResult result = client_->SendCommand(args.get("name").get<std::string>(),
++                                               args.get("command").get<std::string>(),
++                                               args.get("data"), reply_cb, &request_id);
  
    if (result) {
      ReportSuccess(out);
@@@ -203,8 -207,8 +203,9 @@@ PlatformResult MediaControllerServer::S
    return PlatformResult(ErrorCode::NO_ERROR);
  }
  
 -void MediaControllerServer::OnCommandReceived(const char* client_name, const char* command,
 -                                              bundle* bundle, void* user_data) {
 +void MediaControllerServer::OnCommandReceived(const char* client_name, const char* request_id,
-                                               const char* command, bundle* bundle, void* user_data) {
++                                              const char* command, bundle* bundle,
++                                              void* user_data) {
    ScopeLogger();
  
    MediaControllerServer* server = static_cast<MediaControllerServer*>(user_data);
@@@ -271,11 -291,11 +272,11 @@@ PlatformResult MediaControllerServer::C
  PlatformResult MediaControllerServer::SetCommandListener(const JsonCallback& callback) {
    ScopeLogger();
  
 -  int ret = mc_server_set_custom_command_received_cb(handle_, OnCommandReceived, this);
 +  int ret = mc_server_set_custom_cmd_received_cb(handle_, OnCommandReceived, this);
    if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
      return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unable to set command callback",
-                               ("mc_server_set_custom_cmd_received_cb() error: %d, message: %s",
 -                              ("mc_server_set_custom_command_received_cb() error: %d, message: %s",
--                               ret, get_error_message(ret)));
++                              ("mc_server_set_custom_cmd_received_cb() error: %d, message: %s", ret,
++                               get_error_message(ret)));
    }
    command_listener_ = callback;
  
@@@ -407,23 -425,16 +408,25 @@@ void MediaControllerServer::OnPlaybackA
  
    MediaControllerServer* server = static_cast<MediaControllerServer*>(user_data);
  
 -  if (server->playback_state_ == state_e) {
 -    LoggerD("The media playback state did not change, skipping");
 +  // Here, we need to convert mc_playback_action_e enum to mc_playback_states_e enum.
 +  std::string action_str;
 +  PlatformResult result = types::MediaControllerPlaybackActionEnum.getName(action, &action_str);
 +  if (!result) {
-     LoggerW("MediaControllerPlaybackActionEnum.getName() failed, error: %s", result.message().c_str());
++    LoggerW("MediaControllerPlaybackActionEnum.getName() failed, error: %s",
++            result.message().c_str());
      return;
    }
  
 -  std::string state;
 -  PlatformResult result = Types::PlatformEnumToString(Types::kMediaControllerPlaybackState,
 -                                                      static_cast<int>(state_e), &state);
 +  mc_playback_states_e state_e;
 +  result = types::MediaControllerPlaybackStateEnum.getValue(action_str, &state_e);
    if (!result) {
-     LoggerE("MediaControllerPlaybackStateEnum.getValue() failed, error: %s", result.message().c_str());
 -    LoggerE("PlatformEnumToString failed, error: %s", result.message().c_str());
++    LoggerE("MediaControllerPlaybackStateEnum.getValue() failed, error: %s",
++            result.message().c_str());
 +    return;
 +  }
 +
 +  if (server->playback_state_ == state_e) {
 +    LoggerD("The media playback state did not change, skipping");
      return;
    }
  
@@@ -28,77 -28,104 +28,66 @@@ namespace mediacontroller 
  using common::PlatformResult;
  using common::ErrorCode;
  
 -const std::string Types::kMediaControllerServerState = "MediaControllerServerState";
 -const std::string Types::kMediaControllerPlaybackState = "MediaControllerPlaybackState";
 -const std::string Types::kMediaControllerMetadataAttribute = "MediaControllerMetadataAttribute";
 -
 -const PlatformEnumMap Types::platform_enum_map_ = {{kMediaControllerServerState,
 -                                                    {{"NONE", MC_SERVER_STATE_NONE},
 -                                                     {"ACTIVE", MC_SERVER_STATE_ACTIVATE},
 -                                                     {"INACTIVE", MC_SERVER_STATE_DEACTIVATE}}},
 -                                                   {kMediaControllerPlaybackState,
 -                                                    {{"PLAY", MC_PLAYBACK_STATE_PLAYING},
 -                                                     {"PAUSE", MC_PLAYBACK_STATE_PAUSED},
 -                                                     {"STOP", MC_PLAYBACK_STATE_STOPPED},
 -                                                     {"NEXT", MC_PLAYBACK_STATE_NEXT_FILE},
 -                                                     {"PREV", MC_PLAYBACK_STATE_PREV_FILE},
 -                                                     {"FORWARD", MC_PLAYBACK_STATE_FAST_FORWARD},
 -                                                     {"REWIND", MC_PLAYBACK_STATE_REWIND}}},
 -                                                   {kMediaControllerMetadataAttribute,
 -                                                    {{"title", MC_META_MEDIA_TITLE},
 -                                                     {"artist", MC_META_MEDIA_ARTIST},
 -                                                     {"album", MC_META_MEDIA_ALBUM},
 -                                                     {"author", MC_META_MEDIA_AUTHOR},
 -                                                     {"genre", MC_META_MEDIA_GENRE},
 -                                                     {"duration", MC_META_MEDIA_DURATION},
 -                                                     {"date", MC_META_MEDIA_DATE},
 -                                                     {"copyright", MC_META_MEDIA_COPYRIGHT},
 -                                                     {"description", MC_META_MEDIA_DESCRIPTION},
 -                                                     {"trackNum", MC_META_MEDIA_TRACK_NUM},
 -                                                     {"picture", MC_META_MEDIA_PICTURE}}}};
 -
 -PlatformEnumReverseMap Types::platform_enum_reverse_map_ = {};
 -
 -PlatformResult Types::GetPlatformEnumMap(const std::string& type,
 -                                         std::map<std::string, int>* enum_map) {
 -  ScopeLogger();
 -
 -  auto iter = platform_enum_map_.find(type);
 -  if (iter == platform_enum_map_.end()) {
 -    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
 -                              std::string("Undefined platform enum type ") + type);
 -  }
 -
 -  *enum_map = platform_enum_map_.at(type);
 -
 -  return PlatformResult(ErrorCode::NO_ERROR);
 -}
 -
 -PlatformResult Types::StringToPlatformEnum(const std::string& type, const std::string& value,
 -                                           int* platform_enum) {
 -  ScopeLogger();
 -
 -  std::map<std::string, int> def;
 -  PlatformResult result = GetPlatformEnumMap(type, &def);
 -  if (!result) {
 -    return result;
 -  }
 -
 -  auto def_iter = def.find(value);
 -  if (def_iter != def.end()) {
 -    *platform_enum = def_iter->second;
 -    return PlatformResult(ErrorCode::NO_ERROR);
 -  }
 -
 -  std::string message = "Platform enum value " + value + " not found for " + type;
 -  return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, message);
 -}
 -
 -PlatformResult Types::PlatformEnumToString(const std::string& type, int value,
 -                                           std::string* platform_str) {
 -  ScopeLogger();
 -
 -  if (platform_enum_reverse_map_.empty()) {
 -    for (auto& def : platform_enum_map_) {
 -      platform_enum_reverse_map_[def.first] = {};
 -
 -      for (auto& key : def.second) {
 -        platform_enum_reverse_map_[def.first][key.second] = key.first;
 -      }
 -    }
 -  }
 -
 -  auto it = platform_enum_reverse_map_.find(type);
 -  if (it == platform_enum_reverse_map_.end()) {
 -    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
 -                              std::string("Undefined platform enum type ") + type);
 -  }
 -
 -  auto def = platform_enum_reverse_map_.at(type);
 -  auto def_it = def.find(value);
 -  if (def_it != def.end()) {
 -    *platform_str = def_it->second;
 -    return PlatformResult(ErrorCode::NO_ERROR);
 -  }
 -
 -  std::string message = "Platform enum value " + std::to_string(value) + " not found for " + type;
 -  return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, message);
 -}
 -
 -PlatformResult Types::ConvertPlaybackState(mc_playback_h playback_h, std::string* state) {
 +namespace types {
 +
- const common::PlatformEnum<mc_server_state_e> MediaControllerServerStateEnum {
++const common::PlatformEnum<mc_server_state_e> MediaControllerServerStateEnum{
 +    {"NONE", MC_SERVER_STATE_NONE},
 +    {"ACTIVE", MC_SERVER_STATE_ACTIVATE},
-     {"INACTIVE", MC_SERVER_STATE_DEACTIVATE}
- };
++    {"INACTIVE", MC_SERVER_STATE_DEACTIVATE}};
 +
- const common::PlatformEnum<mc_playback_states_e> MediaControllerPlaybackStateEnum {
++const common::PlatformEnum<mc_playback_states_e> MediaControllerPlaybackStateEnum{
 +    {"PLAY", MC_PLAYBACK_STATE_PLAYING},
 +    {"PAUSE", MC_PLAYBACK_STATE_PAUSED},
 +    {"STOP", MC_PLAYBACK_STATE_STOPPED},
 +    {"NEXT", MC_PLAYBACK_STATE_MOVING_TO_NEXT},
 +    {"PREV", MC_PLAYBACK_STATE_MOVING_TO_PREVIOUS},
 +    {"FORWARD", MC_PLAYBACK_STATE_FAST_FORWARDING},
-     {"REWIND", MC_PLAYBACK_STATE_REWINDING}
- };
- const common::PlatformEnum<mc_playback_action_e> MediaControllerPlaybackActionEnum {
-     {"PLAY", MC_PLAYBACK_ACTION_PLAY},
-     {"PAUSE", MC_PLAYBACK_ACTION_PAUSE},
-     {"STOP", MC_PLAYBACK_ACTION_STOP},
-     {"NEXT", MC_PLAYBACK_ACTION_NEXT},
-     {"PREV", MC_PLAYBACK_ACTION_PREV},
-     {"FORWARD", MC_PLAYBACK_ACTION_FAST_FORWARD},
-     {"REWIND", MC_PLAYBACK_ACTION_REWIND}
- };
- const common::PlatformEnum<mc_meta_e> MediaControllerMetadataAttributeEnum {
++    {"REWIND", MC_PLAYBACK_STATE_REWINDING}};
++
++const common::PlatformEnum<mc_playback_action_e> MediaControllerPlaybackActionEnum{
++    {"PLAY", MC_PLAYBACK_ACTION_PLAY},    {"PAUSE", MC_PLAYBACK_ACTION_PAUSE},
++    {"STOP", MC_PLAYBACK_ACTION_STOP},    {"NEXT", MC_PLAYBACK_ACTION_NEXT},
++    {"PREV", MC_PLAYBACK_ACTION_PREV},    {"FORWARD", MC_PLAYBACK_ACTION_FAST_FORWARD},
++    {"REWIND", MC_PLAYBACK_ACTION_REWIND}};
++
++const common::PlatformEnum<mc_meta_e> MediaControllerMetadataAttributeEnum{
 +    {"title", MC_META_MEDIA_TITLE},
 +    {"artist", MC_META_MEDIA_ARTIST},
 +    {"album", MC_META_MEDIA_ALBUM},
 +    {"author", MC_META_MEDIA_AUTHOR},
 +    {"genre", MC_META_MEDIA_GENRE},
 +    {"duration", MC_META_MEDIA_DURATION},
 +    {"date", MC_META_MEDIA_DATE},
 +    {"copyright", MC_META_MEDIA_COPYRIGHT},
 +    {"description", MC_META_MEDIA_DESCRIPTION},
 +    {"trackNum", MC_META_MEDIA_TRACK_NUM},
-     {"picture", MC_META_MEDIA_PICTURE}
- };
++    {"picture", MC_META_MEDIA_PICTURE}};
 +
- const common::PlatformEnum<mc_repeat_mode_e> MediaControllerRepeatModeEnum {
++const common::PlatformEnum<mc_repeat_mode_e> MediaControllerRepeatModeEnum{
 +    {"REPEAT_OFF", MC_REPEAT_MODE_OFF},
 +    {"REPEAT_ONE", MC_REPEAT_MODE_ONE_MEDIA},
-     {"REPEAT_ALL", MC_REPEAT_MODE_ON}
- };
- const common::PlatformEnum<mc_content_age_rating_e> MediaControllerContentAgeRatingEnum {
-      {"ALL", MC_CONTENT_RATING_ALL},    {"1", MC_CONTENT_RATING_1_PLUS},
-      {"2", MC_CONTENT_RATING_2_PLUS},   {"3", MC_CONTENT_RATING_3_PLUS},
-      {"4", MC_CONTENT_RATING_4_PLUS},   {"5", MC_CONTENT_RATING_5_PLUS},
-      {"6", MC_CONTENT_RATING_6_PLUS},   {"7", MC_CONTENT_RATING_7_PLUS},
-      {"8", MC_CONTENT_RATING_8_PLUS},   {"9", MC_CONTENT_RATING_9_PLUS},
-      {"10", MC_CONTENT_RATING_10_PLUS}, {"11", MC_CONTENT_RATING_11_PLUS},
-      {"12", MC_CONTENT_RATING_12_PLUS}, {"13", MC_CONTENT_RATING_13_PLUS},
-      {"14", MC_CONTENT_RATING_14_PLUS}, {"15", MC_CONTENT_RATING_15_PLUS},
-      {"16", MC_CONTENT_RATING_16_PLUS}, {"17", MC_CONTENT_RATING_17_PLUS},
-      {"18", MC_CONTENT_RATING_18_PLUS}, {"19", MC_CONTENT_RATING_19_PLUS}
- };
- const common::PlatformEnum<mc_content_type_e> MediaControllerContentTypeEnum {
++    {"REPEAT_ALL", MC_REPEAT_MODE_ON}};
++
++const common::PlatformEnum<mc_content_age_rating_e> MediaControllerContentAgeRatingEnum{
++    {"ALL", MC_CONTENT_RATING_ALL},    {"1", MC_CONTENT_RATING_1_PLUS},
++    {"2", MC_CONTENT_RATING_2_PLUS},   {"3", MC_CONTENT_RATING_3_PLUS},
++    {"4", MC_CONTENT_RATING_4_PLUS},   {"5", MC_CONTENT_RATING_5_PLUS},
++    {"6", MC_CONTENT_RATING_6_PLUS},   {"7", MC_CONTENT_RATING_7_PLUS},
++    {"8", MC_CONTENT_RATING_8_PLUS},   {"9", MC_CONTENT_RATING_9_PLUS},
++    {"10", MC_CONTENT_RATING_10_PLUS}, {"11", MC_CONTENT_RATING_11_PLUS},
++    {"12", MC_CONTENT_RATING_12_PLUS}, {"13", MC_CONTENT_RATING_13_PLUS},
++    {"14", MC_CONTENT_RATING_14_PLUS}, {"15", MC_CONTENT_RATING_15_PLUS},
++    {"16", MC_CONTENT_RATING_16_PLUS}, {"17", MC_CONTENT_RATING_17_PLUS},
++    {"18", MC_CONTENT_RATING_18_PLUS}, {"19", MC_CONTENT_RATING_19_PLUS}};
++
++const common::PlatformEnum<mc_content_type_e> MediaControllerContentTypeEnum{
 +    {"IMAGE", MC_CONTENT_TYPE_IMAGE},
 +    {"MUSIC", MC_CONTENT_TYPE_MUSIC},
 +    {"VIDEO", MC_CONTENT_TYPE_VIDEO},
 +    {"OTHER", MC_CONTENT_TYPE_OTHER},
-     {"UNDECIDED", MC_CONTENT_TYPE_UNDECIDED}
- };
++    {"UNDECIDED", MC_CONTENT_TYPE_UNDECIDED}};
 +
 +PlatformResult ConvertPlaybackState(mc_playback_h playback_h, std::string* state) {
    ScopeLogger();
  
    int ret;
      state_e = MC_PLAYBACK_STATE_STOPPED;
    }
  
 -  PlatformResult result = Types::PlatformEnumToString(Types::kMediaControllerPlaybackState,
 -                                                      static_cast<int>(state_e), state);
 +  PlatformResult result = MediaControllerPlaybackStateEnum.getName(state_e, state);
    if (!result) {
-     LoggerE("MediaControllerPlaybackStateEnum.getName() failed, error: %s", result.message().c_str());
 -    LoggerE("PlatformEnumToString failed, error: %s", result.message().c_str());
++    LoggerE("MediaControllerPlaybackStateEnum.getName() failed, error: %s",
++            result.message().c_str());
      return result;
    }
  
@@@ -148,22 -184,19 +138,21 @@@ PlatformResult ConvertMetadata(mc_metad
      free(value);
    };
  
-   for (auto entry: MediaControllerMetadataAttributeEnum) {
 -  for (auto& field : metadata_fields) {
 -    int ret = mc_client_get_metadata(metadata_h, static_cast<mc_meta_e>(field.second), &value);
++  for (auto entry : MediaControllerMetadataAttributeEnum) {
 +    int ret = mc_metadata_get(metadata_h, entry.second, &value);
      if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
        return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Error getting metadata",
 -                                ("mc_client_get_metadata(%s) error: %d, message: %s",
 -                                 field.first.c_str(), ret, get_error_message(ret)));
 +                                ("mc_metadata_get(%s) error: %d, message: %s", entry.first.c_str(),
 +                                 ret, get_error_message(ret)));
      }
  
 -    (*metadata)[field.first] = picojson::value(std::string(value ? value : ""));
 +    (*metadata)[entry.first] = picojson::value(std::string(value ? value : ""));
    }
  
    return PlatformResult(ErrorCode::NO_ERROR);
  }
  
- } // types
++}  // types
 +
  }  // namespace mediacontroller
  }  // namespace extension
  #include <map>
  #include <string>
  
- #include "common/platform_result.h"
 +#include "common/platform_enum.h"
+ #include "common/platform_result.h"
  
  namespace extension {
  namespace mediacontroller {
  
 -typedef std::map<std::string, std::map<std::string, int>> PlatformEnumMap;
 -typedef std::map<std::string, std::map<int, std::string>> PlatformEnumReverseMap;
  typedef std::function<void(picojson::value*)> JsonCallback;
  
 -class Types {
 - public:
 -  static const std::string kMediaControllerServerState;
 -  static const std::string kMediaControllerPlaybackState;
 -  static const std::string kMediaControllerMetadataAttribute;
 +namespace types {
  
 -  static common::PlatformResult GetPlatformEnumMap(const std::string& type,
 -                                                   std::map<std::string, int>* platform_str);
 +common::PlatformResult ConvertPlaybackState(mc_playback_h playback_h, std::string* state);
 +common::PlatformResult ConvertContentAgeRating(mc_playback_h playback_h, std::string* state);
 +common::PlatformResult ConvertPlaybackPosition(mc_playback_h playback_h, double* position);
 +common::PlatformResult ConvertMetadata(mc_metadata_h metadata_h, picojson::object* metadata);
 +common::PlatformResult ConvertContentType(mc_playback_h playback_h, std::string* contentType);
  
 -  static common::PlatformResult StringToPlatformEnum(const std::string& type,
 -                                                     const std::string& value, int* platform_enum);
 +extern const common::PlatformEnum<mc_server_state_e> MediaControllerServerStateEnum;
 +extern const common::PlatformEnum<mc_playback_states_e> MediaControllerPlaybackStateEnum;
 +extern const common::PlatformEnum<mc_playback_action_e> MediaControllerPlaybackActionEnum;
 +extern const common::PlatformEnum<mc_meta_e> MediaControllerMetadataAttributeEnum;
 +extern const common::PlatformEnum<mc_repeat_mode_e> MediaControllerRepeatModeEnum;
 +extern const common::PlatformEnum<mc_content_age_rating_e> MediaControllerContentAgeRatingEnum;
 +extern const common::PlatformEnum<mc_content_type_e> MediaControllerContentTypeEnum;
  
- } // namespace types
 -  static common::PlatformResult PlatformEnumToString(const std::string& type, int value,
 -                                                     std::string* platform_str);
 -
 -  static common::PlatformResult ConvertPlaybackState(mc_playback_h playback_h, std::string* state);
 -  static common::PlatformResult ConvertPlaybackPosition(mc_playback_h playback_h, double* position);
 -  static common::PlatformResult ConvertMetadata(mc_metadata_h metadata_h,
 -                                                picojson::object* metadata);
--
 - private:
 -  static const PlatformEnumMap platform_enum_map_;
 -  static PlatformEnumReverseMap platform_enum_reverse_map_;
 -};
++}  // namespace types
  
  }  // namespace mediacontroller
  }  // namespace extension