diff --git a/src/php/lib/Grpc/BidiStreamingSurfaceActiveCall.php b/src/php/lib/Grpc/AbstractCall.php
old mode 100755
new mode 100644
similarity index 64%
rename from src/php/lib/Grpc/BidiStreamingSurfaceActiveCall.php
rename to src/php/lib/Grpc/AbstractCall.php
index 0459f21e2795cdcec50f69e3b7c14c3dfb08dc51..b813d16470d3a650c9b1d999b891de857da74266
--- a/src/php/lib/Grpc/BidiStreamingSurfaceActiveCall.php
+++ b/src/php/lib/Grpc/AbstractCall.php
@@ -32,44 +32,48 @@
  *
  */
 namespace Grpc;
+
 require_once realpath(dirname(__FILE__) . '/../autoload.php');
 
-/**
- * Represents an active call that allows for sending and recieving messages in
- * streams in any order.
- */
-class BidiStreamingSurfaceActiveCall extends AbstractSurfaceActiveCall {
+abstract class AbstractCall {
+
+  protected $call;
+  protected $deserialize;
+  protected $metadata;
 
   /**
-   * Reads the next value from the server.
-   * @return The next value from the server, or null if there is none
+   * Create a new Call wrapper object.
+   * @param Channel $channel The channel to communicate on
+   * @param string $method The method to call on the remote server
    */
-  public function read() {
-    return $this->_read();
+  public function __construct(Channel $channel, $method, $deserialize) {
+    $this->call = new Call($channel, $method, Timeval::inf_future());
+    $this->deserialize = $deserialize;
   }
 
   /**
-   * Writes a single message to the server. This cannot be called after
-   * writesDone is called.
-   * @param $value The message to send
+   * @return The metadata sent by the server.
    */
-  public function write($value) {
-    $this->_write($value);
+  public function getMetadata() {
+    return $this->metadata;
   }
 
   /**
-   * Indicate that no more writes will be sent
+   * Cancels the call
    */
-  public function writesDone() {
-    $this->_writesDone();
+  public function cancel() {
+    $this->call->cancel();
   }
 
   /**
-   * Wait for the server to send the status, and return it.
-   * @return object The status object, with integer $code and string $details
-   *     members
+   * Deserialize a response value to an object.
+   * @param string $value The binary value to deserialize
+   * @return The deserialized value
    */
-  public function getStatus() {
-    return $this->_getStatus();
+  protected function deserializeResponse($value) {
+    if ($value === null) {
+      return null;
+    }
+    return call_user_func($this->deserialize, $value);
   }
-}
+}
\ No newline at end of file
diff --git a/src/php/lib/Grpc/AbstractSurfaceActiveCall.php b/src/php/lib/Grpc/AbstractSurfaceActiveCall.php
deleted file mode 100755
index 9d0af090ceb0f98822263b8565adb1fdc95e082a..0000000000000000000000000000000000000000
--- a/src/php/lib/Grpc/AbstractSurfaceActiveCall.php
+++ /dev/null
@@ -1,98 +0,0 @@
-<?php
-
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-namespace Grpc;
-
-require_once realpath(dirname(__FILE__) . '/../autoload.php');
-
-/**
- * Represents an active call that allows sending and recieving messages.
- * Subclasses restrict how data can be sent and recieved.
- */
-abstract class AbstractSurfaceActiveCall {
-  private $active_call;
-  private $deserialize;
-
-  /**
-   * Create a new surface active call.
-   * @param Channel $channel The channel to communicate on
-   * @param string $method The method to call on the remote server
-   * @param callable $deserialize The function to deserialize a value
-   * @param array $metadata Metadata to send with the call, if applicable
-   * @param long $flags Write flags to use with this call
-   */
-  public function __construct(Channel $channel,
-                       $method,
-                       callable $deserialize,
-                       $metadata = array(),
-                       $flags = 0) {
-    $this->active_call = new ActiveCall($channel, $method, $metadata, $flags);
-    $this->deserialize = $deserialize;
-  }
-
-  /**
-   * @return The metadata sent by the server
-   */
-  public function getMetadata() {
-    return $this->metadata();
-  }
-
-  /**
-   * Cancels the call
-   */
-  public function cancel() {
-    $this->active_call->cancel();
-  }
-
-  protected function _read() {
-    $response = $this->active_call->read();
-    if ($response === null) {
-      return null;
-    }
-    return call_user_func($this->deserialize, $response);
-  }
-
-  protected function _write($value) {
-    return $this->active_call->write($value->serialize());
-  }
-
-  protected function _writesDone() {
-    $this->active_call->writesDone();
-  }
-
-  protected function _getStatus() {
-    return $this->active_call->getStatus();
-  }
-}
diff --git a/src/php/lib/Grpc/BaseStub.php b/src/php/lib/Grpc/BaseStub.php
index fde055a3b327a979e3bff0ef443b052fca5617d1..9bc1711110686cdb45a5b5dcecfafd4a4fbd538b 100755
--- a/src/php/lib/Grpc/BaseStub.php
+++ b/src/php/lib/Grpc/BaseStub.php
@@ -69,11 +69,9 @@ class BaseStub {
                                  $argument,
                                  callable $deserialize,
                                  $metadata = array()) {
-    return new SimpleSurfaceActiveCall($this->channel,
-                                       $method,
-                                       $deserialize,
-                                       $argument,
-                                       $metadata);
+    $call = new UnaryCall($this->channel, $method, $deserialize);
+    $call->start($argument, $metadata);
+    return $call;
   }
 
   /**
@@ -91,11 +89,9 @@ class BaseStub {
                                        $arguments,
                                        callable $deserialize,
                                        $metadata = array()) {
-    return new ClientStreamingSurfaceActiveCall($this->channel,
-                                                $method,
-                                                $deserialize,
-                                                $arguments,
-                                                $metadata);
+    $call = new ClientStreamingCall($this->channel, $method, $deserialize);
+    $call->start($arguments, $metadata);
+    return $call;
   }
 
   /**
@@ -112,11 +108,9 @@ class BaseStub {
                                        $argument,
                                        callable $deserialize,
                                        $metadata = array()) {
-    return new ServerStreamingSurfaceActiveCall($this->channel,
-                                                $method,
-                                                $deserialize,
-                                                $argument,
-                                                $metadata);
+    $call = new ServerStreamingCall($this->channel, $method, $deserialize);
+    $call->start($argument, $metadata);
+    return $call;
   }
 
   /**
@@ -130,9 +124,8 @@ class BaseStub {
   public function _bidiRequest($method,
                                callable $deserialize,
                                $metadata = array()) {
-    return new BidiStreamingSurfaceActiveCall($this->channel,
-                                              $method,
-                                              $deserialize,
-                                              $metadata);
+    $call = new BidiStreamingCall($this->channel, $method, $deserialize);
+    $call->start($metadata);
+    return $call;
   }
 }
diff --git a/src/php/lib/Grpc/ActiveCall.php b/src/php/lib/Grpc/BidiStreamingCall.php
old mode 100755
new mode 100644
similarity index 72%
rename from src/php/lib/Grpc/ActiveCall.php
rename to src/php/lib/Grpc/BidiStreamingCall.php
index 9e048ae03b4266f4ec34f8d8b1ef818fcff23b66..0d3dd629f254825aeeca403f1019decdce407b7f
--- a/src/php/lib/Grpc/ActiveCall.php
+++ b/src/php/lib/Grpc/BidiStreamingCall.php
@@ -35,49 +35,28 @@ namespace Grpc;
 require_once realpath(dirname(__FILE__) . '/../autoload.php');
 
 /**
- * Represents an active call that allows sending and recieving binary data
+ * Represents an active call that allows for sending and recieving messages in
+ * streams in any order.
  */
-class ActiveCall {
-  private $call;
-  private $metadata;
-
+class BidiStreamingCall extends AbstractCall {
   /**
-   * Create a new active call.
-   * @param Channel $channel The channel to communicate on
-   * @param string $method The method to call on the remote server
+   * Start the call
    * @param array $metadata Metadata to send with the call, if applicable
    */
-  public function __construct(Channel $channel,
-                              $method,
-                              $metadata = array()) {
-    $this->call = new Call($channel, $method, Timeval::inf_future());
-
-    $event = $this->call->start_batch([OP_SEND_INITIAL_METADATA => $metadata]);
-
+  public function start($metadata) {
+    $event = $this->call->start_batch([
+        OP_SEND_INITIAL_METADATA => $metadata,
+        OP_RECV_INITIAL_METADATA => true]);
     $this->metadata = $event->metadata;
   }
 
   /**
-   * @return The metadata sent by the server.
-   */
-  public function getMetadata() {
-    return $this->metadata;
-  }
-
-  /**
-   * Cancels the call
-   */
-  public function cancel() {
-    $this->call->cancel();
-  }
-
-  /**
-   * Read a single message from the server.
-   * @return The next message from the server, or null if there is none.
+   * Reads the next value from the server.
+   * @return The next value from the server, or null if there is none
    */
   public function read() {
     $read_event = $this->call->start_batch([OP_RECV_MESSAGE => true]);
-    return $read_event->message;
+    return $this->deserializeResponse($read_event->message);
   }
 
   /**
@@ -86,7 +65,7 @@ class ActiveCall {
    * @param ByteBuffer $data The data to write
    */
   public function write($data) {
-    $this->call->start_batch([OP_SEND_MESSAGE => $data]);
+    $this->call->start_batch([OP_SEND_MESSAGE => $data->serialize()]);
   }
 
   /**
@@ -107,4 +86,4 @@ class ActiveCall {
                                               ]);
     return $status_event->status;
   }
-}
+}
\ No newline at end of file
diff --git a/src/php/lib/Grpc/ClientStreamingSurfaceActiveCall.php b/src/php/lib/Grpc/ClientStreamingCall.php
old mode 100755
new mode 100644
similarity index 72%
rename from src/php/lib/Grpc/ClientStreamingSurfaceActiveCall.php
rename to src/php/lib/Grpc/ClientStreamingCall.php
index d33f09fbe4e36ca59e0434aaef82e42588807e97..4b3abcbdec5a9ffe8c5b492c77f843cd94a16d31
--- a/src/php/lib/Grpc/ClientStreamingSurfaceActiveCall.php
+++ b/src/php/lib/Grpc/ClientStreamingCall.php
@@ -38,25 +38,21 @@ require_once realpath(dirname(__FILE__) . '/../autoload.php');
  * Represents an active call that sends a stream of messages and then gets a
  * single response.
  */
-class ClientStreamingSurfaceActiveCall extends AbstractSurfaceActiveCall {
+class ClientStreamingCall extends AbstractCall {
   /**
-   * Create a new simple (single request/single response) active call.
-   * @param Channel $channel The channel to communicate on
-   * @param string $method The method to call on the remote server
-   * @param callable $deserialize The function to deserialize a value
+   * Start the call.
    * @param Traversable $arg_iter The iterator of arguments to send
    * @param array $metadata Metadata to send with the call, if applicable
    */
-  public function __construct(Channel $channel,
-                              $method,
-                              callable $deserialize,
-                              $arg_iter,
-                              $metadata = array()) {
-    parent::__construct($channel, $method, $deserialize, $metadata, 0);
+  public function start($arg_iter, $metadata = array()) {
+    $event = $this->call->start_batch([
+        OP_SEND_INITIAL_METADATA => $metadata,
+        OP_RECV_INITIAL_METADATA => true]);
+    $this->metadata = $event->metadata;
     foreach($arg_iter as $arg) {
-      $this->_write($arg);
+      $this->call->start_batch([OP_SEND_MESSAGE => $arg->serialize()]);
     }
-    $this->_writesDone();
+    $this->call->start_batch([OP_SEND_CLOSE_FROM_CLIENT => true]);
   }
 
   /**
@@ -64,8 +60,9 @@ class ClientStreamingSurfaceActiveCall extends AbstractSurfaceActiveCall {
    * @return [response data, status]
    */
   public function wait() {
-    $response = $this->_read();
-    $status = $this->_getStatus();
-    return array($response, $status);
+    $event = $this->call->start_batch([
+        OP_RECV_MESSAGE => true,
+        OP_RECV_STATUS_ON_CLIENT => true]);
+    return array($this->deserializeResponse($event->message), $event->status);
   }
-}
+}
\ No newline at end of file
diff --git a/src/php/lib/Grpc/ServerStreamingSurfaceActiveCall.php b/src/php/lib/Grpc/ServerStreamingCall.php
old mode 100755
new mode 100644
similarity index 67%
rename from src/php/lib/Grpc/ServerStreamingSurfaceActiveCall.php
rename to src/php/lib/Grpc/ServerStreamingCall.php
index fd08e86e51334430a0a93b5f77fe121efeb21205..7458f28bcbfae4563561fe7e6359976e71cfc7a7
--- a/src/php/lib/Grpc/ServerStreamingSurfaceActiveCall.php
+++ b/src/php/lib/Grpc/ServerStreamingCall.php
@@ -39,36 +39,41 @@ require_once realpath(dirname(__FILE__) . '/../autoload.php');
  * Represents an active call that sends a single message and then gets a stream
  * of reponses
  */
-class ServerStreamingSurfaceActiveCall extends AbstractSurfaceActiveCall {
+class ServerStreamingCall extends AbstractCall {
   /**
-   * Create a new simple (single request/single response) active call.
-   * @param Channel $channel The channel to communicate on
-   * @param string $method The method to call on the remote server
-   * @param callable $deserialize The function to deserialize a value
+   * Start the call
    * @param $arg The argument to send
    * @param array $metadata Metadata to send with the call, if applicable
    */
-  public function __construct(Channel $channel,
-                              $method,
-                              callable $deserialize,
-                              $arg,
-                              $metadata = array()) {
-    parent::__construct($channel, $method, $deserialize, $metadata,
-                        \Grpc\WRITE_BUFFER_HINT);
-    $this->_write($arg);
-    $this->_writesDone();
+  public function start($arg, $metadata = array()) {
+    $event = $this->call->start_batch([
+        OP_SEND_INITIAL_METADATA => $metadata,
+        OP_RECV_INITIAL_METADATA => true,
+        OP_SEND_MESSAGE => $arg->serialize(),
+        OP_SEND_CLOSE_FROM_CLIENT => true]);
+    $this->metadata = $event->metadata;
   }
 
   /**
    * @return An iterator of response values
    */
   public function responses() {
-    while(($response = $this->_read()) !== null) {
-      yield $response;
+    $response = $this->call->start_batch([OP_RECV_MESSAGE => true])->message;
+    while($response !== null) {
+      yield $this->deserializeResponse($response);
+      $response = $this->call->start_batch([OP_RECV_MESSAGE => true])->message;
     }
   }
 
+  /**
+   * Wait for the server to send the status, and return it.
+   * @return object The status object, with integer $code, string $details,
+   *     and array $metadata members
+   */
   public function getStatus() {
-    return $this->_getStatus();
+    $status_event = $this->call->start_batch([
+        OP_RECV_STATUS_ON_CLIENT => true
+                                              ]);
+    return $status_event->status;
   }
-}
+}
\ No newline at end of file
diff --git a/src/php/lib/Grpc/SimpleSurfaceActiveCall.php b/src/php/lib/Grpc/UnaryCall.php
old mode 100755
new mode 100644
similarity index 70%
rename from src/php/lib/Grpc/SimpleSurfaceActiveCall.php
rename to src/php/lib/Grpc/UnaryCall.php
index ba82f5704f58f94f0918c6f4b9ecae1b077e28c6..bbf9cfb5883f2be0281fa50b3fc2be6b33cfa5f3
--- a/src/php/lib/Grpc/SimpleSurfaceActiveCall.php
+++ b/src/php/lib/Grpc/UnaryCall.php
@@ -39,24 +39,19 @@ require_once realpath(dirname(__FILE__) . '/../autoload.php');
  * Represents an active call that sends a single message and then gets a single
  * response.
  */
-class SimpleSurfaceActiveCall extends AbstractSurfaceActiveCall {
+class UnaryCall extends AbstractCall {
   /**
-   * Create a new simple (single request/single response) active call.
-   * @param Channel $channel The channel to communicate on
-   * @param string $method The method to call on the remote server
-   * @param callable $deserialize The function to deserialize a value
+   * Start the call
    * @param $arg The argument to send
    * @param array $metadata Metadata to send with the call, if applicable
    */
-  public function __construct(Channel $channel,
-                              $method,
-                              callable $deserialize,
-                              $arg,
-                              $metadata = array()) {
-    parent::__construct($channel, $method, $deserialize, $metadata,
-                        \Grpc\WRITE_BUFFER_HINT);
-    $this->_write($arg);
-    $this->_writesDone();
+  public function start($arg, $metadata = array()) {
+    $event = $this->call->start_batch([
+        OP_SEND_INITIAL_METADATA => $metadata,
+        OP_RECV_INITIAL_METADATA => true,
+        OP_SEND_MESSAGE => $arg->serialize(),
+        OP_SEND_CLOSE_FROM_CLIENT => true]);
+    $this->metadata = $event->metadata;
   }
 
   /**
@@ -64,8 +59,9 @@ class SimpleSurfaceActiveCall extends AbstractSurfaceActiveCall {
    * @return [response data, status]
    */
   public function wait() {
-    $response = $this->_read();
-    $status = $this->_getStatus();
-    return array($response, $status);
+    $event = $this->call->start_batch([
+        OP_RECV_MESSAGE => true,
+        OP_RECV_STATUS_ON_CLIENT => true]);
+    return array($this->deserializeResponse($event->message), $event->status);
   }
-}
+}
\ No newline at end of file