Add intelligent Network Selection 75/229975/9 accepted/tizen/unified/20200417.152700 submit/tizen/20200417.010643
authorhyunuk.tak <hyunuk.tak@samsung.com>
Tue, 7 Apr 2020 03:57:45 +0000 (12:57 +0900)
committerhyunuk.tak <hyunuk.tak@samsung.com>
Thu, 16 Apr 2020 03:39:44 +0000 (12:39 +0900)
Change-Id: I049207e7d662f657ca21a4046be953f8f33bbd10
Signed-off-by: hyunuk.tak <hyunuk.tak@samsung.com>
17 files changed:
gsupplicant/gsupplicant.h [changed mode: 0644->0755]
gsupplicant/supplicant.c [changed mode: 0644->0755]
include/device.h [changed mode: 0644->0755]
include/network.h
include/service.h [changed mode: 0644->0755]
include/setting.h
packaging/connman.spec
plugins/wifi.c
src/connman.h [changed mode: 0644->0755]
src/device.c [changed mode: 0644->0755]
src/main.c [changed mode: 0644->0755]
src/main.conf
src/network.c
src/service.c [changed mode: 0644->0755]
src/storage.c
src/wispr.c [changed mode: 0644->0755]
vpn/main.c

old mode 100644 (file)
new mode 100755 (executable)
index 3e51348..6dfd9c7
@@ -179,6 +179,14 @@ typedef enum {
        G_SUPPLICANT_PEER_GROUP_FAILED,
 } GSupplicantPeerState;
 
