MountService: Refactor to use NativeDaemonConnector and clean-up

Signed-off-by: San Mehat <san@google.com>
diff --git a/services/java/com/android/server/MountListener.java b/services/java/com/android/server/MountListener.java
deleted file mode 100644
index 9443ff8..0000000
--- a/services/java/com/android/server/MountListener.java
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-package com.android.server;
-
-import android.net.LocalSocketAddress;
-import android.net.LocalSocket;
-import android.os.Environment;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.util.Config;
-import android.util.Log;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.Socket;
-import java.lang.IllegalStateException;
-
-import java.util.List;
-import java.util.ArrayList;
-import java.util.ListIterator;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingQueue;
-
-/**
- * Vold Connection class
- */
-final class MountListener implements Runnable {
-    private static final String TAG = "MountListener";
-    private static final String VOLD_SOCKET = "vold";
-    private static final int    RESPONSE_QUEUE_SIZE = 10;
-
-    private MountService          mService;
-    private BlockingQueue<String> mResponseQueue;
-    private OutputStream          mOutputStream;
-
-    class ResponseCode {
-        public static final int ActionInitiated                = 100;
-        public static final int VolumeListResult               = 110;
-        public static final int AsecListResult                 = 111;
-
-        public static final int CommandOkay                    = 200;
-        public static final int ShareAvailabilityResult        = 210;
-        public static final int AsecPathResult                 = 211;
-
-        public static final int UnsolicitedInformational       = 600;
-        public static final int VolumeStateChange              = 605;
-        public static final int VolumeMountFailedBlank         = 610;
-        public static final int VolumeMountFailedDamaged       = 611;
-        public static final int VolumeMountFailedNoMedia       = 612;
-        public static final int ShareAvailabilityChange        = 620;
-        public static final int VolumeDiskInserted             = 630;
-        public static final int VolumeDiskRemoved              = 631;
-        public static final int VolumeBadRemoval               = 632;
-    }
-
-    MountListener(MountService service) {
-        mService = service;
-        mResponseQueue = new LinkedBlockingQueue<String>(RESPONSE_QUEUE_SIZE);
-    }
-
-    public void run() {
-        // Vold does not run in the simulator, so fake out a mounted event to trigger the Media Scanner
-        if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
-            mService.notifyMediaMounted(Environment.getExternalStorageDirectory().getPath(), false);
-            return;
-        }
-
-        try {
-            while (true) {
-                listenToSocket();
-            }
-        } catch (Throwable t) {
-            Log.e(TAG, "Fatal error " + t + " in MountListener thread!");
-        }
-    }
-
-    private void listenToSocket() {
-       LocalSocket socket = null;
-
-        try {
-            socket = new LocalSocket();
-            LocalSocketAddress address = new LocalSocketAddress(VOLD_SOCKET, 
-                    LocalSocketAddress.Namespace.RESERVED);
-
-            socket.connect(address);
-            mService.onVoldConnected();
-
-            InputStream inputStream = socket.getInputStream();
-            mOutputStream = socket.getOutputStream();
-
-            byte[] buffer = new byte[4096];
-
-            while (true) {
-                int count = inputStream.read(buffer);
-                if (count < 0) break;
-
-                int start = 0;
-                for (int i = 0; i < count; i++) {
-                    if (buffer[i] == 0) {
-                        String event = new String(buffer, start, i - start);
-//                        Log.d(TAG, "Got packet {" + event + "}");
-
-                        String[] tokens = event.split(" ");
-                        try {
-                            int code = Integer.parseInt(tokens[0]);
-
-                            if (code >= ResponseCode.UnsolicitedInformational) {
-                                try {
-                                    handleUnsolicitedEvent(code, event, tokens);
-                                } catch (Exception ex) {
-                                    Log.e(TAG, String.format(
-                                            "Error handling '%s'", event), ex);
-                                }
-                            } else {
-                                try {
-                                    mResponseQueue.put(event);
-                                } catch (InterruptedException ex) {
-                                    Log.e(TAG, "InterruptedException");
-                                }
-                            }
-                        } catch (NumberFormatException nfe) {
-                            Log.w(TAG,
-                                  "Unknown msg from Vold '" + event + "'");
-                        }
-                        start = i + 1;
-                    }                   
-                }
-            }                
-        } catch (IOException ex) {
-            Log.e(TAG, "IOException in listenToSocket");
-        }
-        
-        synchronized (this) {
-            if (mOutputStream != null) {
-                try {
-                    mOutputStream.close();
-                } catch (IOException e) {
-                    Log.w(TAG, "IOException closing output stream");
-                }
-                
-                mOutputStream = null;
-            }
-        }
-        
-        try {
-            if (socket != null) {
-                socket.close();
-            }
-        } catch (IOException ex) {
-            Log.w(TAG, "IOException closing socket");
-        }
-       
-        Log.e(TAG, "Failed to connect to Vold", new IllegalStateException());
-        SystemClock.sleep(5000);
-    }
-
-    private void handleUnsolicitedEvent(int code, String raw,
-                                        String[] cooked) throws IllegalStateException {
-//        Log.d(TAG, "unsolicited {" + raw + "}");
-        if (code == ResponseCode.VolumeStateChange) {
-            // FMT: NNN Volume <label> <mountpoint> state changed from <old_#> (<old_str>) to <new_#> (<new_str>)
-            mService.notifyVolumeStateChange(cooked[2], cooked[3],
-                                             Integer.parseInt(cooked[7]),
-                                             Integer.parseInt(cooked[10]));
-        } else if (code == ResponseCode.VolumeMountFailedBlank) {
-            // FMT: NNN Volume <label> <mountpoint> mount failed - no supported file-systems
-            mService.notifyMediaNoFs(cooked[3]);
-            // FMT: NNN Volume <label> <mountpoint> mount failed - no media
-        } else if (code == ResponseCode.VolumeMountFailedNoMedia) {
-            mService.notifyMediaRemoved(cooked[3]);
-        } else if (code == ResponseCode.VolumeMountFailedDamaged) {
-            // FMT: NNN Volume <label> <mountpoint> mount failed - filesystem check failed
-            mService.notifyMediaUnmountable(cooked[3]);
-        } else if (code == ResponseCode.ShareAvailabilityChange) {
-            // FMT: NNN Share method <method> now <available|unavailable>
-            boolean avail = false;
-            if (cooked[5].equals("available")) {
-                avail = true;
-            }
-            mService.notifyShareAvailabilityChange(cooked[3], avail);
-        } else if (code == ResponseCode.VolumeDiskInserted) {
-            // FMT: NNN Volume <label> <mountpoint> disk inserted (<major>:<minor>)
-            mService.notifyMediaInserted(cooked[3]);
-        } else if (code == ResponseCode.VolumeDiskRemoved) {
-            // FMT: NNN Volume <label> <mountpoint> disk removed (<major>:<minor>)
-            mService.notifyMediaRemoved(cooked[3]);
-        } else if (code == ResponseCode.VolumeBadRemoval) {
-            // FMT: NNN Volume <label> <mountpoint> bad removal (<major>:<minor>)
-            mService.notifyMediaBadRemoval(cooked[3]);
-        } else {
-            Log.w(TAG, "Unhandled event {" + raw + "}");
-        }
-    }
-    
-
-    private void sendCommand(String command) {
-        sendCommand(command, null);
-    }
-
-    /**
-     * Sends a command to Vold with a single argument
-     *
-     * @param command  The command to send to the mount service daemon
-     * @param argument The argument to send with the command (or null)
-     */
-    private void sendCommand(String command, String argument) {
-        synchronized (this) {
-            // Log.d(TAG, "sendCommand {" + command + "} {" + argument + "}");
-            if (mOutputStream == null) {
-                Log.e(TAG, "No connection to Vold", new IllegalStateException());
-            } else {
-                StringBuilder builder = new StringBuilder(command);
-                if (argument != null) {
-                    builder.append(argument);
-                }
-                builder.append('\0');
-
-                try {
-                    mOutputStream.write(builder.toString().getBytes());
-                } catch (IOException ex) {
-                    Log.e(TAG, "IOException in sendCommand", ex);
-                }
-            }
-        }
-    }
-
-    private synchronized ArrayList<String> doCommand(String cmd) throws IllegalStateException {
-        sendCommand(cmd);
-
-        ArrayList<String> response = new ArrayList<String>();
-        boolean complete = false;
-        int code = -1;
-
-        while (!complete) {
-            try {
-                String line = mResponseQueue.take();
-//                Log.d(TAG, "Removed off queue -> " + line);
-                String[] tokens = line.split(" ");
-                code = Integer.parseInt(tokens[0]);
-
-                if ((code >= 200) && (code < 600))
-                    complete = true;
-                response.add(line);
-            } catch (InterruptedException ex) {
-                Log.e(TAG, "InterruptedException");
-            }
-        }
-
-        if (code >= 400 && code < 600) {
-            throw new IllegalStateException(String.format(
-                                               "Command %s failed with code %d",
-                                                cmd, code));
-        }
-        return response;
-    }
-
-    boolean getShareAvailable(String method) throws IllegalStateException  {
-        ArrayList<String> rsp = doCommand("share_available " + method);
-
-        for (String line : rsp) {
-            String []tok = line.split(" ");
-            int code = Integer.parseInt(tok[0]);
-            if (code == ResponseCode.ShareAvailabilityResult) {
-                if (tok[2].equals("available"))
-                    return true;
-                return false;
-            } else {
-                throw new IllegalStateException(String.format("Unexpected response code %d", code));
-            }
-        }
-        throw new IllegalStateException("Got an empty response");
-    }
-
-    /**
-     * Enables or disables USB mass storage support.
-     * 
-     * @param enable  true to enable USB mass storage support
-     */
-    void setShareMethodEnabled(String mountPoint, String method,
-                               boolean enable) throws IllegalStateException {
-        doCommand((enable ? "" : "un") + "share " + mountPoint + " " + method);
-    }
-
-    /**
-     * Mount media at given mount point.
-     */
-    public void mountVolume(String label) throws IllegalStateException {
-        doCommand("mount " + label);
-    }
-
-    /**
-     * Unmount media at given mount point.
-     */
-    public void unmountVolume(String label) throws IllegalStateException {
-        doCommand("unmount " + label);
-    }
-
-    /**
-     * Format media at given mount point.
-     */
-    public void formatVolume(String label) throws IllegalStateException {
-        doCommand("format " + label);
-    }
-
-    public String createAsec(String id, int sizeMb, String fstype, String key,
-                           int ownerUid) throws IllegalStateException {
-        String cmd = String.format("create_asec %s %d %s %s %d",
-                                   id, sizeMb, fstype, key, ownerUid);
-        doCommand(cmd);
-        return getAsecPath(id);
-    }
-
-    public void finalizeAsec(String id) throws IllegalStateException {
-        doCommand("finalize_asec " + id);
-    }
-
-    public void destroyAsec(String id) throws IllegalStateException {
-        doCommand("destroy_asec " + id);
-    }
-
-    public String mountAsec(String id, String key, int ownerUid) throws IllegalStateException {
-        String cmd = String.format("mount_asec %s %s %d",
-                                   id, key, ownerUid);
-        doCommand(cmd);
-        return getAsecPath(id);
-    }
-
-    public String getAsecPath(String id) throws IllegalStateException {
-        ArrayList<String> rsp = doCommand("asec_path " + id);
-
-        for (String line : rsp) {
-            String []tok = line.split(" ");
-            int code = Integer.parseInt(tok[0]);
-            if (code == ResponseCode.AsecPathResult) {
-                return tok[1];
-            } else {
-                throw new IllegalStateException(String.format("Unexpected response code %d", code));
-            }
-        }
-        throw new IllegalStateException("Got an empty response");
-    }
-
-    public String[] listAsec() throws IllegalStateException {
-        ArrayList<String> rsp = doCommand("list_asec");
-
-        String[] rdata = new String[rsp.size()];
-        int idx = 0;
-
-        for (String line : rsp) {
-            String []tok = line.split(" ");
-            int code = Integer.parseInt(tok[0]);
-            if (code == ResponseCode.AsecListResult) {
-                rdata[idx++] = tok[1];
-            } else if (code == ResponseCode.CommandOkay) {
-                return rdata;
-            } else {
-                throw new IllegalStateException(String.format("Unexpected response code %d", code));
-            }
-        }
-        throw new IllegalStateException("Got an empty response");
-    }
-}
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 81ebe03..c8a6915 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -33,6 +33,7 @@
 import android.os.Handler;
 import android.text.TextUtils;
 import android.util.Log;
