Revert "Revert "libdvr: Remove direct dependency between libdvr and DTVKit  [1/1]""

This reverts commit 98707a3acf733d705d2a2c5a271806fc1fe63820.

Change-Id: I165ffa019f14097322cf013e5ec4dca5bb26cd58
diff --git a/include/dvr_utils.h b/include/dvr_utils.h
index fbfa024..c070f99 100644
--- a/include/dvr_utils.h
+++ b/include/dvr_utils.h
@@ -10,99 +10,45 @@
 extern "C" {
 #endif
 
-
-/**\brief read sysfs node
- *  name file name
- *  buf  store sysfs value buf
- *  len  buf len
- */
-typedef void (*DVR_Read_Sysfs_Cb)(const char *name, char *buf, int len);
-
-/**\brief write sysfs
- *  name file name
- *  cmd  write to sysfs node cmd
- */
-typedef void (*DVR_Write_Sysfs_Cb)(const char *name, const char *cmd);
-
-/**\brief read prop
- *  name prop name
- *  buf  store prop value buf
- *  len  buf len
- */
-typedef void (*DVR_Read_Prop_Cb)(const char *name, char *buf, int len);
-
-/**\brief write prop
- *  name prop name
- *  cmd  write to prop node cmd
- */
-typedef void (*DVR_Write_Prop_Cb)(const char *name, const char *cmd);
-
-
-/**\brief regist rw sysfs cb
- * \param[in] fun callback
- * \return
- *   - DVR_SUCCESS
- *   - error
- */
-int dvr_register_rw_sys(DVR_Read_Sysfs_Cb RCb, DVR_Write_Sysfs_Cb WCb);
-
-/**\brief unregist rw sys cb
- */
-int dvr_unregister_rw_sys(void);
-
-
-/**\brief regist rw prop cb
- * \param[in] fun callback
- * \return
- *   - DVR_SUCCESS
- *   - error
- */
-
-int dvr_register_rw_prop(DVR_Read_Prop_Cb RCb, DVR_Write_Prop_Cb WCb);
-
-/**\brief unregist rw prop cb */
-int dvr_unregister_rw_prop(void);
-
-
 /**\brief Write a string cmd to a file
  * \param[in] name File name
  * \param[in] cmd String command
  * \return DVR_SUCCESS On success
  * \return Error code On failure
  */
-
 int dvr_file_echo(const char *name, const char *cmd);
 
-
 /**\brief read sysfs file
  * \param[in] name, File name
  * \param[out] buf, store sysfs node value
  * \return DVR_SUCCESS On success
  * \return Error code On failure
  */
-
 int dvr_file_read(const char *name, char *buf, int len);
 
-
-/**\brief Write a string cmd to a prop
- * \param[in] name, prop name
- * \param[in] cmd, String command
+/**\brief read property value
+ * \param[in] name, property name
+ * \param[out] buf, property value
  * \return DVR_SUCCESS On success
- * \return Error code On failure
+ * \return DVR_FAILURE On failure
  */
-
-int dvr_prop_echo(const char *name, const char *cmd);
-
-
-/**\brief read prop value
- * \param[in] name, prop name
- * \param[out] buf, store prop node value
- * \return DVR_SUCCESS On success
- * \return Error code On failure
- */
-
 int dvr_prop_read(const char *name, char *buf, int len);
 
+/**\brief write property value
+ * \param[in] name, property name
+ * \param[in] value, property value
+ * \return DVR_SUCCESS On success
+ * \return DVR_FAILURE On failure
+ */
+int dvr_prop_write(const char *name, char *value);
+
+/**\brief read int type property value
+ * \param[in] name, property name
+ * \param[in] def, default property value in case any failure
+ * \return int type property value. If any failure default value will be returned instead
+ */
+int dvr_prop_read_int(const char *name, int def);
+
 /**\brief calculates the difference between ts1 and ts2
  * \param[in] ts1, higher bound of the timespec* whose length is calculated
  * \param[in] ts2, lower bound of the timespec* whose length is calculated
diff --git a/include/dvr_wrapper.h b/include/dvr_wrapper.h
index dd71264..2917dc7 100644
--- a/include/dvr_wrapper.h
+++ b/include/dvr_wrapper.h
@@ -392,6 +392,25 @@
  */
 int dvr_wrapper_set_ac4_preselection_id(DVR_WrapperPlayback_t playback, int presel_id);
 
+/**
+ * Set various libdvr properties
+ * \param[in] prop_name property name
+ * \param[in] prop_value property value
+ * \retval DVR_SUCCESS On success.
+ * \return DVR_FAILURE On failure.
+ */
+int dvr_wrapper_property_set(const char* prop_name, const char* prop_value);
+
+/**
+ * Get various libdvr properties
+ * \param[in] prop_name property name
+ * \param[out] prop_value property value. Buffer lifecycle is managed by caller.
+ * \param[in] length buffer length of prop_value
+ * \retval DVR_SUCCESS On success.
+ * \return DVR_FAILURE On failure.
+ */
+int dvr_wrapper_property_get(const char* prop_name, char* prop_value, int length);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/dvr_playback.c b/src/dvr_playback.c
index 898f2aa..dbeb867 100644
--- a/src/dvr_playback.c
+++ b/src/dvr_playback.c
@@ -932,13 +932,6 @@
     DVR_PB_INFO("player is NULL");
     return DVR_TRUE;
   }
