Rework postinstall unittests to pass on Android.

Postinstall unittests were creating and mounting an image on each test
run. This patch adds several test scripts to one of the pre-generated
images and uses that image during postinstall testing instead.

To workaround problems with mount/umount of loop devices on Android,
this patch rewrites the `losetup` logic to make the appropriate
syscalls and create the loop device with mknod if it doesn't exists.

The tests require some extra SELinux policies to run in enforcing mode.

Bug: 26955860
TEST=Ran all Postinstall unittests.

Change-Id: I47a56b80b97596bc65ffe30cbc8118f05faff0ae
diff --git a/common/test_utils.h b/common/test_utils.h
index 7be027a..2c8a6de 100644
--- a/common/test_utils.h
+++ b/common/test_utils.h
@@ -57,8 +57,15 @@
 bool WriteFileVector(const std::string& path, const brillo::Blob& data);
 bool WriteFileString(const std::string& path, const std::string& data);
 
-bool BindToUnusedLoopDevice(const std::string &filename,
-                            std::string* lo_dev_name_ptr);
+// Binds provided |filename| to an unused loopback device, whose name is written
+// to the string pointed to by |out_lo_dev_name|. The new loop device will be
+// read-only unless |writable| is set to true. Returns true on success, false
+// otherwise (along with corresponding test failures), in which case the content
+// of |out_lo_dev_name| is unknown.
+bool BindToUnusedLoopDevice(const std::string& filename,
+                            bool writable,
+                            std::string* out_lo_dev_name);
+bool UnbindLoopDevice(const std::string& lo_dev_name);
 
 // Returns true iff a == b
 bool ExpectVectorsEq(const brillo::Blob& a, const brillo::Blob& b);
@@ -120,8 +127,10 @@
 
 class ScopedLoopbackDeviceBinder {
  public:
-  ScopedLoopbackDeviceBinder(const std::string& file, std::string* dev) {
-    is_bound_ = BindToUnusedLoopDevice(file, &dev_);
+  ScopedLoopbackDeviceBinder(const std::string& file,
+                             bool writable,
+                             std::string* dev) {
+    is_bound_ = BindToUnusedLoopDevice(file, writable, &dev_);
     EXPECT_TRUE(is_bound_);
 
     if (is_bound_ && dev)
@@ -133,15 +142,8 @@
       return;
 
     for (int retry = 0; retry < 5; retry++) {
-      std::vector<std::string> args;
-      args.push_back("/sbin/losetup");
-      args.push_back("-d");
-      args.push_back(dev_);
-      int return_code = 0;
-      EXPECT_TRUE(Subprocess::SynchronousExec(args, &return_code, nullptr));
-      if (return_code == 0) {
+      if (UnbindLoopDevice(dev_))
         return;
-      }
       sleep(1);
     }
     ADD_FAILURE();