Refine the DSU SD card support

Refine the openImageService and allow images to be installed in a SD card.
This also fixes the error when execute the "gsi_tool status" command.

Bug: 171861574
Test: execute following command on a device with a SD card inserted
       adb shell am start-activity \
        -n com.android.dynsystem/com.android.dynsystem.VerificationActivity \
        -a android.os.image.action.START_INSTALL \
        -d file:///storage/emulated/0/Download/system.raw.gz \
        --el KEY_SYSTEM_SIZE $(du -b system.raw|cut -f1) \
        --el KEY_USERDATA_SIZE 4294967296

Change-Id: I764cf66984e74ab66cc4316b087751937e20a242
diff --git a/gsi_service.cpp b/gsi_service.cpp
index 6d310a4..cc6497a 100644
--- a/gsi_service.cpp
+++ b/gsi_service.cpp
@@ -116,6 +116,8 @@
     return INSTALL_OK;
 }
 
+static bool IsExternalStoragePath(const std::string& path);
+
 binder::Status GsiService::openInstall(const std::string& install_dir, int* _aidl_return) {
     ENFORCE_SYSTEM;
     std::lock_guard<std::mutex> guard(lock_);
@@ -128,6 +130,15 @@
         *_aidl_return = status;
         return binder::Status::ok();
     }
+    if (access(install_dir_.c_str(), F_OK) != 0 && errno == ENOENT) {
+        if (IsExternalStoragePath(install_dir_)) {
+            if (mkdir(install_dir_.c_str(), 0755) != 0) {
+                PLOG(ERROR) << "Failed to create " << install_dir_;
+                *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
+                return binder::Status::ok();
+            }
+        }
+    }
     std::string message;
     auto dsu_slot = GetDsuSlot(install_dir_);
     if (!RemoveFileIfExists(GetCompleteIndication(dsu_slot), &message)) {
@@ -752,6 +763,8 @@
 
 binder::Status GsiService::openImageService(const std::string& prefix,
                                             android::sp<IImageService>* _aidl_return) {
+    using android::base::StartsWith;
+
     static constexpr char kImageMetadataPrefix[] = "/metadata/gsi/";
     static constexpr char kImageDataPrefix[] = "/data/gsi/";
 
@@ -773,9 +786,11 @@
         PLOG(ERROR) << "realpath failed for data: " << in_data_dir;
         return BinderError("Invalid path");
     }
-    if (!android::base::StartsWith(metadata_dir, kImageMetadataPrefix) ||
-        !android::base::StartsWith(data_dir, kImageDataPrefix)) {
-        return BinderError("Invalid path");
+    if (!StartsWith(metadata_dir, kImageMetadataPrefix)) {
+        return BinderError("Invalid metadata path");
+    }
+    if (!StartsWith(data_dir, kImageDataPrefix) && !StartsWith(data_dir, kDsuSDPrefix)) {
+        return BinderError("Invalid data path");
     }
 
     uid_t uid = IPCThreadState::self()->getCallingUid();
@@ -808,7 +823,7 @@
 }
 
 static bool IsExternalStoragePath(const std::string& path) {
-    if (!android::base::StartsWith(path, "/mnt/media_rw/")) {
+    if (!android::base::StartsWith(path, kDsuSDPrefix)) {
         return false;
     }
     unique_fd fd(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));