gralloc: Optimize ION cache clean and invalidate calls

-Clients not having WRITE_OFTEN or READ_OFTEN are uncached.
-Invalidate cache on lock only if CPU needs to read and there
are non-CPU writers in system (camera,gpu etc)
-Flush cache on unlock only if CPU writes. Since all buffers will be
read in HWC(MDP) there is no need to check if readers exist.

Change-Id: Icd114e60b7456bd71592b81016892e806c37cb22
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 0e80843..c361095 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -76,16 +76,6 @@
     return true;
 }
 
-static bool useUncached(int usage)
-{
-    if (usage & GRALLOC_USAGE_PRIVATE_UNCACHED)
-        return true;
-    if(((usage & GRALLOC_USAGE_SW_WRITE_MASK) == GRALLOC_USAGE_SW_WRITE_RARELY)
-       ||((usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_RARELY))
-        return true;
-    return false;
-}
-
 //-------------- AdrenoMemInfo-----------------------//
 AdrenoMemInfo::AdrenoMemInfo()
 {
@@ -664,3 +654,14 @@
         delete hnd;
 
 }
+
+bool useUncached(const int& usage) {
+    if(usage & GRALLOC_USAGE_PRIVATE_UNCACHED)
+        return true;
+
+    if(not (usage & (GRALLOC_USAGE_SW_WRITE_OFTEN |
+            GRALLOC_USAGE_SW_READ_OFTEN)))
+        return true;
+
+    return false;
+}
diff --git a/libgralloc/gr.h b/libgralloc/gr.h
index 797d57e..37ee4e5 100644
--- a/libgralloc/gr.h
+++ b/libgralloc/gr.h
@@ -71,6 +71,10 @@
 void free_buffer(private_handle_t *hnd);
 int getYUVPlaneInfo(private_handle_t* pHnd, struct android_ycbcr* ycbcr);
 
+// Use uncached for all scenarios except when the CPU needs to read or write
+// often
+bool useUncached(const int& usage);
+
 /*****************************************************************************/
 
 class Locker {
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index f029b80..75b8349 100644
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -180,6 +180,7 @@
             PRIV_FLAGS_USES_ION           = 0x00000008,
             PRIV_FLAGS_USES_ASHMEM        = 0x00000010,
             PRIV_FLAGS_NEEDS_FLUSH        = 0x00000020,
+            // Uncached memory or no CPU writers
             PRIV_FLAGS_DO_NOT_FLUSH       = 0x00000040,
             PRIV_FLAGS_SW_LOCK            = 0x00000080,
             PRIV_FLAGS_NONCONTIGUOUS_MEM  = 0x00000100,
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index 13e662a..0b2279d 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -229,21 +229,37 @@
             err = gralloc_map(module, handle);
             pthread_mutex_unlock(lock);
         }
-        if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) {
-            //Invalidate if reading in software. No need to do this for the
-            //metadata buffer as it is only read/written in software.
-            IMemAlloc* memalloc = getAllocator(hnd->flags) ;
-            err = memalloc->clean_buffer((void*)hnd->base,
-                                         hnd->size, hnd->offset, hnd->fd,
-                                         CACHE_INVALIDATE);
+        if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION and
+                    not useUncached(usage)) {
+            bool nonCPUWriters = usage & (
+                        GRALLOC_USAGE_HW_RENDER |
+                        GRALLOC_USAGE_HW_FB |
+                        GRALLOC_USAGE_HW_VIDEO_ENCODER |
+                        GRALLOC_USAGE_HW_CAMERA_WRITE);
+
+            //Invalidate if CPU reads in software and there are non-CPU
+            //writers. No need to do this for the metadata buffer as it is
+            //only read/written in software.
+            //Corner case: If we reach here with a READ_RARELY, then there must
+            //be a WRITE_OFTEN that caused caching to be used.
+            if ((usage & GRALLOC_USAGE_SW_READ_MASK) and nonCPUWriters) {
+                IMemAlloc* memalloc = getAllocator(hnd->flags) ;
+                err = memalloc->clean_buffer((void*)hnd->base,
+                        hnd->size, hnd->offset, hnd->fd,
+                        CACHE_INVALIDATE);
+            }
+            //Mark the buffer to be flushed after CPU write.
+            //Corner case: If we reach here with a WRITE_RARELY, then there
+            //must be a READ_OFTEN that caused caching to be used.
             if (usage & GRALLOC_USAGE_SW_WRITE_MASK) {
-                // Mark the buffer to be flushed after cpu read/write
                 hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
             }
         }
-    } else {
-        hnd->flags |= private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
     }
+
+    if(useUncached(usage))
+        hnd->flags |= private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
+
     return err;
 }
 
@@ -283,24 +299,17 @@
     int err = 0;
     private_handle_t* hnd = (private_handle_t*)handle;
 
-    if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) {
-        IMemAlloc* memalloc = getAllocator(hnd->flags);
-        if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
-            err = memalloc->clean_buffer((void*)hnd->base,
-                                         hnd->size, hnd->offset, hnd->fd,
-                                         CACHE_CLEAN_AND_INVALIDATE);
-            hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
-        } else if(hnd->flags & private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH) {
-            hnd->flags &= ~private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
-        } else {
-            //Probably a round about way to do this, but this avoids adding new
-            //flags
-            err = memalloc->clean_buffer((void*)hnd->base,
-                                         hnd->size, hnd->offset, hnd->fd,
-                                         CACHE_INVALIDATE);
-        }
+    IMemAlloc* memalloc = getAllocator(hnd->flags);
+    if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
+        err = memalloc->clean_buffer((void*)hnd->base,
+                hnd->size, hnd->offset, hnd->fd,
+                CACHE_CLEAN);
+        hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
     }
 
+    if(hnd->flags & private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH)
+            hnd->flags &= ~private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
+
     return err;
 }