+import java.util.ArrayList;
 
 import android.provider.Settings;
 import android.content.ContentResolver;
@@ -46,7 +47,8 @@
  * MountService implements an to the mount service daemon
  * @hide
  */
-class MountService extends IMountService.Stub {
+class MountService extends IMountService.Stub
+        implements INativeDaemonConnectorCallbacks {
     
     private static final String TAG = "MountService";
 
@@ -63,15 +65,33 @@
         public static final int SharedMnt  = 8;
     }
 
+    class VoldResponseCode {
+        public static final int VolumeListResult               = 110;
+        public static final int AsecListResult                 = 111;
+
+        public static final int ShareAvailabilityResult        = 210;
+        public static final int AsecPathResult                 = 211;
+
+        public static final int VolumeStateChange              = 605;
+        public static final int VolumeMountFailedBlank         = 610;
+        public static final int VolumeMountFailedDamaged       = 611;
+        public static final int VolumeMountFailedNoMedia       = 612;
+        public static final int ShareAvailabilityChange        = 620;
+        public static final int VolumeDiskInserted             = 630;
+        public static final int VolumeDiskRemoved              = 631;
+        public static final int VolumeBadRemoval               = 632;
+    }
+
+
     /**
      * Binder context for this service
      */
     private Context mContext;
     
     /**
-     * listener object for communicating with the mount service daemon
+     * connectorr object for communicating with vold
      */
-    private MountListener mListener;
+    private NativeDaemonConnector mConnector;
 
     /**
      * The notification that is shown when a USB mass storage host
@@ -119,12 +139,12 @@
         mContext = context;
 
         // Register a BOOT_COMPLETED handler so that we can start
-        // MountListener. We defer the startup so that we don't
+        // our NativeDaemonConnector. We defer the startup so that we don't
         // start processing events before we ought-to
         mContext.registerReceiver(mBroadcastReceiver,
                 new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
 
-        mListener =  new MountListener(this);       
+        mConnector = new NativeDaemonConnector(this, "vold", 10, "VoldConnector");
         mShowSafeUnmountNotificationWhenUnmounted = false;
 
         mPlaySounds = SystemProperties.get("persist.service.mount.playsnd", "1").equals("1");
@@ -202,7 +222,18 @@
             String action = intent.getAction();
 
             if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
-                Thread thread = new Thread(mListener, MountListener.class.getName());
+                /*
+                 * Vold does not run in the simulator, so fake out a mounted
+                 * event to trigger MediaScanner
+                 */
+                if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
+                    notifyMediaMounted(
+                            Environment.getExternalStorageDirectory().getPath(), false);
+                    return;
+                }
+
+                Thread thread = new Thread(
+                        mConnector, NativeDaemonConnector.class.getName());
                 thread.start();
             }
         }