+#if defined TIZEN_EXT
+typedef enum {
+       G_SUPPLICANT_INS_PREFERRED_FREQ_UNKNOWN,
+       G_SUPPLICANT_INS_PREFERRED_FREQ_24GHZ,
+       G_SUPPLICANT_INS_PREFERRED_FREQ_5GHZ,
+} GSupplicantINSPreferredFreq;
+#endif
+
 struct _GSupplicantSSID {
 #if defined TIZEN_EXT
        void *ssid;
@@ -469,6 +477,15 @@ const unsigned char *g_supplicant_network_get_countrycode(GSupplicantNetwork
 void *g_supplicant_network_get_bssid_list(GSupplicantNetwork *network);
 GSupplicantPhy_mode g_supplicant_network_get_phy_mode(GSupplicantNetwork *network);
 #endif
+#if defined TIZEN_EXT
+void g_supplicant_network_set_last_connected_bssid(GSupplicantNetwork *network, const unsigned char *bssid);
+const unsigned char *g_supplicant_network_get_last_connected_bssid(GSupplicantNetwork *network);
+void g_supplicant_network_update_assoc_reject(GSupplicantInterface *interface,
+               GSupplicantNetwork *network);
+GHashTable *g_supplicant_network_get_assoc_reject_table(GSupplicantNetwork *network);
+GSupplicantNetwork *g_supplicant_interface_get_network(GSupplicantInterface *interface,
+               const char *group);
+#endif
 
 struct _GSupplicantCallbacks {
        void (*system_ready) (void);
@@ -518,6 +535,13 @@ struct _GSupplicantCallbacks {
 
 typedef struct _GSupplicantCallbacks GSupplicantCallbacks;
 
+#if defined TIZEN_EXT
+void g_supplicant_set_ins_settings(GSupplicantINSPreferredFreq preferred_freq_bssid,
+               bool last_connected_bssid, bool assoc_reject, bool signal_bssid,
+               unsigned int preferred_freq_bssid_score, unsigned int last_connected_bssid_score,
+               unsigned int assoc_reject_score, int signal_level3_5ghz, int signal_level3_24ghz);
+#endif
+
 int g_supplicant_register(const GSupplicantCallbacks *callbacks);
 void g_supplicant_unregister(const GSupplicantCallbacks *callbacks);
 
old mode 100644 (file)
new mode 100755 (executable)
index 2e8af6a..957312c
 #define WIFI_BSSID_LEN_MAX 6
 #endif
 
+#if defined TIZEN_EXT
+#define LAST_CONNECTED_TIMEOUT       (5 * 60)
+#define ASSOC_REJECT_TIMEOUT         10
+#define FREQ_RANGE_24GHZ_CHANNEL_1   2412
+#define FREQ_RANGE_24GHZ_CHANNEL_14  2484
+#define FREQ_RANGE_5GHZ_CHANNEL_32   5160
+#define FREQ_RANGE_5GHZ_CHANNEL_165  5825
+#endif
+
 #define BSS_UNKNOWN_STRENGTH    -90
 
 static DBusConnection *connection;
@@ -155,6 +164,26 @@ static struct strvalmap mode_capa_map[] = {
        { }
 };
 
+#if defined TIZEN_EXT
+struct _GSupplicantINSSettings {
+       GSupplicantINSPreferredFreq preferred_freq_bssid;
+       unsigned int preferred_freq_bssid_score;
+       bool last_connected_bssid;
+       unsigned int last_connected_bssid_score;
+       bool assoc_reject;
+       unsigned int assoc_reject_score;
+       bool signal_bssid;
+       int signal_level3_5ghz;
+       int signal_level3_24ghz;
+};
+
+static struct _GSupplicantINSSettings ins_settings;
+
+static unsigned char invalid_bssid[WIFI_BSSID_LEN_MAX] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+#endif
+
 static GHashTable *interface_table;
 static GHashTable *bss_mapping;
 static GHashTable *peer_mapping;
@@ -225,6 +254,10 @@ struct _GSupplicantInterface {
        dbus_bool_t is_5_0_Ghz_supported;
        int disconnect_reason;
 #endif
+#if defined TIZEN_EXT
+       unsigned char add_network_bssid[WIFI_BSSID_LEN_MAX];
+       unsigned char connected_bssid[WIFI_BSSID_LEN_MAX];
+#endif
 #if defined TIZEN_EXT_WIFI_MESH
        bool mesh_support;
        struct _GSupplicantMeshGroupInfo group_info;
@@ -295,6 +328,10 @@ struct _GSupplicantNetwork {
        unsigned char country_code[COUNTRY_CODE_LENGTH];
        GSupplicantPhy_mode phy_mode;
 #endif
+#if defined TIZEN_EXT
+       unsigned char last_connected_bssid[WIFI_BSSID_LEN_MAX];
+       GHashTable *assoc_reject_table;
+#endif
 };
 
 struct _GSupplicantPeer {
@@ -377,7 +414,29 @@ struct g_connman_bssids {
        unsigned char bssid[WIFI_BSSID_LEN_MAX];
        uint16_t strength;
        uint16_t frequency;
+       uint16_t assoc_reject_cnt;
+       bool is_last_connected;
+       int ins_score;
 };
+
+struct update_bssid_data {
+       GSupplicantNetwork *network;
+       unsigned char last_connected_bssid[WIFI_BSSID_LEN_MAX];
+       GHashTable *assoc_reject_table;
+       GSList *bssid_list;
+};
+
+struct assoc_reject_data {
+       char *bssid;
+       GSList *reject_time_list;
+};
+
+struct assoc_count_data {
+       time_t ref_time;
+       int assoc_count;
+};
+
+static unsigned int last_connected_bss_timeout = 0;
 #endif
 
 static int network_remove(struct interface_data *data);
@@ -971,6 +1030,9 @@ static void remove_network(gpointer data)
        callback_network_removed(network);
 
        g_hash_table_destroy(network->config_table);
+#if defined TIZEN_EXT
+       g_hash_table_destroy(network->assoc_reject_table);
+#endif
 
        g_free(network->path);
        g_free(network->group);
@@ -1023,6 +1085,18 @@ static void remove_peer(gpointer data)
        g_free(peer);
 }
 
+#if defined TIZEN_EXT
+static void remove_assoc_data(gpointer data)
+{
+       struct assoc_reject_data *assoc_data = data;
+
+       g_free(assoc_data->bssid);
+       g_slist_free(assoc_data->reject_time_list);
+
+       g_free(assoc_data);
+}
+#endif
+
 static void debug_strvalmap(const char *label, struct strvalmap *map,
                                                        unsigned int val)
 {
@@ -1807,11 +1881,92 @@ void *g_supplicant_network_get_wifi_vsie(GSupplicantNetwork *network)
        return vsie_list;
 }
 
+static bool compare_bssid(unsigned char *bssid_a, unsigned char *bssid_b)
+{
+       if (!memcmp(bssid_a, bssid_b, WIFI_BSSID_LEN_MAX))
+               return true;
+
+       return false;
+}
+
+static gchar *convert_bssid_to_str(unsigned char *bssid)
+{
+       GString *bssid_str;
+       unsigned int i;
+
+       bssid_str = g_string_sized_new(18);
+       if (!bssid_str)
+               return NULL;
+
+       for (i = 0; i < WIFI_BSSID_LEN_MAX; i++) {
+               g_string_append_printf(bssid_str, "%02x", bssid[i]);
+               if (i < WIFI_BSSID_LEN_MAX - 1)
+                       g_string_append(bssid_str, ":");
+       }
+
+       return g_string_free(bssid_str, FALSE);
+}
+
+static void count_assoc_reject(gpointer data, gpointer user_data)
+{
+       time_t assoc_reject_time = GPOINTER_TO_INT(data);
+       struct assoc_count_data *assoc_count = user_data;
+
+       if (assoc_reject_time > assoc_count->ref_time)
+               assoc_count->assoc_count++;
+}
+
+static uint16_t get_assoc_reject_cnt(GHashTable *assoc_reject_table, unsigned char *bssid)
+{
+       gchar *bssid_str;
+       struct assoc_reject_data *assoc_data;
+       struct assoc_count_data assoc_count;
+       time_t curr_time;
+       struct tm* timeinfo;
+
+       if (g_hash_table_size(assoc_reject_table) < 1)
+               return 0;
+
+       if (!bssid)
+               return 0;
+
+       if (!memcmp(bssid, invalid_bssid, WIFI_BSSID_LEN_MAX))
+               return 0;
+
+       bssid_str = convert_bssid_to_str(bssid);
+       if (!bssid_str)
+               return 0;
+
+       assoc_data = g_hash_table_lookup(assoc_reject_table, bssid_str);
+       if (!assoc_data) {
+               g_free(bssid_str);
+               return 0;
+       }
+
+       if (g_slist_length(assoc_data->reject_time_list) < 1) {
+               g_free(bssid_str);
+               return 0;
+       }
+
+       /* Only events that occur within one hour are appened. */
+       curr_time = time(NULL);
+       timeinfo = localtime(&curr_time);
+       timeinfo->tm_hour -= 1;
+
+       assoc_count.ref_time = mktime(timeinfo);
+       assoc_count.assoc_count = 0;
+
+       g_slist_foreach(assoc_data->reject_time_list, count_assoc_reject, &assoc_count);
+
+       g_free(bssid_str);
+       return assoc_count.assoc_count;
+}
+
 static void update_bssid_list(gpointer key, gpointer value, gpointer user_data)
 {
        struct g_supplicant_bss *bss = value;
        struct g_connman_bssids *bssids = NULL;
-       GSList **list = (GSList **)user_data;
+       struct update_bssid_data *bssid_data = (struct update_bssid_data *)user_data;
 
        bssids = (struct g_connman_bssids *)g_try_malloc0(sizeof(struct g_connman_bssids));
 
@@ -1825,36 +1980,187 @@ static void update_bssid_list(gpointer key, gpointer value, gpointer user_data)
                        bssids->strength = 100;
 
                bssids->frequency = bss->frequency;
-               *list = g_slist_append(*list, bssids);
+
+               bssids->assoc_reject_cnt = get_assoc_reject_cnt(bssid_data->assoc_reject_table, bssids->bssid);
+
+               bssids->is_last_connected = compare_bssid(bssids->bssid, bssid_data->last_connected_bssid);
+
+               bssid_data->bssid_list = g_slist_append(bssid_data->bssid_list, bssids);
        } else
                SUPPLICANT_DBG("Failed to allocate memory");
 }
 
+static int calculate_score(dbus_int16_t strength, dbus_uint16_t frequency,
+               uint16_t assoc_reject_cnt, bool is_last_connected)
+{
+       int score = 0;
+
+       /* 5GHz & Signal >= RSSI Level 3 */
+       switch (ins_settings.preferred_freq_bssid) {
+       case G_SUPPLICANT_INS_PREFERRED_FREQ_24GHZ:
+               if ((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
+                       frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
+                       (strength > ins_settings.signal_level3_24ghz))
+                       score += ins_settings.preferred_freq_bssid_score;
+
+               break;
+       case G_SUPPLICANT_INS_PREFERRED_FREQ_5GHZ:
+               if ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
+                       frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
+                       (strength > ins_settings.signal_level3_5ghz))
+                       score += ins_settings.preferred_freq_bssid_score;
+
+               break;
+       default:
+               break;
+       }
+
+       /* Last connected BSSID */
+       if (ins_settings.last_connected_bssid) {
+               if (is_last_connected)
+                       score += ins_settings.last_connected_bssid_score;
+       }
+
+       /* Assoc reject */
+       if (ins_settings.assoc_reject)
+               score -= (assoc_reject_cnt * ins_settings.assoc_reject_score);
+
+       /* Signal */
+       if (ins_settings.signal_bssid)
+               score += (((strength > -60) ? -60 : strength) + 85);
+
+       return score;
+}
+
 static gint cmp_bss(gconstpointer a, gconstpointer b)
 {
        struct g_connman_bssids *entry_a = (struct g_connman_bssids *)a;
        struct g_connman_bssids *entry_b = (struct g_connman_bssids *)b;
+       int score_a = calculate_score(entry_a->strength - 120, entry_a->frequency,
+                       entry_a->assoc_reject_cnt, entry_a->is_last_connected);
+       int score_b = calculate_score(entry_b->strength - 120, entry_b->frequency,
+                       entry_b->assoc_reject_cnt, entry_b->is_last_connected);
+
+       entry_a->ins_score = score_a;
+       entry_b->ins_score = score_b;
 
-       if (entry_a->strength > entry_b->strength)
+       if (score_a > score_b)
                return -1;
 
-       if (entry_a->strength < entry_b->strength)
+       if (score_a < score_b)
                return 1;
 
        return 0;
 }
 
+#if defined TIZEN_EXT_INS
+static void print_bssid_sort(gpointer data, gpointer user_data)
+{
+       struct g_connman_bssids *bssids = data;
+
+       SUPPLICANT_DBG("bssid[%02x:%02x:%02x:%02x:%02x:%02x] score[%d] "
+                       "strength[%d] freq[%d] assoc_reject[%d] last_conn[%d]",
+                       bssids->bssid[0], bssids->bssid[1], bssids->bssid[2],
+                       bssids->bssid[3], bssids->bssid[4], bssids->bssid[5],
+                       bssids->ins_score, bssids->strength, bssids->frequency,
+                       bssids->assoc_reject_cnt, bssids->is_last_connected);
+}
+#endif
+
 void *g_supplicant_network_get_bssid_list(GSupplicantNetwork *network)
 {
-       GSList *bssid_list = NULL;
+       struct update_bssid_data bssid_data;
 
        if (g_hash_table_size(network->bss_table) < 1)
                return NULL;
 
-       g_hash_table_foreach(network->bss_table, update_bssid_list, &bssid_list);
-       bssid_list = g_slist_sort(bssid_list, cmp_bss);
+       bssid_data.network = network;
+       memset(&bssid_data, 0, sizeof(bssid_data));
+       memcpy(bssid_data.last_connected_bssid, network->last_connected_bssid, WIFI_BSSID_LEN_MAX);
+       bssid_data.assoc_reject_table = network->assoc_reject_table;
+
+       g_hash_table_foreach(network->bss_table, update_bssid_list, &bssid_data);
+       bssid_data.bssid_list = g_slist_sort(bssid_data.bssid_list, cmp_bss);
+#if defined TIZEN_EXT_INS
+       g_slist_foreach(bssid_data.bssid_list, print_bssid_sort, NULL);
+#endif
+
+       return bssid_data.bssid_list;
+}
+
+void g_supplicant_network_set_last_connected_bssid(GSupplicantNetwork *network, const unsigned char *bssid)
+{
+       if (!bssid)
+               return;
+
+       if (!memcmp(bssid, invalid_bssid, WIFI_BSSID_LEN_MAX))
+               return;
+
+       memcpy(network->last_connected_bssid, bssid, WIFI_BSSID_LEN_MAX);
+
+       SUPPLICANT_DBG("last connected bssid [%02x:%02x:%02x:%02x:%02x:%02x]",
+                       bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
+}
+
+const unsigned char *g_supplicant_network_get_last_connected_bssid(GSupplicantNetwork *network)
+{
+       if (network == NULL)
+               return NULL;
 
-       return bssid_list;
+       return (const unsigned char *)network->last_connected_bssid;
+}
+
+void g_supplicant_network_update_assoc_reject(GSupplicantInterface *interface,
+               GSupplicantNetwork *network)
+{
+       struct assoc_reject_data *assoc_data;
+       gchar *bssid_str;
+       time_t curr_time;
+
+       if (!network)
+               return;
+
+       bssid_str = convert_bssid_to_str(interface->add_network_bssid);
+       if (!bssid_str)
+               return;
+
+       assoc_data = g_hash_table_lookup(network->assoc_reject_table, bssid_str);
+       if (!assoc_data) {
+               assoc_data = g_try_new0(struct assoc_reject_data, 1);
+               if (!assoc_data) {
+                       g_free(bssid_str);
+                       return;
+               }
+
+               assoc_data->bssid = g_strdup(bssid_str);
+               g_hash_table_insert(network->assoc_reject_table, assoc_data->bssid, assoc_data);
+       }
+
+       curr_time = time(NULL);
+       assoc_data->reject_time_list = g_slist_append(assoc_data->reject_time_list, GINT_TO_POINTER(curr_time));
+
+       SUPPLICANT_DBG("bssid [%s] time [%u]", bssid_str, curr_time);
+
+       g_free(bssid_str);
+
+       callback_network_changed(network, "UpdateAssocReject");
+}
+
+GHashTable *g_supplicant_network_get_assoc_reject_table(GSupplicantNetwork *network)
+{
+       if (!network)
+               return NULL;
+
+       return network->assoc_reject_table;
+}
+
+GSupplicantNetwork *g_supplicant_interface_get_network(GSupplicantInterface *interface,
+               const char *group)
+{
+       if (!interface)
+               return NULL;
+
+       return g_hash_table_lookup(interface->network_table, group);
 }
 #endif
 
@@ -2093,6 +2399,42 @@ static char *create_group(struct g_supplicant_bss *bss)
        return g_string_free(str, FALSE);
 }
 
+static bool update_best_bss(GSupplicantNetwork *network,
+               struct g_supplicant_bss *bss, struct g_supplicant_bss *best_bss)
+{
+       int score_new;
+       int score_best;
+
+       score_new = calculate_score(bss->signal, bss->frequency,
+               get_assoc_reject_cnt(network->assoc_reject_table, bss->bssid),
+               compare_bssid(bss->bssid, network->last_connected_bssid));
+       score_best = calculate_score(network->best_bss->signal, network->best_bss->frequency,
+               get_assoc_reject_cnt(network->assoc_reject_table, network->best_bss->bssid),
+               compare_bssid(network->best_bss->bssid, network->last_connected_bssid));
+
+       if (score_new > score_best) {
+               SUPPLICANT_DBG("new[%02x:%02x:%02x:%02x:%02x:%02x][%u] : "
+                       "best[%02x:%02x:%02x:%02x:%02x:%02x][%u]",
+                       bss->bssid[0], bss->bssid[1], bss->bssid[2],
+                       bss->bssid[3], bss->bssid[4], bss->bssid[5],
+                       score_new,
+                       network->best_bss->bssid[0], network->best_bss->bssid[1],
+                       network->best_bss->bssid[2], network->best_bss->bssid[3],
+                       network->best_bss->bssid[4], network->best_bss->bssid[5],
+                       score_best);
+
+               network->signal = bss->signal;
+               network->frequency = bss->frequency;
+               network->best_bss = bss;
+
+               SUPPLICANT_DBG("Update best BSS for %s", network->name);
+
+               return true;
+       }
+
+       return false;
+}
+
 static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
 {
        GSupplicantInterface *interface = bss->interface;
@@ -2172,6 +2514,11 @@ static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
        network->config_table = g_hash_table_new_full(g_str_hash, g_str_equal,
                                                        g_free, g_free);
 
+#if defined TIZEN_EXT
+       network->assoc_reject_table = g_hash_table_new_full(g_str_hash, g_str_equal,
+                                                       NULL, remove_assoc_data);
+#endif
+
        g_hash_table_replace(interface->network_table,
                                                network->group, network);
 
@@ -2191,12 +2538,19 @@ done:
         * Do not change best BSS if we are connected. It will be done through
         * CurrentBSS property in case of misalignment with wpa_s or roaming.
         */
+#if defined TIZEN_EXT
+       if (network != interface->current_network) {
+               if (update_best_bss(network, bss, network->best_bss))
+                       callback_network_changed(network, "Signal");
+       }
+#else
        if (network != interface->current_network &&
                                bss->signal > network->signal) {
                network->signal = bss->signal;
                network->best_bss = bss;
                callback_network_changed(network, "Signal");
        }
+#endif
 
        g_hash_table_replace(interface->bss_mapping, bss->path, network);
        g_hash_table_replace(network->bss_table, bss->path, bss);
@@ -2818,10 +3172,22 @@ static void update_signal(gpointer key, gpointer value,
        struct g_supplicant_bss *bss = value;
        GSupplicantNetwork *network = user_data;
 
+#if defined TIZEN_EXT
+       if (!network->best_bss || (network->best_bss == bss)) {
+               if (bss->signal > network->signal) {
+                       network->signal = bss->signal;
+                       network->best_bss = bss;
+               }
+               return;
+       }
+
+       update_best_bss(network, bss, network->best_bss);
+#else
        if (bss->signal > network->signal) {
                network->signal = bss->signal;
                network->best_bss = bss;
        }
+#endif
 }
 
 static void update_network_signal(GSupplicantNetwork *network)
@@ -2835,6 +3201,61 @@ static void update_network_signal(GSupplicantNetwork *network)
        SUPPLICANT_DBG("New network signal %d", network->signal);
 }
 
+#if defined TIZEN_EXT
+static gboolean last_connected_timeout(gpointer data)
+{
+       GSupplicantInterface *interface = data;
+       GSupplicantNetwork *current_network = interface->current_network;
+
+       SUPPLICANT_DBG("Timeout last connected bss");
+
+       if (current_network && current_network->best_bss) {
+               if (compare_bssid(current_network->best_bss->bssid, interface->connected_bssid)) {
+                       g_supplicant_network_set_last_connected_bssid(current_network, interface->connected_bssid);
+                       callback_network_changed(current_network, "LastConnectedBSSID");
+               }
+       }
+
+       last_connected_bss_timeout = 0;
+       return FALSE;
+}
+
+static void add_timer_for_last_connected(GSupplicantInterface *interface)
+{
+       GSupplicantNetwork *current_network = interface->current_network;
+
+       if (interface->state == G_SUPPLICANT_STATE_COMPLETED) {
+               if (current_network) {
+                       struct g_supplicant_bss *best_bss = current_network->best_bss;
+
+                       memcpy(interface->connected_bssid, best_bss->bssid, WIFI_BSSID_LEN_MAX);
+
+                       if (last_connected_bss_timeout)
+                               g_source_remove(last_connected_bss_timeout);
+
+                       last_connected_bss_timeout = g_timeout_add_seconds(LAST_CONNECTED_TIMEOUT,
+                               last_connected_timeout, interface);
+
+                       SUPPLICANT_DBG("Add timer for last connected bssid "
+                               "[%02x:%02x:%02x:%02x:%02x:%02x]",
+                               best_bss->bssid[0], best_bss->bssid[1], best_bss->bssid[2],
+                               best_bss->bssid[3], best_bss->bssid[4], best_bss->bssid[5]);
+               }
+       }
+}
+
+static void remove_timer_for_last_connected(GSupplicantInterface *interface)
+{
+       if (interface->state == G_SUPPLICANT_STATE_DISCONNECTED) {
+               if (last_connected_bss_timeout != 0) {
+                       g_source_remove(last_connected_bss_timeout);
+                       last_connected_bss_timeout = 0;
+                       SUPPLICANT_DBG("Remove timer for last connected bss");
+               }
+       }
+}
+#endif
+
 static void interface_current_bss(GSupplicantInterface *interface,
                                                DBusMessageIter *iter)
 {
@@ -2859,6 +3280,9 @@ static void interface_current_bss(GSupplicantInterface *interface,
                return;
 
        interface->current_network = network;
+#if defined TIZEN_EXT
+       SUPPLICANT_DBG("current network [%p]", interface->current_network);
+#endif
 
        if (bss != network->best_bss) {
                /*
@@ -2900,6 +3324,9 @@ static void interface_current_bss(GSupplicantInterface *interface,
        case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
        case G_SUPPLICANT_STATE_COMPLETED:
                callback_network_associated(network);
+#if defined TIZEN_EXT
+               add_timer_for_last_connected(interface);
+#endif
                break;
        }
 }
@@ -3037,7 +3464,18 @@ static void interface_property(const char *key, DBusMessageIter *iter,
                                interface->state = string2state(str);
                                callback_interface_state(interface);
                        }
-
+#if defined TIZEN_EXT
+               switch (interface->state) {
+               case G_SUPPLICANT_STATE_COMPLETED:
+                       add_timer_for_last_connected(interface);
+                       break;
+               case G_SUPPLICANT_STATE_DISCONNECTED:
+                       remove_timer_for_last_connected(interface);
+                       break;
+               default:
+                       break;
+               }
+#endif
                if (interface->ap_create_in_progress) {
                        if (interface->state == G_SUPPLICANT_STATE_DISCONNECTED)
                                callback_ap_create_fail(interface);
@@ -3122,12 +3560,18 @@ static void interface_property(const char *key, DBusMessageIter *iter,
                if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
                        dbus_message_iter_get_basic(iter, &reason_code);
                        callback_disconnect_reason_code(interface, reason_code);
+#if defined TIZEN_EXT
+                       SUPPLICANT_DBG("reason code (%d)", reason_code);
+#endif
                }
        } else if (g_strcmp0(key, "AssocStatusCode") == 0) {
                int status_code;
                if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
                        dbus_message_iter_get_basic(iter, &status_code);
                        callback_assoc_status_code(interface, status_code);
+#if defined TIZEN_EXT
+                       SUPPLICANT_DBG("status code (%d)", status_code);
+#endif
                }
        } else {
                SUPPLICANT_DBG("key %s type %c",
@@ -3658,22 +4102,28 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter)
         * If the new signal is lower than the SSID signal, we need
         * to check for the new maximum.
         */
-       if (bss->signal < network->signal) {
-               if (bss != network->best_bss)
-#ifndef TIZEN_EXT
-                       return;
-#else
-               {
+#if defined TIZEN_EXT
+       if (!update_best_bss(network, bss, network->best_bss)) {
+               if (bss != network->best_bss) {
                        callback_network_changed(network, "");
                        return;
                }
-#endif
+
+               network->signal = bss->signal;
+               update_network_signal(network);
+       }
+#else
+       if (bss->signal < network->signal) {
+               if (bss != network->best_bss)
+                       return;
+
                network->signal = bss->signal;
                update_network_signal(network);
        } else {
                network->signal = bss->signal;
                network->best_bss = bss;
        }
+#endif
 
        SUPPLICANT_DBG("New network signal for %s %d dBm", network->ssid,
                        network->signal);
@@ -6474,6 +6924,9 @@ static void interface_add_network_params(DBusMessageIter *iter, void *user_data)
        DBusMessageIter dict;
        struct interface_connect_data *data = user_data;
        GSupplicantSSID *ssid = data->ssid;
+#if defined TIZEN_EXT
+       GSupplicantInterface *interface = data->interface;
+#endif
 
        supplicant_dbus_dict_open(iter, &dict);
 
@@ -6511,14 +6964,22 @@ static void interface_add_network_params(DBusMessageIter *iter, void *user_data)
                        return;
                }
 
-               if (ssid->bssid_for_connect_len)
+               if (ssid->bssid_for_connect_len) {
                        snprintf(bssid, 18, "%02x:%02x:%02x:%02x:%02x:%02x",
                                        ssid->bssid_for_connect[0], ssid->bssid_for_connect[1], ssid->bssid_for_connect[2],
                                        ssid->bssid_for_connect[3], ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
-               else
+                       memcpy(interface->add_network_bssid, ssid->bssid_for_connect, WIFI_BSSID_LEN_MAX);
+               } else {
                        snprintf(bssid, 18, "%02x:%02x:%02x:%02x:%02x:%02x",
                                        ssid->bssid[0], ssid->bssid[1], ssid->bssid[2],
                                        ssid->bssid[3], ssid->bssid[4], ssid->bssid[5]);
+                       memcpy(interface->add_network_bssid, ssid->bssid, WIFI_BSSID_LEN_MAX);
+               }
+
+               SUPPLICANT_DBG("bssid [%02x:%02x:%02x:%02x:%02x:%02x]",
+                       interface->add_network_bssid[0], interface->add_network_bssid[1],
+                       interface->add_network_bssid[2], interface->add_network_bssid[3],
+                       interface->add_network_bssid[4], interface->add_network_bssid[5]);
 
                supplicant_dbus_dict_append_basic(&dict, "bssid",
                                        DBUS_TYPE_STRING, &bssid);
@@ -7706,6 +8167,34 @@ static void invoke_introspect_method(void)
        dbus_message_unref(message);
 }
 
+#if defined TIZEN_EXT
+void g_supplicant_set_ins_settings(GSupplicantINSPreferredFreq preferred_freq_bssid,
+               bool last_connected_bssid, bool assoc_reject, bool signal_bssid,
+               unsigned int preferred_freq_bssid_score, unsigned int last_connected_bssid_score,
+               unsigned int assoc_reject_score, int signal_level3_5ghz, int signal_level3_24ghz)
+{
+       ins_settings.preferred_freq_bssid = preferred_freq_bssid;
+       ins_settings.last_connected_bssid = last_connected_bssid;
+       ins_settings.assoc_reject = assoc_reject;
+       ins_settings.signal_bssid = signal_bssid;
+       ins_settings.preferred_freq_bssid_score = preferred_freq_bssid_score;
+       ins_settings.last_connected_bssid_score = last_connected_bssid_score;
+       ins_settings.assoc_reject_score = assoc_reject_score;
+       ins_settings.signal_level3_5ghz = signal_level3_5ghz;
+       ins_settings.signal_level3_24ghz = signal_level3_24ghz;
+
+       SUPPLICANT_DBG("preferred_freq_bssid [%s]", preferred_freq_bssid ? "true" : "false");
+       SUPPLICANT_DBG("preferred_freq_bssid_score [%d]", preferred_freq_bssid_score);
+       SUPPLICANT_DBG("last_connected_bssid [%s]", last_connected_bssid ? "true" : "false");
+       SUPPLICANT_DBG("last_connected_bssid_score [%d]", last_connected_bssid_score);
+       SUPPLICANT_DBG("assoc_reject [%s]", assoc_reject ? "true" : "false");
+       SUPPLICANT_DBG("assoc_reject_score [%d]", assoc_reject_score);
+       SUPPLICANT_DBG("signal_bssid [%s]", signal_bssid ? "true" : "false");
+       SUPPLICANT_DBG("signal_level3_5ghz [%d]", signal_level3_5ghz);
+       SUPPLICANT_DBG("signal_level3_24ghz [%d]", signal_level3_24ghz);
+}
+#endif
+
 int g_supplicant_register(const GSupplicantCallbacks *callbacks)
 {
        connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
old mode 100644 (file)
new mode 100755 (executable)
index 77c476a..98c7bd8
@@ -123,6 +123,22 @@ struct connman_device *connman_device_create_from_index(int index);
 struct connman_device *connman_device_find_by_index(int index);
 int connman_device_reconnect_service(struct connman_device *device);
 
+#if defined TIZEN_EXT
+bool connman_device_set_last_user_selection_time(struct connman_device *device,
+                                               time_t time);
+time_t connman_device_get_last_user_selection_time(struct connman_device *device);
+bool connman_device_set_last_user_selection_ident(struct connman_device *device,
+                                               const char *ident);
+const char *connman_device_get_last_user_selection_ident(struct connman_device *device);
+bool connman_device_set_last_connected_ident(struct connman_device *device,
+                                               const char *ident);
+const char *connman_device_get_last_connected_ident(struct connman_device *device);
+void connman_device_save_last_user_selection(struct connman_device *device);
+void connman_device_load_last_user_selection(struct connman_device *device);
+void connman_device_save_last_connected(struct connman_device *device);
+void connman_device_load_last_connected(struct connman_device *device);
+#endif
+
 struct connman_device_driver {
        const char *name;
        enum connman_device_type type;
index 14b9442..8cefb79 100755 (executable)
@@ -211,6 +211,14 @@ unsigned char *connman_network_get_countrycode(struct connman_network *network);
 int connman_network_set_bssid_list(struct connman_network *network,
                                        GSList *bssids);
 void *connman_network_get_bssid_list(struct connman_network *network);
+#if defined TIZEN_EXT
+int connman_network_set_last_connected_bssid(struct connman_network *network,
+                               const unsigned char *bssid);
+unsigned char *connman_network_get_last_connected_bssid(struct connman_network *network);
+void connman_network_set_assoc_reject_table(struct connman_network *network,
+               GHashTable *assoc_reject_table);
+GHashTable *connman_network_get_assoc_reject_table(struct connman_network *network);
+#endif
 int connman_network_set_phy_mode(struct connman_network *network,
                                ieee80211_modes_e mode);
 ieee80211_modes_e connman_network_get_phy_mode(struct connman_network *network);
old mode 100644 (file)
new mode 100755 (executable)
index 0337186..617735e
@@ -73,6 +73,9 @@ enum connman_service_security {
        CONNMAN_SERVICE_SECURITY_OWE     = 11,
        CONNMAN_SERVICE_SECURITY_DPP     = 12,
 #endif
+#if defined TIZEN_EXT
+       CONNMAN_SERVICE_SECURITY_MAX
+#endif
 };
 
 enum connman_service_state {
@@ -201,6 +204,12 @@ void connman_service_set_disconnection_requested(struct connman_service *service
                                                 bool disconnection_requested);
 #endif
 
+#if defined TIZEN_EXT
+void connman_service_set_internet_connection(struct connman_service *service,
+                                                       bool internet_connection);
+bool connman_service_get_internet_connection(struct connman_service *service);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
index a882021..3625f3e 100755 (executable)
@@ -29,6 +29,10 @@ extern "C" {
 #endif
 
 bool connman_setting_get_bool(const char *key);
+#if defined TIZEN_EXT
+unsigned int connman_setting_get_uint(const char *key);
+int connman_setting_get_int(const char *key);
+#endif
 char **connman_setting_get_string_list(const char *key);
 unsigned int *connman_setting_get_uint_list(const char *key);
 
index f4fa2a9..31ab4ca 100644 (file)
@@ -5,7 +5,7 @@
 
 Name:           connman
 Version:        1.37
-Release:        35
+Release:        36
 License:        GPL-2.0+
 Summary:        Connection Manager
 Url:            http://connman.net
index bbfdbf9..bce1424 100755 (executable)
@@ -4305,8 +4305,19 @@ static void interface_state(GSupplicantInterface *interface)
 #if defined TIZEN_EXT
                if (handle_assoc_status_code(interface, wifi)) {
                        GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
+                       const char *group = connman_network_get_group(network);
+                       GSupplicantNetwork *supplicant_network;
                        guint bssid_length = 0;
 
+                       if (group) {
+                               supplicant_network = g_supplicant_interface_get_network(interface, group);
+
+                               connman_network_set_assoc_reject_table(network,
+                                       g_supplicant_network_get_assoc_reject_table(supplicant_network));
+
+                               g_supplicant_network_update_assoc_reject(interface, supplicant_network);
+                       }
+
                        if (bssid_list)
                                bssid_length = g_slist_length(bssid_list);
 
@@ -4817,6 +4828,10 @@ static void network_added(GSupplicantNetwork *supplicant_network)
                        g_supplicant_network_is_hs20AP(supplicant_network));
        connman_network_set_bssid_list(network,
                        (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
+       connman_network_set_last_connected_bssid(network,
+                       g_supplicant_network_get_last_connected_bssid(supplicant_network));
+       connman_network_set_assoc_reject_table(network,
+                       g_supplicant_network_get_assoc_reject_table(supplicant_network));
 #endif
        connman_network_set_available(network, true);
        connman_network_set_string(network, "WiFi.Mode", mode);
@@ -4829,6 +4844,11 @@ static void network_added(GSupplicantNetwork *supplicant_network)
                connman_network_set_group(network, group);
 
 #if defined TIZEN_EXT
+       g_supplicant_network_set_last_connected_bssid(supplicant_network,
+                       connman_network_get_last_connected_bssid(network));
+#endif
+
+#if defined TIZEN_EXT
        if (wifi_first_scan == true)
                found_with_first_scan = true;
 #endif
@@ -4924,7 +4944,11 @@ static void network_changed(GSupplicantNetwork *network, const char *property)
        identifier = g_supplicant_network_get_identifier(network);
        name = g_supplicant_network_get_name(network);
 
+#if defined TIZEN_EXT
+       DBG("name %s property %s", name, property);
+#else
        DBG("name %s", name);
+#endif
 
        if (!wifi)
                return;
@@ -4964,7 +4988,35 @@ static void network_changed(GSupplicantNetwork *network, const char *property)
                connman_network_set_strength(connman_network,
                                        calculate_strength(network));
                update_needed = true;
-       } else
+       }
+#if defined TIZEN_EXT
+       else if (g_str_equal(property, "LastConnectedBSSID")) {
+               const char *ident, *group;
+               char *service_ident;
+               bool need_save;
+
+               ident = connman_device_get_ident(wifi->device);
+               group = connman_network_get_group(connman_network);
+               if (ident && group) {
+                       service_ident = g_strdup_printf("%s_%s_%s",
+                               __connman_network_get_type(connman_network), ident, group);
+
+                       need_save = connman_device_set_last_connected_ident(wifi->device, service_ident);
+                       if (need_save)
+                               connman_device_save_last_connected(wifi->device);
+               }
+
+               connman_network_set_last_connected_bssid(connman_network,
+                                       g_supplicant_network_get_last_connected_bssid(network));
+
+               update_needed = true;
+       } else if (g_str_equal(property, "UpdateAssocReject")) {
+               connman_network_set_assoc_reject_table(connman_network,
+                                       g_supplicant_network_get_assoc_reject_table(network));
+               update_needed = true;
+       }
+#endif
+       else
                update_needed = false;
 
        if (update_needed)
@@ -5380,7 +5432,11 @@ static void scan_done(GSupplicantInterface *interface)
 
 static void debug(const char *str)
 {
+#if defined TIZEN_EXT
+       if (connman_setting_get_bool("ConnmanSupplicantDebug"))
+#else
        if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
+#endif
                connman_debug("%s", str);
 }
 
@@ -5741,6 +5797,33 @@ static int tech_set_regdom(struct connman_technology *technology, const char *al
        return g_supplicant_set_country(alpha2, regdom_callback, NULL);
 }
 
+#if defined TIZEN_EXT
+static void supp_ins_init(void)
+{
+       const char *string;
+       GSupplicantINSPreferredFreq preferred_freq;
+
+       string = connman_option_get_string("INSPreferredFreqBSSID");
+       if (g_strcmp0(string, "5GHz") == 0)
+               preferred_freq = G_SUPPLICANT_INS_PREFERRED_FREQ_5GHZ;
+       else if (g_strcmp0(string, "2.4GHz") == 0)
+               preferred_freq = G_SUPPLICANT_INS_PREFERRED_FREQ_24GHZ;
+       else
+               preferred_freq = G_SUPPLICANT_INS_PREFERRED_FREQ_UNKNOWN;
+
+       g_supplicant_set_ins_settings(preferred_freq,
+               connman_setting_get_bool("INSLastConnectedBSSID"),
+               connman_setting_get_bool("INSAssocReject"),
+               connman_setting_get_bool("INSSignalBSSID"),
+               connman_setting_get_uint("INSPreferredFreqBSSIDScore"),
+               connman_setting_get_uint("INSLastConnectedBSSIDScore"),
+               connman_setting_get_uint("INSAssocRejectScore"),
+               connman_setting_get_int("INSSignalLevel3_5GHz"),
+               connman_setting_get_int("INSSignalLevel3_24GHz")
+       );
+}
+#endif
+
 static struct connman_technology_driver tech_driver = {
        .name           = "wifi",
        .type           = CONNMAN_SERVICE_TYPE_WIFI,
@@ -5774,6 +5857,10 @@ static int wifi_init(void)
 #if defined TIZEN_EXT
        failed_bssids = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
 #endif
+
+#if defined TIZEN_EXT
+       supp_ins_init();
+#endif
        return 0;
 }
 
old mode 100644 (file)
new mode 100755 (executable)
index 57c3050..833e09a
@@ -279,6 +279,10 @@ GKeyFile *__connman_storage_open_global(void);
 GKeyFile *__connman_storage_load_global(void);
 int __connman_storage_save_global(GKeyFile *keyfile);
 void __connman_storage_delete_global(void);
+#if defined TIZEN_EXT
+GKeyFile *__connman_storage_load_ins(void);
+int __connman_storage_save_ins(GKeyFile *keyfile);
+#endif
 
 GKeyFile *__connman_storage_load_config(const char *ident);
 GKeyFile *__connman_storage_load_provider_config(const char *ident);
old mode 100644 (file)
new mode 100755 (executable)
index df7b2bb..2029871
@@ -68,6 +68,11 @@ struct connman_device {
        char *last_network;
        struct connman_network *network;
        GHashTable *networks;
+#if defined TIZEN_EXT
+       time_t last_user_selection_time;
+       char *last_user_selection_ident;
+       char *last_connected_ident;
+#endif
 };
 
 static void clear_pending_trigger(struct connman_device *device)
@@ -423,6 +428,11 @@ static void device_destruct(struct connman_device *device)
 
        g_free(device->last_network);
 
+#if defined TIZEN_EXT
+       g_free(device->last_user_selection_ident);
+       g_free(device->last_connected_ident);
+#endif
+
        g_free(device);
 }
 
@@ -696,6 +706,194 @@ int connman_device_reconnect_service(struct connman_device *device)
        return 0;
 }
 
+#if defined TIZEN_EXT
+bool connman_device_set_last_user_selection_time(struct connman_device *device,
+                                               time_t time)
+{
+       if (device->last_user_selection_time != time) {
+               device->last_user_selection_time = time;
+               return true;
+       }
+
+       return false;
+}
+
+time_t connman_device_get_last_user_selection_time(struct connman_device *device)
+{
+       return device->last_user_selection_time;
+}
+
+bool connman_device_set_last_user_selection_ident(struct connman_device *device,
+                                               const char *ident)
+{
+       if (g_strcmp0(device->last_user_selection_ident, ident) != 0) {
+               g_free(device->last_user_selection_ident);
+               device->last_user_selection_ident = g_strdup(ident);
+
+               return true;
+       }
+
+       return false;
+}
+
+const char *connman_device_get_last_user_selection_ident(struct connman_device *device)
+{
+       return device->last_user_selection_ident;
+}
+
+bool connman_device_set_last_connected_ident(struct connman_device *device,
+                                               const char *ident)
+{
+       if (g_strcmp0(device->last_connected_ident, ident) != 0) {
+               g_free(device->last_connected_ident);
+               device->last_connected_ident = g_strdup(ident);
+
+               return true;
+       }
+
+       return false;
+}
+
+const char *connman_device_get_last_connected_ident(struct connman_device *device)
+{
+       return device->last_connected_ident;
+}
+
+void connman_device_save_last_user_selection(struct connman_device *device)
+{
+       GKeyFile *keyfile;
+       gchar *get_str;
+       gchar *selection_str;
+
+       keyfile = __connman_storage_load_ins();
+
+       selection_str = g_strdup_printf("%s:%ld",
+                       device->last_user_selection_ident, device->last_user_selection_time);
+
+       if (!keyfile) {
+               keyfile = g_key_file_new();
+
+               g_key_file_set_string(keyfile, device->interface, "LastUserSelection", selection_str);
+               DBG("%s", selection_str);
+               __connman_storage_save_ins(keyfile);
+
+       } else {
+               get_str = g_key_file_get_string(keyfile, device->interface, "LastUserSelection", NULL);
+               if (!get_str || g_strcmp0(get_str, selection_str) != 0) {
+                       g_key_file_set_string(keyfile, device->interface, "LastUserSelection", selection_str);
+                       DBG("%s -> %s", get_str, selection_str);
+                       __connman_storage_save_ins(keyfile);
+               }
+
+               g_free(get_str);
+       }
+
+       g_free(selection_str);
+       g_key_file_free(keyfile);
+}
+
+void connman_device_load_last_user_selection(struct connman_device *device)
+{
+       GKeyFile *keyfile;
+       gchar *get_str;
+       char **selection_str;
+
+       keyfile = __connman_storage_load_ins();
+       if (!keyfile)
+               return;
+
+       get_str = g_key_file_get_string(keyfile, device->interface, "LastUserSelection", NULL);
+       if (get_str) {
+               selection_str = g_strsplit(get_str, ":", 0);
+               if (selection_str) {
+                       time_t ref_time;
+                       struct tm* timeinfo;
+                       time_t last_user_selection_time;
+
+                       /* Only events that occur within 8 hours are counted. */
+                       ref_time = time(NULL);
+                       timeinfo = localtime(&ref_time);
+                       timeinfo->tm_hour -= 8;
+                       ref_time = mktime(timeinfo);
+
+                       last_user_selection_time = strtol(selection_str[1], NULL, 10);
+
+                       if (last_user_selection_time > ref_time) {
+                               if (g_strcmp0(selection_str[0], device->last_user_selection_ident) != 0) {
+                                       g_free(device->last_user_selection_ident);
+                                       device->last_user_selection_ident = g_strdup(selection_str[0]);
+                               }
+
+                               device->last_user_selection_time = last_user_selection_time;
+
+                               DBG("%s %ld", device->last_user_selection_ident, device->last_user_selection_time);
+                       }
+
+                       g_strfreev(selection_str);
+               }
+
+               g_free(get_str);
+       }
+
+       g_key_file_free(keyfile);
+}
+
+void connman_device_save_last_connected(struct connman_device *device)
+{
+       GKeyFile *keyfile;
+       gchar *get_str;
+
+       if (!device->last_connected_ident)
+               return;
+
+       keyfile = __connman_storage_load_ins();
+
+       if (!keyfile) {
+               keyfile = g_key_file_new();
+
+               g_key_file_set_string(keyfile, device->interface, "LastConnected", device->last_connected_ident);
+               DBG("%s", device->last_connected_ident);
+               __connman_storage_save_ins(keyfile);
+
+       } else {
+               get_str = g_key_file_get_string(keyfile, device->interface, "LastConnected", NULL);
+               if (!get_str || g_strcmp0(get_str, device->last_connected_ident) != 0) {
+                       g_key_file_set_string(keyfile, device->interface, "LastConnected", device->last_connected_ident);
+                       DBG("%s -> %s", get_str, device->last_connected_ident);
+                       __connman_storage_save_ins(keyfile);
+               }
+
+               g_free(get_str);
+       }
+
+       g_key_file_free(keyfile);
+}
+
+void connman_device_load_last_connected(struct connman_device *device)
+{
+       GKeyFile *keyfile;
+       gchar *get_str;
+
+       keyfile = __connman_storage_load_ins();
+       if (!keyfile)
+               return;
+
+       get_str = g_key_file_get_string(keyfile, device->interface, "LastConnected", NULL);
+       if (get_str) {
+               if (g_strcmp0(get_str, device->last_connected_ident) != 0) {
+                       g_free(device->last_connected_ident);
+                       device->last_connected_ident = g_strdup(get_str);
+               }
+
+               DBG("%s", device->last_connected_ident);
+
+               g_free(get_str);
+       }
+
+       g_key_file_free(keyfile);
+}
+#endif
+
 static void mark_network_available(gpointer key, gpointer value,
                                                        gpointer user_data)
 {
@@ -1531,6 +1729,10 @@ struct connman_device *connman_device_create_from_index(int index)
 
        connman_device_set_index(device, index);
        connman_device_set_interface(device, devname);
+#if defined TIZEN_EXT
+       connman_device_load_last_connected(device);
+       connman_device_load_last_user_selection(device);
+#endif
 
        if (ident) {
                connman_device_set_ident(device, ident);
old mode 100644 (file)
new mode 100755 (executable)
index 1fecef0..6dcdced
@@ -98,6 +98,7 @@ static struct {
        bool tizen_tv_extension;
        bool auto_ip;
        char *global_nameserver;
+       bool supplicant_debug;
 #endif
 } connman_settings  = {
        .bg_scan = true,
@@ -126,9 +127,66 @@ static struct {
        .tizen_tv_extension = false,
        .auto_ip = true,
        .global_nameserver = NULL,
+       .supplicant_debug = false,
 #endif
 };
 
+#if defined TIZEN_EXT
+static struct {
+       /* BSSID */
+       char *ins_preferred_freq_bssid;
+       bool ins_last_connected_bssid;
+       bool ins_assoc_reject;
+       bool ins_signal_bssid;
+       unsigned int ins_preferred_freq_bssid_score;
+       unsigned int ins_last_connected_bssid_score;
+       unsigned int ins_assoc_reject_score;
+       /* SSID */
+       bool ins_last_user_selection;
+       unsigned int ins_last_user_selection_time;
+       bool ins_last_connected;
+       char *ins_preferred_freq;
+       char **ins_security_priority;
+       unsigned int ins_security_priority_count;
+       bool ins_signal;
+       bool ins_internet;
+       unsigned int ins_last_user_selection_score;
+       unsigned int ins_last_connected_score;
+       unsigned int ins_preferred_freq_score;
+       unsigned int ins_security_priority_score;
+       unsigned int ins_internet_score;
+       /* Common */
+       int ins_signal_level3_5ghz;
+       int ins_signal_level3_24ghz;
+} connman_ins_settings = {
+       /* BSSID */
+       .ins_preferred_freq_bssid = NULL,
+       .ins_last_connected_bssid = true,
+       .ins_assoc_reject = true,
+       .ins_signal_bssid = true,
+       .ins_preferred_freq_bssid_score = 20,
+       .ins_last_connected_bssid_score = 20,
+       .ins_assoc_reject_score = 10,
+       /* SSID */
+       .ins_last_user_selection = true,
+       .ins_last_user_selection_time = 480,
+       .ins_last_connected = true,
+       .ins_preferred_freq = NULL,
+       .ins_security_priority = NULL,
+       .ins_security_priority_count = 0,
+       .ins_signal = true,
+       .ins_internet = true,
+       .ins_last_user_selection_score = 30,
+       .ins_last_connected_score = 30,
+       .ins_preferred_freq_score = 60,
+       .ins_security_priority_score = 5,
+       .ins_internet_score = 30,
+       /* Common */
+       .ins_signal_level3_5ghz = -76,
+       .ins_signal_level3_24ghz = -74,
+};
+#endif
+
 #define CONF_BG_SCAN                    "BackgroundScanning"
 #define CONF_PREF_TIMESERVERS           "FallbackTimeservers"
 #define CONF_AUTO_CONNECT_TECHS         "DefaultAutoConnectTechnologies"
@@ -152,9 +210,38 @@ static struct {
 #define CONF_USE_GATEWAYS_AS_TIMESERVERS "UseGatewaysAsTimeservers"
 #if defined TIZEN_EXT
 #define CONF_CELLULAR_INTERFACE         "NetworkCellularInterfaceList"
-#define CONF_TIZEN_TV_EXT              "TizenTVExtension"
-#define CONF_ENABLE_AUTO_IP            "EnableAutoIp"
+#define CONF_TIZEN_TV_EXT                      "TizenTVExtension"
+#define CONF_ENABLE_AUTO_IP                    "EnableAutoIp"
 #define CONF_GLOBAL_NAMESERVER          "GlobalNameserver"
+#define CONF_CONNMAN_SUPPLICANT_DEBUG   "ConnmanSupplicantDebug"
+#endif
+
+#if defined TIZEN_EXT
+/* BSSID */
+#define CONF_INS_PREFERRED_FREQ_BSSID        "INSPreferredFreqBSSID"
+#define CONF_INS_PREFERRED_FREQ_BSSID_SCORE  "INSPreferredFreqBSSIDScore"
+#define CONF_INS_LAST_CONNECTED_BSSID        "INSLastConnectedBSSID"
+#define CONF_INS_LAST_CONNECTED_BSSID_SCORE  "INSLastConnectedBSSIDScore"
+#define CONF_INS_ASSOC_REJECT                "INSAssocReject"
+#define CONF_INS_ASSOC_REJECT_SCORE          "INSAssocRejectScore"
+#define CONF_INS_SIGNAL_BSSID                "INSSignalBSSID"
+/* SSID */
+#define CONF_INS_LAST_USER_SELECTION         "INSLastUserSelection"
+#define CONF_INS_LAST_USER_SELECTION_TIME    "INSLastUserSelectionTime"
+#define CONF_INS_LAST_USER_SELECTION_SCORE   "INSLastUserSelectionScore"
+#define CONF_INS_LAST_CONNECTED              "INSLastConnected"
+#define CONF_INS_LAST_CONNECTED_SCORE        "INSLastConnectedScore"
+#define CONF_INS_PREFERRED_FREQ              "INSPreferredFreq"
+#define CONF_INS_PREFERRED_FREQ_SCORE        "INSPreferredFreqScore"
+#define CONF_INS_SECURITY_PRIORITY           "INSSecurityPriority"
+#define CONF_INS_SECURITY_PRIORITY_COUNT     "INSSecurityPriorityCount"
+#define CONF_INS_SECURITY_PRIORITY_SCORE     "INSSecurityPriorityScore"
+#define CONF_INS_SIGNAL                      "INSSignal"
+#define CONF_INS_INTERNET                    "INSInternet"
+#define CONF_INS_INTERNET_SCORE              "INSInternetScore"
+/* Common */
+#define CONF_INS_SIGNAL_LEVEL3_5GHZ          "INSSignalLevel3_5GHz"
+#define CONF_INS_SIGNAL_LEVEL3_24GHZ         "INSSignalLevel3_24GHz"
 #endif
 
 static const char *supported_options[] = {
@@ -183,10 +270,42 @@ static const char *supported_options[] = {
        CONF_TIZEN_TV_EXT,
        CONF_ENABLE_AUTO_IP,
        CONF_GLOBAL_NAMESERVER,
+       CONF_CONNMAN_SUPPLICANT_DEBUG,
 #endif
        NULL
 };
 
+#if defined TIZEN_EXT
+static const char *supported_ins_options[] = {
+       /* BSSID */
+       CONF_INS_PREFERRED_FREQ_BSSID,
+       CONF_INS_PREFERRED_FREQ_BSSID_SCORE,
+       CONF_INS_LAST_CONNECTED_BSSID,
+       CONF_INS_LAST_CONNECTED_BSSID_SCORE,
+       CONF_INS_ASSOC_REJECT,
+       CONF_INS_ASSOC_REJECT_SCORE,
+       CONF_INS_SIGNAL_BSSID,
+       /* SSID */
+       CONF_INS_LAST_USER_SELECTION,
+       CONF_INS_LAST_USER_SELECTION_TIME,
+       CONF_INS_LAST_USER_SELECTION_SCORE,
+       CONF_INS_LAST_CONNECTED,
+       CONF_INS_LAST_CONNECTED_SCORE,
+       CONF_INS_PREFERRED_FREQ,
+       CONF_INS_PREFERRED_FREQ_SCORE,
+       CONF_INS_SECURITY_PRIORITY,
+       CONF_INS_SECURITY_PRIORITY_COUNT,
+       CONF_INS_SECURITY_PRIORITY_SCORE,
+       CONF_INS_SIGNAL,
+       CONF_INS_INTERNET,
+       CONF_INS_INTERNET_SCORE,
+       /* Common */
+       CONF_INS_SIGNAL_LEVEL3_5GHZ,
+       CONF_INS_SIGNAL_LEVEL3_24GHZ,
+       NULL
+};
+#endif
+
 static GKeyFile *load_config(const char *file)
 {
        GError *err = NULL;
@@ -270,7 +389,12 @@ static void check_config(GKeyFile *config)
        keys = g_key_file_get_groups(config, NULL);
 
        for (j = 0; keys && keys[j]; j++) {
+#if defined TIZEN_EXT
+               if (g_strcmp0(keys[j], "General") != 0 &&
+                       g_strcmp0(keys[j], "INS") != 0)
+#else
                if (g_strcmp0(keys[j], "General") != 0)
+#endif
                        connman_warn("Unknown group %s in %s",
                                                keys[j], MAINFILE);
        }
@@ -296,9 +420,192 @@ static void check_config(GKeyFile *config)
        }
 
        g_strfreev(keys);
+
+#if defined TIZEN_EXT
+       keys = g_key_file_get_keys(config, "INS", NULL, NULL);
+
+       for (j = 0; keys && keys[j]; j++) {
+               bool found;
+               int i;
+
+               found = false;
+               for (i = 0; supported_ins_options[i]; i++) {
+                       if (g_strcmp0(keys[j], supported_ins_options[i]) == 0) {
+                               found = true;
+                               break;
+                       }
+               }
+               if (!found && !supported_ins_options[i])
+                       connman_warn("Unknown option %s in %s",
+                                               keys[j], MAINFILE);
+       }
+
+       g_strfreev(keys);
+#endif
 }
 
 #if defined TIZEN_EXT
+static void check_Tizen_INS_configuration(GKeyFile *config)
+{
+       GError *error = NULL;
+       char *ins_preferred_freq_bssid;
+       char *ins_preferred_freq;
+       char **ins_security_priority;
+       bool boolean;
+       int integer;
+       gsize len;
+
+       ins_preferred_freq_bssid = __connman_config_get_string(config, "INS",
+                                       CONF_INS_PREFERRED_FREQ_BSSID, &error);
+       if (!error)
+               connman_ins_settings.ins_preferred_freq_bssid = ins_preferred_freq_bssid;
+
+       g_clear_error(&error);
+
+       integer = g_key_file_get_integer(config, "INS",
+                       CONF_INS_PREFERRED_FREQ_BSSID_SCORE, &error);
+       if (!error && integer >= 0)
+               connman_ins_settings.ins_preferred_freq_bssid_score = integer;
+
+       g_clear_error(&error);
+
+       boolean = __connman_config_get_bool(config, "INS",
+                       CONF_INS_LAST_CONNECTED_BSSID, &error);
+       if (!error)
+               connman_ins_settings.ins_last_connected_bssid = boolean;
+
+       g_clear_error(&error);
+
+       integer = g_key_file_get_integer(config, "INS",
+                       CONF_INS_LAST_CONNECTED_BSSID_SCORE, &error);
+       if (!error && integer >= 0)
+               connman_ins_settings.ins_last_connected_bssid_score = integer;
+
+       g_clear_error(&error);
+
+       boolean = __connman_config_get_bool(config, "INS",
+                       CONF_INS_ASSOC_REJECT, &error);
+       if (!error)
+               connman_ins_settings.ins_assoc_reject = boolean;
+
+       g_clear_error(&error);
+
+       integer = g_key_file_get_integer(config, "INS",
+                       CONF_INS_ASSOC_REJECT_SCORE, &error);
+       if (!error && integer >= 0)
+               connman_ins_settings.ins_assoc_reject_score = integer;
+
+       g_clear_error(&error);
+
+       boolean = __connman_config_get_bool(config, "INS",
+                       CONF_INS_SIGNAL_BSSID, &error);
+       if (!error)
+               connman_ins_settings.ins_signal_bssid = boolean;
+
+       g_clear_error(&error);
+
+       boolean = __connman_config_get_bool(config, "INS",
+                       CONF_INS_LAST_USER_SELECTION, &error);
+       if (!error)
+               connman_ins_settings.ins_last_user_selection = boolean;
+
+       g_clear_error(&error);
+
+       integer = g_key_file_get_integer(config, "INS",
+                       CONF_INS_LAST_USER_SELECTION_TIME, &error);
+       if (!error && integer >= 0)
+               connman_ins_settings.ins_last_user_selection_time = integer;
+
+       g_clear_error(&error);
+
+       integer = g_key_file_get_integer(config, "INS",
+                       CONF_INS_LAST_USER_SELECTION_SCORE, &error);
+       if (!error && integer >= 0)
+               connman_ins_settings.ins_last_user_selection_score = integer;
+
+       g_clear_error(&error);
+
+       boolean = __connman_config_get_bool(config, "INS",
+                       CONF_INS_LAST_CONNECTED, &error);
+       if (!error)
+               connman_ins_settings.ins_last_connected = boolean;
+
+       g_clear_error(&error);
+
+       integer = g_key_file_get_integer(config, "INS",
+                       CONF_INS_LAST_CONNECTED_SCORE, &error);
+       if (!error && integer >= 0)
+               connman_ins_settings.ins_last_connected_score = integer;
+
+       g_clear_error(&error);
+
+       ins_preferred_freq = __connman_config_get_string(config, "INS",
+                                       CONF_INS_PREFERRED_FREQ, &error);
+       if (!error)
+               connman_ins_settings.ins_preferred_freq = ins_preferred_freq;
+
+       g_clear_error(&error);
+
+       integer = g_key_file_get_integer(config, "INS",
+                       CONF_INS_PREFERRED_FREQ_SCORE, &error);
+       if (!error && integer >= 0)
+               connman_ins_settings.ins_preferred_freq_score = integer;
+
+       g_clear_error(&error);
+
+       ins_security_priority = g_key_file_get_string_list(config, "INS",
+                       CONF_INS_SECURITY_PRIORITY, &len, &error);
+
+       if (error == NULL) {
+               connman_ins_settings.ins_security_priority = ins_security_priority;
+               connman_ins_settings.ins_security_priority_count = len;
+       }
+
+       g_clear_error(&error);
+
+       integer = g_key_file_get_integer(config, "INS",
+                       CONF_INS_SECURITY_PRIORITY_SCORE, &error);
+       if (!error && integer >= 0)
+               connman_ins_settings.ins_security_priority_score = integer;
+
+       g_clear_error(&error);
+
+       boolean = __connman_config_get_bool(config, "INS",
+                       CONF_INS_SIGNAL, &error);
+       if (!error)
+               connman_ins_settings.ins_signal = boolean;
+
+       g_clear_error(&error);
+
+       boolean = __connman_config_get_bool(config, "INS",
+                       CONF_INS_INTERNET, &error);
+       if (!error)
+               connman_ins_settings.ins_internet = boolean;
+
+       g_clear_error(&error);
+
+       integer = g_key_file_get_integer(config, "INS",
+                       CONF_INS_INTERNET_SCORE, &error);
+       if (!error && integer >= 0)
+               connman_ins_settings.ins_internet_score = integer;
+
+       g_clear_error(&error);
+
+       integer = g_key_file_get_integer(config, "INS",
+                       CONF_INS_SIGNAL_LEVEL3_5GHZ, &error);
+       if (!error)
+               connman_ins_settings.ins_signal_level3_5ghz = integer;
+
+       g_clear_error(&error);
+
+       integer = g_key_file_get_integer(config, "INS",
+                       CONF_INS_SIGNAL_LEVEL3_24GHZ, &error);
+       if (!error)
+               connman_ins_settings.ins_signal_level3_24ghz = integer;
+
+       g_clear_error(&error);
+}
+
 static void check_Tizen_configuration(GKeyFile *config)
 {
        GError *error = NULL;
@@ -335,6 +642,15 @@ static void check_Tizen_configuration(GKeyFile *config)
                connman_settings.global_nameserver = global_nameserver;
 
        g_clear_error(&error);
+
+       boolean = __connman_config_get_bool(config, "General",
+                       CONF_CONNMAN_SUPPLICANT_DEBUG, &error);
+       if (!error)
+               connman_settings.supplicant_debug = boolean;
+
+       g_clear_error(&error);
+
+       check_Tizen_INS_configuration(config);
 }
 
 static void set_nofile_inc(void)
@@ -752,6 +1068,14 @@ const char *connman_option_get_string(const char *key)
        if (g_str_equal(key, CONF_GLOBAL_NAMESERVER))
                return connman_settings.global_nameserver;
 #endif
+
+#if defined TIZEN_EXT
+       if (g_str_equal(key, CONF_INS_PREFERRED_FREQ_BSSID))
+               return connman_ins_settings.ins_preferred_freq_bssid;
+
+       if (g_str_equal(key, CONF_INS_PREFERRED_FREQ))
+               return connman_ins_settings.ins_preferred_freq;
+#endif
        return NULL;
 }
 
@@ -790,11 +1114,85 @@ bool connman_setting_get_bool(const char *key)
 #if defined TIZEN_EXT
        if (g_str_equal(key, CONF_ENABLE_AUTO_IP))
                return connman_settings.auto_ip;
+
+       if (g_str_equal(key, CONF_CONNMAN_SUPPLICANT_DEBUG))
+               return connman_settings.supplicant_debug;
+#endif
+
+#if defined TIZEN_EXT
+       if (g_str_equal(key, CONF_INS_LAST_CONNECTED_BSSID))
+               return connman_ins_settings.ins_last_connected_bssid;
+
+       if (g_str_equal(key, CONF_INS_ASSOC_REJECT))
+               return connman_ins_settings.ins_assoc_reject;
+
+       if (g_str_equal(key, CONF_INS_SIGNAL_BSSID))
+               return connman_ins_settings.ins_signal_bssid;
+
+       if (g_str_equal(key, CONF_INS_LAST_USER_SELECTION))
+               return connman_ins_settings.ins_last_user_selection;
+
+       if (g_str_equal(key, CONF_INS_LAST_CONNECTED))
+               return connman_ins_settings.ins_last_connected;
+
+       if (g_str_equal(key, CONF_INS_SIGNAL))
+               return connman_ins_settings.ins_signal;
+
+       if (g_str_equal(key, CONF_INS_INTERNET))
+               return connman_ins_settings.ins_internet;
 #endif
 
        return false;
 }
 
+#if defined TIZEN_EXT
+unsigned int connman_setting_get_uint(const char *key)
+{
+       if (g_str_equal(key, CONF_INS_PREFERRED_FREQ_BSSID_SCORE))
+               return connman_ins_settings.ins_preferred_freq_bssid_score;
+
+       if (g_str_equal(key, CONF_INS_LAST_CONNECTED_BSSID_SCORE))
+               return connman_ins_settings.ins_last_connected_bssid_score;
+
+       if (g_str_equal(key, CONF_INS_ASSOC_REJECT_SCORE))
+               return connman_ins_settings.ins_assoc_reject_score;
+
+       if (g_str_equal(key, CONF_INS_LAST_USER_SELECTION_TIME))
+               return connman_ins_settings.ins_last_user_selection_time;
+
+       if (g_str_equal(key, CONF_INS_SECURITY_PRIORITY_COUNT))
+               return connman_ins_settings.ins_security_priority_count;
+
+       if (g_str_equal(key, CONF_INS_LAST_USER_SELECTION_SCORE))
+               return connman_ins_settings.ins_last_user_selection_score;
+
+       if (g_str_equal(key, CONF_INS_LAST_CONNECTED_SCORE))
+               return connman_ins_settings.ins_last_connected_score;
+
+       if (g_str_equal(key, CONF_INS_PREFERRED_FREQ_SCORE))
+               return connman_ins_settings.ins_preferred_freq_score;
+
+       if (g_str_equal(key, CONF_INS_SECURITY_PRIORITY_SCORE))
+               return connman_ins_settings.ins_security_priority_score;
+
+       if (g_str_equal(key, CONF_INS_INTERNET_SCORE))
+               return connman_ins_settings.ins_internet_score;
+
+       return 0;
+}
+
+int connman_setting_get_int(const char *key)
+{
+       if (g_str_equal(key, CONF_INS_SIGNAL_LEVEL3_5GHZ))
+               return connman_ins_settings.ins_signal_level3_5ghz;
+
+       if (g_str_equal(key, CONF_INS_SIGNAL_LEVEL3_24GHZ))
+               return connman_ins_settings.ins_signal_level3_24ghz;
+
+       return 0;
+}
+#endif
+
 char **connman_setting_get_string_list(const char *key)
 {
        if (g_str_equal(key, CONF_PREF_TIMESERVERS))
@@ -814,6 +1212,11 @@ char **connman_setting_get_string_list(const char *key)
                return connman_settings.cellular_interfaces;
 #endif
 
+#if defined TIZEN_EXT
+       if (g_str_equal(key, CONF_INS_SECURITY_PRIORITY))
+               return connman_ins_settings.ins_security_priority;
+#endif
+
        return NULL;
 }
 
@@ -1032,6 +1435,13 @@ int main(int argc, char *argv[])
        g_strfreev(connman_settings.blacklisted_interfaces);
        g_strfreev(connman_settings.tethering_technologies);
 
+#if defined TIZEN_EXT
+       g_free(connman_ins_settings.ins_preferred_freq_bssid);
+       g_free(connman_ins_settings.ins_preferred_freq);
+       if (connman_ins_settings.ins_security_priority)
+               g_strfreev(connman_ins_settings.ins_security_priority);
+#endif
+
        g_free(option_debug);
        g_free(option_wifi);
 
index ab0dc2d..6e26464 100755 (executable)
@@ -168,3 +168,37 @@ NetworkCellularInterfaceList = pdp,rmnet,seth_td,seth_w
 # if all nameservers are failed to resolve DNS query. The nameserver
 # entries must be in numeric format.
 # GlobalNameserver = 8.8.8.8
+
+# Enable supplicant debugging log
+ConnmanSupplicantDebug = false
+
+[INS]
+# INS(Intelligent Network Selection) configuration: BSSID Selection.
+INSPreferredFreqBSSID = 5GHz
+INSPreferredFreqBSSIDScore = 20
+INSLastConnectedBSSID = true
+INSLastConnectedBSSIDScore = 20
+INSAssocReject = true
+INSAssocRejectScore = 10
+INSSignalBSSID = true
+
+# INS(Intelligent Network Selection) configuration: SSID Selection.
+INSLastUserSelection = true
+INSLastUserSelectionTime = 480
+INSLastUserSelectionScore = 30
+# (INSLastUserSelectionTime - selection time diff) / (INSLastUserSelectionTime / INSLastUserSelectionScore)
+# This means '(480 - selection time) / x) <= 30'
+INSLastConnected = true
+INSLastConnectedScore = 30
+INSPreferredFreq = 5GHz
+INSPreferredFreqScore = 60
+INSSecurityPriority = SAE,RSN
+INSSecurityPriorityScore = 5
+# In this case, SAE(10 score), RSN(5 score)
+INSSignal = true
+INSInternet = true
+INSInternetScore = 30
+
+# INS(Intelligent Network Selection) configuration: Common.
+INSSignalLevel3_5GHz = -76
+INSSignalLevel3_24GHz = -74
index d8756ec..f1183b3 100755 (executable)
 
 #define DHCP_RETRY_TIMEOUT     10
 
+#if defined TIZEN_EXT
+static unsigned char invalid_bssid[WIFI_BSSID_LEN_MAX] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+#endif
+
 static GSList *network_list = NULL;
 static GSList *driver_list = NULL;
 
@@ -131,6 +137,10 @@ struct connman_network {
                char *c_sign_key;
                char *net_access_key;
 #endif
+#if defined TIZEN_EXT
+               unsigned char last_connected_bssid[WIFI_BSSID_LEN_MAX];
+               GHashTable *assoc_reject_table;
+#endif
        } wifi;
 
 #if defined TIZEN_EXT
@@ -2509,6 +2519,45 @@ void *connman_network_get_bssid_list(struct connman_network *network)
 {
        return network->wifi.bssid_list;
 }
+
+int connman_network_set_last_connected_bssid(struct connman_network *network,
+                               const unsigned char *bssid)
+{
+       if (!bssid)
+               return -EINVAL;
+
+       if (!memcmp(bssid, invalid_bssid, WIFI_BSSID_LEN_MAX))
+               return -EINVAL;
+
+       memcpy(network->wifi.last_connected_bssid, bssid, WIFI_BSSID_LEN_MAX);
+
+       return 0;
+}
+
+unsigned char *connman_network_get_last_connected_bssid(struct connman_network *network)
+{
+       return (unsigned char *)network->wifi.last_connected_bssid;
+}
+
+void connman_network_set_assoc_reject_table(struct connman_network *network,
+               GHashTable *assoc_reject_table)
+{
+       if (!network)
+               return;
+
+       if (!assoc_reject_table)
+               return;
+
+       network->wifi.assoc_reject_table = assoc_reject_table;
+}
+
+GHashTable *connman_network_get_assoc_reject_table(struct connman_network *network)
+{
+       if (!network)
+               return NULL;
+
+       return network->wifi.assoc_reject_table;
+}
 #endif
 
 int connman_network_set_nameservers(struct connman_network *network,
old mode 100644 (file)
new mode 100755 (executable)
index cbedb34..606ef7d
 #define MAX_WIFI_PROFILES      200
 #endif
 
+#if defined TIZEN_EXT
+#define FREQ_RANGE_24GHZ_CHANNEL_1   2412
+#define FREQ_RANGE_24GHZ_CHANNEL_14  2484
+#define FREQ_RANGE_5GHZ_CHANNEL_32   5160
+#define FREQ_RANGE_5GHZ_CHANNEL_165  5825
+#endif
+
 static DBusConnection *connection = NULL;
 
 static GList *service_list = NULL;
@@ -64,6 +71,38 @@ struct saved_profiles {
 
 #endif
 
+#if defined TIZEN_EXT
+enum connman_ins_preferred_freq {
+       CONNMAN_INS_PREFERRED_FREQ_UNKNOWN,
+       CONNMAN_INS_PREFERRED_FREQ_24GHZ,
+       CONNMAN_INS_PREFERRED_FREQ_5GHZ,
+};
+
+struct connman_ins_settings {
+       bool last_user_selection;
+       unsigned int last_user_selection_time;
+       unsigned int last_user_selection_score;
+       bool last_connected;
+       unsigned int last_connected_score;
+       enum connman_ins_preferred_freq preferred_freq;
+       unsigned int preferred_freq_score;
+       unsigned int security_priority[CONNMAN_SERVICE_SECURITY_MAX];
+       unsigned int security_priority_count;
+       unsigned int security_priority_score;
+       bool signal;
+       bool internet;
+       unsigned int internet_score;
+       int signal_level3_5ghz;
+       int signal_level3_24ghz;
+};
+
+static struct connman_ins_settings ins_settings;
+
+static unsigned char invalid_bssid[WIFI_BSSID_LEN_MAX] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+#endif
+
 struct connman_stats {
        bool valid;
        bool enabled;
@@ -184,6 +223,12 @@ struct connman_service {
        char *c_sign_key;
        char *net_access_key;
 #endif
+#if defined TIZEN_EXT
+       unsigned char last_connected_bssid[WIFI_BSSID_LEN_MAX];
+       bool is_internet_connection;
+       int assoc_reject_count;
+       int ins_score;
+#endif
 };
 
 static bool allow_property_changed(struct connman_service *service);
@@ -200,6 +245,13 @@ struct find_data {
 };
 
 #if defined TIZEN_EXT
+struct assoc_reject_data {
+       char *bssid;
+       GSList *reject_time_list;
+};
+#endif
+
+#if defined TIZEN_EXT
 /*
  * Public APIs to use user_pdn_connection_refcount
  */
@@ -572,6 +624,242 @@ int __connman_service_load_modifiable(struct connman_service *service)
        return 0;
 }
 
+#if defined TIZEN_EXT
+static void save_assoc_reject(gpointer key, gpointer value, gpointer user_data)
+{
+       struct assoc_reject_data *assoc_rd = value;
+       GString *assoc_reject_str = user_data;
+       GSList *list;
+       char *val_str;
+
+       if (g_slist_length(assoc_rd->reject_time_list) < 1)
+               return;
+
+       for (list = assoc_rd->reject_time_list; list; list = list->next) {
+               time_t assoc_reject_time = GPOINTER_TO_INT(list->data);
+
+               val_str = g_strdup_printf("%s_%ld", assoc_rd->bssid, assoc_reject_time);
+
+               if (assoc_reject_str->len > 0)
+                       g_string_append_printf(assoc_reject_str, " %s", val_str);
+               else
+                       g_string_append(assoc_reject_str, val_str);
+
+               g_free(val_str);
+       }
+}
+
+static void count_assoc_reject(gpointer key, gpointer value, gpointer user_data)
+{
+       struct assoc_reject_data *assoc_data = value;
+       int *assoc_reject_count = user_data;
+
+       *assoc_reject_count += g_slist_length(assoc_data->reject_time_list);
+}
+
+static bool update_assoc_reject(struct connman_service *service)
+{
+       GHashTable *assoc_reject_table;
+       int assoc_reject_count;
+
+       if (!service->network)
+               return false;
+
+       assoc_reject_table = connman_network_get_assoc_reject_table(service->network);
+       if (assoc_reject_table) {
+               assoc_reject_count = 0;
+               g_hash_table_foreach(assoc_reject_table, count_assoc_reject, &assoc_reject_count);
+#if defined TIZEN_EXT_INS
+               DBG("assoc reject count [%d -> %d]",
+                       service->assoc_reject_count, assoc_reject_count);
+#endif
+               if (service->assoc_reject_count != assoc_reject_count) {
+                       service->assoc_reject_count = assoc_reject_count;
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+static int service_ext_load(struct connman_service *service)
+{
+       GKeyFile *keyfile;
+       GHashTable *reject_table;
+       char **reject_list;
+       gsize reject_len;
+       struct assoc_reject_data *reject_data;
+       char **bssid_time;
+       char *bssid;
+       time_t reject_time;
+       time_t curr_time;
+       time_t ref_time;
+       struct tm* ref_timeinfo;
+       int i;
+       int err = 0;
+
+       DBG("service %p", service);
+
+       if (!service->network)
+               return -EINVAL;
+
+       if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
+               return -EINVAL;
+
+       keyfile = connman_storage_load_service(service->identifier);
+       if (!keyfile)
+               return -EIO;
+
+       reject_table = connman_network_get_assoc_reject_table(service->network);
+
+       reject_list = g_key_file_get_string_list(keyfile,
+               service->identifier, "AssocReject", &reject_len, NULL);
+
+       if (!reject_list || reject_len == 0) {
+               g_strfreev(reject_list);
+               goto done;
+       }
+
+       /* Only events that occur within one hour are appened. */
+       curr_time = time(NULL);
+       ref_timeinfo = localtime(&curr_time);
+       ref_timeinfo->tm_hour -= 1;
+       ref_time = mktime(ref_timeinfo);
+
+       for (i = 0; reject_list[i]; i++) {
+               bssid_time = g_strsplit(reject_list[i], "_", 0);
+               if (!bssid_time) {
+                       err = -ERANGE;
+                       continue;
+               }
+
+               bssid = bssid_time[0];
+               reject_time = strtol(bssid_time[1], NULL, 10);
+
+               if (reject_time < ref_time) {
+                       g_strfreev(bssid_time);
+                       err = -ERANGE;
+                       continue;
+               }
+
+               reject_data = g_hash_table_lookup(reject_table, bssid);
+               if (!reject_data) {
+                       reject_data = g_try_new0(struct assoc_reject_data, 1);
+                       if (!reject_data) {
+                               g_strfreev(bssid_time);
+                               err = -ERANGE;
+                               continue;
+                       }
+
+                       memset(reject_data, 0, sizeof(struct assoc_reject_data));
+                       reject_data->bssid = g_strdup(bssid);
+                       g_hash_table_insert(reject_table, reject_data->bssid, reject_data);
+               }
+
+               reject_data->reject_time_list = g_slist_append(reject_data->reject_time_list,
+                               GINT_TO_POINTER(reject_time));
+
+#if defined TIZEN_EXT_INS
+               DBG("assoc reject [%s_%ld]", bssid, reject_time);
+#endif
+
+               g_strfreev(bssid_time);
+       }
+
+       g_strfreev(reject_list);
+
+done:
+       g_key_file_free(keyfile);
+       return err;
+}
+
+static int service_ext_save(struct connman_service *service)
+{
+       GKeyFile *keyfile;
+       GHashTable *reject_table;
+       GString *reject_str;
+       char **reject_list;
+       guint reject_len;
+       int err = 0;
+
+       DBG("service %p", service);
+
+       if (!service->network)
+               return -EINVAL;
+
+       if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
+               return -EINVAL;
+
+       keyfile = __connman_storage_open_service(service->identifier);
+       if (!keyfile)
+               return -EIO;
+
+       /* Last connected BSSID */
+       if (memcmp(service->last_connected_bssid, invalid_bssid, WIFI_BSSID_LEN_MAX)) {
+               char *identifier = service->identifier;
+               GString *bssid_str;
+               unsigned int i;
+
+               bssid_str = g_string_sized_new(MAC_ADDRESS_LENGTH);
+               if (!bssid_str) {
+                       err = -ENOMEM;
+                       goto next;
+               }
+
+               for (i = 0; i < WIFI_BSSID_LEN_MAX; i++) {
+                       g_string_append_printf(bssid_str,
+                                       "%02x", service->last_connected_bssid[i]);
+                       if (i < WIFI_BSSID_LEN_MAX - 1)
+                               g_string_append(bssid_str, ":");
+               }
+
+               g_key_file_set_string(keyfile, identifier,
+                                       "LastConnectedBSSID", bssid_str->str);
+
+#if defined TIZEN_EXT_INS
+               DBG("last connected bssid[%s]", bssid_str->str);
+#endif
+
+               g_string_free(bssid_str, TRUE);
+       }
+
+next:
+
+       /* Assoc reject */
+       reject_table = connman_network_get_assoc_reject_table(service->network);
+       if (reject_table && g_hash_table_size(reject_table) > 0) {
+               reject_str = g_string_new(NULL);
+               if (!reject_str) {
+                       err = -ENOMEM;
+                       goto done;
+               }
+
+               g_hash_table_foreach(reject_table, save_assoc_reject, reject_str);
+
+               reject_list = g_strsplit_set(reject_str->str, " ", 0);
+               reject_len = g_strv_length(reject_list);
+
+               g_key_file_set_string_list(keyfile, service->identifier,
+                       "AssocReject", (const gchar **)reject_list, reject_len);
+
+#if defined TIZEN_EXT_INS
+               DBG("assoc reject table [%d]", reject_len);
+#endif
+
+               g_strfreev(reject_list);
+               g_string_free(reject_str, TRUE);
+       } else {
+               g_key_file_remove_key(keyfile, service->identifier, "AssocReject", NULL);
+       }
+
+done:
+       __connman_storage_save_service(keyfile, service->identifier);
+
+       g_key_file_free(keyfile);
+       return err;
+}
+#endif
+
 static int service_load(struct connman_service *service)
 {
        GKeyFile *keyfile;
@@ -581,6 +869,9 @@ static int service_load(struct connman_service *service)
        bool autoconnect;
        unsigned int ssid_len;
        int err = 0;
+#if defined TIZEN_EXT
+       bool internet_connection;
+#endif
 
        DBG("service %p", service);
 
@@ -661,6 +952,46 @@ static int service_load(struct connman_service *service)
 
                        g_free(hex_ssid);
                }
+
+#if defined TIZEN_EXT
+               /* Last connected BSSID */
+               if (service->network) {
+                       gchar *bssid_str;
+                       unsigned char last_connected_bssid[WIFI_BSSID_LEN_MAX];
+                       char **str_list;
+                       unsigned int i;
+
+                       bssid_str = g_key_file_get_string(keyfile,
+                               service->identifier, "LastConnectedBSSID", NULL);
+
+                       if (bssid_str) {
+                               str_list = g_strsplit(bssid_str, ":", 0);
+
+                               if (str_list) {
+                                       for (i = 0; i < WIFI_BSSID_LEN_MAX; i++)
+                                               last_connected_bssid[i] = strtol(str_list[i], NULL, 16);
+
+                                       memcpy(service->last_connected_bssid,
+                                               last_connected_bssid, WIFI_BSSID_LEN_MAX);
+
+                                       connman_network_set_last_connected_bssid(service->network,
+                                               last_connected_bssid);
+
+                                       g_strfreev(str_list);
+                               }
+
+                               g_free(bssid_str);
+                       }
+               }
+
+               /* Internet connection */
+               internet_connection = g_key_file_get_boolean(keyfile,
+                               service->identifier, "InternetConnection", &error);
+               if (!error)
+                       service->is_internet_connection = internet_connection;
+
+               g_clear_error(&error);
+#endif
                /* fall through */
 
        case CONNMAN_SERVICE_TYPE_GADGET:
@@ -899,6 +1230,9 @@ static int service_save(struct connman_service *service)
                if (service->network) {
                        const unsigned char *ssid;
                        unsigned int ssid_len = 0;
+#if defined TIZEN_EXT
+                       GHashTable *assoc_reject_table;
+#endif
 
                        ssid = connman_network_get_blob(service->network,
                                                        "WiFi.SSID", &ssid_len);
@@ -927,6 +1261,74 @@ static int service_save(struct connman_service *service)
                        freq = connman_network_get_frequency(service->network);
                        g_key_file_set_integer(keyfile, service->identifier,
                                                "Frequency", freq);
+
+#if defined TIZEN_EXT
+                       /* Last connected BSSID */
+                       if (memcmp(service->last_connected_bssid, invalid_bssid, WIFI_BSSID_LEN_MAX)) {
+                               char *identifier = service->identifier;
+                               GString *bssid_str;
+                               unsigned int i;
+
+                               bssid_str = g_string_sized_new(18);
+                               if (!bssid_str) {
+                                       err = -ENOMEM;
+                                       goto done;
+                               }
+
+                               for (i = 0; i < WIFI_BSSID_LEN_MAX; i++) {
+                                       g_string_append_printf(bssid_str,
+                                                       "%02x", service->last_connected_bssid[i]);
+                                       if (i < WIFI_BSSID_LEN_MAX - 1)
+                                               g_string_append(bssid_str, ":");
+                               }
+
+                               g_key_file_set_string(keyfile, identifier,
+                                                       "LastConnectedBSSID", bssid_str->str);
+
+#if defined TIZEN_EXT_INS
+                               DBG("last connected bssid[%s]", bssid_str->str);
+#endif
+
+                               g_string_free(bssid_str, TRUE);
+                       }
+
+                       /* Assoc reject */
+                       assoc_reject_table = connman_network_get_assoc_reject_table(service->network);
+                       if (assoc_reject_table && g_hash_table_size(assoc_reject_table) > 0) {
+                               GString *assoc_reject_str;
+                               char **assoc_reject_list;
+                               guint assoc_reject_len;
+
+                               assoc_reject_str = g_string_new(NULL);
+                               if (!assoc_reject_str) {
+                                       err = -ENOMEM;
+                                       goto done;
+                               }
+
+                               g_hash_table_foreach(assoc_reject_table, save_assoc_reject, assoc_reject_str);
+
+                               assoc_reject_list = g_strsplit_set(assoc_reject_str->str, " ", 0);
+                               assoc_reject_len = g_strv_length(assoc_reject_list);
+
+                               g_key_file_set_string_list(keyfile, service->identifier,
+                                       "AssocReject", (const gchar **)assoc_reject_list, assoc_reject_len);
+
+#if defined TIZEN_EXT_INS
+                               DBG("assoc reject table [%d]", assoc_reject_len);
+#endif
+
+                               g_strfreev(assoc_reject_list);
+                               g_string_free(assoc_reject_str, TRUE);
+                       } else
+                               g_key_file_remove_key(keyfile, service->identifier, "AssocReject", NULL);
+
+                       /* Internet connection */
+                       g_key_file_set_boolean(keyfile, service->identifier,
+                                       "InternetConnection", service->is_internet_connection);
+#if defined TIZEN_EXT_INS
+                       DBG("internet connection [%s]", service->is_internet_connection ? "true" : "false");
+#endif
+#endif
                }
                /* fall through */
 
@@ -2353,12 +2755,31 @@ static void state_changed(struct connman_service *service)
 #if defined TIZEN_EXT
 static void connect_reason_changed(struct connman_service *service)
 {
+       struct connman_device *device;
+
        if (!service->path)
                return;
 
        if (!allow_property_changed(service))
                return;
 
+       if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER) {
+               device = connman_network_get_device(service->network);
+               if (device) {
+                       bool need_save = false;
+
+                       need_save |= connman_device_set_last_user_selection_ident(device, service->identifier);
+                       need_save |= connman_device_set_last_user_selection_time(device, time(NULL));
+
+                       DBG("last user selection ident[%s] time[%ld]",
+                               connman_device_get_last_user_selection_ident(device),
+                               connman_device_get_last_user_selection_time(device));
+
+                       if (need_save)
+                               connman_device_save_last_user_selection(device);
+               }
+       }
+
        connman_dbus_property_changed_basic(service->path,
                                            CONNMAN_SERVICE_INTERFACE,
                                            "ConnectReason",
@@ -2408,6 +2829,27 @@ static void strength_changed(struct connman_service *service)
                                        DBUS_TYPE_BYTE, &service->strength);
 }
 
+#if defined TIZEN_EXT
+static bool update_last_connected_bssid(struct connman_service *service)
+{
+       const unsigned char *last_connected_bssid;
+
+       if (!service->network)
+               return false;
+
+       last_connected_bssid = connman_network_get_last_connected_bssid(service->network);
+       if (memcmp(last_connected_bssid, invalid_bssid, WIFI_BSSID_LEN_MAX) == 0)
+               return false;
+
+       if (memcmp(last_connected_bssid, service->last_connected_bssid, WIFI_BSSID_LEN_MAX) != 0) {
+               memcpy(service->last_connected_bssid, last_connected_bssid, WIFI_BSSID_LEN_MAX);
+               return true;
+       }
+
+       return false;
+}
+#endif
+
 static void favorite_changed(struct connman_service *service)
 {
        dbus_bool_t favorite;
@@ -4016,6 +4458,30 @@ const char *connman_service_get_proxy_url(struct connman_service *service)
        return service->pac;
 }
 
+#if defined TIZEN_EXT
+void connman_service_set_internet_connection(struct connman_service *service,
+                                                       bool internet_connection)
+{
+       if (!service)
+               return;
+
+       if (service->is_internet_connection != internet_connection) {
+               service->is_internet_connection = internet_connection;
+
+               g_get_current_time(&service->modified);
+               service_save(service);
+       }
+}
+
+bool connman_service_get_internet_connection(struct connman_service *service)
+{
+       if (!service)
+               return false;
+
+       return service->is_internet_connection;
+}
+#endif
+
 void __connman_service_set_proxy_autoconfig(struct connman_service *service,
                                                        const char *url)
 {
@@ -6536,6 +7002,11 @@ static void service_initialize(struct connman_service *service)
        service->wps = false;
        service->wps_advertizing = false;
 #if defined TIZEN_EXT
+       memset(service->last_connected_bssid, 0, WIFI_BSSID_LEN_MAX);
+       service->is_internet_connection = false;
+       service->assoc_reject_count = 0;
+#endif
+#if defined TIZEN_EXT
        service->disconnection_requested = false;
        service->storage_reload = false;
        /*
@@ -6632,13 +7103,173 @@ void connman_service_unref_debug(struct connman_service *service,
        g_hash_table_remove(service_hash, service->identifier);
 }
 
+#if defined TIZEN_EXT
+static int calculate_score_last_user_selection(struct connman_service *service)
+{
+       int score = 0;
+       struct connman_device *device;
+       const char *last_user_selection_ident;
+       time_t last_user_selection_time;
+       unsigned int frequency;
+       time_t curr_time;
+       time_t ref_time;
+       struct tm* ref_timeinfo;
+
+       device = connman_network_get_device(service->network);
+       last_user_selection_time = connman_device_get_last_user_selection_time(device);
+       last_user_selection_ident = connman_device_get_last_user_selection_ident(device);
+       frequency = connman_network_get_frequency(service->network);
+
+       if (ins_settings.last_user_selection) {
+               if (g_strcmp0(last_user_selection_ident, service->identifier) == 0 &&
+                       (((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
+                       frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
+                       service->strength >= ins_settings.signal_level3_24ghz) ||
+                       ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
+                       frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
+                       service->strength >= ins_settings.signal_level3_5ghz))) {
+
+                       /* Only events that occur within 8 hours are counted. */
+                       curr_time = time(NULL);
+                       ref_timeinfo = localtime(&curr_time);
+                       ref_timeinfo->tm_hour -= 8;
+                       ref_time = mktime(ref_timeinfo);
+
+                       if (last_user_selection_time > ref_time) {
+                               int time_diff = (curr_time - last_user_selection_time) / 60;
+                               int denominator = ins_settings.last_user_selection_time - time_diff;
+                               int numerator = ins_settings.last_user_selection_time /
+                                                                       ins_settings.last_user_selection_score;
+                               int last_user_score = denominator / numerator;
+
+                               score += (last_user_score > ins_settings.last_user_selection_score ?
+                                       ins_settings.last_user_selection_score : last_user_score);
+                       }
+               }
+       }
+
+       return score;
+}
+
+static int calculate_score_last_connected(struct connman_service *service)
+{
+       int score = 0;
+       struct connman_device *device;
+       const char *last_connected_ident;
+       unsigned int frequency;
+
+       device = connman_network_get_device(service->network);
+       last_connected_ident = connman_device_get_last_connected_ident(device);
+       frequency = connman_network_get_frequency(service->network);
+
+       if (g_strcmp0(last_connected_ident, service->identifier) == 0 &&
+               (((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
+               frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
+               service->strength >= ins_settings.signal_level3_24ghz) ||
+               ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
+               frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
+               service->strength >= ins_settings.signal_level3_5ghz))) {
+               score += ins_settings.last_connected_score;
+       }
+
+       return score;
+}
+
+static int calculate_score_frequency(struct connman_service *service)
+{
+       int score = 0;
+       unsigned int frequency;
+
+       frequency = connman_network_get_frequency(service->network);
+
+       switch (ins_settings.preferred_freq) {
+       case CONNMAN_INS_PREFERRED_FREQ_24GHZ:
+               if ((frequency >= FREQ_RANGE_24GHZ_CHANNEL_14 &&
+                       frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
+                       (service->strength >= ins_settings.signal_level3_24ghz))
+                       score += ins_settings.preferred_freq_score;
+
+               break;
+       case CONNMAN_INS_PREFERRED_FREQ_5GHZ:
+               if ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
+                       frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
+                       (service->strength >= ins_settings.signal_level3_5ghz))
+                       score += ins_settings.preferred_freq_score;
+
+               break;
+       default:
+               break;
+       }
+
+       return score;
+}
+
+static int calculate_score_security_priority(struct connman_service *service)
+{
+       int score = 0;
+
+       if (ins_settings.security_priority_count)
+               score += ins_settings.security_priority[service->security];
+
+       return score;
+}
+
+static int calculate_score_internet_connection(struct connman_service *service)
+{
+       int score = 0;
+
+       if (ins_settings.internet) {
+               if (service->is_internet_connection)
+                       score += ins_settings.internet_score;
+       }
+
+       return score;
+}
+
+static int calculate_score_strength(struct connman_service *service)
+{
+       int score = 0;
+
+       if (ins_settings.signal)
+               score += (((service->strength > 60) ? 60 : service->strength) - 35);
+
+       return score;
+}
+
+static int calculate_score(struct connman_service *service)
+{
+       int score = 0;
+
+       if (service->type != CONNMAN_SERVICE_TYPE_WIFI) {
+               score += calculate_score_internet_connection(service);
+               service->ins_score = score;
+               return score;
+       }
+
+       score += calculate_score_last_user_selection(service);
+       score += calculate_score_last_connected(service);
+       score += calculate_score_frequency(service);
+       score += calculate_score_security_priority(service);
+       score += calculate_score_internet_connection(service);
+       score += calculate_score_strength(service);
+
+       service->ins_score = score;
+       return score;
+}
+#endif
+
 static gint service_compare(gconstpointer a, gconstpointer b)
 {
        struct connman_service *service_a = (void *) a;
        struct connman_service *service_b = (void *) b;
        enum connman_service_state state_a, state_b;
        bool a_connected, b_connected;
+#if defined TIZEN_EXT
+       int score_a;
+       int score_b;
+#else
        gint strength;
+#endif
 
        state_a = service_a->state;
        state_b = service_b->state;
@@ -6727,17 +7358,60 @@ static gint service_compare(gconstpointer a, gconstpointer b)
                        return 1;
        }
 
+#if defined TIZEN_EXT
+       score_a = calculate_score(service_a);
+       score_b = calculate_score(service_b);
+       if (score_b != score_a)
+               return score_b - score_a;
+#else
        strength = (gint) service_b->strength - (gint) service_a->strength;
        if (strength)
                return strength;
+#endif
 
        return g_strcmp0(service_a->name, service_b->name);
 }
 
+#if defined TIZEN_EXT_INS
+static void print_service_sort(gpointer data, gpointer user_data)
+{
+       struct connman_service *service = data;
+       struct connman_device *device;
+       const char *last_user_selection_ident;
+       const char *last_connected_ident;
+       unsigned int frequency;
+       time_t ref_time;
+       struct tm* timeinfo;
+       time_t last_user_selection_time;
+
+       device = connman_network_get_device(service->network);
+       last_user_selection_ident = connman_device_get_last_user_selection_ident(device);
+       last_user_selection_time = connman_device_get_last_user_selection_time(device);
+       last_connected_ident = connman_device_get_last_connected_ident(device);
+       frequency = connman_network_get_frequency(service->network);
+
+       /* Only events that occur within 8 hours are checked. */
+       ref_time = time(NULL);
+       timeinfo = localtime(&ref_time);
+       timeinfo->tm_hour -= 8;
+       ref_time = mktime(timeinfo);
+
+       DBG("name[%s] score[%d] strength[%d] freq[%d] last_usr[%d] last_conn[%d] internet[%d]",
+               service->name, service->ins_score, service->strength, frequency,
+               (g_strcmp0(last_user_selection_ident, service->identifier) == 0 &&
+               last_user_selection_time > ref_time) ? 1 : 0,
+               g_strcmp0(last_connected_ident, service->identifier) == 0 ? 1 : 0,
+               service->is_internet_connection);
+}
+#endif
+
 static void service_list_sort(void)
 {
        if (service_list && service_list->next) {
                service_list = g_list_sort(service_list, service_compare);
+#if defined TIZEN_EXT_INS
+               g_list_foreach(service_list, print_service_sort, NULL);
+#endif
                service_schedule_changed();
        }
 }
@@ -7657,6 +8331,10 @@ static int service_indicate_state(struct connman_service *service)
                        single_connected_tech(service);
 #endif
 
+#if defined TIZEN_EXT
+               if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
+                       connman_service_set_internet_connection(service, true);
+#endif
                break;
 
        case CONNMAN_SERVICE_STATE_DISCONNECT:
@@ -8784,8 +9462,12 @@ static int service_register(struct connman_service *service)
        DBG("path %s", service->path);
 
 #if defined TIZEN_EXT
+       int ret;
        service_load(service);
-       int ret = __connman_config_provision_service(service);
+       ret = service_ext_load(service);
+       if (ret == -ERANGE)
+               service_ext_save(service);
+       ret = __connman_config_provision_service(service);
        if (ret < 0)
                DBG("Failed to provision service");
 #else
@@ -9416,6 +10098,9 @@ void __connman_service_update_from_network(struct connman_network *network)
        bool roaming;
        const char *name;
        bool stats_enable;
+#if defined TIZEN_EXT
+       bool need_save = false;
+#endif
 
        service = connman_service_lookup_from_network(network);
        if (!service)
@@ -9472,6 +10157,16 @@ roaming:
        roaming_changed(service);
 
 sorting:
+#if defined TIZEN_EXT
+       need_save |= update_last_connected_bssid(service);
+       need_save |= update_assoc_reject(service);
+       if (need_save) {
+               g_get_current_time(&service->modified);
+               service_ext_save(service);
+               need_sort = true;
+       }
+#endif
+
        if (need_sort) {
                service_list_sort();
        }
@@ -9654,6 +10349,94 @@ static struct connman_agent_driver agent_driver = {
        .context_unref  = agent_context_unref,
 };
 
+#if defined TIZEN_EXT
+static void ins_setting_init(void)
+{
+       int i;
+       const char *string;
+       char **string_list;
+       unsigned int string_count;
+
+       ins_settings.last_user_selection = connman_setting_get_bool("INSLastUserSelection");
+       ins_settings.last_user_selection_time = connman_setting_get_uint("INSLastUserSelectionTime");
+       ins_settings.last_connected = connman_setting_get_bool("INSLastConnected");
+
+       string = connman_option_get_string("INSPreferredFreq");
+       if (g_str_equal(string, "5GHz"))
+               ins_settings.preferred_freq = CONNMAN_INS_PREFERRED_FREQ_5GHZ;
+       else if (g_str_equal(string, "2.4GHz"))
+               ins_settings.preferred_freq = CONNMAN_INS_PREFERRED_FREQ_24GHZ;
+       else
+               ins_settings.preferred_freq = CONNMAN_INS_PREFERRED_FREQ_UNKNOWN;
+
+       ins_settings.security_priority_count = connman_setting_get_uint("INSSecurityPriorityCount");
+       ins_settings.security_priority_score = connman_setting_get_uint("INSSecurityPriorityScore");
+       string_count = ins_settings.security_priority_count;
+
+       memset(ins_settings.security_priority, 0, sizeof(ins_settings.security_priority));
+       string_list = connman_setting_get_string_list("INSSecurityPriority");
+       for (i = 0; string_list && string_list[i]; i++) {
+               unsigned int security_score = string_count * ins_settings.security_priority_score;
+
+               if (g_str_equal(string_list[i], "WEP"))
+                       ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_WEP] = security_score;
+               else if (g_str_equal(string_list[i], "PSK"))
+                       ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_PSK] = security_score;
+               else if (g_str_equal(string_list[i], "8021X"))
+                       ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_8021X] = security_score;
+               else if (g_str_equal(string_list[i], "WPA"))
+                       ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_WPA] = security_score;
+               else if (g_str_equal(string_list[i], "RSN"))
+                       ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_RSN] = security_score;
+               else if (g_str_equal(string_list[i], "SAE"))
+                       ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_SAE] = security_score;
+               else if (g_str_equal(string_list[i], "OWE"))
+                       ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_OWE] = security_score;
+               else if (g_str_equal(string_list[i], "DPP"))
+                       ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_DPP] = security_score;
+
+               string_count--;
+       }
+
+       ins_settings.signal = connman_setting_get_bool("INSSignal");
+       ins_settings.internet = connman_setting_get_bool("INSInternet");
+
+       ins_settings.last_user_selection_score = connman_setting_get_uint("INSLastUserSelectionScore");
+       ins_settings.last_connected_score = connman_setting_get_uint("INSLastConnectedScore");
+       ins_settings.preferred_freq_score = connman_setting_get_uint("INSPreferredFreqScore");
+       ins_settings.internet_score = connman_setting_get_uint("INSInternetScore");
+
+       ins_settings.signal_level3_5ghz = connman_setting_get_int("INSSignalLevel3_5GHz");
+       ins_settings.signal_level3_24ghz = connman_setting_get_int("INSSignalLevel3_24GHz");
+
+       DBG("last_user_selection [%s]", ins_settings.last_user_selection ? "true" : "false");
+       DBG("last_user_selection_time [%d]", ins_settings.last_user_selection_time);
+       DBG("last_user_selection_score [%d]", ins_settings.last_user_selection_score);
+
+       DBG("last_connected [%s]", ins_settings.last_connected ? "true" : "false");
+       DBG("last_connected_score [%d]", ins_settings.last_connected_score);
+
+       DBG("preferred_freq [%s]", ins_settings.preferred_freq ? "true" : "false");
+       DBG("preferred_freq_score [%d]", ins_settings.preferred_freq_score);
+
+       DBG("security_priority_count [%d]", ins_settings.security_priority_count);
+       for (i = 0; i < CONNMAN_SERVICE_SECURITY_MAX; i++) {
+               if (ins_settings.security_priority[i])
+                       DBG("security_priority %s [%d]", security2string(i),
+                                       ins_settings.security_priority[i]);
+       }
+       DBG("security_priority_score [%d]", ins_settings.security_priority_score);
+
+       DBG("signal [%s]", ins_settings.signal ? "true" : "false");
+
+       DBG("internet [%s]", ins_settings.internet ? "true" : "false");
+       DBG("internet_score [%d]", ins_settings.internet_score);
+
+       DBG("signal_level3_5ghz [%d]", ins_settings.signal_level3_5ghz);
+       DBG("signal_level3_24ghz [%d]", ins_settings.signal_level3_24ghz);
+}
+#endif
+
 int __connman_service_init(void)
 {
        int err;
@@ -9681,6 +10464,10 @@ int __connman_service_init(void)
 
        remove_unprovisioned_services();
 
+#if defined TIZEN_EXT
+       ins_setting_init();
+#endif
+
        return 0;
 }
 
index 6ca600b..277e5f5 100755 (executable)
@@ -35,6 +35,9 @@
 
 #define SETTINGS       "settings"
 #define DEFAULT                "default.profile"
+#if defined TIZEN_EXT
+#define INS_SETTINGS   "settings.ins"
+#endif
 
 #define MODE           (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | \
                        S_IXGRP | S_IROTH | S_IXOTH)
@@ -130,6 +133,40 @@ int __connman_storage_save_global(GKeyFile *keyfile)
        return ret;
 }
 
+#if defined TIZEN_EXT
+GKeyFile *__connman_storage_load_ins(void)
+{
+       gchar *pathname;
+       GKeyFile *keyfile = NULL;
+
+       pathname = g_strdup_printf("%s/%s", STORAGEDIR, INS_SETTINGS);
+       if (!pathname)
+               return NULL;
+
+       keyfile = storage_load(pathname);
+
+       g_free(pathname);
+
+       return keyfile;
+}
+
+int __connman_storage_save_ins(GKeyFile *keyfile)
+{
+       gchar *pathname;
+       int ret;
+
+       pathname = g_strdup_printf("%s/%s", STORAGEDIR, INS_SETTINGS);
+       if (!pathname)
+               return -ENOMEM;
+
+       ret = storage_save(keyfile, pathname);
+
+       g_free(pathname);
+
+       return ret;
+}
+#endif
+
 void __connman_storage_delete_global(void)
 {
        gchar *pathname;
old mode 100644 (file)
new mode 100755 (executable)
index 57abdf1..62f6b8d
@@ -422,6 +422,10 @@ static void wispr_portal_error(struct connman_wispr_portal_context *wp_context)
        DBG("Failed to proceed wispr/portal web request");
 
        wp_context->wispr_result = CONNMAN_WISPR_RESULT_FAILED;
+
+#if defined TIZEN_EXT
+       connman_service_set_internet_connection(wp_context->service, false);
+#endif
 }
 
 static void portal_manage_status(GWebResult *result,
index c18fee4..474c62f 100755 (executable)
@@ -232,6 +232,18 @@ bool connman_setting_get_bool(const char *key)
        return false;
 }
 
+#if defined TIZEN_EXT
+unsigned int connman_setting_get_uint(const char *key)
+{
+       return 0;
+}
+
+int connman_setting_get_int(const char *key)
+{
+       return 0;
+}
+#endif
+
 char **connman_setting_get_string_list(const char *key)
 {
        return NULL;