vold: Add support for xwarp

Signed-off-by: San Mehat <san@google.com>
diff --git a/Android.mk b/Android.mk
index bdb2325..7b18ca0 100644
--- a/Android.mk
+++ b/Android.mk
@@ -25,7 +25,8 @@
                   Fat.cpp                              \
                   Loop.cpp                             \
                   Devmapper.cpp                        \
-                  ResponseCode.cpp
+                  ResponseCode.cpp                     \
+                  Xwarp.cpp
 
 LOCAL_MODULE:= vold
 
diff --git a/CommandListener.cpp b/CommandListener.cpp
index 9516a67..7f81cc7 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -21,6 +21,7 @@
 #include <arpa/inet.h>
 #include <dirent.h>
 #include <errno.h>
+#include <fcntl.h>
 
 #define LOG_TAG "CommandListener"
 #include <cutils/log.h>
@@ -31,6 +32,7 @@
 #include "VolumeManager.h"
 #include "ResponseCode.h"
 #include "Process.h"
+#include "Xwarp.h"
 
 CommandListener::CommandListener() :
                  FrameworkListener("vold") {
@@ -38,6 +40,7 @@
     registerCmd(new AsecCmd());
     registerCmd(new ShareCmd());
     registerCmd(new StorageCmd());
+    registerCmd(new XwarpCmd());
 }
 
 CommandListener::VolumeCmd::VolumeCmd() :
@@ -285,3 +288,47 @@
 
     return 0;
 }
+
+CommandListener::XwarpCmd::XwarpCmd() :
+                 VoldCommand("xwarp") {
+}
+
+int CommandListener::XwarpCmd::runCommand(SocketClient *cli,
+                                                      int argc, char **argv) {
+    if (argc < 2) {
+        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
+        return 0;
+    }
+
+    if (!strcmp(argv[1], "enable")) {
+        if (Xwarp::enable()) {
+            cli->sendMsg(ResponseCode::OperationFailed, "Failed to enable xwarp", true);
+            return 0;
+        }
+
+        cli->sendMsg(ResponseCode::CommandOkay, "Xwarp mirroring started", false);
+    } else if (!strcmp(argv[1], "disable")) {
+        if (Xwarp::disable()) {
+            cli->sendMsg(ResponseCode::OperationFailed, "Failed to disable xwarp", true);
+            return 0;
+        }
+
+        cli->sendMsg(ResponseCode::CommandOkay, "Xwarp disabled", false);
+    } else if (!strcmp(argv[1], "status")) {
+        char msg[255];
+        bool r;
+        unsigned mirrorPos, maxSize;
+
+        if (Xwarp::status(&r, &mirrorPos, &maxSize)) {
+            cli->sendMsg(ResponseCode::OperationFailed, "Failed to get xwarp status", true);
+            return 0;
+        }
+        snprintf(msg, sizeof(msg), "%s %u %u", (r ? "ready" : "not-ready"), mirrorPos, maxSize);
+        cli->sendMsg(ResponseCode::XwarpStatusResult, msg, false);
+    } else {
+        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown storage cmd", false);
+    }
+
+    return 0;
+}
+
diff --git a/CommandListener.h b/CommandListener.h
index 7d4560f..8861e38 100644
--- a/CommandListener.h
+++ b/CommandListener.h
@@ -54,6 +54,13 @@
         virtual ~StorageCmd() {}
         int runCommand(SocketClient *c, int argc, char ** argv);
     };
+
+    class XwarpCmd : public VoldCommand {
+    public:
+        XwarpCmd();
+        virtual ~XwarpCmd() {}
+        int runCommand(SocketClient *c, int argc, char ** argv);
+    };
 };
 
 #endif
diff --git a/ResponseCode.h b/ResponseCode.h
index 31d6482..5e15c80 100644
--- a/ResponseCode.h
+++ b/ResponseCode.h
@@ -32,6 +32,7 @@
     static const int ShareStatusResult        = 210;
     static const int AsecPathResult           = 211;
     static const int ShareEnabledResult       = 212;
+    static const int XwarpStatusResult        = 213;
 
     // 400 series - The command was accepted but the requested action
     // did not take place.
diff --git a/Xwarp.cpp b/Xwarp.cpp
new file mode 100644
index 0000000..1435a53
--- /dev/null
+++ b/Xwarp.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define LOG_TAG "Vold"
+
+#include <cutils/log.h>
+
+#include "Xwarp.h"
+const char *Xwarp::XWARP_BACKINGFILE = "/mnt/secure/asec/xwarp.img";
+const char *Xwarp::XWARP_CFG = "/sys/fs/yaffs/mtd3/xwarp-backing-store";
+const char *Xwarp::XWARP_READY = "/sys/fs/yaffs/mtd3/xwarp-ready";
+const char *Xwarp::XWARP_MIRROR_STATUS = "/sys/fs/yaffs/mtd3/xwarp-mirror";
+
+int Xwarp::enable() {
+    return doEnableDisable(true);
+}
+
+int Xwarp::disable() {
+    return doEnableDisable(false);
+}
+
+int Xwarp::status(bool *ready, unsigned *mirrorPos, unsigned *maxSize) {
+    FILE *fp;
+
+    *ready = false;
+    *mirrorPos = 0;
+    *maxSize = 0;
+    if (!(fp = fopen(XWARP_READY, "r"))) {
+        return -1;
+    }
+
+    fscanf(fp, "%d", (int *) ready);
+    fclose(fp);
+
+    if (!(fp = fopen(XWARP_MIRROR_STATUS, "r"))) {
+        return -1;
+    }
+
+    fscanf(fp, "%u %u", mirrorPos, maxSize);
+    fclose(fp);
+    return 0;
+}
+
+int Xwarp::doEnableDisable(bool enable) {
+    const char *tmp;
+    int fd = open(XWARP_CFG, O_WRONLY);
+
+    if (fd < 0) 
+        return -1;
+
+    tmp = (enable ? XWARP_BACKINGFILE : "");
+
+    if (write(fd, tmp, strlen(tmp)+1) < 0) {
+        LOGE("Failed to write xwarp cfg (%s)", strerror(errno));
+        close(fd);
+        return -1;
+    }
+
+    close(fd);
+    return 0;
+}
diff --git a/Xwarp.h b/Xwarp.h
new file mode 100644
index 0000000..918a843
--- /dev/null
+++ b/Xwarp.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _XWARP_H
+#define _XWARP_H
+
+#include <unistd.h>
+
+class Xwarp {
+    static const char *XWARP_BACKINGFILE;
+    static const char *XWARP_CFG;
+    static const char *XWARP_READY;
+    static const char *XWARP_MIRROR_STATUS;
+
+public:
+    static int enable();
+    static int disable();
+    static int status(bool *ready, unsigned *mirrorPos, unsigned *maxSize);
+
+private:
+    static int doEnableDisable(bool enable);
+};
+
+#endif