@@ -258,7 +289,7 @@
              */
             try {
                 String m = Environment.getExternalStorageDirectory().toString();
-                unmountMedia(m);
+                unmountVolume(m);
 
                 int retries = 12;
                 while (!state.equals(Environment.MEDIA_UNMOUNTED) && (retries-- >=0)) {
@@ -302,17 +333,14 @@
             String vs = getVolumeState(vp);
 
             if (enable && vs.equals(Environment.MEDIA_MOUNTED)) {
-                mListener.unmountVolume(vp);
+                unmountVolume(vp);
                 updateUsbMassStorageNotification(true, false);
             }
 
-            mListener.setShareMethodEnabled(Environment
-                                            .getExternalStorageDirectory()
-                                            .getPath(),
-                                            "ums", enable);
+            setShareMethodEnabled(vp, "ums", enable);
             mUmsEnabled = enable;
             if (!enable) {
-                mountMedia(vp);
+                mountVolume(vp);
                 if (mPromptUms) {
                     updateUsbMassStorageNotification(false, false);
                 } else {
@@ -352,19 +380,19 @@
     /**
      * Attempt to mount external media
      */
-    public void mountMedia(String mountPath) throws IllegalStateException {
+    public void mountVolume(String mountPath) throws IllegalStateException {
         if (mContext.checkCallingOrSelfPermission(
                 android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS) 
                 != PackageManager.PERMISSION_GRANTED) {
             throw new SecurityException("Requires MOUNT_UNMOUNT_FILESYSTEMS permission");
         }
-        mListener.mountVolume(mountPath);
+        mConnector.doCommand(String.format("mount %s", mountPath));
     }
 
     /**
      * Attempt to unmount external media to prepare for eject
      */
-    public void unmountMedia(String mountPath) throws IllegalStateException {
+    public void unmountVolume(String mountPath) throws IllegalStateException {
         if (mContext.checkCallingOrSelfPermission(
                 android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS) 
                 != PackageManager.PERMISSION_GRANTED) {
@@ -375,23 +403,51 @@
         // to display the notification
         mShowSafeUnmountNotificationWhenUnmounted = true;
 
-        // tell mountd to unmount the media
-        mListener.unmountVolume(mountPath);
+        mConnector.doCommand(String.format("unmount %s", mountPath));
     }
 
     /**
      * Attempt to format external media
      */
-    public void formatMedia(String formatPath) throws IllegalStateException {
+    public void formatVolume(String formatPath) throws IllegalStateException {
         if (mContext.checkCallingOrSelfPermission(
                 android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS) 
                 != PackageManager.PERMISSION_GRANTED) {
             throw new SecurityException("Requires MOUNT_FORMAT_FILESYSTEMS permission");
         }
 
-        mListener.formatVolume(formatPath);
+        mConnector.doCommand(String.format("format %s", formatPath));
     }
 
+    boolean getShareAvailable(String method) throws IllegalStateException  {
+        ArrayList<String> rsp = mConnector.doCommand("share_available " + method);
+
+        for (String line : rsp) {
+            String []tok = line.split(" ");
+            int code = Integer.parseInt(tok[0]);
+            if (code == VoldResponseCode.ShareAvailabilityResult) {
+                if (tok[2].equals("available"))
+                    return true;
+                return false;
+            } else {
+                throw new IllegalStateException(String.format("Unexpected response code %d", code));
+            }
+        }
+        throw new IllegalStateException("Got an empty response");
+    }
+
+    /**
+     * Enables or disables USB mass storage support.
+     * 
+     * @param enable  true to enable USB mass storage support
+     */
+    void setShareMethodEnabled(String mountPoint, String method,
+                               boolean enable) throws IllegalStateException {
+        mConnector.doCommand(String.format(
+                "%sshare %s %s", (enable ? "" : "un"), mountPoint, method));
+    }
+
+
     /**
      * Returns true if we're playing media notification sounds.
      */
@@ -417,7 +473,7 @@
             Log.w(TAG, "Multiple volumes not currently supported");
             return;
         }
-        Log.w(TAG, "State for {" + mountPoint + "} = {" + state + "}");
+        Log.i(TAG, "State for {" + mountPoint + "} = {" + state + "}");
         mLegacyState = state;
     }
 
@@ -455,14 +511,18 @@
         }
     }
 
-    void onVoldConnected() {
+    /**
+     *
+     * Callback from NativeDaemonConnector
+     */
+    public void onDaemonConnected() {
         new Thread() {
             public void run() {
                 try {
                     if (!getVolumeState(Environment.getExternalStorageDirectory().getPath())
                                  .equals(Environment.MEDIA_MOUNTED)) {
                         try {
-                            mountMedia(Environment.getExternalStorageDirectory().getPath());
+                            mountVolume(Environment.getExternalStorageDirectory().getPath());
                         } catch (Exception ex) {
                             Log.w(TAG, "Connection-mount failed");
                         }
@@ -474,7 +534,7 @@
                 }
 
                 try {
-                    boolean avail = mListener.getShareAvailable("ums");
+                    boolean avail = getShareAvailable("ums");
                     notifyShareAvailabilityChange("ums", avail);
                 } catch (Exception ex) {
                     Log.w(TAG, "Failed to get share availability");
@@ -483,6 +543,49 @@
         }.start();
     }
 
+    /**
+     *
+     * Callback from NativeDaemonConnector
+     */
+    public boolean onEvent(int code, String raw, String[] cooked) {
+        // Log.d(TAG, "event {" + raw + "}");
+        if (code == VoldResponseCode.VolumeStateChange) {
+            // FMT: NNN Volume <label> <mountpoint> state changed
+            // from <old_#> (<old_str>) to <new_#> (<new_str>)
+            notifyVolumeStateChange(
+                    cooked[2], cooked[3], Integer.parseInt(cooked[7]),
+                            Integer.parseInt(cooked[10]));
+        } else if (code == VoldResponseCode.VolumeMountFailedBlank) {
+            // FMT: NNN Volume <label> <mountpoint> mount failed - no supported file-systems
+            notifyMediaNoFs(cooked[3]);
+            // FMT: NNN Volume <label> <mountpoint> mount failed - no media
+        } else if (code == VoldResponseCode.VolumeMountFailedNoMedia) {
+            notifyMediaRemoved(cooked[3]);
+        } else if (code == VoldResponseCode.VolumeMountFailedDamaged) {
+            // FMT: NNN Volume <label> <mountpoint> mount failed - filesystem check failed
+            notifyMediaUnmountable(cooked[3]);
+        } else if (code == VoldResponseCode.ShareAvailabilityChange) {
+            // FMT: NNN Share method <method> now <available|unavailable>
+            boolean avail = false;
+            if (cooked[5].equals("available")) {
+                avail = true;
+            }
+            notifyShareAvailabilityChange(cooked[3], avail);
+        } else if (code == VoldResponseCode.VolumeDiskInserted) {
+            // FMT: NNN Volume <label> <mountpoint> disk inserted (<major>:<minor>)
+            notifyMediaInserted(cooked[3]);
+        } else if (code == VoldResponseCode.VolumeDiskRemoved) {
+            // FMT: NNN Volume <label> <mountpoint> disk removed (<major>:<minor>)
+            notifyMediaRemoved(cooked[3]);
+        } else if (code == VoldResponseCode.VolumeBadRemoval) {
+            // FMT: NNN Volume <label> <mountpoint> bad removal (<major>:<minor>)
+            notifyMediaBadRemoval(cooked[3]);
+        } else {
+            return false;
+        }
+       return true;
+    }
+
     void notifyVolumeStateChange(String label, String mountPoint, int oldState,
                                  int newState) throws IllegalStateException {
         String vs = getVolumeState(mountPoint);
@@ -587,7 +690,7 @@
         new Thread() {
             public void run() {
                 try {
-                    mountMedia(path);
+                    mountVolume(path);
                 } catch (Exception ex) {
                     Log.w(TAG, "Failed to mount media on insertion", ex);
                 }
@@ -903,29 +1006,62 @@
     }
 
     public String[] getSecureContainerList() throws IllegalStateException {
-        return mListener.listAsec();
+        ArrayList<String> rsp = mConnector.doCommand("list_asec");
+
+        String[] rdata = new String[rsp.size()];
+        int idx = 0;
+
+        for (String line : rsp) {
+            String []tok = line.split(" ");
+            int code = Integer.parseInt(tok[0]);
+            if (code == VoldResponseCode.AsecListResult) {
+                rdata[idx++] = tok[1];
+            } else if (code == NativeDaemonConnector.ResponseCode.CommandOkay) {
+                return rdata;
+            } else {
+                throw new IllegalStateException(String.format("Unexpected response code %d", code));
+            }
+        }
+        throw new IllegalStateException("Got an empty response");
     }
 
     public String createSecureContainer(String id, int sizeMb, String fstype,
                                     String key, int ownerUid) throws IllegalStateException {
-        return mListener.createAsec(id, sizeMb, fstype, key, ownerUid);
+        String cmd = String.format("create_asec %s %d %s %s %d",
+                                   id, sizeMb, fstype, key, ownerUid);
+        mConnector.doCommand(cmd);
+        return getSecureContainerPath(id);
     }
 
     public void finalizeSecureContainer(String id) throws IllegalStateException {
-        mListener.finalizeAsec(id);
+        mConnector.doCommand(String.format("finalize_asec %s", id));
     }
 
     public void destroySecureContainer(String id) throws IllegalStateException {
-        mListener.destroyAsec(id);
+        mConnector.doCommand(String.format("destroy_asec %s", id));
     }
    
-    public String mountSecureContainer(String id, String key, int ownerUid) throws IllegalStateException {
-        return mListener.mountAsec(id, key, ownerUid);
+    public String mountSecureContainer(String id, String key,
+                                       int ownerUid) throws IllegalStateException {
+        String cmd = String.format("mount_asec %s %s %d",
+                                   id, key, ownerUid);
+        mConnector.doCommand(cmd);
+        return getSecureContainerPath(id);
     }
 
     public String getSecureContainerPath(String id) throws IllegalStateException {
-        return mListener.getAsecPath(id);
-    }
+        ArrayList<String> rsp = mConnector.doCommand("asec_path " + id);
 
+        for (String line : rsp) {
+            String []tok = line.split(" ");
+            int code = Integer.parseInt(tok[0]);
+            if (code == VoldResponseCode.AsecPathResult) {
+                return tok[1];
+            } else {
+                throw new IllegalStateException(String.format("Unexpected response code %d", code));
+            }
+        }
+        throw new IllegalStateException("Got an empty response");
+    }
 }