Implement server-side GetCurrentUser method 43/274843/8
authorAdam Michalski <a.michalski2@partner.samsung.com>
Tue, 10 May 2022 15:03:39 +0000 (17:03 +0200)
committerAdam Michalski <a.michalski2@partner.samsung.com>
Thu, 12 May 2022 15:00:57 +0000 (17:00 +0200)
Change-Id: I765ee5179e4cf4f9c849a7946ee18f5e0fc47b01

sessiond/src/main.cpp

index 5fb4f39..518bb89 100644 (file)
@@ -93,6 +93,10 @@ struct main_loop {
 };
 
 struct sessiond_context {
+       /* A special value representing the state
+        * before any sub session is switched to. */
+       static constexpr int INITIAL_SUB_SESSION_ID = 0;
+
        sessiond_context() : data(xml), id(bus_name, glib_bus_connected, glib_name_lost, this), loop()
        {
        }
@@ -176,6 +180,8 @@ struct sessiond_context {
                                vals_to_g_variant(session_uid, switch_id, prev_subsession_id, next_subsession_id), &err))
                        g_error_throw(err, "Failed to emit a signal: ");
 
+               last_subsession_per_session[session_uid] = next_subsession_id;
+
                wait_switch.try_emplace(session_uid, session_uid, connection, "SwitchUserCompleted");
                wait_switch.at(session_uid).on_start(switch_id, { prev_subsession_id, next_subsession_id });
 
@@ -292,6 +298,23 @@ struct sessiond_context {
                g_dbus_method_invocation_return_value(invocation, ret);
        }
 
+       void on_get_current_user(GDBusMethodInvocation *invocation, std::string_view sender, GVariant *parameters)
+       {
+               auto [ session_uid ] = tuple_from_g_variant<int>(parameters);
+
+               if (session_uid <= 0) {
+                       g_dbus_method_invocation_return_dbus_error(invocation, "org.freedesktop.DBus.Error.InvalidArgs", "Negative UID passed");
+                       return;
+               }
+
+               int subsession_id = INITIAL_SUB_SESSION_ID;
+               if (last_subsession_per_session.contains(session_uid))
+                       subsession_id = last_subsession_per_session.at(session_uid);
+
+               auto ret = vals_to_g_variant(subsession_id);
+               g_dbus_method_invocation_return_value(invocation, ret);
+       }
+
        static void glib_bus_connected(GDBusConnection *conn, const gchar *name, gpointer user_data)
        {
                auto self = static_cast<sessiond_context *>(user_data);
@@ -378,6 +401,10 @@ struct sessiond_context {
                                        "<arg name=\"session_uid\"        type=\"i\" direction=\"in\"/>"
                                        "<arg name=\"subsession_id_list\" type=\"ai\" direction=\"out\"/>"
                                "</method>"
+                               "<method name=\"GetCurrentUser\">"
+                                       "<arg name=\"session_uid\"        type=\"i\" direction=\"in\"/>"
+                                       "<arg name=\"subsession_id\"      type=\"i\" direction=\"out\"/>"
+                               "</method>"
                                "<signal name=\"AddUserStarted\">"
                                        "<arg name=\"session_uid\"        type=\"i\" direction=\"out\"/>"
                                        "<arg name=\"subsession_id\"      type=\"i\" direction=\"out\"/>"
@@ -413,7 +440,7 @@ struct sessiond_context {
                        std::pair<
                                std::string_view,
                                void (sessiond_context::*)(GDBusMethodInvocation *, std::string_view, GVariant *)
-                       >, 10> methods = {
+                       >, 11> methods = {
                std::make_pair("AddUser",        &sessiond_context::on_add_user),
                std::make_pair("RemoveUser",     &sessiond_context::on_remove_user),
                std::make_pair("SwitchUser",     &sessiond_context::on_switch_user),
@@ -424,14 +451,20 @@ struct sessiond_context {
                std::make_pair("RemoveUserDone", &sessiond_context::on_remove_user_done),
                std::make_pair("SwitchUserDone", &sessiond_context::on_switch_user_done),
                std::make_pair("GetUserList",    &sessiond_context::on_get_user_list),
+               std::make_pair("GetCurrentUser", &sessiond_context::on_get_current_user),
        };
 
        // TODO: Currently, the first parameter is always a single-element tuple.
        // Consider simplifying wait_manager.
+       // N.B. Although GLib is multi-threaded, the following data structures do not need
+       // to be protected by mutexes as all of them are accessed from DBus handlers only.
        std::unordered_map<int, wait_manager<std::tuple<int>, std::tuple<>>> wait_add;
        std::unordered_map<int, wait_manager<std::tuple<int>, std::tuple<>>> wait_remove;
        std::unordered_map<int, wait_manager<std::tuple<uint64_t>, std::tuple<int, int>>> wait_switch;
 
+       // used for tracking subsession switches for each `session_uid`
+       std::unordered_map<int, int> last_subsession_per_session;
+
        uint64_t switch_id = 0;
 
        introspection_data data;