Add support for read-only SharedFileRegion

A receiver of a SharedFileRegion needs to know whether it is allowed
to write into it. Added a flag in the AIDL file to indicate that and
made this compatible with the READ_ONLY flag of IMemoryHeap.

Test: atest shmemTest
Change-Id: I3f26a36e152c2e9bf3aac4ff7f0067f9242b565b
diff --git a/media/libshmem/ShmemCompat.cpp b/media/libshmem/ShmemCompat.cpp
index 44fe39c..246cb24 100644
--- a/media/libshmem/ShmemCompat.cpp
+++ b/media/libshmem/ShmemCompat.cpp
@@ -49,8 +49,10 @@
         return false;
     }
 
+    uint32_t flags = !shmem.writeable ? IMemoryHeap::READ_ONLY : 0;
+
     const sp<MemoryHeapBase> heap =
-            new MemoryHeapBase(shmem.fd.get(), heapSize, 0, heapStartOffset);
+            new MemoryHeapBase(shmem.fd.get(), heapSize, flags, heapStartOffset);
     *result = sp<MemoryBase>::make(heap,
                                    shmem.offset - heapStartOffset,
                                    shmem.size);
@@ -89,6 +91,7 @@
         result->fd.reset(base::unique_fd(fd));
         result->size = size;
         result->offset = heap->getOffset() + offset;
+        result->writeable = (heap->getFlags() & IMemoryHeap::READ_ONLY) == 0;
     }
     return true;
 }
diff --git a/media/libshmem/ShmemTest.cpp b/media/libshmem/ShmemTest.cpp
index d076ad0..874f34c 100644
--- a/media/libshmem/ShmemTest.cpp
+++ b/media/libshmem/ShmemTest.cpp
@@ -44,10 +44,11 @@
     return shmem;
 }
 
-sp<IMemory> makeIMemory(const std::vector<uint8_t>& content) {
+sp<IMemory> makeIMemory(const std::vector<uint8_t>& content, bool writeable = true) {
     constexpr size_t kOffset = 19;
 
-    sp<MemoryHeapBase> heap = new MemoryHeapBase(content.size());
+    sp<MemoryHeapBase> heap = new MemoryHeapBase(content.size(),
+                                                 !writeable ? IMemoryHeap::READ_ONLY : 0);
     sp<IMemory> result = sp<MemoryBase>::make(heap, kOffset, content.size());
     memcpy(result->unsecurePointer(), content.data(), content.size());
     return result;
@@ -69,9 +70,31 @@
         ASSERT_TRUE(convertIMemoryToSharedFileRegion(imem, &shmem));
         ASSERT_EQ(3, shmem.size);
         ASSERT_GE(shmem.fd.get(), 0);
+        ASSERT_TRUE(shmem.writeable);
         ASSERT_TRUE(convertSharedFileRegionToIMemory(shmem, &reconstructed));
     }
     ASSERT_EQ(3, reconstructed->size());
+    ASSERT_EQ(reconstructed->getMemory()->getFlags() & IMemoryHeap::READ_ONLY,  0);
+    const uint8_t* p =
+            reinterpret_cast<const uint8_t*>(reconstructed->unsecurePointer());
+    EXPECT_EQ(6, p[0]);
+    EXPECT_EQ(5, p[1]);
+    EXPECT_EQ(3, p[2]);
+}
+
+TEST(ShmemTest, ConversionReadOnly) {
+    sp<IMemory> reconstructed;
+    {
+        SharedFileRegion shmem;
+        sp<IMemory> imem = makeIMemory({6, 5, 3}, false);
+        ASSERT_TRUE(convertIMemoryToSharedFileRegion(imem, &shmem));
+        ASSERT_EQ(3, shmem.size);
+        ASSERT_GE(shmem.fd.get(), 0);
+        ASSERT_FALSE(shmem.writeable);
+        ASSERT_TRUE(convertSharedFileRegionToIMemory(shmem, &reconstructed));
+    }
+    ASSERT_EQ(3, reconstructed->size());
+    ASSERT_NE(reconstructed->getMemory()->getFlags() & IMemoryHeap::READ_ONLY,  0);
     const uint8_t* p =
             reinterpret_cast<const uint8_t*>(reconstructed->unsecurePointer());
     EXPECT_EQ(6, p[0]);
diff --git a/media/libshmem/aidl/android/media/SharedFileRegion.aidl b/media/libshmem/aidl/android/media/SharedFileRegion.aidl
index a910e69..199b647 100644
--- a/media/libshmem/aidl/android/media/SharedFileRegion.aidl
+++ b/media/libshmem/aidl/android/media/SharedFileRegion.aidl
@@ -34,4 +34,6 @@
     long offset;
     /** Size, in bytes of the memory region. Must be non-negative. */
     long size;
+    /** Whether the region is writeable. */
+    boolean writeable;
 }