hikey: gralloc Update for new ION interface

4.12+ kernels have an updated ION interface; this adapts hikey's gralloc
to work seemlessly with both old and new kernels' interfaces.

Test: validated with both new and old kernels on hikey, with aosp master

Signed-off-by: Laura Abbott <labbott@redhat.com>
Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>
  [sumits: maintain compatibility with older kernels]

Change-Id: Ic30470004b48f14765fdee8179de6d17f7b448b5
diff --git a/gralloc/alloc_device.cpp b/gralloc/alloc_device.cpp
index cef5851..d1377ff 100644
--- a/gralloc/alloc_device.cpp
+++ b/gralloc/alloc_device.cpp
@@ -16,6 +16,7 @@
  * limitations under the License.
  */
 
+#include <cstdlib>
 #include <string.h>
 #include <errno.h>
 #include <pthread.h>
@@ -40,11 +41,11 @@
 #if GRALLOC_ARM_DMA_BUF_MODULE
 #include <linux/ion.h>
 #include <ion/ion.h>
+#include "ion_4.12.h"
 #endif
 
 #define GRALLOC_ALIGN( value, base ) (((value) + ((base) - 1)) & ~((base) - 1))
 
-
 #if GRALLOC_SIMULATE_FAILURES
 #include <cutils/properties.h>
 
@@ -106,34 +107,47 @@
 		int shared_fd;
 		int ret;
 
-		ret = ion_alloc(m->ion_client, size, 0, ION_HEAP_SYSTEM_MASK, 0, &(ion_hnd));
-
-		if (ret != 0)
+		if (m->gralloc_legacy_ion)
 		{
-			AERR("Failed to ion_alloc from ion_client:%d", m->ion_client);
-			return -1;
-		}
+			ret = ion_alloc(m->ion_client, size, 0, ION_HEAP_SYSTEM_MASK, 0, &(ion_hnd));
 
-		ret = ion_share(m->ion_client, ion_hnd, &shared_fd);
-
-		if (ret != 0)
-		{
-			AERR("ion_share( %d ) failed", m->ion_client);
-
-			if (0 != ion_free(m->ion_client, ion_hnd))
+			if (ret != 0)
 			{
-				AERR("ion_free( %d ) failed", m->ion_client);
+				AERR("Failed to ion_alloc from ion_client:%d", m->ion_client);
+				return -1;
 			}
 
-			return -1;
-		}
+			ret = ion_share(m->ion_client, ion_hnd, &shared_fd);
 
-		// we do not need ion_hnd once we have shared_fd
-		if (0 != ion_free(m->ion_client, ion_hnd))
-		{
-			AWAR("ion_free( %d ) failed", m->ion_client);
+			if (ret != 0)
+			{
+				AERR("ion_share( %d ) failed", m->ion_client);
+
+				if (0 != ion_free(m->ion_client, ion_hnd))
+				{
+					AERR("ion_free( %d ) failed", m->ion_client);
+				}
+
+				return -1;
+			}
+
+			// we do not need ion_hnd once we have shared_fd
+			if (0 != ion_free(m->ion_client, ion_hnd))
+			{
+				AWAR("ion_free( %d ) failed", m->ion_client);
+			}
+			ion_hnd = ION_INVALID_HANDLE;
 		}
-		ion_hnd = ION_INVALID_HANDLE;
+		else
+		{
+			ret = ion_alloc_fd(m->ion_client, size, 0, 1 << m->system_heap_id, 0, &(shared_fd));
+
+			if (ret != 0)
+			{
+				AERR("Failed to ion_alloc_fd from ion_client:%d", m->ion_client);
+				return -1;
+			}
+		}
 
 		cpu_ptr = (unsigned char *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shared_fd, 0);
 
@@ -597,6 +611,54 @@
 	return 0;
 }
 
+#if GRALLOC_ARM_DMA_BUF_MODULE
+static int find_system_heap_id(int ion_client)
+{
+	int i, ret, cnt, system_heap_id = -1;
+	struct ion_heap_data *data;
+
+	ret = ion_query_heap_cnt(ion_client, &cnt);
+
+	if (ret)
+	{
+		AERR("ion count query failed with %s", strerror(errno));
+		return -1;
+	}
+
+	data = (struct ion_heap_data *)malloc(cnt * sizeof(*data));
+	if (!data)
+	{
+		AERR("Error allocating data %s\n", strerror(errno));
+		return -1;
+	}
+
+	ret = ion_query_get_heaps(ion_client, cnt, data);
+	if (ret)
+	{
+		AERR("Error querying heaps from ion %s", strerror(errno));
+	}
+	else
+	{
+		for (i = 0; i < cnt; i++) {
+			struct ion_heap_data *dat = (struct ion_heap_data *)data;
+			if (strcmp(dat[i].name, "ion_system_heap") == 0) {
+				system_heap_id = dat[i].heap_id;
+				break;
+			}
+		}
+
+		if (i > cnt)
+		{
+			AERR("No System Heap Found amongst %d heaps\n", cnt);
+			system_heap_id = -1;
+		}
+	}
+
+	free(data);
+	return system_heap_id;
+}
+#endif
+
 int alloc_device_open(hw_module_t const *module, const char *name, hw_device_t **device)
 {
 	MALI_IGNORE(name);
@@ -643,6 +705,20 @@
 		return -1;
 	}
 
+	m->gralloc_legacy_ion = ion_is_legacy(m->ion_client);
+
+	if (!m->gralloc_legacy_ion)
+	{
+		m->system_heap_id = find_system_heap_id(m->ion_client);
+		if (m->system_heap_id < 0)
+		{
+			delete dev;
+			ion_close(m->ion_client);
+			m->ion_client = -1;
+			return -1;
+		}
+	}
+
 #endif
 
 	*device = &dev->common;
diff --git a/gralloc/gralloc_priv.h b/gralloc/gralloc_priv.h
index 3615960..582c487 100644
--- a/gralloc/gralloc_priv.h
+++ b/gralloc/gralloc_priv.h
@@ -110,6 +110,8 @@
 	pthread_mutex_t lock;
 	buffer_handle_t currentBuffer;
 	int ion_client;
+	int system_heap_id;
+	bool gralloc_legacy_ion;
 
 	struct fb_var_screeninfo info;
 	struct fb_fix_screeninfo finfo;