fm: Added support for configuring performance parameters

Add apis to configure fm performance related parameters.

CRs-Fixed: 671803
Change-Id: I37565c21a731023e42372be71fb28edc30154672
diff --git a/jni/ConfFileParser.cpp b/jni/ConfFileParser.cpp
new file mode 100644
index 0000000..103c240
--- /dev/null
+++ b/jni/ConfFileParser.cpp
@@ -0,0 +1,917 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *        * Redistributions of source code must retain the above copyright
+ *            notice, this list of conditions and the following disclaimer.
+ *        * Redistributions in binary form must reproduce the above copyright
+ *            notice, this list of conditions and the following disclaimer in the
+ *            documentation and/or other materials provided with the distribution.
+ *        * Neither the name of The Linux Foundation nor
+ *            the names of its contributors may be used to endorse or promote
+ *            products derived from this software without specific prior written
+ *            permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.    IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ConfFileParser.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+#include <math.h>
+#include <utils/Log.h>
+
+//declaration of functions only specific to this file
+static char parse_line
+(
+  group_table *key_file,
+  const char *line,
+  char **cur_grp
+);
+
+static char parse_load_frm_fhandler
+(
+  group_table *key_file,
+  FILE *fp
+);
+
+static char line_is_grp
+(
+  group_table *key_file,
+  const char *str,
+  char **cur_grp
+);
+
+static void free_grp_list
+(
+  group *a
+);
+
+static void free_key_list
+(
+  key_value_pair_list *a
+);
+
+static char line_is_key_value_pair
+(
+  group_table *key_file,
+  const char *str,
+  const char *cur_grp
+);
+
+static char line_is_comment
+(
+  const char *str
+);
+
+static char grp_exist
+(
+  const group_table *key_file,
+  const char *new_grp
+);
+
+static char add_grp
+(
+  group_table *key_file,
+  const char *new_grp
+);
+
+static group *alloc_group
+(
+  void
+);
+
+static key_value_pair_list *alloc_key_value_pair
+(
+  void
+);
+
+static char add_key_value_pair
+(
+  group_table *key_file,
+  const char *cur_grp,
+  const char *key,
+  const char *val
+);
+
+
+//Definitions
+void free_strs
+(
+  char **str_array
+)
+{
+  char **str_array_cpy = str_array;
+  if(str_array != NULL) {
+     while(*str_array != NULL) {
+           free(*str_array);
+           str_array++;
+     }
+  }
+  free(str_array_cpy);
+}
+//ToDo: Come up with code hashing
+//function
+unsigned int get_hash_code
+(
+  const char *str
+)
+{
+
+  unsigned len = strlen(str);
+  unsigned int i;
+  unsigned int hash_code = 0;
+
+  for(i = 0; len > 0; len--, i++) {
+      hash_code += (int)((str[i] * pow(2, len))) % INT_MAX;
+      hash_code %= INT_MAX;
+  }
+  return hash_code;
+}
+
+static key_value_pair_list *alloc_key_value_pair
+(
+  void
+)
+{
+  key_value_pair_list *key_list = NULL;
+
+  key_list = (key_value_pair_list *)malloc(
+                                       sizeof(key_value_pair_list));
+  if(key_list != NULL) {
+     key_list->key = NULL;
+     key_list->next = NULL;
+     key_list->value = NULL;
+  }
+  return key_list;
+}
+
+static group * alloc_group
+(
+  void
+)
+{
+  group *grp = NULL;
+  unsigned int i;
+
+  grp = (group *)malloc(sizeof(group));
+  if(grp != NULL) {
+     grp->grp_name = NULL;
+     grp->grp_next = NULL;
+     grp->num_of_keys = 0;
+     grp->keys_hash_size = MAX_UNIQ_KEYS;
+     grp->list = (key_value_pair_list **)malloc
+                    (sizeof(key_value_pair_list *) * grp->keys_hash_size);
+     if(grp->list == NULL) {
+        ALOGE("Could not alloc group\n");
+        free(grp);
+        grp = NULL;
+     }else {
+        for(i = 0; i < grp->keys_hash_size; i++) {
+            grp->list[i] = NULL;
+        }
+     }
+  }
+  return grp;
+}
+
+group_table *get_key_file
+(
+)
+{
+  group_table *t = NULL;
+  unsigned int i;
+
+  t = (group_table *)malloc(sizeof(group_table));
+  if (t != NULL) {
+      t->grps_hash_size = MAX_UNIQ_GRPS;
+      t->num_of_grps = 0;
+      t->grps_hash = (group **)malloc(sizeof(group *)
+                                       * t->grps_hash_size);
+      if (t->grps_hash == NULL) {
+          free(t);
+          return NULL;
+      }
+      for(i = 0; i < t->grps_hash_size; i++) {
+          t->grps_hash[i] = NULL;
+      }
+  }
+  return t;
+}
+
+void free_key_file(
+  group_table *key_file
+)
+{
+  unsigned int i;
+
+  if(key_file != NULL) {
+     if(key_file->grps_hash != NULL) {
+        for(i = 0; i < key_file->grps_hash_size; i++) {
+            free_grp_list(key_file->grps_hash[i]);
+        }
+     }
+     free(key_file->grps_hash);
+     free(key_file);
+  }
+}
+
+static void free_grp_list
+(
+  group *a
+)
+{
+  group *next;
+  unsigned int i;
+
+  while(a != NULL) {
+       next = a->grp_next;
+       if(a->list != NULL) {
+          for(i = 0; i < a->keys_hash_size; i++) {
+              free_key_list(a->list[i]);
+          }
+       }
+       free(a->grp_name);
+       free(a->list);
+       free(a);
+       a = next;
+  }
+}
+
+static void free_key_list
+(
+  key_value_pair_list *a
+)
+{
+  key_value_pair_list *next;
+
+  while(a != NULL) {
+       next = a->next;
+       free(a->key);
+       free(a->value);
+       free(a);
+       a = next;
+  }
+}
+//return all the groups
+//present in the file
+char **get_grps
+(
+  const group_table *key_file
+)
+{
+  char **grps = NULL;
+  unsigned int i = 0;
+  unsigned int j = 0;
+  unsigned int grp_len;
+  group *grp_list;
+
+  if((key_file == NULL)
+     || (key_file->grps_hash == NULL)
+     || (key_file->grps_hash_size == 0)
+     || (key_file->num_of_grps == 0)) {
+     return grps;
+  }
+  grps = (char **)calloc((key_file->num_of_grps + 1),
+                           sizeof(char *));
+  if(grps == NULL) {
+     return grps;
+  }
+  for(i = 0; i < key_file->grps_hash_size; i++) {
+      grp_list = key_file->grps_hash[i];
+      while(grp_list != NULL) {
+            grp_len = strlen(grp_list->grp_name);
+            grps[j] = (char *)malloc(sizeof(char) *
+                                     (grp_len + 1));
+            if(grps[j] == NULL) {
+               free_strs(grps);
+               grps = NULL;
+               return grps;
+            }
+            memcpy(grps[j], grp_list->grp_name,
+                   (grp_len + 1));
+            grp_list = grp_list->grp_next;
+            j++;
+      }
+  }
+  grps[j] = NULL;
+  return grps;
+}
+
+//returns the list of keys
+//associated with group name
+char **get_keys
+(
+  const group_table *key_file,
+  const char *grp_name
+)
+{
+  unsigned int grp_hash_code;
+  unsigned int grp_index;
+  unsigned int num_of_keys;
+  unsigned int i;
+  unsigned int j = 0;
+  unsigned int key_len;
+  group *grp;
+  key_value_pair_list *key_val_list;
+  char **keys = NULL;
+
+  if((key_file == NULL) || (grp_name == NULL)
+     || (key_file->num_of_grps == 0) ||
+     (key_file->grps_hash_size == 0) ||
+     (key_file->grps_hash == NULL) ||
+     (!strcmp(grp_name, ""))) {
+      return keys;
+  }
+  grp_hash_code = get_hash_code(grp_name);
+  grp_index = (grp_hash_code % key_file->grps_hash_size);
+  grp = key_file->grps_hash[grp_index];
+  while(grp != NULL) {
+        if(!strcmp(grp_name, grp->grp_name)) {
+            if((grp->num_of_keys == 0)
+               || (grp->keys_hash_size == 0)
+               || (grp->list == 0)) {
+               return keys;
+            }
+            keys = (char **)calloc((grp->num_of_keys + 1),
+                                   sizeof(char *));
+            if(keys == NULL) {
+                return keys;
+            }
+            for(i = 0; i < grp->keys_hash_size; i++) {
+                key_val_list = grp->list[i];
+                while(key_val_list != NULL) {
+                     key_len = strlen(key_val_list->key);
+                     keys[j] = (char *)malloc(sizeof(char) *
+                                              (key_len + 1));
+                     if(keys[j] == NULL) {
+                         free_strs(keys);
+                         keys = NULL;
+                         return keys;
+                     }
+                     memcpy(keys[j], key_val_list->key,
+                            (key_len + 1));
+                     j++;
+                     key_val_list = key_val_list->next;
+                }
+            }
+            keys[j] = NULL;
+            return keys;
+        }
+        grp = grp->grp_next;
+  }
+  return keys;
+}
+
+char *get_value
+(
+   const group_table *key_file,
+   const char *grp_name,
+   const char *key
+)
+{
+   unsigned int grp_hash_code;
+   unsigned int key_hash_code;
+   unsigned int grp_index;
+   unsigned int key_index;
+   unsigned val_len;
+   char *val = NULL;
+   group *grp;
+   key_value_pair_list *list;
+
+   if((key_file == NULL) || (grp_name == NULL)
+      || (key == NULL) || (key_file->grps_hash == NULL)
+      || (key_file->grps_hash_size == 0) || !strcmp(grp_name, "")
+      ||(!strcmp(key, ""))) {
+       return NULL;
+   }
+   grp_hash_code = get_hash_code(grp_name);
+   key_hash_code = get_hash_code(key);
+   grp_index = (grp_hash_code % key_file->grps_hash_size);
+   grp = key_file->grps_hash[grp_index];
+   while(grp != NULL) {
+         if(!strcmp(grp_name, grp->grp_name) && grp->keys_hash_size
+            && grp->list) {
+            key_index = (key_hash_code % grp->keys_hash_size);
+            list = grp->list[key_index];
+            while((list != NULL) && (strcmp(list->key, key))) {
+                   list = list->next;
+            }
+            if(list != NULL) {
+                val_len = strlen(list->value);
+                val = (char *)malloc(sizeof(char) * (val_len + 1));
+                if(val != NULL) {
+                   memcpy(val, list->value, val_len);
+                   val[val_len] = '\0';
+                }
+            }
+            return val;
+         }
+         grp = grp->grp_next;
+   }
+   return val;
+}
+//open the file,
+//read, parse and load
+//returns PARSE_SUCCESS if successfully
+//loaded else PARSE_FAILED
+char parse_load_file
+(
+  group_table *key_file,
+  const char *file
+)
+{
+  FILE *fp;
+  char ret = FALSE;
+
+  if((file == NULL) || !strcmp(file, "")) {
+     ALOGE("File name is null or empty \n");
+     return ret;
+  }
+
+  fp = fopen(file, "r");
+  if(fp == NULL) {
+     ALOGE("could not open file for read\n");
+     return ret;
+  }
+
+  ret = parse_load_frm_fhandler(key_file, fp);
+  fclose(fp);
+
+  return ret;
+}
+
+//Read block of data from file handler
+//extract each line, check kind of line(comment,
+//group, key value pair)
+static char parse_load_frm_fhandler
+(
+  group_table *key_file,
+  FILE *fp
+)
+{
+  char buf[MAX_LINE_LEN];
+  char ret = TRUE;
+  char *line = NULL;
+  void *new_line;
+  char *cur_grp = NULL;
+  unsigned line_len = 0;
+  unsigned line_allocated = 0;
+  unsigned int bytes_read = 0;
+  unsigned int i;
+  bool has_carriage_rtn = false;
+
+  while((bytes_read = fread(buf, 1, MAX_LINE_LEN, fp))) {
+        for(i = 0; i < bytes_read; i++) {
+            if(line_len == line_allocated) {
+                line_allocated += 25;
+                new_line = realloc(line, line_allocated);
+                if(new_line == NULL) {
+                   ret = FALSE;
+                   ALOGE("memory allocation failed for line\n");
+                   break;
+                }
+                line = (char *)new_line;
+            }
+            if((buf[i] == '\n')) {
+                has_carriage_rtn = false;
+                line[line_len] = '\0';
+                ret = parse_line(key_file, line, &cur_grp);
+                line_len = 0;
+                if(ret == FALSE) {
+                   ALOGE("could not parse the line, line not proper\n");
+                   break;
+                }
+            }else if(buf[i] == '\r') {
+                ALOGE("File has carriage return\n");
+                has_carriage_rtn = true;
+            }else if(has_carriage_rtn) {
+                ALOGE("File format is not proper, no line character\
+                        after carraige return\n");
+                ret = FALSE;
+                break;
+            }else {
+                line[line_len] = buf[i];
+                line_len++;
+            }
+        }
+        if (!ret) {
+            break;
+        }
+  }
+  free(line);
+  free(cur_grp);
+
+  return ret;
+}
+
+//checks whether a line is
+//comment or grp or key pair value
+//and accordingly adds to list
+static char parse_line
+(
+  group_table *key_file,
+  const char *line,
+  char **cur_grp
+)
+{
+  const char *line_begin;
+  char *grp_name;
+  unsigned int len;
+
+  if((line == NULL) || (key_file == NULL)) {
+      ALOGE("key file or line is null\n");
+      return FALSE;
+  }
+
+  for(line_begin = line; isspace(*line_begin);
+          line_begin++);
+
+  if(line_is_comment(line_begin)) {
+      ALOGE("line is comment\n");
+      return TRUE;
+  }else if(line_is_grp(key_file, line_begin, cur_grp)) {
+      ALOGE("line is grp\n");
+      return TRUE;
+  }else if(line_is_key_value_pair(key_file, line_begin, *cur_grp)) {
+      ALOGE("line is key value pair\n");
+      return TRUE;
+  }else {
+     ALOGE("line is neither comment, grp nor key value pair\n");
+     return FALSE;
+  }
+}
+
+static char line_is_comment
+(
+  const char *str
+)
+{
+  if(str == NULL) {
+      return FALSE;
+  }else if(((*str) == '#') || ((*str) == '\0')
+       || ((*str) == '\n')) {
+      return TRUE;
+  }else {
+      ALOGE("line is not comment\n");
+      return FALSE;
+  }
+}
+
+//return true if a group
+//name already exist
+//else false
+static char grp_exist
+(
+  const group_table *key_file,
+  const char *new_grp
+)
+{
+  unsigned hash_code;
+  unsigned int index;
+  group *grp;
+
+  if((key_file == NULL) || (new_grp == NULL)
+     || (!key_file->grps_hash_size)) {
+     return FALSE;
+  }else {
+    hash_code = get_hash_code(new_grp);
+    index = hash_code % key_file->grps_hash_size;
+    grp = key_file->grps_hash[index];
+    while(grp != NULL) {
+          if (!strcmp(grp->grp_name, new_grp))
+              return TRUE;
+          grp = grp->grp_next;
+    }
+    return FALSE;
+  }
+}
+
+//Add a group to group
+//table if it does not exist
+static char add_grp
+(
+  group_table *key_file,
+  const char *new_grp
+)
+{
+  unsigned int hash_code;
+  unsigned int index;
+  unsigned int grp_name_len;
+  group *grp;
+
+  if(!grp_exist(key_file, new_grp)) {
+      if((key_file == NULL) || (new_grp == NULL)
+         || !key_file->grps_hash_size) {
+         return FALSE;
+      }
+      hash_code = get_hash_code(new_grp);
+      ALOGE("group hash code is: %u\n", hash_code);
+      index = hash_code % key_file->grps_hash_size;
+      ALOGE("group index is: %u\n", index);
+      grp = alloc_group();
+      if(grp == NULL) {
+         return FALSE;
+      }
+      grp_name_len = strlen(new_grp);
+      grp->grp_name = (char *)malloc(
+                                  sizeof(char) * (grp_name_len + 1));
+      if(grp->grp_name == NULL) {
+         ALOGE("could not alloc memory for group name\n");
+         ALOGE("Add group failed\n");
+         free_grp_list(grp);
+         return FALSE;
+      }else {
+         memcpy(grp->grp_name, new_grp, (grp_name_len + 1));
+      }
+      grp->grp_next = key_file->grps_hash[index];
+      key_file->grps_hash[index] = grp;
+      key_file->num_of_grps++;
+      return TRUE;
+  }else {
+     return FALSE;
+  }
+}
+
+//checks validity of a group
+//a valid group is
+//inside [] group name must be
+//alphanumeric
+//Example: [grpName]
+static char line_is_grp
+(
+  group_table *key_file,
+  const char *str,
+  char **cur_grp
+)
+{
+  const char *g_start;
+  const char *g_end;
+  char *new_grp;
+  unsigned int grp_len;
+
+  if ((str == NULL) || (key_file == NULL)) {
+      ALOGE("str is null or key file is null\n");
+      return FALSE;
+  }
+  //checks start mark char ']'
+  if(((*str) != '[')) {
+      ALOGE("start mark is not '['\n");
+      return FALSE;
+  }else {
+      str++;
+      g_start = str;
+  }
+  //checks the end char '['
+  while((*str != '\0') && ((*str) != ']')) {
+        str++;
+  }
+  //if end mark group not found
+  if ((*str) != ']') {
+       ALOGE("grp end mark is not '['\n");
+       return FALSE;
+  }else {
+       g_end = (str - 1);
+  }
+
+  str++;
+  //if end mark found checks the rest chars as well
+  //rest chars should be space
+  while(((*str) == ' ') || ((*str) == '\t')) {
+        str++;
+  }
+  if(*str) {
+     ALOGE("after ']' there are some character\n");
+     return FALSE;
+  }
+
+  str = g_start;
+  while((*g_start != '\0') && (g_start != g_end)
+         && isalnum(*g_start)) {
+        g_start++;
+  }
+  if((g_start == g_end) && isalnum(*g_start)) {
+      //look up if already exist
+      //return false else insert the grp in grp table
+      grp_len = (g_end - str + 1);
+      new_grp = (char *)malloc(sizeof(char) * (grp_len + 1));
+      if (new_grp == NULL) {
+          ALOGE("could not alloc memory for new group\n");
+          return FALSE;
+      }
+      memcpy(new_grp, str, grp_len);
+      new_grp[grp_len] = '\0';
+
+      if(add_grp(key_file, new_grp)) {
+          free(*cur_grp);
+         *cur_grp = new_grp;
+         return TRUE;
+      }else {
+         ALOGE("could not add group to group table\n");
+         return FALSE;
+      }
+  }else {
+      return FALSE;
+  }
+}
+
+static char key_exist
+(
+  const group_table *key_file,
+  const char *cur_grp,
+  const char *key
+)
+{
+  unsigned int grp_hash_code;
+  unsigned int key_hash_code;
+  unsigned int grp_index;
+  unsigned int key_index;
+  group *grp = NULL;
+  key_value_pair_list *list = NULL;
+
+  if((key_file != NULL) && (cur_grp != NULL)
+      && (key != NULL) && ((key_file->grps_hash != NULL))
+      && (strcmp(key, ""))) {
+     grp_hash_code = get_hash_code(cur_grp);
+     grp_index = (grp_hash_code % key_file->grps_hash_size);
+     grp = key_file->grps_hash[grp_index];
+     key_hash_code = get_hash_code(key);
+     while((grp != NULL)) {
+           if(!strcmp(cur_grp, grp->grp_name)) {
+              key_index = (key_hash_code % grp->keys_hash_size);
+              if(!grp->list)
+                 list = grp->list[key_index];
+              while((list != NULL) && strcmp(key, list->key)) {
+                    list = list->next;
+              }
+              if(list != NULL){
+                  return TRUE;
+              }else{
+                  return FALSE;
+              }
+           }
+           grp = grp->grp_next;
+     }
+     if(!grp) {
+        return TRUE;
+     }else {
+        return FALSE;
+     }
+  }else {
+     return FALSE;
+  }
+}
+
+//checks validity of key
+//a valid key must start in
+//a seperate line and key must
+//be alphanumeric and before '='
+//there must not be any space
+//Example: key=value
+static char line_is_key_value_pair
+(
+  group_table *key_file,
+  const char *str,
+  const char *cur_grp
+)
+{
+  char *equal_start;
+  char *key;
+  char *val;
+  unsigned key_len;
+  unsigned val_len;
+
+  if((str == NULL) || (cur_grp == NULL) ||
+     !strcmp(cur_grp, "") || (key_file == NULL)) {
+     ALOGE("line is null or cur group or key file is null or empty\n");
+     return FALSE;
+  }
+  equal_start = strchr(str, '=');
+  key_len = (equal_start - str);
+  if((equal_start == NULL) || (equal_start == str)) {
+     ALOGE("line does not have '=' character or no key\n");
+     return FALSE;
+  }
+  while((str != equal_start) && isalnum(*str))
+        str++;
+  if((str == equal_start)) {
+      key = (char *)malloc(sizeof(char) * (key_len + 1));
+      if(key == NULL) {
+         ALOGE("could not alloc memory for new key\n");
+         return FALSE;
+      }
+      equal_start++;
+      val_len = strlen(equal_start);
+      val = (char *)malloc(sizeof(char) * (val_len + 1));
+      if(val == NULL) {
+         ALOGE("could not alloc memory for value\n");
+         return FALSE;
+      }
+      memcpy(key, (str - key_len), key_len);
+      memcpy(val, equal_start, val_len);
+      key[key_len] = '\0';
+      val[val_len] = '\0';
+      ALOGE("Grp: %s, key: %s, value: %s\n", cur_grp, key, val);
+      return add_key_value_pair(key_file,
+                                 cur_grp, key, val);
+  }else {
+     ALOGE("key name doesnot have alpha numeric char\n");
+     return FALSE;
+  }
+}
+
+static char add_key_value_pair
+(
+  group_table *key_file,
+  const char *cur_grp,
+  const char *key,
+  const char *val
+)
+{
+  unsigned int grp_hash_code;
+  unsigned int key_hash_code;
+  unsigned int grp_index;
+  unsigned int key_index;
+  unsigned key_len, val_len;
+  group *grp = NULL;
+  key_value_pair_list *list = NULL;
+
+  if((key_file != NULL) && (cur_grp != NULL)
+      && (key != NULL) && ((key_file->grps_hash != NULL))
+      && (strcmp(key, ""))) {
+     grp_hash_code = get_hash_code(cur_grp);
+     ALOGE("grp hash code is %u\n", grp_hash_code);
+     grp_index = (grp_hash_code % key_file->grps_hash_size);
+     ALOGE("grp index is %u\n", grp_index);
+     grp = key_file->grps_hash[grp_index];
+     key_hash_code = get_hash_code(key);
+     while((grp != NULL)) {
+           if(!strcmp(cur_grp, grp->grp_name)) {
+              key_index = (key_hash_code % grp->keys_hash_size);
+              if(grp->list) {
+                 list = grp->list[key_index];
+              }else {
+                 ALOGE("group list is null\n");
+                 return FALSE;
+              }
+              while((list != NULL) && strcmp(key, list->key)) {
+                    list = list->next;
+              }
+              if(list != NULL) {
+                  ALOGE("group already contains the key\n");
+                  return FALSE;
+              }else{
+                  list = alloc_key_value_pair();
+                  if(list == NULL) {
+                     ALOGE("add key value failed as could not alloc memory for key\
+                            val pair\n");
+                     return FALSE;
+                  }
+                  key_len = strlen(key);
+                  list->key = (char *)malloc(sizeof(char) *
+                                              (key_len + 1));
+                  if(list->key == NULL) {
+                     ALOGE("could not alloc memory for key\n");
+                     free(list);
+                     return FALSE;
+                  }
+                  val_len = strlen(val);
+                  list->value = (char *)malloc(sizeof(char) *
+                                                (val_len + 1));
+                  if(!list->value) {
+                      free(list->key);
+                      free(list);
+                      return FALSE;
+                  }
+                  memcpy(list->key, key, key_len);
+                  memcpy(list->value, val, val_len);
+                  list->key[key_len] = '\0';
+                  list->value[val_len] = '\0';
+                  list->next = grp->list[key_index];
+                  grp->list[key_index] = list;
+                  grp->num_of_keys++;
+                  return TRUE;
+              }
+           }
+           grp = grp->grp_next;
+     }
+     ALOGE("group does not exist\n");
+     return FALSE;
+  }else {
+     return FALSE;
+  }
+}