-  char buf[10] = {0};
-  dvr_prop_read("vendor.tv.libdvr.con", buf, sizeof(buf));
-  DVR_PB_INFO("player get prop[%d][%s]", atoi(buf), buf);
-
-  if (atoi(buf) != 1) {
-    //return DVR_TRUE;
-  }
 
   DVR_PB_INFO(":play speed: %f  ply dur: %u sys_dur: %u",
                 player->speed,
@@ -1014,30 +1007,17 @@
   #define MAX_REACHEND_TIMEOUT (3000)
   int reach_end_timeout = 0;//ms
   int cache_time = 0;
-  int timeout = 200;//ms
   int check_no_data_time = 4;
-  uint64_t write_timeout_ms = 50;
   int buf_len = player->openParams.block_size > 0 ? player->openParams.block_size : (256 * 1024);
   DVR_Bool_t b_writed_whole_block = player->openParams.block_size > 0 ? DVR_TRUE:DVR_FALSE;
   int first_write = 0;
   int dec_buf_size = buf_len + 188;
   int real_read = 0;
   DVR_Bool_t goto_rewrite = DVR_FALSE;
-  char prop_buf[10];
-	int read = 0;
+  int read = 0;
 
-  memset(prop_buf, 0 ,sizeof(prop_buf));
-  dvr_prop_read("vendor.tv.libdvr.writetm", prop_buf, sizeof(prop_buf));
-  DVR_PB_INFO("---vendor.tv.libdvr.writetm get prop[%d][%s]block_size[%d]", atoi(prop_buf), prop_buf, player->openParams.block_size);
-  if (atoi(prop_buf) > 0)
-    write_timeout_ms = atoi(prop_buf);
-
-
-  memset(prop_buf, 0 ,sizeof(prop_buf));
-  dvr_prop_read("vendor.tv.libdvr.waittm", prop_buf, sizeof(prop_buf));
-  DVR_PB_INFO("---vendor.tv.libdvr.waittm get prop[%d][%s]block_size[%d]", atoi(prop_buf), prop_buf, player->openParams.block_size);
-  if (atoi(prop_buf) > 0)
-    timeout = atoi(prop_buf);
+  const uint64_t write_timeout_ms = (uint64_t)dvr_prop_read_int("vendor.tv.libdvr.writetm",50);
+  const int timeout = dvr_prop_read_int("vendor.tv.libdvr.waittm",200);
 
   if (player->is_secure_mode) {
     if (dec_buf_size > player->secure_buffer_size) {
@@ -1644,18 +1624,7 @@
 
 static int getFakePid()
 {
-   char fake_pid_prop[] = "vendor.tv.dtv.fake_pid";
-   char buf[32] = {0};
-   int pid = 0xffff;
-
-   dvr_prop_read(fake_pid_prop, buf, sizeof(buf));
-
-   if (sscanf(buf, "%i", &pid) != 1)
-   {
-      DVR_PB_INFO("get fake pid error");
-      pid = 0xffff;
-   }
-   return pid;
+   return dvr_prop_read_int("vendor.tv.dtv.fake_pid",0xffff);
 }
 
 void dvr_playback_change_seek_state(DVR_PlaybackHandle_t handle,int pid) {
diff --git a/src/dvr_utils.c b/src/dvr_utils.c
index 6b99d7a..40dcfec 100644
--- a/src/dvr_utils.c
+++ b/src/dvr_utils.c
@@ -12,6 +12,12 @@
 #include <cutils/properties.h>
 #endif
 
+#define _GNU_SOURCE
+#define __USE_GNU
+#include <search.h>
+
+static struct hsearch_data  *prop_htab = NULL;
+
 /****************************************************************************
  * Macro definitions
  ***************************************************************************/
@@ -19,94 +25,11 @@
 /****************************************************************************
  * Static functions
  ***************************************************************************/
-int (*Write_Sysfs_ptr)(const char *path, char *value);
-int (*ReadNum_Sysfs_ptr)(const char *path, char *value, int size);
-int (*Read_Sysfs_ptr)(const char *path, char *value);
-
-typedef struct dvr_rw_sysfs_cb_s
-{
-  DVR_Read_Sysfs_Cb readSysfsCb;
-  DVR_Write_Sysfs_Cb writeSysfsCb;
-}dvr_rw_sysfs_cb_t;
-
-dvr_rw_sysfs_cb_t rwSysfsCb = {.readSysfsCb = NULL, .writeSysfsCb = NULL};
-
-typedef struct dvr_rw_prop_cb_s
-{
-  DVR_Read_Prop_Cb readPropCb;
-  DVR_Write_Prop_Cb writePropCb;
-}dvr_rw_prop_cb_t;
-
-dvr_rw_prop_cb_t rwPropCb = {.readPropCb = NULL, .writePropCb = NULL};
 
 /****************************************************************************
  * API functions
  ***************************************************************************/
 
-/**\brief regist rw sysfs cb
- * \param[in] fun callback
- * \return
- *   - DVR_SUCCESS
- *   - error
- */
-int dvr_register_rw_sys(DVR_Read_Sysfs_Cb RCb, DVR_Write_Sysfs_Cb WCb)
-{
-
-  if (RCb == NULL || WCb == NULL) {
-    DVR_INFO("dvr_register_rw_sys error param is NULL !!");
-    return DVR_FAILURE;
-  }
-  if (!rwSysfsCb.readSysfsCb)
-    rwSysfsCb.readSysfsCb = RCb;
-  if (!rwSysfsCb.writeSysfsCb)
-    rwSysfsCb.writeSysfsCb = WCb;
-  DVR_INFO("dvr_register_rw_sys success !!");
-  return DVR_SUCCESS;
-}
-
-/**\brief unregist rw sys cb
- */
-int dvr_unregister_rw_sys()
-{
-  if (rwSysfsCb.readSysfsCb)
-    rwSysfsCb.readSysfsCb = NULL;
-  if (rwSysfsCb.writeSysfsCb)
-    rwSysfsCb.writeSysfsCb = NULL;
-  return DVR_SUCCESS;
-}
-
-/**\brief regist rw prop cb
- * \param[in] fun callback
- * \return
- *   - DVR_SUCCESS
- *   - error
- */
-
-int dvr_register_rw_prop(DVR_Read_Prop_Cb RCb, DVR_Write_Prop_Cb WCb)
-{
-  if (RCb == NULL || WCb == NULL) {
-    DVR_INFO("dvr_register_rw_prop error param is NULL !!");
-    return DVR_FAILURE;
-  }
-
-  if (!rwPropCb.readPropCb)
-    rwPropCb.readPropCb = RCb;
-  if (!rwPropCb.writePropCb)
-    rwPropCb.writePropCb = WCb;
-
-  DVR_INFO("dvr_register_rw_prop !!");
-  return DVR_SUCCESS;
-}
-
-/**\brief unregist rw prop cb */
-int dvr_unregister_rw_prop()
-{
-  if (rwPropCb.readPropCb)
-    rwPropCb.readPropCb = NULL;
-  if (rwPropCb.writePropCb)
-    rwPropCb.writePropCb = NULL;
-  return DVR_SUCCESS;
-}
 
 /**\brief Write a string cmd to a file
  * \param[in] name, File name
@@ -122,12 +45,6 @@
     return DVR_FAILURE;
   }
 
-  if (rwSysfsCb.writeSysfsCb)
-  {
-    rwSysfsCb.writeSysfsCb(name, cmd);
-    return DVR_SUCCESS;
-  }
-
   fd = open(name, O_WRONLY);
   if (fd == -1)
   {
@@ -166,13 +83,6 @@
     return DVR_FAILURE;
   }
 
-  if (rwSysfsCb.readSysfsCb)
-  {
-    rwSysfsCb.readSysfsCb(name, buf, len);
-    return DVR_SUCCESS;
-  }
-
-
   fp = fopen(name, "r");
   if (!fp)
   {
@@ -190,59 +100,126 @@
   return ret ? DVR_SUCCESS : DVR_FAILURE;
 }
 
-
-/**\brief Write a string cmd to a prop
- * \param[in] name, prop name
- * \param[in] cmd, String command
+/**\brief read property value
+ * \param[in] name, property name
+ * \param[out] buf, property value
  * \return DVR_SUCCESS On success
- * \return Error code On failure
+ * \return DVR_FAILURE On failure
  */
-
-int dvr_prop_echo(const char *name, const char *cmd)
-{
-  if (name == NULL || cmd == NULL) {
-    DVR_ERROR("dvr_prop_echo: error param is NULL");
-    return DVR_FAILURE;
-  }
-
-  if (rwPropCb.writePropCb)
-  {
-    rwPropCb.writePropCb(name, cmd);
-    return DVR_SUCCESS;
-  }
-
-#ifdef __ANDROID_API__
-  property_set(name, cmd);
-#endif
-  DVR_DEBUG("dvr_prop_echo: error writePropCb is NULL, used property_set");
-  return DVR_FAILURE;
-}
-
-/**\brief read prop value
- * \param[in] name, prop name
- * \param[out] buf, store prop node value
- * \return DVR_SUCCESS On success
- * \return Error code On failure
- */
-
 int dvr_prop_read(const char *name, char *buf, int len)
 {
   if (name == NULL || buf == NULL) {
-    DVR_INFO("dvr_prop_read: error param is NULL");
+    DVR_ERROR("%s, property name or value buffer is NULL",__func__);
     return DVR_FAILURE;
   }
 
-  if (rwPropCb.readPropCb)
-  {
-    rwPropCb.readPropCb(name, buf, len);
+#ifdef __ANDROID_API__
+  memset(buf,0,len);
+  property_get(name, buf, "");
+  if (strlen(buf)>0) {
+    DVR_INFO("%s, Read property, name:%s, value:%s",__func__,name,buf);
     return DVR_SUCCESS;
   }
+#endif
+
+  if (prop_htab == NULL) {
+    prop_htab = calloc(1,sizeof(struct hsearch_data));
+    if (prop_htab == NULL) {
+      DVR_ERROR("%s, Failed to allocate memory for prop_htab",__func__);
+      return DVR_FAILURE;
+    }
+    if (0 == hcreate_r(100,prop_htab))
+    {
+      DVR_ERROR("%s, Failed to create hash table with hcreate_r",__func__);
+      return DVR_FAILURE;
+    }
+  }
+
+  ENTRY e, *ep;
+  e.key = name;
+  if (hsearch_r(e,FIND,&ep,prop_htab) == 0) {
+    DVR_ERROR("%s, Failed to read property %s",__func__,name);
+    return DVR_FAILURE;
+  }
+
+  strncpy(buf,ep->data,len);
+  DVR_INFO("%s, Read property from hash table, name:%s, value:%s",__func__,name,buf);
+  return DVR_SUCCESS;
+}
+
+/**\brief write property value
+ * \param[in] name, property name
+ * \param[in] value, property value
+ * \return DVR_SUCCESS On success
+ * \return DVR_FAILURE On failure
+ */
+int dvr_prop_write(const char *name, char *value)
+{
+  if (name == NULL || value == NULL) {
+    DVR_ERROR("%s: property name or value buffer is NULL",__func__);
+    return DVR_FAILURE;
+  }
 
 #ifdef __ANDROID_API__
-  property_get(name, buf, "");
+  property_set(name, value);
 #endif
-  DVR_INFO("dvr_prop_read: error readPropCb is NULL, used property_get");
-  return DVR_FAILURE;
+
+  if (prop_htab == NULL) {
+    prop_htab = calloc(1,sizeof(struct hsearch_data));
+    if (prop_htab == NULL) {
+      DVR_ERROR("%s, Failed to allocate memory for prop_htab",__func__);
+      return DVR_FAILURE;
+    }
+    if (0 == hcreate_r(100,prop_htab))
+    {
+      DVR_ERROR("%s, Failed to create hash table with hcreate_r",__func__);
+      return DVR_FAILURE;
+    }
+  }
+
+  ENTRY e, *ep;
+  e.key = name;
+  if (hsearch_r(e,FIND,&ep,prop_htab) != 0) {
+    // in case matched item is found
+    free(ep->data);
+    ep->data=strdup(value);
+  } else {
+    // in case no matched item, we need to add new one to hash table
+    e.key=strdup(name);
+    e.data=strdup(value);
+    if ( e.key != NULL && e.data != NULL ) {
+      if (hsearch_r(e,ENTER,&ep,prop_htab) == 0) {
+        DVR_ERROR("%s, Failed to add an entry to hash table %s:%s",__func__,name,value);
+        return DVR_FAILURE;
+      }
+    } else {
+      if (e.key != NULL) {
+        free(e.key);
+      }
+      if (e.data != NULL) {
+        free(e.data);
+      }
+      DVR_ERROR("%s, Failed to duplicate strings %s,%s",__func__,name,value);
+      return DVR_FAILURE;
+    }
+  }
+
+  DVR_INFO("%s, Wrote property to hash table, name:%s, value:%s",__func__,name,value);
+  return DVR_SUCCESS;
+}
+
+/**\brief read int type property value
+ * \param[in] name, property name
+ * \param[in] def, default property value in case any failure
+ * \return int type property value. If any failure default value will be returned instead
+ */
+int dvr_prop_read_int(const char *name, int def)
+{
+  char buf[16] = {0};
+  if (dvr_prop_read(name,buf,sizeof(buf)) == DVR_SUCCESS) {
+    return atoi(buf);
+  }
+  return def;
 }
 
 #define NSEC_PER_SEC 1000000000L
diff --git a/src/dvr_wrapper.c b/src/dvr_wrapper.c
index fd25a05..b7aee85 100644
--- a/src/dvr_wrapper.c
+++ b/src/dvr_wrapper.c
@@ -3129,3 +3129,13 @@
   return error;
 }
 
+int dvr_wrapper_property_set(const char* prop_name, const char* prop_value)
+{
+  return dvr_prop_write(prop_name,prop_value);
+}
+
+int dvr_wrapper_property_get(const char* prop_name, char* prop_value, int length)
+{
+  return dvr_prop_read(prop_name,prop_value,length);
+}
+