summaryrefslogtreecommitdiff
path: root/xwalk/vehicle.cc
diff options
context:
space:
mode:
Diffstat (limited to 'xwalk/vehicle.cc')
-rw-r--r--xwalk/vehicle.cc816
1 files changed, 816 insertions, 0 deletions
diff --git a/xwalk/vehicle.cc b/xwalk/vehicle.cc
new file mode 100644
index 00000000..84a41b02
--- /dev/null
+++ b/xwalk/vehicle.cc
@@ -0,0 +1,816 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "vehicle.h"
+
+#include <abstractpropertytype.h>
+#include <debugout.h>
+#include <gio/gio.h>
+#include <glib.h>
+#include <listplusplus.h>
+#include <picojson.h>
+#include <superptr.hpp>
+
+#include <algorithm>
+#include <map>
+#include <memory>
+
+#include "common/extension.h"
+
+common::Instance* Vehicle::CallbackInfo::instance = nullptr;
+
+namespace {
+const char* amb_service = "org.automotive.message.broker";
+const char* prop_iface = "org.freedesktop.DBus.Properties";
+
+const char* vehicle_error_permission_denied = "permission_denied";
+const char* vehicle_error_invalid_operation = "invalid_operation";
+const char* vehicle_error_timeout = "timeout";
+const char* vehicle_error_invalid_zone = "invalid_zone";
+const char* vehicle_error_unknown = "unknown";
+
+picojson::value::array AmbZoneToW3C(const std::vector<int>& amb_zones);
+picojson::value::array AmbZoneToW3C(int amb_zone);
+
+template<typename T> unique_ptr<T> make_unique(T* t) {
+ return unique_ptr<T>(t);
+}
+
+void PostReply(Vehicle::CallbackInfo* cb_obj, picojson::value object) {
+ DebugOut() << "Posting reply" << endl;
+ picojson::object msg;
+
+ msg["method"] = picojson::value(cb_obj->method);
+ msg["asyncCallId"] = picojson::value(cb_obj->callback_id);
+ msg["value"] = object;
+
+ std::string message = picojson::value(msg).serialize();
+
+ DebugOut() << "Reply message: " << message << endl;
+
+ cb_obj->instance->PostMessage(message.c_str());
+}
+
+void PostError(Vehicle::CallbackInfo* cb_obj, const std::string& error) {
+ picojson::object msg;
+ msg["method"] = picojson::value(cb_obj->method);
+ msg["error"] = picojson::value(true);
+ msg["value"] = picojson::value(error);
+ msg["asyncCallId"] =
+ picojson::value(static_cast<double>(cb_obj->callback_id));
+
+ std::string message = picojson::value(msg).serialize();
+
+ DebugOut() << "Error Reply message: " << message << endl;
+
+ cb_obj->instance->PostMessage(message.c_str());
+}
+
+picojson::value GetBasic(GVariant* value) {
+ std::string type = g_variant_get_type_string(value);
+ picojson::value v;
+
+ if (type == "i") {
+ int tempVal = GVS<int>::value(value);
+ v = picojson::value(static_cast<double>(tempVal));
+ } else if (type == "d") {
+ v = picojson::value(GVS<double>::value(value));
+ } else if (type == "q") {
+ v = picojson::value(static_cast<double>(GVS<uint16_t>::value(value)));
+ } else if (type == "n") {
+ v = picojson::value(static_cast<double>(GVS<int16_t>::value(value)));
+ } else if (type == "y") {
+ v = picojson::value(static_cast<double>(GVS<char>::value(value)));
+ } else if (type == "u") {
+ v = picojson::value(static_cast<double>(GVS<uint32_t>::value(value)));
+ } else if (type == "x") {
+ v = picojson::value(static_cast<double>(GVS<int64_t>::value(value)));
+ } else if (type == "t") {
+ v = picojson::value(static_cast<double>(GVS<uint64_t>::value(value)));
+ } else if (type == "b") {
+ v = picojson::value(GVS<bool>::value(value));
+ } else if (type == "s") {
+ v = picojson::value(g_variant_get_string(value, nullptr));
+ } else {
+ DebugOut(DebugOut::Error) << "Unsupported type: " << type << endl;
+ }
+
+ return v;
+}
+
+GVariant* GetBasic(picojson::value value, const std::string& type) {
+ GVariant* v = nullptr;
+
+ if (type == "i") {
+ v = g_variant_new(type.c_str(), (int32_t)value.get<double>());
+ } else if (type == "d") {
+ v = g_variant_new(type.c_str(), value.get<double>());
+ } else if (type == "q") {
+ v = g_variant_new(type.c_str(), (uint16_t)value.get<double>());
+ } else if (type == "n") {
+ v = g_variant_new(type.c_str(), (int16_t)value.get<double>());
+ } else if (type == "u") {
+ v = g_variant_new(type.c_str(), (uint32_t)value.get<double>());
+ } else if (type == "x") {
+ v = g_variant_new(type.c_str(), (int64_t)value.get<double>());
+ } else if (type == "t") {
+ v = g_variant_new(type.c_str(), (uint64_t)value.get<double>());
+ } else if (type == "b") {
+ v = g_variant_new(type.c_str(), value.get<bool>());
+ } else if (type == "s") {
+ v = g_variant_new(type.c_str(), value.get<std::string>().c_str());
+ } else {
+ DebugOut(DebugOut::Error) << "Unsupported type: " << type << endl;
+ }
+
+ return v;
+}
+
+void AsyncGetCallback(GObject* source, GAsyncResult* res, gpointer user_data) {
+ debugOut("GetAll() method call completed");
+
+ Vehicle::CallbackInfo *cb_obj =
+ static_cast<Vehicle::CallbackInfo*>(user_data);
+
+ auto cb_obj_ptr = make_unique(cb_obj);
+
+ if (!cb_obj_ptr) {
+ debugOut("invalid cb object");
+ return;
+ }
+
+ GError* error = nullptr;
+
+ auto property_map = amb::make_super(
+ g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error));
+
+ auto error_ptr = amb::make_super(error);
+
+ if (error_ptr) {
+ DebugOut() << "failed to call GetAll on interface: "
+ << error_ptr->message << endl;
+ PostError(cb_obj_ptr.get(), "unknown");
+ return;
+ }
+
+ GVariantIter* iter;
+ gchar* key;
+ GVariant* value;
+
+ g_variant_get(property_map.get(), "(a{sv})", &iter);
+
+ auto iter_ptr = amb::make_super(iter);
+
+ picojson::value::object object;
+
+ while (g_variant_iter_next(iter_ptr.get(), "{sv}", &key, &value)) {
+ auto key_ptr = amb::make_super(key);
+ auto value_ptr = amb::make_super(value);
+
+ std::string temp_key = key_ptr.get();
+
+ std::transform(temp_key.begin(), temp_key.begin() + 1,
+ temp_key.begin(), ::tolower);
+
+ object[temp_key] = GetBasic(value_ptr.get());
+
+ if (temp_key == "zone") {
+ object[temp_key] =
+ picojson::value(AmbZoneToW3C(object[temp_key].get<double>()));
+ }
+ }
+
+ PostReply(cb_obj_ptr.get(), picojson::value(object));
+}
+
+picojson::value::array AmbZoneToW3C(int amb_zone) {
+ picojson::value::array z;
+
+ if (amb_zone & Zone::Left) {
+ z.push_back(picojson::value("left"));
+ }
+ if (amb_zone & Zone::Right) {
+ z.push_back(picojson::value("right"));
+ }
+ if (amb_zone & Zone::Front) {
+ z.push_back(picojson::value("front"));
+ }
+ if (amb_zone & Zone::Middle) {
+ z.push_back(picojson::value("middle"));
+ }
+ if (amb_zone & Zone::Center) {
+ z.push_back(picojson::value("center"));
+ }
+ if (amb_zone & Zone::Rear) {
+ z.push_back(picojson::value("rear"));
+ }
+
+ return z;
+}
+
+picojson::value::array AmbZoneToW3C(const std::vector<int>& amb_zones) {
+ picojson::value::array zones;
+
+ for (auto i : amb_zones) {
+ zones.push_back(picojson::value(AmbZoneToW3C(i)));
+ }
+
+ return zones;
+}
+
+static void SignalCallback(GDBusConnection* connection,
+ const gchar*,
+ const gchar* object_path,
+ const gchar*,
+ const gchar*,
+ GVariant* parameters,
+ gpointer user_data) {
+ DebugOut() << "Got signal" << endl;
+ std::vector<ObjectZone*> amb_objects_ =
+ *(static_cast<std::vector<ObjectZone*>*>(user_data));
+
+ GVariant* value_array;
+ GVariant* iface_name;
+ GVariant* invalidated;
+
+ g_variant_get(parameters,
+ "(&s@a{sv}^a&s)",
+ &iface_name,
+ &value_array,
+ &invalidated);
+
+ GVariantIter iter;
+
+ g_variant_iter_init(&iter, value_array);
+
+ ObjectZone* object = nullptr;
+
+ for (auto i : amb_objects_) {
+ if (i->object_path == object_path) {
+ object = i;
+ }
+ }
+
+ if (!object) {
+ DebugOut(DebugOut::Error) << "received signal for which "
+ << "we have no corresponding amb object" << endl;
+ return;
+ }
+
+ char* key;
+ GVariant* value;
+
+ while (g_variant_iter_next(&iter, "{sv}", &key, &value)) {
+ auto key_ptr = amb::make_super(key);
+ auto value_ptr = amb::make_super(value);
+
+ std::string tempkey = key_ptr.get();
+
+ std::transform(tempkey.begin(), tempkey.begin() + 1, tempkey.begin(),
+ ::tolower);
+
+ object->value[tempkey] = GetBasic(value_ptr.get());
+
+ if (tempkey == "zone") {
+ object->value[tempkey] =
+ picojson::value(AmbZoneToW3C(object->value[tempkey].get<double>()));
+ }
+ }
+
+ object->value["interfaceName"] = picojson::value(object->name);
+
+ Vehicle::CallbackInfo call;
+ call.method = "subscribe";
+ call.callback_id = -1;
+
+ PostReply(&call, picojson::value(object->value));
+}
+
+} // namespace
+
+Vehicle::Vehicle(common::Instance* instance)
+ : main_loop_(g_main_loop_new(0, FALSE)),
+ thread_(Vehicle::SetupMainloop, this),
+ instance_(instance),
+ manager_proxy_(nullptr){
+ CallbackInfo::instance = instance_;
+ thread_.detach();
+
+ GError* error = nullptr;
+
+ dbus_connection_ = amb::make_super(g_bus_get_sync(G_BUS_TYPE_SYSTEM,
+ nullptr,
+ &error));
+
+ auto errorPtr = amb::make_super(error);
+ if (errorPtr) {
+ DebugOut(DebugOut::Error) << "getting bus: "
+ << errorPtr->message << std::endl;
+ }
+
+ GError* error_manager = nullptr;
+ manager_proxy_ = amb::make_super(g_dbus_proxy_new_sync(dbus_connection_.get(),
+ G_DBUS_PROXY_FLAGS_NONE, NULL,
+ amb_service,
+ "/",
+ "org.automotive.Manager",
+ NULL,
+ &error));
+
+ auto error_ptr = amb::make_super(error_manager);
+
+ if (error_ptr) {
+ DebugOut(DebugOut::Error) << "calling GetAutomotiveManager: "
+ << error_ptr->message << endl;
+ }
+
+
+ GError* list_error = nullptr;
+ auto supported_list_variant = amb::make_super(
+ g_dbus_proxy_call_sync(manager_proxy_.get(),
+ "List",
+ nullptr,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &list_error));
+
+ auto list_error_ptr = amb::make_super(list_error);
+
+ if (list_error_ptr) {
+ DebugOut(DebugOut::Error) << "error calling List: "
+ << error_ptr->message << endl;
+ return;
+ }
+
+ GVariantIter iter;
+ g_variant_iter_init(&iter, supported_list_variant.get());
+ picojson::array list;
+
+ gchar* propertyName = nullptr;
+
+ while(g_variant_iter_next(&iter,"s", &propertyName))
+ {
+ auto propertyNamePtr = amb::make_super(propertyName);
+
+ std::string p = propertyNamePtr.get();
+
+ std::transform(p.begin(), p.begin()+1, p.begin(), ::tolower);
+ list.push_back(picojson::value(p));
+ }
+
+ picojson::object obj;
+ obj["method"] = picojson::value("vehicleSupportedAttributes");
+ obj["value"] = picojson::value(list);
+
+ instance->PostMessage(picojson::value(obj).serialize().c_str());
+}
+
+Vehicle::~Vehicle() {
+ g_main_loop_quit(main_loop_);
+ g_main_loop_unref(main_loop_);
+
+ for (auto i : amb_objects_) {
+ delete i;
+ }
+}
+
+void Vehicle::Get(const std::string& property, Zone::Type zone, double ret_id) {
+ CallbackInfo* data = new CallbackInfo;
+
+ data->callback_id = ret_id;
+ data->method = "get";
+ data->instance = instance_;
+
+
+ std::string find_error;
+ std::string obj_pstr = FindProperty(property, zone, find_error);
+
+ if (obj_pstr.empty()) {
+ debugOut("could not find property " + property);
+ PostError(data, find_error);
+ return;
+ }
+
+ GError* error = nullptr;
+
+ auto properties_proxy = amb::make_super(
+ g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE, NULL,
+ amb_service,
+ obj_pstr.c_str(),
+ prop_iface,
+ NULL,
+ &error));
+
+ auto error_ptr = amb::make_super(error);
+
+ if (error_ptr) {
+ DebugOut(DebugOut::Error) << "failed to get properties proxy: " << error->message << endl;
+ return;
+ }
+
+ std::string interfaceName = "org.automotive." + property;
+
+ g_dbus_proxy_call(properties_proxy.get(),
+ "GetAll",
+ g_variant_new("(s)", interfaceName.c_str()),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL,
+ AsyncGetCallback, data);
+}
+
+void Vehicle::GetZones(const std::string& object_name, double ret_id) {
+ GError* error(nullptr);
+
+ auto zones_variant = amb::make_super(
+ g_dbus_proxy_call_sync(manager_proxy_.get(),
+ "ZonesForObjectName",
+ g_variant_new("(s)",
+ object_name.c_str()),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error));
+
+ auto error_ptr = amb::make_super(error);
+
+ if (error_ptr) {
+ DebugOut() << "error calling ZonesForObjectName: "
+ << error_ptr->message << endl;
+ return;
+ }
+
+ if (!zones_variant) {
+ DebugOut() << "Invalid response from ZonesForObjectName " << endl;
+ return;
+ }
+
+ GVariantIter* iter(nullptr);
+
+ g_variant_get(zones_variant.get(), "(ai)", &iter);
+
+ if (!iter) {
+ DebugOut() << "No zones for object " << object_name << endl;
+ return;
+ }
+
+ auto iter_ptr = amb::make_super(iter);
+
+ std::vector<int> zones_array;
+
+ GVariant* value(nullptr);
+
+ while ((value = g_variant_iter_next_value(iter_ptr.get()))) {
+ auto value_ptr = amb::make_super(value);
+ int v = 0;
+
+ g_variant_get(value_ptr.get(), "i", &v);
+ zones_array.push_back(v);
+ }
+
+ picojson::value::array w3c_zones = AmbZoneToW3C(zones_array);
+
+ CallbackInfo* data = new CallbackInfo;
+
+ data->callback_id = ret_id;
+ data->method = "zones";
+ data->instance = instance_;
+
+ PostReply(data, picojson::value(w3c_zones));
+}
+
+std::string Vehicle::FindProperty(const std::string& object_name, int zone, std::string& error_str) {
+ GError* error(nullptr);
+
+ auto object_path_variant = amb::make_super(
+ g_dbus_proxy_call_sync(manager_proxy_.get(),
+ "FindObjectForZone",
+ g_variant_new("(si)",
+ object_name.c_str(),
+ zone),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error));
+
+ auto error_ptr = amb::make_super(error);
+
+ if (error_ptr) {
+ DebugOut(DebugOut::Error) << "error calling FindObjectForZone: "
+ << error_ptr->message << endl;
+
+ DebugOut() << "Could not find object in zone: " << zone << endl;
+ error_str = vehicle_error_invalid_operation;
+ return "";
+ }
+
+ if (!object_path_variant) {
+ DebugOut() << "Could not find object in zone: " << zone << endl;
+ error_str = vehicle_error_invalid_operation;
+ return "";
+ }
+
+ gchar* obj_path = nullptr;
+ g_variant_get(object_path_variant.get(), "(o)", &obj_path);
+
+ auto obj_path_ptr = amb::make_super(obj_path);
+
+ DebugOut() << "FindObjectForZone() returned object path: "
+ << obj_path_ptr.get() << endl;
+
+ return obj_path;
+}
+
+void Vehicle::SetupMainloop(void* data) {
+ Vehicle* self = reinterpret_cast<Vehicle*>(data);
+ GMainContext* ctx = g_main_context_default();
+
+ g_main_context_push_thread_default(ctx);
+ g_main_loop_run(self->main_loop_);
+}
+
+
+void Vehicle::Subscribe(const std::string& object_name, Zone::Type zone) {
+ std::string find_error;
+ std::string object_path = FindProperty(object_name, zone, find_error);
+
+ if (object_path.empty()) {
+ DebugOut() << "Error FindProperty failed for " << object_name;
+ return;
+ }
+
+ bool already_subscribed = false;
+
+ for (auto i : amb_objects_) {
+ if (i->object_path == object_path) {
+ already_subscribed = true;
+ break;
+ }
+ }
+
+ if (!already_subscribed) {
+ GError* proxy_error = nullptr;
+
+ auto properties_proxy =
+ amb::make_super(g_dbus_proxy_new_sync(dbus_connection_.get(),
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ amb_service,
+ object_path.c_str(),
+ prop_iface,
+ NULL,
+ &proxy_error));
+
+ auto proxy_error_ptr = amb::make_super(proxy_error);
+
+ if (proxy_error_ptr) {
+ DebugOut() << "error creating properties proxy: "
+ << proxy_error_ptr->message << endl;
+ }
+
+ std::string interface_name = "org.automotive." + object_name;
+
+ GError* get_all_error = nullptr;
+
+ GVariant* property_map =
+ g_dbus_proxy_call_sync(properties_proxy.get(),
+ "GetAll",
+ g_variant_new("(s)", interface_name.c_str()),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL,
+ &get_all_error);
+
+ auto get_all_error_ptr = amb::make_super(get_all_error);
+
+ if (get_all_error_ptr) {
+ DebugOut(DebugOut::Error) << "failed to call GetAll on interface "
+ << interface_name << " "
+ << get_all_error_ptr->message << endl;
+ return;
+ }
+
+ GVariantIter* iter;
+
+ g_variant_get(property_map, "(a{sv})", &iter);
+
+ auto iter_ptr = amb::make_super(iter);
+
+ char* key;
+ GVariant* value;
+
+ ObjectZone* object = new ObjectZone(object_name, zone, object_path);
+
+ while (g_variant_iter_next(iter_ptr.get(), "{sv}", &key, &value)) {
+ auto key_ptr = amb::make_super(key);
+ auto value_ptr = amb::make_super(value);
+
+ std::string tempkey = key_ptr.get();
+
+ std::transform(tempkey.begin(), tempkey.begin() + 1, tempkey.begin(),
+ ::tolower);
+
+ object->value[tempkey] = GetBasic(value_ptr.get());
+ }
+
+ object->handle =
+ g_dbus_connection_signal_subscribe(dbus_connection_.get(),
+ amb_service,
+ prop_iface,
+ "PropertiesChanged",
+ object_path.c_str(), NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ SignalCallback, &amb_objects_,
+ NULL);
+
+ amb_objects_.push_back(object);
+ } else {
+ DebugOut() << "Already subscribed to " << object_name << endl;
+ }
+}
+
+
+void Vehicle::Unsubscribe(const std::string& property, Zone::Type zone) {
+ std::vector<ObjectZone*> to_clean;
+
+ for (auto obj : amb_objects_) {
+ if (obj->name == property && obj->zone == zone) {
+ g_dbus_connection_signal_unsubscribe(dbus_connection_.get(),
+ obj->handle);
+ to_clean.push_back(obj);
+ }
+ }
+
+ for (auto obj : to_clean) {
+ removeOne(&amb_objects_, obj);
+ delete obj;
+ }
+}
+
+
+void Vehicle::Set(const std::string &object_name, picojson::object value,
+ Zone::Type zone, double ret_id)
+{
+ std::string find_error;
+ std::string object_path = FindProperty(object_name, zone, find_error);
+
+ Vehicle::CallbackInfo callback;
+ callback.callback_id = ret_id;
+ callback.method = "set";
+ callback.instance = instance_;
+
+ if (object_path.empty() || !find_error.empty()) {
+ DebugOut(DebugOut::Error) << "Object not found. Check object Name and zone."
+ << object_name << std::endl;
+ PostError(&callback, find_error);
+ return;
+ }
+
+ GError* proxy_error = nullptr;
+
+ auto properties_proxy =
+ amb::make_super(g_dbus_proxy_new_sync(dbus_connection_.get(),
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ amb_service,
+ object_path.c_str(),
+ prop_iface,
+ NULL,
+ &proxy_error));
+
+ auto proxy_error_ptr = amb::make_super(proxy_error);
+
+ if (proxy_error_ptr) {
+ DebugOut(DebugOut::Error) << "Error creating property proxy for " << object_path << std::endl;
+ PostError(&callback, vehicle_error_unknown);
+ return;
+ }
+
+ std::string interface_name = "org.automotive." + object_name;
+
+ for (auto itr : value) {
+ GError* err = nullptr;
+ std::string attribute = itr.first;
+
+ std::transform(attribute.begin(), attribute.begin()+1, attribute.begin(), ::toupper);
+
+ auto var_value =
+ amb::make_super(g_dbus_proxy_call_sync(properties_proxy.get(),
+ "Get",
+ g_variant_new("(ss)",
+ interface_name.c_str(),
+ attribute.c_str()),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &err));
+ auto err_ptr = amb::make_super(err);
+ if (err_ptr || !var_value) {
+ DebugOut(DebugOut::Error) << "Error getting initial property signature type: " <<
+ err_ptr->message << endl;
+ PostError(&callback, vehicle_error_unknown);
+ return;
+ }
+
+ GVariant* get_value = nullptr;
+ g_variant_get(var_value.get(), "(v)", &get_value);
+
+ auto get_value_ptr = amb::make_super(get_value);
+
+ if (!get_value_ptr) {
+ DebugOut(DebugOut::Error) << "Error getting variant value." << endl;
+ PostError(&callback, vehicle_error_unknown);
+ return;
+ }
+
+ GVariant* v = GetBasic(itr.second, g_variant_get_type_string(get_value_ptr.get()));
+
+ if (!v) {
+ DebugOut(DebugOut::Error) << "Error converting value to GVariant" << endl;
+ PostError(&callback, vehicle_error_unknown);
+ return;
+ }
+
+ GError* set_error = nullptr;
+
+ DebugOut() << "Trying to set " << attribute << " to " << itr.second.serialize() << endl;
+
+ g_dbus_proxy_call_sync(properties_proxy.get(), "Set",
+ g_variant_new("(ssv)",
+ interface_name.c_str(),
+ attribute.c_str(),
+ v),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &set_error);
+
+ auto set_error_ptr = amb::make_super(set_error);
+
+ if (set_error_ptr) {
+ DebugOut(DebugOut::Error) << "error setting property:" << set_error_ptr->message << endl;
+
+ if(set_error_ptr->code == G_IO_ERROR_PERMISSION_DENIED
+ || std::string(g_dbus_error_get_remote_error(set_error_ptr.get())) == "org.freedesktop.DBus.Error.AccessDenied")
+ {
+ DebugOut(DebugOut::Error) << "permission denied" << endl;
+ PostError(&callback, vehicle_error_permission_denied);
+ return;
+ }
+ PostError(&callback, vehicle_error_unknown);
+ return;
+ }
+ }
+
+ PostReply(&callback, picojson::value());
+}
+
+void Vehicle::Supported(const string& object_name, double ret_id)
+{
+ Vehicle::CallbackInfo callback;
+ callback.callback_id = ret_id;
+ callback.method = "supported";
+ callback.instance = instance_;
+
+ GError* error(nullptr);
+
+ auto object_path_variant = amb::make_super(
+ g_dbus_proxy_call_sync(manager_proxy_.get(),
+ "FindObject",
+ g_variant_new("(s)", object_name.c_str()),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error));
+
+ auto error_ptr = amb::make_super(error);
+
+ if (error_ptr) {
+ DebugOut(DebugOut::Error) << "error calling FindObjectForZone: "
+ << error_ptr->message << endl;
+
+ DebugOut() << "Could not find object for: " << object_name << endl;
+ PostReply(&callback, picojson::value(false));
+ return;
+ }
+
+ if (!object_path_variant) {
+ DebugOut() << "Could not find object for: " << object_name << endl;
+ PostReply(&callback, picojson::value(false));
+ return;
+ }
+
+ PostReply(&callback, picojson::value(true));
+}
+
+bool Vehicle::AvailableForRetrieval(const string &objectName, const string &attName)
+{
+ GError* error = nullptr;
+
+ auto supportedVariant = amb::make_super(
+ g_dbus_proxy_call_sync(manager_proxy_.get(),
+ "SupportsProperty",
+ g_variant_new("(ss)", objectName.c_str(), attName.c_str()),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error));
+
+ auto error_ptr = amb::make_super(error);
+
+ if (error_ptr) {
+ DebugOut(DebugOut::Error) << "error calling SupportsProperty: "
+ << error_ptr->message << endl;
+
+ DebugOut() << "Could not find object for: " << objectName << endl;
+ return false;
+ }
+
+ bool supported = false;
+ g_variant_get(supportedVariant.get(), "(b)", &supported);
+
+ return supported;
+}