Removing guava dependency for the invalidation client (part of an effort to reduce method count in Android applications)



git-svn-id: http://google-cache-invalidation-api.googlecode.com/svn/trunk@340 1cc9d426-c294-39be-ba72-c0199ca0f247
diff --git a/src/example-app-build/libs/guava-13.0.1.jar b/src/example-app-build/libs/guava-13.0.1.jar
deleted file mode 100644
index 09c5449..0000000
--- a/src/example-app-build/libs/guava-13.0.1.jar
+++ /dev/null
Binary files differ
diff --git a/src/java/com/google/common/base/Receiver.java b/src/java/com/google/common/base/Receiver.java
deleted file mode 100644
index 536e8c7..0000000
--- a/src/java/com/google/common/base/Receiver.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2008 The Guava Authors
- *
- * 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.google.common.base;
-
-/**
- * General purpose receiver of objects of a single type.
- *
- * <p>This interface is complementary to the {@code Supplier} interface.
- * Semantically, it can be used as an Output Stream, Sink, Closure or something
- * else entirely. No guarantees are implied by this interface.
- *
- * @param <T> type of received object
- *
- * @author micapolos@google.com (Michal Pociecha-Los)
- */
-public interface Receiver<T> {
-
-  /**
-   * Accepts received object.
-   *
-   * @param object received object
-   */
-  void accept(T object);
-}
diff --git a/src/java/com/google/ipc/invalidation/common/DigestFunction.java b/src/java/com/google/ipc/invalidation/common/DigestFunction.java
index a61b92d..421c372 100644
--- a/src/java/com/google/ipc/invalidation/common/DigestFunction.java
+++ b/src/java/com/google/ipc/invalidation/common/DigestFunction.java
@@ -15,12 +15,10 @@
  */
 package com.google.ipc.invalidation.common;
 
-
 /**
  * Interface specifying a function to compute digests.
  *
  */
-
 public interface DigestFunction {
   /** Clears the digest state. */
   void reset();
diff --git a/src/java/com/google/ipc/invalidation/common/ObjectIdDigestUtils.java b/src/java/com/google/ipc/invalidation/common/ObjectIdDigestUtils.java
index 6762f4b..248803e 100644
--- a/src/java/com/google/ipc/invalidation/common/ObjectIdDigestUtils.java
+++ b/src/java/com/google/ipc/invalidation/common/ObjectIdDigestUtils.java
@@ -16,8 +16,8 @@
 
 package com.google.ipc.invalidation.common;
 
-import com.google.common.base.Preconditions;
 import com.google.ipc.invalidation.util.Bytes;
+import com.google.ipc.invalidation.util.Preconditions;
 
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
@@ -28,13 +28,12 @@
  * Digest-related utilities for object ids.
  *
  */
-
 public class ObjectIdDigestUtils {
   /**
    * Implementation of {@link DigestFunction} using SHA-1.
    */
-  
-  public static class Sha1DigestFunction implements DigestFunction {
+  public static class Sha1DigestFunction
+      implements DigestFunction {
     /** Digest implementation. */
     private MessageDigest sha1;
 
@@ -78,7 +77,6 @@
    * <p>
    * REQUIRES: {@code objectIdDigests} iterate in sorted order.
    */
-  
   public static Bytes getDigest(Iterable<Bytes> objectIdDigests, DigestFunction digestFn) {
     digestFn.reset();
     for (Bytes objectIdDigest : objectIdDigests) {
@@ -91,7 +89,6 @@
    * Returns the digest for the object id with source {@code objectSource} and name
    * {@code objectName} using {@code digestFn}.
    */
-  
   public static Bytes getDigest(int objectSource, byte[] objectName, DigestFunction digestFn) {
     digestFn.reset();
     ByteBuffer buffer = ByteBuffer.allocate(Integer.SIZE / 8).order(ByteOrder.LITTLE_ENDIAN);
diff --git a/src/java/com/google/ipc/invalidation/external/client/SystemResourcesBuilder.java b/src/java/com/google/ipc/invalidation/external/client/SystemResourcesBuilder.java
index f735f67..72aae74 100644
--- a/src/java/com/google/ipc/invalidation/external/client/SystemResourcesBuilder.java
+++ b/src/java/com/google/ipc/invalidation/external/client/SystemResourcesBuilder.java
@@ -16,12 +16,12 @@
 
 package com.google.ipc.invalidation.external.client;
 
-import com.google.common.base.Preconditions;
 import com.google.ipc.invalidation.external.client.SystemResources.Logger;
 import com.google.ipc.invalidation.external.client.SystemResources.NetworkChannel;
 import com.google.ipc.invalidation.external.client.SystemResources.Scheduler;
 import com.google.ipc.invalidation.external.client.SystemResources.Storage;
 import com.google.ipc.invalidation.ticl.BasicSystemResources;
+import com.google.ipc.invalidation.util.Preconditions;
 
 
 /**
diff --git a/src/java/com/google/ipc/invalidation/external/client/contrib/AndroidListener.java b/src/java/com/google/ipc/invalidation/external/client/contrib/AndroidListener.java
index aad35b9..b9a4e9a 100644
--- a/src/java/com/google/ipc/invalidation/external/client/contrib/AndroidListener.java
+++ b/src/java/com/google/ipc/invalidation/external/client/contrib/AndroidListener.java
@@ -15,7 +15,6 @@
  */
 package com.google.ipc.invalidation.external.client.contrib;
 
-import com.google.common.base.Preconditions;
 import com.google.ipc.invalidation.external.client.InvalidationClient;
 import com.google.ipc.invalidation.external.client.InvalidationClientConfig;
 import com.google.ipc.invalidation.external.client.InvalidationListener;
@@ -40,6 +39,7 @@
 import com.google.ipc.invalidation.ticl.proto.ClientProtocol.InvalidationP;
 import com.google.ipc.invalidation.ticl.proto.ClientProtocol.ObjectIdP;
 import com.google.ipc.invalidation.util.Bytes;
+import com.google.ipc.invalidation.util.Preconditions;
 import com.google.ipc.invalidation.util.ProtoWrapper.ValidationException;
 
 import android.app.IntentService;
diff --git a/src/java/com/google/ipc/invalidation/external/client/contrib/MultiplexingGcmListener.java b/src/java/com/google/ipc/invalidation/external/client/contrib/MultiplexingGcmListener.java
index 6a0645f..10cb3ce 100644
--- a/src/java/com/google/ipc/invalidation/external/client/contrib/MultiplexingGcmListener.java
+++ b/src/java/com/google/ipc/invalidation/external/client/contrib/MultiplexingGcmListener.java
@@ -136,9 +136,6 @@
     private static final String EXTRA_WAKELOCK_NAME =
         "com.google.ipc.invalidation.gcmmplex.listener.WAKELOCK_NAME";
 
-    /** Logger for {@code AbstractListener}. */
-    private static final Logger logger = AndroidLogger.forTag("MplexGcmAbsListener");
-
     /**
      * A {@code BroadcastReceiver} to receive intents from the {@code MultiplexingGcmListener}
      * service. It acquires a wakelock and forwards the intent to the service named by
diff --git a/src/java/com/google/ipc/invalidation/external/client/types/ApplicationClientId.java b/src/java/com/google/ipc/invalidation/external/client/types/ApplicationClientId.java
index 8648408..fa3cdbc 100644
--- a/src/java/com/google/ipc/invalidation/external/client/types/ApplicationClientId.java
+++ b/src/java/com/google/ipc/invalidation/external/client/types/ApplicationClientId.java
@@ -16,7 +16,7 @@
 
 package com.google.ipc.invalidation.external.client.types;
 
-import com.google.common.base.Preconditions;
+import com.google.ipc.invalidation.util.Preconditions;
 
 import java.util.Arrays;
 
diff --git a/src/java/com/google/ipc/invalidation/external/client/types/Invalidation.java b/src/java/com/google/ipc/invalidation/external/client/types/Invalidation.java
index 6c8c5f2..acfe952 100644
--- a/src/java/com/google/ipc/invalidation/external/client/types/Invalidation.java
+++ b/src/java/com/google/ipc/invalidation/external/client/types/Invalidation.java
@@ -16,7 +16,7 @@
 
 package com.google.ipc.invalidation.external.client.types;
 
-import com.google.common.base.Preconditions;
+import com.google.ipc.invalidation.util.Preconditions;
 
 import java.util.Arrays;
 
diff --git a/src/java/com/google/ipc/invalidation/external/client/types/ObjectId.java b/src/java/com/google/ipc/invalidation/external/client/types/ObjectId.java
index cced110..2a6217f 100644
--- a/src/java/com/google/ipc/invalidation/external/client/types/ObjectId.java
+++ b/src/java/com/google/ipc/invalidation/external/client/types/ObjectId.java
@@ -16,7 +16,7 @@
 
 package com.google.ipc.invalidation.external.client.types;
 
-import com.google.common.base.Preconditions;
+import com.google.ipc.invalidation.util.Preconditions;
 
 import java.util.Arrays;
 
diff --git a/src/java/com/google/ipc/invalidation/ticl/AckCache.java b/src/java/com/google/ipc/invalidation/ticl/AckCache.java
index 4812050..207b959 100644
--- a/src/java/com/google/ipc/invalidation/ticl/AckCache.java
+++ b/src/java/com/google/ipc/invalidation/ticl/AckCache.java
@@ -71,33 +71,26 @@
     if (version > getHighestAckedVersion(objectId)) {
       highestAckedVersionMap.put(objectId, version);
     }
-  };
+  }
 
   /**
    * Returns true if the client has already acked a restarted invalidation with
    * a version number greater than or equal to that in {@code inv} and the same
    * object id, and {@code inv} is a known version invalidation. Unknown version
    * invalidations are never considered already acked.
-   *
-   * @param {!invalidation.proto.InvalidationP} inv
-   * @return {boolean}
    */
   boolean isAcked(InvalidationP inv) {
     return inv.getIsKnownVersion()
         && this.getHighestAckedVersion(inv.getObjectId()) >= inv.getVersion();
-  };
+  }
 
 
   /**
    * Returns the highest acked version for the object id with the given key, or
    * -1 if no versions have been acked.
-   *
-   * @param {string} objectIdKey The string key for an object id.
-   * @return {!goog.math.Long}
-   * @private
    */
   private long getHighestAckedVersion(ObjectIdP objectId) {
     Long version = TypedUtil.mapGet(highestAckedVersionMap, objectId);
     return (version != null) ? version : -1L;
-  };
+  }
 }
diff --git a/src/java/com/google/ipc/invalidation/ticl/CheckingInvalidationListener.java b/src/java/com/google/ipc/invalidation/ticl/CheckingInvalidationListener.java
index 744e1ad..845037e 100644
--- a/src/java/com/google/ipc/invalidation/ticl/CheckingInvalidationListener.java
+++ b/src/java/com/google/ipc/invalidation/ticl/CheckingInvalidationListener.java
@@ -18,7 +18,6 @@
 
 import static com.google.ipc.invalidation.external.client.SystemResources.Scheduler.NO_DELAY;
 
-import com.google.common.base.Preconditions;
 import com.google.ipc.invalidation.external.client.InvalidationClient;
 import com.google.ipc.invalidation.external.client.InvalidationListener;
 import com.google.ipc.invalidation.external.client.SystemResources.Logger;
@@ -29,6 +28,7 @@
 import com.google.ipc.invalidation.external.client.types.ObjectId;
 import com.google.ipc.invalidation.ticl.Statistics.ListenerEventType;
 import com.google.ipc.invalidation.util.NamedRunnable;
+import com.google.ipc.invalidation.util.Preconditions;
 
 
 /**
diff --git a/src/java/com/google/ipc/invalidation/ticl/InvalidationClientCore.java b/src/java/com/google/ipc/invalidation/ticl/InvalidationClientCore.java
index 79fa23a..1eca3d4 100644
--- a/src/java/com/google/ipc/invalidation/ticl/InvalidationClientCore.java
+++ b/src/java/com/google/ipc/invalidation/ticl/InvalidationClientCore.java
@@ -18,7 +18,6 @@
 
 import static com.google.ipc.invalidation.external.client.SystemResources.Scheduler.NO_DELAY;
 
-import com.google.common.base.Preconditions;
 import com.google.ipc.invalidation.common.DigestFunction;
 import com.google.ipc.invalidation.common.ObjectIdDigestUtils;
 import com.google.ipc.invalidation.external.client.InvalidationListener;
@@ -69,6 +68,7 @@
 import com.google.ipc.invalidation.util.Bytes;
 import com.google.ipc.invalidation.util.InternalBase;
 import com.google.ipc.invalidation.util.Marshallable;
+import com.google.ipc.invalidation.util.Preconditions;
 import com.google.ipc.invalidation.util.ProtoWrapper.ValidationException;
 import com.google.ipc.invalidation.util.Smearer;
 import com.google.ipc.invalidation.util.TextBuilder;
@@ -289,7 +289,6 @@
   }
 
   /** The task that is scheduled to send batched messages to the server (when needed). **/
-  
   static class BatchingTask extends RecurringTask {
     /*
      * This class is static and extends RecurringTask directly so that it can be instantiated
@@ -348,7 +347,6 @@
   //
 
   /** The single key used to write all the Ticl state. */
-  
   public static final String CLIENT_TOKEN_KEY = "ClientToken";
 
   /** Resources for the Ticl. */
@@ -431,6 +429,9 @@
   /** Task to do the first heartbeat after a persistent restart. */
   private InitialPersistentHeartbeatTask initialPersistentHeartbeatTask;
 
+  /** A cache of already acked invalidations to avoid duplicate delivery. */
+  private final AckCache ackCache = new AckCache();
+
   /**
    * Constructs a client.
    *
@@ -1014,6 +1015,10 @@
     }
     statistics.recordIncomingOperation(IncomingOperationType.ACKNOWLEDGE);
     protocolHandler.sendInvalidationAck(invalidation, batchingTask);
+
+    // Record that the invalidation has been acknowledged to potentially avoid unnecessary delivery
+    // of earlier invalidations for the same object.
+    ackCache.recordAck(invalidation);
   }
 
   //
@@ -1164,8 +1169,10 @@
   /** Handles a server {@code header}. */
   private void handleIncomingHeader(ServerMessageHeader header) {
     Preconditions.checkState(internalScheduler.isRunningOnThread(), "Not on internal thread");
-    Preconditions.checkState(nonce == null,
-        "Cannot process server header with non-null nonce (have %s): %s", nonce, header);
+    if (nonce != null) {
+      throw new IllegalStateException(
+          "Cannot process server header with non-null nonce (have " + nonce + "): " + header);
+    }
     if (header.registrationSummary != null) {
       // We've received a summary from the server, so if we were suppressing registrations, we
       // should now allow them to go to the registrar.
@@ -1176,7 +1183,7 @@
       // operations have succeeded.
       Set<RegistrationP> upcalls =
           registrationManager.informServerRegistrationSummary(header.registrationSummary);
-      logger.fine("Receivced new server registration summary (%s); will make %s upcalls",
+      logger.fine("Received new server registration summary (%s); will make %s upcalls",
           header.registrationSummary, upcalls.size());
       for (RegistrationP registration : upcalls) {
         ObjectId objectId =
@@ -1193,7 +1200,14 @@
 
     for (InvalidationP invalidation : invalidations) {
       AckHandle ackHandle = AckHandle.newInstance(AckHandleP.create(invalidation).toByteArray());
-      if (CommonProtos.isAllObjectId(invalidation.getObjectId())) {
+      if (ackCache.isAcked(invalidation)) {
+        // If the ack cache indicates that the client has already acked a restarted invalidation
+        // with an equal or greater version, then the TICL can simply acknowledge it immediately
+        // rather than delivering it to the listener.
+        logger.info("Stale invalidation {0}, not delivering", invalidation);
+        acknowledge(ackHandle);
+        statistics.recordReceivedMessage(ReceivedMessageType.STALE_INVALIDATION);
+      } else if (CommonProtos.isAllObjectId(invalidation.getObjectId())) {
         logger.info("Issuing invalidate all");
         listener.invalidateAll(InvalidationClientCore.this, ackHandle);
       } else {
@@ -1419,8 +1433,9 @@
    * client token, unless the nonce is being cleared.
    */
   private void setNonce(Bytes newNonce) {
-    Preconditions.checkState((newNonce == null) || (clientToken == null),
-        "Tried to set nonce with existing token %s", clientToken);
+    if ((newNonce != null) && (clientToken != null)) {
+      throw new IllegalStateException("Tried to set nonce with existing token " + clientToken);
+    }
     this.nonce = newNonce;
   }
 
@@ -1428,7 +1443,7 @@
    * Returns a randomly generated nonce. Visible for testing only.
    */
   
-  public static Bytes generateNonce(Random random) {
+  static Bytes generateNonce(Random random) {
     // Generate 8 random bytes.
     byte[] randomBytes = new byte[8];
     random.nextBytes(randomBytes);
@@ -1443,8 +1458,9 @@
    * nonce, unless the token is being cleared.
    */
   private void setClientToken(Bytes newClientToken) {
-    Preconditions.checkState((newClientToken == null) || (nonce == null),
-        "Tried to set token with existing nonce %s", nonce);
+    if ((newClientToken != null) && (nonce != null)) {
+      throw new IllegalStateException("Tried to set token with existing nonce " + nonce);
+    }
 
     // If the ticl is in the process of being started and we are getting a new token (either from
     // persistence or from the server, start the ticl and inform the application.
diff --git a/src/java/com/google/ipc/invalidation/ticl/PersistenceUtils.java b/src/java/com/google/ipc/invalidation/ticl/PersistenceUtils.java
index e25a4a8..be4fe21 100644
--- a/src/java/com/google/ipc/invalidation/ticl/PersistenceUtils.java
+++ b/src/java/com/google/ipc/invalidation/ticl/PersistenceUtils.java
@@ -28,12 +28,11 @@
  * Utility methods for handling the Ticl persistent state.
  *
  */
-
 public class PersistenceUtils {
 
   /** Serializes a Ticl state blob. */
-  
-  public static byte[] serializeState(PersistentTiclState state, DigestFunction digestFn) {
+  public static byte[] serializeState(
+      PersistentTiclState state, DigestFunction digestFn) {
     Bytes mac = generateMac(state, digestFn);
     return PersistentStateBlob.create(state, mac).toByteArray();
   }
diff --git a/src/java/com/google/ipc/invalidation/ticl/ProtoWrapperConverter.java b/src/java/com/google/ipc/invalidation/ticl/ProtoWrapperConverter.java
index f6c585b..79f5f18 100644
--- a/src/java/com/google/ipc/invalidation/ticl/ProtoWrapperConverter.java
+++ b/src/java/com/google/ipc/invalidation/ticl/ProtoWrapperConverter.java
@@ -16,13 +16,13 @@
 
 package com.google.ipc.invalidation.ticl;
 
-import com.google.common.base.Preconditions;
 import com.google.ipc.invalidation.external.client.types.Invalidation;
 import com.google.ipc.invalidation.external.client.types.ObjectId;
 import com.google.ipc.invalidation.ticl.proto.ClientProtocol.InvalidationP;
 import com.google.ipc.invalidation.ticl.proto.ClientProtocol.ObjectIdP;
 import com.google.ipc.invalidation.ticl.proto.CommonProtos;
 import com.google.ipc.invalidation.util.Bytes;
+import com.google.ipc.invalidation.util.Preconditions;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -31,7 +31,6 @@
  * Utilities to convert between {@link com.google.ipc.invalidation.util.ProtoWrapper ProtoWrapper}
  * wrappers and externally-exposed types in the Ticl.
  */
-
 public class ProtoWrapperConverter {
 
   /**
@@ -47,7 +46,6 @@
    * Converts an object id {@code objectId} to the corresponding protocol buffer
    * and returns it.
    */
-  
   public static ObjectIdP convertToObjectIdProto(ObjectId objectId) {
     Preconditions.checkNotNull(objectId);
     return ObjectIdP.create(objectId.getSource(), new Bytes(objectId.getName()));
diff --git a/src/java/com/google/ipc/invalidation/ticl/ProtocolHandler.java b/src/java/com/google/ipc/invalidation/ticl/ProtocolHandler.java
index 2234087..131de39 100644
--- a/src/java/com/google/ipc/invalidation/ticl/ProtocolHandler.java
+++ b/src/java/com/google/ipc/invalidation/ticl/ProtocolHandler.java
@@ -16,7 +16,6 @@
 
 package com.google.ipc.invalidation.ticl;
 
-import com.google.common.base.Preconditions;
 import com.google.ipc.invalidation.external.client.SystemResources;
 import com.google.ipc.invalidation.external.client.SystemResources.Logger;
 import com.google.ipc.invalidation.external.client.SystemResources.NetworkChannel;
@@ -61,6 +60,7 @@
 import com.google.ipc.invalidation.util.Bytes;
 import com.google.ipc.invalidation.util.InternalBase;
 import com.google.ipc.invalidation.util.Marshallable;
+import com.google.ipc.invalidation.util.Preconditions;
 import com.google.ipc.invalidation.util.ProtoWrapper;
 import com.google.ipc.invalidation.util.ProtoWrapper.ValidationException;
 import com.google.ipc.invalidation.util.Smearer;
diff --git a/src/java/com/google/ipc/invalidation/ticl/RecurringTask.java b/src/java/com/google/ipc/invalidation/ticl/RecurringTask.java
index 32dd3a2..8973854 100644
--- a/src/java/com/google/ipc/invalidation/ticl/RecurringTask.java
+++ b/src/java/com/google/ipc/invalidation/ticl/RecurringTask.java
@@ -16,7 +16,6 @@
 
 package com.google.ipc.invalidation.ticl;
 
-import com.google.common.base.Preconditions;
 import com.google.ipc.invalidation.external.client.SystemResources.Logger;
 import com.google.ipc.invalidation.external.client.SystemResources.Scheduler;
 import com.google.ipc.invalidation.ticl.proto.Client.ExponentialBackoffState;
@@ -25,6 +24,7 @@
 import com.google.ipc.invalidation.util.InternalBase;
 import com.google.ipc.invalidation.util.Marshallable;
 import com.google.ipc.invalidation.util.NamedRunnable;
+import com.google.ipc.invalidation.util.Preconditions;
 import com.google.ipc.invalidation.util.Smearer;
 import com.google.ipc.invalidation.util.TextBuilder;
 
diff --git a/src/java/com/google/ipc/invalidation/ticl/RegistrationManager.java b/src/java/com/google/ipc/invalidation/ticl/RegistrationManager.java
index 97adc0d..e985295 100644
--- a/src/java/com/google/ipc/invalidation/ticl/RegistrationManager.java
+++ b/src/java/com/google/ipc/invalidation/ticl/RegistrationManager.java
@@ -128,11 +128,6 @@
     this.lastKnownServerSummary = getRegistrationSummary();
   }
 
-  
-  Collection<ObjectIdP> getRegisteredObjectsForTest() {
-    return desiredRegistrations.getElements(EMPTY_PREFIX, 0);
-  }
-
   /** Perform registration/unregistation for all objects in {@code objectIds}. */
   Collection<ObjectIdP> performOperations(Collection<ObjectIdP> objectIds, int regOpType) {
     // Record that we have pending operations on the objects.
diff --git a/src/java/com/google/ipc/invalidation/ticl/RunState.java b/src/java/com/google/ipc/invalidation/ticl/RunState.java
index 0cee26e..6e022b0 100644
--- a/src/java/com/google/ipc/invalidation/ticl/RunState.java
+++ b/src/java/com/google/ipc/invalidation/ticl/RunState.java
@@ -16,7 +16,6 @@
 
 package com.google.ipc.invalidation.ticl;
 
-import com.google.common.base.Preconditions;
 import com.google.ipc.invalidation.ticl.proto.Client.RunStateP;
 import com.google.ipc.invalidation.util.Marshallable;
 
@@ -47,8 +46,9 @@
    */
   public void start() {
     synchronized (lock) {
-      Preconditions.checkState(currentState == RunStateP.State.NOT_STARTED,
-          "Cannot start: %s", currentState);
+      if (currentState != RunStateP.State.NOT_STARTED) {
+        throw new IllegalStateException("Cannot start: " + currentState);
+      }
       currentState = RunStateP.State.STARTED;
     }
   }
@@ -60,8 +60,9 @@
    */
   public void stop() {
     synchronized (lock) {
-      Preconditions.checkState(currentState == RunStateP.State.STARTED,
-          "Cannot stop: %s", currentState);
+      if (currentState != RunStateP.State.STARTED) {
+        throw new IllegalStateException("Cannot stop: " + currentState);
+      }
       currentState = RunStateP.State.STOPPED;
     }
   }
diff --git a/src/java/com/google/ipc/invalidation/ticl/SafeStorage.java b/src/java/com/google/ipc/invalidation/ticl/SafeStorage.java
index 6dac000..55d754a 100644
--- a/src/java/com/google/ipc/invalidation/ticl/SafeStorage.java
+++ b/src/java/com/google/ipc/invalidation/ticl/SafeStorage.java
@@ -18,7 +18,6 @@
 
 import static com.google.ipc.invalidation.external.client.SystemResources.Scheduler.NO_DELAY;
 
-import com.google.common.base.Preconditions;
 import com.google.ipc.invalidation.external.client.SystemResources;
 import com.google.ipc.invalidation.external.client.SystemResources.Scheduler;
 import com.google.ipc.invalidation.external.client.SystemResources.Storage;
@@ -26,6 +25,7 @@
 import com.google.ipc.invalidation.external.client.types.SimplePair;
 import com.google.ipc.invalidation.external.client.types.Status;
 import com.google.ipc.invalidation.util.NamedRunnable;
+import com.google.ipc.invalidation.util.Preconditions;
 
 /**
  * An implementation of the Storage resource that schedules the callbacks on the given scheduler
diff --git a/src/java/com/google/ipc/invalidation/ticl/Statistics.java b/src/java/com/google/ipc/invalidation/ticl/Statistics.java
index 6bfd25a..899955e 100644
--- a/src/java/com/google/ipc/invalidation/ticl/Statistics.java
+++ b/src/java/com/google/ipc/invalidation/ticl/Statistics.java
@@ -63,6 +63,7 @@
     TOKEN_CONTROL,
     ERROR,
     CONFIG_CHANGE,
+    STALE_INVALIDATION,  // An already acked INVALIDATION.
     TOTAL, // Refers to the actual ServerToClientMessage messages received from the network.
   }
 
diff --git a/src/java/com/google/ipc/invalidation/ticl/TestableInvalidationClient.java b/src/java/com/google/ipc/invalidation/ticl/TestableInvalidationClient.java
index 1cb3b1f..898c10b 100644
--- a/src/java/com/google/ipc/invalidation/ticl/TestableInvalidationClient.java
+++ b/src/java/com/google/ipc/invalidation/ticl/TestableInvalidationClient.java
@@ -16,7 +16,6 @@
 
 package com.google.ipc.invalidation.ticl;
 
-import com.google.common.base.Preconditions;
 import com.google.ipc.invalidation.common.DigestFunction;
 import com.google.ipc.invalidation.external.client.InvalidationClient;
 import com.google.ipc.invalidation.external.client.InvalidationListener;
@@ -27,6 +26,7 @@
 import com.google.ipc.invalidation.ticl.proto.ClientProtocol.RegistrationSummary;
 import com.google.ipc.invalidation.util.Bytes;
 import com.google.ipc.invalidation.util.InternalBase;
+import com.google.ipc.invalidation.util.Preconditions;
 import com.google.ipc.invalidation.util.TextBuilder;
 
 import java.util.ArrayList;
diff --git a/src/java/com/google/ipc/invalidation/ticl/android/c2dm/WakeLockManager.java b/src/java/com/google/ipc/invalidation/ticl/android/c2dm/WakeLockManager.java
deleted file mode 100644
index 59d2742..0000000
--- a/src/java/com/google/ipc/invalidation/ticl/android/c2dm/WakeLockManager.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * 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.google.ipc.invalidation.ticl.android.c2dm;
-
-
-import android.content.Context;
-
-/**
- * Forwarding placeholder for {@link com.google.ipc.invalidation.ticl.android2.WakeLockManager} in
- * its original location. This class can be removed after all dependencies have been removed.
- */
-@Deprecated
-public class WakeLockManager {
-  private final com.google.ipc.invalidation.ticl.android2.WakeLockManager delegate;
-
-  private WakeLockManager(com.google.ipc.invalidation.ticl.android2.WakeLockManager delegate) {
-    this.delegate = delegate;
-  }
-
-  /** Returns the wake lock manager. */
-  public static WakeLockManager getInstance(Context context) {
-    return new WakeLockManager(
-        com.google.ipc.invalidation.ticl.android2.WakeLockManager.getInstance(context));
-  }
-
-  /**
-   * Acquires a wake lock identified by the {@code key} that will be automatically released after at
-   * most {@code timeoutMs}.
-   */
-  public void acquire(Object key, int timeoutMs) {
-    delegate.acquire(key, timeoutMs);
-  }
-
-  /**
-   * Releases the wake lock identified by the {@code key} if it is currently held.
-   */
-  public void release(Object key) {
-    delegate.release(key);
-  }
-
-  /**
-   * Returns whether there is currently a wake lock held for the provided {@code key}.
-   */
-  public boolean isHeld(Object key) {
-    return delegate.isHeld(key);
-  }
-
-  /** Returns whether the manager has any active (held) wake locks. */
-  
-  public boolean hasWakeLocks() {
-    return delegate.hasWakeLocks();
-  }
-
-  /** Discards (without releasing) all wake locks. */
-  
-  public void resetForTest() {
-    delegate.resetForTest();
-  }
-}
diff --git a/src/java/com/google/ipc/invalidation/ticl/android2/AndroidClock.java b/src/java/com/google/ipc/invalidation/ticl/android2/AndroidClock.java
index 21deb67..84bd15f 100644
--- a/src/java/com/google/ipc/invalidation/ticl/android2/AndroidClock.java
+++ b/src/java/com/google/ipc/invalidation/ticl/android2/AndroidClock.java
@@ -16,7 +16,6 @@
 
 package com.google.ipc.invalidation.ticl.android2;
 
-
 /**
  * Interface for the Android Ticl that provides a source of time.
  *
diff --git a/src/java/com/google/ipc/invalidation/ticl/android2/AndroidInternalScheduler.java b/src/java/com/google/ipc/invalidation/ticl/android2/AndroidInternalScheduler.java
index 287adc2..f867d6c 100644
--- a/src/java/com/google/ipc/invalidation/ticl/android2/AndroidInternalScheduler.java
+++ b/src/java/com/google/ipc/invalidation/ticl/android2/AndroidInternalScheduler.java
@@ -16,13 +16,13 @@
 
 package com.google.ipc.invalidation.ticl.android2;
 
-import com.google.common.base.Preconditions;
 import com.google.ipc.invalidation.external.client.SystemResources;
 import com.google.ipc.invalidation.external.client.SystemResources.Logger;
 import com.google.ipc.invalidation.external.client.SystemResources.Scheduler;
 import com.google.ipc.invalidation.ticl.RecurringTask;
 import com.google.ipc.invalidation.ticl.proto.AndroidService.AndroidSchedulerEvent;
 import com.google.ipc.invalidation.util.NamedRunnable;
+import com.google.ipc.invalidation.util.Preconditions;
 import com.google.ipc.invalidation.util.TypedUtil;
 
 import android.app.AlarmManager;
@@ -135,9 +135,10 @@
    * REQUIRES: a recurring task with the name in the intent be present in {@link #registeredTasks}.
    */
   void handleSchedulerEvent(AndroidSchedulerEvent event) {
-    Runnable recurringTaskRunnable = Preconditions.checkNotNull(
-        TypedUtil.mapGet(registeredTasks, event.getEventName()),
-        "No task registered for %s", event.getEventName());
+    Runnable recurringTaskRunnable = TypedUtil.mapGet(registeredTasks, event.getEventName());
+    if (recurringTaskRunnable == null) {
+      throw new NullPointerException("No task registered for " + event.getEventName());
+    }
     if (ticlId != event.getTiclId()) {
       logger.warning("Ignoring event with wrong ticl id (not %s): %s", ticlId, event);
       return;
@@ -152,9 +153,17 @@
    */
   void registerTask(String name, Runnable runnable) {
     Runnable previous = registeredTasks.put(name, runnable);
-    Preconditions.checkState(previous == null,
-        "Cannot overwrite task registered on %s, %s; tasks = %s",
-        name, this, registeredTasks.keySet());
+    if (previous != null) {
+      String message = new StringBuilder()
+          .append("Cannot overwrite task registered on ")
+          .append(name)
+          .append(", ")
+          .append(this)
+          .append("; tasks = ")
+          .append(registeredTasks.keySet())
+          .toString();
+      throw new IllegalStateException(message);
+    }
   }
 
   @Override
diff --git a/src/java/com/google/ipc/invalidation/ticl/android2/AndroidInvalidationClientImpl.java b/src/java/com/google/ipc/invalidation/ticl/android2/AndroidInvalidationClientImpl.java
index fbc0018..a6cecb1 100644
--- a/src/java/com/google/ipc/invalidation/ticl/android2/AndroidInvalidationClientImpl.java
+++ b/src/java/com/google/ipc/invalidation/ticl/android2/AndroidInvalidationClientImpl.java
@@ -15,7 +15,6 @@
  */
 package com.google.ipc.invalidation.ticl.android2;
 
-import com.google.common.base.Preconditions;
 import com.google.ipc.invalidation.external.client.InvalidationClient;
 import com.google.ipc.invalidation.external.client.InvalidationListener;
 import com.google.ipc.invalidation.external.client.SystemResources;
@@ -31,6 +30,7 @@
 import com.google.ipc.invalidation.ticl.proto.Client.AckHandleP;
 import com.google.ipc.invalidation.ticl.proto.ClientProtocol.ApplicationClientIdP;
 import com.google.ipc.invalidation.ticl.proto.ClientProtocol.ClientConfigP;
+import com.google.ipc.invalidation.util.Preconditions;
 import com.google.ipc.invalidation.util.ProtoWrapper.ValidationException;
 
 import android.app.Service;
@@ -222,10 +222,10 @@
    * executed.
    */
   private void initializeSchedulerWithRecurringTasks() {
-    Preconditions.checkState(
-        getResources().getInternalScheduler() instanceof AndroidInternalScheduler,
-        "Scheduler must be an AndroidInternalScheduler, not %s",
-        getResources().getInternalScheduler());
+    if (!(getResources().getInternalScheduler() instanceof AndroidInternalScheduler)) {
+      throw new IllegalStateException("Scheduler must be an AndroidInternalScheduler, not "
+          + getResources().getInternalScheduler());
+    }
     AndroidInternalScheduler scheduler =
         (AndroidInternalScheduler) getResources().getInternalScheduler();
     for (Map.Entry<String, Runnable> entry : getRecurringTasks().entrySet()) {
diff --git a/src/java/com/google/ipc/invalidation/ticl/android2/AndroidInvalidationClientStub.java b/src/java/com/google/ipc/invalidation/ticl/android2/AndroidInvalidationClientStub.java
index 01abf70..1683eda 100644
--- a/src/java/com/google/ipc/invalidation/ticl/android2/AndroidInvalidationClientStub.java
+++ b/src/java/com/google/ipc/invalidation/ticl/android2/AndroidInvalidationClientStub.java
@@ -16,7 +16,6 @@
 
 package com.google.ipc.invalidation.ticl.android2;
 
-import com.google.common.base.Preconditions;
 import com.google.ipc.invalidation.external.client.InvalidationClient;
 import com.google.ipc.invalidation.external.client.SystemResources.Logger;
 import com.google.ipc.invalidation.external.client.types.AckHandle;
@@ -24,6 +23,7 @@
 import com.google.ipc.invalidation.ticl.ProtoWrapperConverter;
 import com.google.ipc.invalidation.ticl.android2.ProtocolIntents.ClientDowncalls;
 import com.google.ipc.invalidation.ticl.proto.ClientProtocol.ObjectIdP;
+import com.google.ipc.invalidation.util.Preconditions;
 
 import android.content.Context;
 import android.content.Intent;
diff --git a/src/java/com/google/ipc/invalidation/ticl/android2/AndroidStorage.java b/src/java/com/google/ipc/invalidation/ticl/android2/AndroidStorage.java
index b9231e5..a98ec2a 100644
--- a/src/java/com/google/ipc/invalidation/ticl/android2/AndroidStorage.java
+++ b/src/java/com/google/ipc/invalidation/ticl/android2/AndroidStorage.java
@@ -15,13 +15,13 @@
  */
 package com.google.ipc.invalidation.ticl.android2;
 
-import com.google.common.base.Preconditions;
 import com.google.ipc.invalidation.external.client.SystemResources;
 import com.google.ipc.invalidation.external.client.SystemResources.Storage;
 import com.google.ipc.invalidation.external.client.types.Callback;
 import com.google.ipc.invalidation.external.client.types.SimplePair;
 import com.google.ipc.invalidation.external.client.types.Status;
 import com.google.ipc.invalidation.ticl.InvalidationClientCore;
+import com.google.ipc.invalidation.util.Preconditions;
 
 import android.content.Context;
 
diff --git a/src/java/com/google/ipc/invalidation/ticl/android2/AndroidTiclManifest.java b/src/java/com/google/ipc/invalidation/ticl/android2/AndroidTiclManifest.java
index 8d020c9..1f4ab07 100644
--- a/src/java/com/google/ipc/invalidation/ticl/android2/AndroidTiclManifest.java
+++ b/src/java/com/google/ipc/invalidation/ticl/android2/AndroidTiclManifest.java
@@ -16,7 +16,7 @@
 
 package com.google.ipc.invalidation.ticl.android2;
 
-import com.google.common.base.Preconditions;
+import com.google.ipc.invalidation.util.Preconditions;
 
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
diff --git a/src/java/com/google/ipc/invalidation/ticl/android2/ResourcesFactory.java b/src/java/com/google/ipc/invalidation/ticl/android2/ResourcesFactory.java
index d53e7df..067b243 100644
--- a/src/java/com/google/ipc/invalidation/ticl/android2/ResourcesFactory.java
+++ b/src/java/com/google/ipc/invalidation/ticl/android2/ResourcesFactory.java
@@ -16,12 +16,12 @@
 
 package com.google.ipc.invalidation.ticl.android2;
 
-import com.google.common.base.Preconditions;
 import com.google.ipc.invalidation.external.client.SystemResources;
 import com.google.ipc.invalidation.external.client.SystemResources.Scheduler;
 import com.google.ipc.invalidation.external.client.android.service.AndroidLogger;
 import com.google.ipc.invalidation.ticl.BasicSystemResources;
 import com.google.ipc.invalidation.ticl.android2.channel.AndroidNetworkChannel;
+import com.google.ipc.invalidation.util.Preconditions;
 
 import android.content.Context;
 
@@ -98,8 +98,9 @@
      * it has a network event to communicate to the Ticl.
      */
     public void setNetworkListener(NetworkChannel.NetworkListener networkListener) {
-      Preconditions.checkState(this.networkListener == null, "Listener already set: %s",
-          networkListener);
+      if (this.networkListener != null) {
+        throw new IllegalStateException("Listener already set: " + networkListener);
+      }
       this.networkListener = Preconditions.checkNotNull(networkListener);
     }
 
diff --git a/src/java/com/google/ipc/invalidation/ticl/android2/TiclStateManager.java b/src/java/com/google/ipc/invalidation/ticl/android2/TiclStateManager.java
index f0ec484..bf9ded0 100644
--- a/src/java/com/google/ipc/invalidation/ticl/android2/TiclStateManager.java
+++ b/src/java/com/google/ipc/invalidation/ticl/android2/TiclStateManager.java
@@ -16,7 +16,6 @@
 
 package com.google.ipc.invalidation.ticl.android2;
 
-import com.google.common.base.Preconditions;
 import com.google.ipc.invalidation.common.ObjectIdDigestUtils.Sha1DigestFunction;
 import com.google.ipc.invalidation.external.client.SystemResources;
 import com.google.ipc.invalidation.external.client.SystemResources.Logger;
@@ -26,6 +25,7 @@
 import com.google.ipc.invalidation.ticl.proto.ClientProtocol.ApplicationClientIdP;
 import com.google.ipc.invalidation.ticl.proto.ClientProtocol.ClientConfigP;
 import com.google.ipc.invalidation.util.Bytes;
+import com.google.ipc.invalidation.util.Preconditions;
 import com.google.ipc.invalidation.util.ProtoWrapper.ValidationException;
 import com.google.ipc.invalidation.util.TypedUtil;
 
@@ -44,8 +44,7 @@
  * Class to save and restore instances of {@code InvalidationClient} to and from stable storage.
  *
  */
-
-public class TiclStateManager {
+class TiclStateManager {
   /** Name of the file to which Ticl state will be persisted. */
   private static final String TICL_STATE_FILENAME = "android_ticl_service_state.bin";
 
@@ -139,7 +138,6 @@
    * Reads and returns the Android Ticl state from persistent storage. If the state was missing
    * or invalid, returns {@code null}.
    */
-  
   static AndroidTiclState readTiclState(Context context, Logger logger) {
     FileInputStream inputStream = null;
     try {
@@ -225,7 +223,6 @@
   }
 
   /** Deletes {@link #TICL_STATE_FILENAME}. */
-  
   public static void deleteStateFile(Context context) {
     context.deleteFile(TICL_STATE_FILENAME);
   }
diff --git a/src/java/com/google/ipc/invalidation/ticl/android2/WakeLockManager.java b/src/java/com/google/ipc/invalidation/ticl/android2/WakeLockManager.java
index 2748e84..f3c3103 100644
--- a/src/java/com/google/ipc/invalidation/ticl/android2/WakeLockManager.java
+++ b/src/java/com/google/ipc/invalidation/ticl/android2/WakeLockManager.java
@@ -16,9 +16,9 @@
 
 package com.google.ipc.invalidation.ticl.android2;
 
-import com.google.common.base.Preconditions;
 import com.google.ipc.invalidation.external.client.SystemResources.Logger;
 import com.google.ipc.invalidation.external.client.android.service.AndroidLogger;
+import com.google.ipc.invalidation.util.Preconditions;
 
 import android.content.Context;
 import android.os.Build;
@@ -72,9 +72,15 @@
       if (theManager == null) {
         theManager = new WakeLockManager(context.getApplicationContext());
       } else {
-        Preconditions.checkState(theManager.applicationContext == context.getApplicationContext(),
-            "Provided context %s does not match stored context %s",
-            context.getApplicationContext(), theManager.applicationContext);
+        if (theManager.applicationContext != context.getApplicationContext()) {
+          String message = new StringBuilder()
+              .append("Provided context ")
+              .append(context.getApplicationContext())
+              .append("does not match stored context ")
+              .append(theManager.applicationContext)
+              .toString();
+          throw new IllegalStateException(message);
+        }
       }
       return theManager;
     }
diff --git a/src/java/com/google/ipc/invalidation/ticl/android2/channel/AndroidChannelConstants.java b/src/java/com/google/ipc/invalidation/ticl/android2/channel/AndroidChannelConstants.java
index 146a311..bc0f4c2 100644
--- a/src/java/com/google/ipc/invalidation/ticl/android2/channel/AndroidChannelConstants.java
+++ b/src/java/com/google/ipc/invalidation/ticl/android2/channel/AndroidChannelConstants.java
@@ -22,22 +22,18 @@
  * Constants used by the network channel.
  *
  */
-
 public final class AndroidChannelConstants {
 
   /** Constants used in Intents sent to retrieve auth tokens from the application. */
-  
   public static class AuthTokenConstants {
     /**
      * Action requesting that an auth token to send a message be provided. This is the action
      * used in the intent to the application.
      */
-    
     public static final String ACTION_REQUEST_AUTH_TOKEN =
         "com.google.ipc.invalidation.AUTH_TOKEN_REQUEST";
 
     /** Extra in an auth token request response providing the pending intent. */
-    
     public static final String EXTRA_PENDING_INTENT =
         "com.google.ipc.invalidation.AUTH_TOKEN_PENDING_INTENT";
 
@@ -45,12 +41,10 @@
      * Extra in an auth token request message indicating that the token provided as the value
      * was invalid when last used. This may be set on the intent to the application.
      */
-    
     public static final String EXTRA_INVALIDATE_AUTH_TOKEN =
         "com.google.ipc.invalidaton.AUTH_TOKEN_INVALIDATE";
 
     /** Extra in the intent from the application that provides the auth token string. */
-    
     public static final String EXTRA_AUTH_TOKEN = "com.google.ipc.invalidation.AUTH_TOKEN";
 
     /**
@@ -60,7 +54,6 @@
      * then this value must have the form "oauth2:{scope}", where {scope} is a Google API
      * authentication scope such as "https://www.googleapis.com/auth/chromesync".
      */
-    
     public static final String EXTRA_AUTH_TOKEN_TYPE =
         "com.google.ipc.invalidation.AUTH_TOKEN_TYPE";
 
@@ -104,17 +97,14 @@
   }
 
   /** Constants used in C2DM messages. */
-  
-  public static class C2dmConstants {
+   public static class C2dmConstants {
     /**
      * Name of C2DM parameter containing message content.  If not set, data is retrieved via
      * the mailbox frontend
      */
-    
     public static final String CONTENT_PARAM = "content";
 
     /** Name of the C2DM parameter containing an opaque token to be echoed on HTTP requests. */
-    
     public static final String ECHO_PARAM = "echo-token";
   }
 
diff --git a/src/java/com/google/ipc/invalidation/ticl/android2/channel/AndroidChannelPreferences.java b/src/java/com/google/ipc/invalidation/ticl/android2/channel/AndroidChannelPreferences.java
index 42c40c5..1dc4c92 100644
--- a/src/java/com/google/ipc/invalidation/ticl/android2/channel/AndroidChannelPreferences.java
+++ b/src/java/com/google/ipc/invalidation/ticl/android2/channel/AndroidChannelPreferences.java
@@ -25,8 +25,7 @@
 
 
 /** Accessor class for shared preference entries used by the channel. */
-
-public class AndroidChannelPreferences {
+ public class AndroidChannelPreferences {
   /** Name of the preferences in which channel preferences are stored. */
   private static final String PREFERENCES_NAME = "com.google.ipc.invalidation.gcmchannel";
 
diff --git a/src/java/com/google/ipc/invalidation/ticl/android2/channel/AndroidMessageSenderService.java b/src/java/com/google/ipc/invalidation/ticl/android2/channel/AndroidMessageSenderService.java
index ddffb08..3bc7f38 100644
--- a/src/java/com/google/ipc/invalidation/ticl/android2/channel/AndroidMessageSenderService.java
+++ b/src/java/com/google/ipc/invalidation/ticl/android2/channel/AndroidMessageSenderService.java
@@ -16,8 +16,6 @@
 package com.google.ipc.invalidation.ticl.android2.channel;
 
 import com.google.android.gcm.GCMRegistrar;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
 import com.google.ipc.invalidation.external.client.SystemResources.Logger;
 import com.google.ipc.invalidation.external.client.android.service.AndroidLogger;
 import com.google.ipc.invalidation.ticl.android2.ProtocolIntents;
@@ -26,6 +24,7 @@
 import com.google.ipc.invalidation.ticl.proto.AndroidService.AndroidNetworkSendRequest;
 import com.google.ipc.invalidation.ticl.proto.ChannelCommon.NetworkEndpointId;
 import com.google.ipc.invalidation.ticl.proto.CommonProtos;
+import com.google.ipc.invalidation.util.Preconditions;
 import com.google.ipc.invalidation.util.ProtoWrapper.ValidationException;
 
 import android.app.IntentService;
@@ -378,7 +377,7 @@
   
   public static NetworkEndpointId getNetworkEndpointId(Context context, Logger logger) {
     String registrationId = GCMRegistrar.getRegistrationId(context);
-    if (Strings.isNullOrEmpty(registrationId)) {
+    if ((registrationId == null) || registrationId.isEmpty()) {
       // No registration with GCM; we cannot compute a network id. The GCM documentation says the
       // string is never null, but we'll be paranoid.
       logger.warning("No GCM registration id; cannot determine our network endpoint id: %s",
diff --git a/src/java/com/google/ipc/invalidation/ticl/android2/channel/AndroidNetworkChannel.java b/src/java/com/google/ipc/invalidation/ticl/android2/channel/AndroidNetworkChannel.java
index f1f9138..afce69c 100644
--- a/src/java/com/google/ipc/invalidation/ticl/android2/channel/AndroidNetworkChannel.java
+++ b/src/java/com/google/ipc/invalidation/ticl/android2/channel/AndroidNetworkChannel.java
@@ -15,12 +15,12 @@
  */
 package com.google.ipc.invalidation.ticl.android2.channel;
 
-import com.google.common.base.Preconditions;
 import com.google.ipc.invalidation.external.client.SystemResources;
 import com.google.ipc.invalidation.ticl.TestableNetworkChannel;
 import com.google.ipc.invalidation.ticl.android2.ProtocolIntents;
 import com.google.ipc.invalidation.ticl.android2.ResourcesFactory.AndroidResources;
 import com.google.ipc.invalidation.ticl.proto.ChannelCommon.NetworkEndpointId;
+import com.google.ipc.invalidation.util.Preconditions;
 
 import android.content.Context;
 import android.content.Intent;
diff --git a/src/java/com/google/ipc/invalidation/ticl/proto/AndroidService.java b/src/java/com/google/ipc/invalidation/ticl/proto/AndroidService.java
index e2d8030..b85ee9c 100644
--- a/src/java/com/google/ipc/invalidation/ticl/proto/AndroidService.java
+++ b/src/java/com/google/ipc/invalidation/ticl/proto/AndroidService.java
@@ -296,14 +296,9 @@
       return new ClientDowncall(null, version, start, null, null, null);
     }
 
-    public static ClientDowncall createWithSerial(long serial,
-        com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version version) {
-      return new ClientDowncall(serial, version, null, null, null, null);
-    }
-
-    public static ClientDowncall createWithAck(com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version version,
-        com.google.ipc.invalidation.ticl.proto.AndroidService.ClientDowncall.AckDowncall ack) {
-      return new ClientDowncall(null, version, null, null, ack, null);
+    public static ClientDowncall createWithStop(com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version version,
+        com.google.ipc.invalidation.ticl.proto.AndroidService.ClientDowncall.StopDowncall stop) {
+      return new ClientDowncall(null, version, null, stop, null, null);
     }
 
     public static ClientDowncall createWithRegistrations(com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version version,
@@ -311,9 +306,14 @@
       return new ClientDowncall(null, version, null, null, null, registrations);
     }
 
-    public static ClientDowncall createWithStop(com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version version,
-        com.google.ipc.invalidation.ticl.proto.AndroidService.ClientDowncall.StopDowncall stop) {
-      return new ClientDowncall(null, version, null, stop, null, null);
+    public static ClientDowncall createWithAck(com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version version,
+        com.google.ipc.invalidation.ticl.proto.AndroidService.ClientDowncall.AckDowncall ack) {
+      return new ClientDowncall(null, version, null, null, ack, null);
+    }
+
+    public static ClientDowncall createWithSerial(long serial,
+        com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version version) {
+      return new ClientDowncall(serial, version, null, null, null, null);
     }
 
     private final long __hazzerBits;
@@ -358,17 +358,11 @@
       if (hasStart()) {
         existingOneOfField = "start";
       }
-      if (hasSerial()) {
+      if (hasStop()) {
         if (existingOneOfField != null) {
-          oneOfViolation(existingOneOfField, "serial");
+          oneOfViolation(existingOneOfField, "stop");
         }
-        existingOneOfField = "serial";
-      }
-      if (this.ack != null) {
-        if (existingOneOfField != null) {
-          oneOfViolation(existingOneOfField, "ack");
-        }
-        existingOneOfField = "ack";
+        existingOneOfField = "stop";
       }
       if (this.registrations != null) {
         if (existingOneOfField != null) {
@@ -376,11 +370,17 @@
         }
         existingOneOfField = "registrations";
       }
-      if (hasStop()) {
+      if (this.ack != null) {
         if (existingOneOfField != null) {
-          oneOfViolation(existingOneOfField, "stop");
+          oneOfViolation(existingOneOfField, "ack");
         }
-        existingOneOfField = "stop";
+        existingOneOfField = "ack";
+      }
+      if (hasSerial()) {
+        if (existingOneOfField != null) {
+          oneOfViolation(existingOneOfField, "serial");
+        }
+        existingOneOfField = "serial";
       }
       if (existingOneOfField == null) { oneOfViolation(); }
     }
@@ -702,26 +702,26 @@
         return msg;
       }
     }
-    public static InternalDowncall createWithNetworkAddrChange(com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version version,
-        boolean networkAddrChange) {
-      return new InternalDowncall(version, null, null, networkAddrChange, null);
-    }
-
-    public static InternalDowncall createWithCreateClient(com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version version,
-        com.google.ipc.invalidation.ticl.proto.AndroidService.InternalDowncall.CreateClient createClient) {
-      return new InternalDowncall(version, null, null, null, createClient);
-    }
-
     public static InternalDowncall createWithServerMessage(com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version version,
         com.google.ipc.invalidation.ticl.proto.AndroidService.InternalDowncall.ServerMessage serverMessage) {
       return new InternalDowncall(version, serverMessage, null, null, null);
     }
 
+    public static InternalDowncall createWithNetworkAddrChange(com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version version,
+        boolean networkAddrChange) {
+      return new InternalDowncall(version, null, null, networkAddrChange, null);
+    }
+
     public static InternalDowncall createWithNetworkStatus(com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version version,
         com.google.ipc.invalidation.ticl.proto.AndroidService.InternalDowncall.NetworkStatus networkStatus) {
       return new InternalDowncall(version, null, networkStatus, null, null);
     }
 
+    public static InternalDowncall createWithCreateClient(com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version version,
+        com.google.ipc.invalidation.ticl.proto.AndroidService.InternalDowncall.CreateClient createClient) {
+      return new InternalDowncall(version, null, null, null, createClient);
+    }
+
     private final long __hazzerBits;
     private final com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version version;
     private final com.google.ipc.invalidation.ticl.proto.AndroidService.InternalDowncall.ServerMessage serverMessage;
@@ -748,27 +748,27 @@
       this.createClient = createClient;
       this.__hazzerBits = hazzerBits;
       String existingOneOfField = null;
-      if (hasNetworkAddrChange()) {
-        existingOneOfField = "network_addr_change";
-      }
-      if (this.createClient != null) {
-        if (existingOneOfField != null) {
-          oneOfViolation(existingOneOfField, "create_client");
-        }
-        existingOneOfField = "create_client";
-      }
       if (this.serverMessage != null) {
-        if (existingOneOfField != null) {
-          oneOfViolation(existingOneOfField, "server_message");
-        }
         existingOneOfField = "server_message";
       }
+      if (hasNetworkAddrChange()) {
+        if (existingOneOfField != null) {
+          oneOfViolation(existingOneOfField, "network_addr_change");
+        }
+        existingOneOfField = "network_addr_change";
+      }
       if (this.networkStatus != null) {
         if (existingOneOfField != null) {
           oneOfViolation(existingOneOfField, "network_status");
         }
         existingOneOfField = "network_status";
       }
+      if (this.createClient != null) {
+        if (existingOneOfField != null) {
+          oneOfViolation(existingOneOfField, "create_client");
+        }
+        existingOneOfField = "create_client";
+      }
       if (existingOneOfField == null) { oneOfViolation(); }
     }
 
@@ -920,9 +920,9 @@
       }
     }
     public static final class InvalidateUpcall extends ProtoWrapper {
-      public static InvalidateUpcall createWithInvalidateUnknown(Bytes ackHandle,
-          com.google.ipc.invalidation.ticl.proto.ClientProtocol.ObjectIdP invalidateUnknown) {
-        return new InvalidateUpcall(ackHandle, null, invalidateUnknown, null);
+      public static InvalidateUpcall createWithInvalidation(Bytes ackHandle,
+          com.google.ipc.invalidation.ticl.proto.ClientProtocol.InvalidationP invalidation) {
+        return new InvalidateUpcall(ackHandle, invalidation, null, null);
       }
 
       public static InvalidateUpcall createWithInvalidateAll(Bytes ackHandle,
@@ -930,9 +930,9 @@
         return new InvalidateUpcall(ackHandle, null, null, invalidateAll);
       }
 
-      public static InvalidateUpcall createWithInvalidation(Bytes ackHandle,
-          com.google.ipc.invalidation.ticl.proto.ClientProtocol.InvalidationP invalidation) {
-        return new InvalidateUpcall(ackHandle, invalidation, null, null);
+      public static InvalidateUpcall createWithInvalidateUnknown(Bytes ackHandle,
+          com.google.ipc.invalidation.ticl.proto.ClientProtocol.ObjectIdP invalidateUnknown) {
+        return new InvalidateUpcall(ackHandle, null, invalidateUnknown, null);
       }
 
       private final long __hazzerBits;
@@ -958,8 +958,8 @@
         }
         this.__hazzerBits = hazzerBits;
         String existingOneOfField = null;
-        if (this.invalidateUnknown != null) {
-          existingOneOfField = "invalidate_unknown";
+        if (this.invalidation != null) {
+          existingOneOfField = "invalidation";
         }
         if (hasInvalidateAll()) {
           if (existingOneOfField != null) {
@@ -967,11 +967,11 @@
           }
           existingOneOfField = "invalidate_all";
         }
-        if (this.invalidation != null) {
+        if (this.invalidateUnknown != null) {
           if (existingOneOfField != null) {
-            oneOfViolation(existingOneOfField, "invalidation");
+            oneOfViolation(existingOneOfField, "invalidate_unknown");
           }
-          existingOneOfField = "invalidation";
+          existingOneOfField = "invalidate_unknown";
         }
         if (existingOneOfField == null) { oneOfViolation(); }
       }
@@ -1361,9 +1361,9 @@
         return msg;
       }
     }
-    public static ListenerUpcall createWithReissueRegistrations(com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version version,
-        com.google.ipc.invalidation.ticl.proto.AndroidService.ListenerUpcall.ReissueRegistrationsUpcall reissueRegistrations) {
-      return new ListenerUpcall(null, version, null, null, null, null, reissueRegistrations, null);
+    public static ListenerUpcall createWithRegistrationStatus(com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version version,
+        com.google.ipc.invalidation.ticl.proto.AndroidService.ListenerUpcall.RegistrationStatusUpcall registrationStatus) {
+      return new ListenerUpcall(null, version, null, null, registrationStatus, null, null, null);
     }
 
     public static ListenerUpcall createWithReady(com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version version,
@@ -1371,9 +1371,14 @@
       return new ListenerUpcall(null, version, ready, null, null, null, null, null);
     }
 
-    public static ListenerUpcall createWithRegistrationFailure(com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version version,
-        com.google.ipc.invalidation.ticl.proto.AndroidService.ListenerUpcall.RegistrationFailureUpcall registrationFailure) {
-      return new ListenerUpcall(null, version, null, null, null, registrationFailure, null, null);
+    public static ListenerUpcall createWithInvalidate(com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version version,
+        com.google.ipc.invalidation.ticl.proto.AndroidService.ListenerUpcall.InvalidateUpcall invalidate) {
+      return new ListenerUpcall(null, version, null, invalidate, null, null, null, null);
+    }
+
+    public static ListenerUpcall createWithReissueRegistrations(com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version version,
+        com.google.ipc.invalidation.ticl.proto.AndroidService.ListenerUpcall.ReissueRegistrationsUpcall reissueRegistrations) {
+      return new ListenerUpcall(null, version, null, null, null, null, reissueRegistrations, null);
     }
 
     public static ListenerUpcall createWithError(com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version version,
@@ -1381,14 +1386,9 @@
       return new ListenerUpcall(null, version, null, null, null, null, null, error);
     }
 
-    public static ListenerUpcall createWithInvalidate(com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version version,
-        com.google.ipc.invalidation.ticl.proto.AndroidService.ListenerUpcall.InvalidateUpcall invalidate) {
-      return new ListenerUpcall(null, version, null, invalidate, null, null, null, null);
-    }
-
-    public static ListenerUpcall createWithRegistrationStatus(com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version version,
-        com.google.ipc.invalidation.ticl.proto.AndroidService.ListenerUpcall.RegistrationStatusUpcall registrationStatus) {
-      return new ListenerUpcall(null, version, null, null, registrationStatus, null, null, null);
+    public static ListenerUpcall createWithRegistrationFailure(com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version version,
+        com.google.ipc.invalidation.ticl.proto.AndroidService.ListenerUpcall.RegistrationFailureUpcall registrationFailure) {
+      return new ListenerUpcall(null, version, null, null, null, registrationFailure, null, null);
     }
 
     public static ListenerUpcall createWithSerial(long serial,
@@ -1436,8 +1436,8 @@
       this.error = error;
       this.__hazzerBits = hazzerBits;
       String existingOneOfField = null;
-      if (this.reissueRegistrations != null) {
-        existingOneOfField = "reissue_registrations";
+      if (this.registrationStatus != null) {
+        existingOneOfField = "registration_status";
       }
       if (hasReady()) {
         if (existingOneOfField != null) {
@@ -1445,11 +1445,17 @@
         }
         existingOneOfField = "ready";
       }
-      if (this.registrationFailure != null) {
+      if (this.invalidate != null) {
         if (existingOneOfField != null) {
-          oneOfViolation(existingOneOfField, "registration_failure");
+          oneOfViolation(existingOneOfField, "invalidate");
         }
-        existingOneOfField = "registration_failure";
+        existingOneOfField = "invalidate";
+      }
+      if (this.reissueRegistrations != null) {
+        if (existingOneOfField != null) {
+          oneOfViolation(existingOneOfField, "reissue_registrations");
+        }
+        existingOneOfField = "reissue_registrations";
       }
       if (this.error != null) {
         if (existingOneOfField != null) {
@@ -1457,17 +1463,11 @@
         }
         existingOneOfField = "error";
       }
-      if (this.invalidate != null) {
+      if (this.registrationFailure != null) {
         if (existingOneOfField != null) {
-          oneOfViolation(existingOneOfField, "invalidate");
+          oneOfViolation(existingOneOfField, "registration_failure");
         }
-        existingOneOfField = "invalidate";
-      }
-      if (this.registrationStatus != null) {
-        if (existingOneOfField != null) {
-          oneOfViolation(existingOneOfField, "registration_status");
-        }
-        existingOneOfField = "registration_status";
+        existingOneOfField = "registration_failure";
       }
       if (hasSerial()) {
         if (existingOneOfField != null) {
diff --git a/src/java/com/google/ipc/invalidation/ticl/proto/ClientProtocol.java b/src/java/com/google/ipc/invalidation/ticl/proto/ClientProtocol.java
index 95b876b..501e580 100644
--- a/src/java/com/google/ipc/invalidation/ticl/proto/ClientProtocol.java
+++ b/src/java/com/google/ipc/invalidation/ticl/proto/ClientProtocol.java
@@ -535,9 +535,9 @@
     private final com.google.ipc.invalidation.ticl.proto.ClientProtocol.ObjectIdP objectId;
     private final boolean isKnownVersion;
     private final long version;
-    private final boolean isTrickleRestart;
     private final Bytes payload;
     private final long bridgeArrivalTimeMsDeprecated;
+    private final boolean isTrickleRestart;
 
     private InvalidationP(com.google.ipc.invalidation.ticl.proto.ClientProtocol.ObjectIdP objectId,
         Boolean isKnownVersion,
@@ -553,24 +553,24 @@
       required("version", version);
       nonNegative("version", version);
       this.version = version;
-      if (isTrickleRestart != null) {
-        hazzerBits |= 0x1;
-        this.isTrickleRestart = isTrickleRestart;
-      } else {
-        this.isTrickleRestart = true;
-      }
       if (payload != null) {
-        hazzerBits |= 0x2;
+        hazzerBits |= 0x1;
         this.payload = payload;
       } else {
         this.payload = Bytes.EMPTY_BYTES;
       }
       if (bridgeArrivalTimeMsDeprecated != null) {
-        hazzerBits |= 0x4;
+        hazzerBits |= 0x2;
         this.bridgeArrivalTimeMsDeprecated = bridgeArrivalTimeMsDeprecated;
       } else {
         this.bridgeArrivalTimeMsDeprecated = 0;
       }
+      if (isTrickleRestart != null) {
+        hazzerBits |= 0x4;
+        this.isTrickleRestart = isTrickleRestart;
+      } else {
+        this.isTrickleRestart = true;
+      }
       this.__hazzerBits = hazzerBits;
       check(isKnownVersion || (isTrickleRestart == null || isTrickleRestart),
           "is_trickle_restart required if not is_known_version");
@@ -582,14 +582,14 @@
 
     public long getVersion() { return version; }
 
-    public boolean getIsTrickleRestart() { return isTrickleRestart; }
-    public boolean hasIsTrickleRestart() { return (0x1 & __hazzerBits) != 0; }
-
     public Bytes getPayload() { return payload; }
-    public boolean hasPayload() { return (0x2 & __hazzerBits) != 0; }
+    public boolean hasPayload() { return (0x1 & __hazzerBits) != 0; }
 
     public long getBridgeArrivalTimeMsDeprecated() { return bridgeArrivalTimeMsDeprecated; }
-    public boolean hasBridgeArrivalTimeMsDeprecated() { return (0x4 & __hazzerBits) != 0; }
+    public boolean hasBridgeArrivalTimeMsDeprecated() { return (0x2 & __hazzerBits) != 0; }
+
+    public boolean getIsTrickleRestart() { return isTrickleRestart; }
+    public boolean hasIsTrickleRestart() { return (0x4 & __hazzerBits) != 0; }
 
     public Builder toBuilder() {
       Builder builder = new Builder(objectId, isKnownVersion, version);
@@ -613,9 +613,9 @@
           && equals(objectId, other.objectId)
           && isKnownVersion == other.isKnownVersion
           && version == other.version
-          && (!hasIsTrickleRestart() || isTrickleRestart == other.isTrickleRestart)
           && (!hasPayload() || equals(payload, other.payload))
-          && (!hasBridgeArrivalTimeMsDeprecated() || bridgeArrivalTimeMsDeprecated == other.bridgeArrivalTimeMsDeprecated);
+          && (!hasBridgeArrivalTimeMsDeprecated() || bridgeArrivalTimeMsDeprecated == other.bridgeArrivalTimeMsDeprecated)
+          && (!hasIsTrickleRestart() || isTrickleRestart == other.isTrickleRestart);
     }
 
     @Override protected int computeHashCode() {
@@ -623,15 +623,15 @@
       result = result * 31 + objectId.hashCode();
       result = result * 31 + hash(isKnownVersion);
       result = result * 31 + hash(version);
-      if (hasIsTrickleRestart()) {
-        result = result * 31 + hash(isTrickleRestart);
-      }
       if (hasPayload()) {
         result = result * 31 + payload.hashCode();
       }
       if (hasBridgeArrivalTimeMsDeprecated()) {
         result = result * 31 + hash(bridgeArrivalTimeMsDeprecated);
       }
+      if (hasIsTrickleRestart()) {
+        result = result * 31 + hash(isTrickleRestart);
+      }
       return result;
     }
 
@@ -640,15 +640,15 @@
       builder.append(" object_id=").append(objectId);
       builder.append(" is_known_version=").append(isKnownVersion);
       builder.append(" version=").append(version);
-      if (hasIsTrickleRestart()) {
-        builder.append(" is_trickle_restart=").append(isTrickleRestart);
-      }
       if (hasPayload()) {
         builder.append(" payload=").append(payload);
       }
       if (hasBridgeArrivalTimeMsDeprecated()) {
         builder.append(" bridge_arrival_time_ms_deprecated=").append(bridgeArrivalTimeMsDeprecated);
       }
+      if (hasIsTrickleRestart()) {
+        builder.append(" is_trickle_restart=").append(isTrickleRestart);
+      }
       builder.append('>');
     }
 
@@ -681,9 +681,9 @@
       msg.objectId = objectId.toMessageNano();
       msg.isKnownVersion = isKnownVersion;
       msg.version = version;
-      msg.isTrickleRestart = hasIsTrickleRestart() ? isTrickleRestart : null;
       msg.payload = hasPayload() ? payload.getByteArray() : null;
       msg.bridgeArrivalTimeMsDeprecated = hasBridgeArrivalTimeMsDeprecated() ? bridgeArrivalTimeMsDeprecated : null;
+      msg.isTrickleRestart = hasIsTrickleRestart() ? isTrickleRestart : null;
       return msg;
     }
   }
diff --git a/src/java/com/google/ipc/invalidation/ticl/proto/CommonProtos.java b/src/java/com/google/ipc/invalidation/ticl/proto/CommonProtos.java
index 649f984..456aa6e 100644
--- a/src/java/com/google/ipc/invalidation/ticl/proto/CommonProtos.java
+++ b/src/java/com/google/ipc/invalidation/ticl/proto/CommonProtos.java
@@ -15,7 +15,6 @@
  */
 package com.google.ipc.invalidation.ticl.proto;
 
-import com.google.common.base.Preconditions;
 import com.google.ipc.invalidation.ticl.proto.AndroidChannel.AndroidEndpointId;
 import com.google.ipc.invalidation.ticl.proto.ChannelCommon.NetworkEndpointId;
 import com.google.ipc.invalidation.ticl.proto.ChannelCommon.NetworkEndpointId.NetworkAddress;
@@ -29,6 +28,7 @@
 import com.google.ipc.invalidation.ticl.proto.ClientProtocol.StatusP;
 import com.google.ipc.invalidation.ticl.proto.ClientProtocol.Version;
 import com.google.ipc.invalidation.util.Bytes;
+import com.google.ipc.invalidation.util.Preconditions;
 
 
 /** Utilities for creating protocol buffer wrappers. */
diff --git a/src/java/com/google/ipc/invalidation/util/Box.java b/src/java/com/google/ipc/invalidation/util/Box.java
index f57c889..0430344 100644
--- a/src/java/com/google/ipc/invalidation/util/Box.java
+++ b/src/java/com/google/ipc/invalidation/util/Box.java
@@ -16,8 +16,6 @@
 
 package com.google.ipc.invalidation.util;
 
-import com.google.common.base.Supplier;
-
 /**
  * Container for a single arbitrary value. Useful when a nested callback needs
  * to modify a primitive type, which is ordinarily not possible as variables
@@ -26,7 +24,7 @@
  * @param <T> Type of the value being boxed.
  *
  */
-public class Box<T> implements Supplier<T> {
+public class Box<T> {
 
   /** Contents of the box. */
   private T value;
@@ -36,14 +34,6 @@
     this.value = value;
   }
 
-  /**
-   * Returns a supplier for the given value. Note that such a getter's internal value cannot be
-   * changed (by definition).
-   */
-  public static <T> Supplier<T> createSupplier(final T value) {
-    return Box.of(value);
-  }
-
   /** Constructs a Box with {@code null} as the value. */
   public Box() {
     this.value = null;
@@ -58,7 +48,6 @@
     this.value = objectValue;
   }
 
-  @Override
   public T get() {
     return value;
   }
diff --git a/src/java/com/google/ipc/invalidation/util/Bytes.java b/src/java/com/google/ipc/invalidation/util/Bytes.java
index 64aab39..53c0bec 100644
--- a/src/java/com/google/ipc/invalidation/util/Bytes.java
+++ b/src/java/com/google/ipc/invalidation/util/Bytes.java
@@ -15,7 +15,6 @@
  */
 package com.google.ipc.invalidation.util;
 
-import com.google.common.base.Preconditions;
 import com.google.ipc.invalidation.util.LazyString.LazyStringReceiver;
 
 import java.nio.ByteBuffer;
diff --git a/src/java/com/google/ipc/invalidation/util/ExponentialBackoffDelayGenerator.java b/src/java/com/google/ipc/invalidation/util/ExponentialBackoffDelayGenerator.java
index 8283d3d..a2fee7e 100644
--- a/src/java/com/google/ipc/invalidation/util/ExponentialBackoffDelayGenerator.java
+++ b/src/java/com/google/ipc/invalidation/util/ExponentialBackoffDelayGenerator.java
@@ -16,8 +16,6 @@
 
 package com.google.ipc.invalidation.util;
 
-import com.google.common.base.Preconditions;
-
 import java.util.Random;
 
 /**
diff --git a/src/java/com/google/ipc/invalidation/util/NamedRunnable.java b/src/java/com/google/ipc/invalidation/util/NamedRunnable.java
index 6587f94..7a29fe0 100644
--- a/src/java/com/google/ipc/invalidation/util/NamedRunnable.java
+++ b/src/java/com/google/ipc/invalidation/util/NamedRunnable.java
@@ -16,8 +16,6 @@
 
 package com.google.ipc.invalidation.util;
 
-import com.google.common.base.Preconditions;
-
 /**
  * A wrapper around the {@link Runnable} interface that provides extra information (e.g., a name)
  * for logging, monitoring, debugging, etc.
diff --git a/src/java/com/google/ipc/invalidation/util/Preconditions.java b/src/java/com/google/ipc/invalidation/util/Preconditions.java
new file mode 100644
index 0000000..324930e
--- /dev/null
+++ b/src/java/com/google/ipc/invalidation/util/Preconditions.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * 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.google.ipc.invalidation.util;
+
+
+/**
+ * Precondition checkers modeled after {@link com.google.common.base.Preconditions}. Duplicated here
+ * to avoid the dependency on guava in Java client code.
+ */
+public class Preconditions {
+
+  /**
+   * Throws {@link NullPointerException} if the {@code reference} argument is
+   * {@code null}. Otherwise, returns {@code reference}.
+   */
+  public static <T> T checkNotNull(T reference) {
+    if (reference == null) {
+      throw new NullPointerException();
+    }
+    return reference;
+  }
+
+  /**
+   * Throws {@link NullPointerException} if the {@code reference} argument is
+   * {@code null}. Otherwise, returns {@code reference}.
+   */
+  public static <T> T checkNotNull(T reference, Object errorMessage) {
+    if (reference == null) {
+      throw new NullPointerException(String.valueOf(errorMessage));
+    }
+    return reference;
+  }
+
+  /** Throws {@link IllegalStateException} if the given {@code expression} is {@code false}. */
+  public static void checkState(boolean expression) {
+    if (!expression) {
+      throw new IllegalStateException();
+    }
+  }
+
+  /** Throws {@link IllegalStateException} if the given {@code expression} is {@code false}. */
+  public static void checkState(boolean expression, Object errorMessage) {
+    if (!expression) {
+      throw new IllegalStateException(String.valueOf(errorMessage));
+    }
+  }
+
+  /** Throws {@link IllegalArgumentException} if the given {@code expression} is {@code false}. */
+  public static void checkArgument(boolean expression) {
+    if (!expression) {
+      throw new IllegalArgumentException();
+    }
+  }
+
+  /** Throws {@link IllegalArgumentException} if the given {@code expression} is {@code false}. */
+  public static void checkArgument(boolean expression, Object errorMessage) {
+    if (!expression) {
+      throw new IllegalArgumentException(String.valueOf(errorMessage));
+    }
+  }
+
+  // Do not instantiate.
+  private Preconditions() {
+  }
+}
diff --git a/src/java/com/google/ipc/invalidation/util/ProtoWrapper.java b/src/java/com/google/ipc/invalidation/util/ProtoWrapper.java
index 44125c9..680b82a 100644
--- a/src/java/com/google/ipc/invalidation/util/ProtoWrapper.java
+++ b/src/java/com/google/ipc/invalidation/util/ProtoWrapper.java
@@ -15,8 +15,6 @@
  */
 package com.google.ipc.invalidation.util;
 
-import com.google.common.base.Preconditions;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
diff --git a/src/java/com/google/ipc/invalidation/util/Smearer.java b/src/java/com/google/ipc/invalidation/util/Smearer.java
index 5a38e09..f95f365 100644
--- a/src/java/com/google/ipc/invalidation/util/Smearer.java
+++ b/src/java/com/google/ipc/invalidation/util/Smearer.java
@@ -16,8 +16,6 @@
 
 package com.google.ipc.invalidation.util;
 
-import com.google.common.base.Preconditions;
-
 import java.util.Random;
 
 /**
diff --git a/src/java/com/google/ipc/invalidation/util/TextBuilder.java b/src/java/com/google/ipc/invalidation/util/TextBuilder.java
index 5e31efb..6d55d52 100644
--- a/src/java/com/google/ipc/invalidation/util/TextBuilder.java
+++ b/src/java/com/google/ipc/invalidation/util/TextBuilder.java
@@ -16,8 +16,6 @@
 
 package com.google.ipc.invalidation.util;
 
-import com.google.common.base.Preconditions;
-
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 
diff --git a/src/java/com/google/ipc/invalidation/util/TypedUtil.java b/src/java/com/google/ipc/invalidation/util/TypedUtil.java
index ab25c61..bb70a80 100644
--- a/src/java/com/google/ipc/invalidation/util/TypedUtil.java
+++ b/src/java/com/google/ipc/invalidation/util/TypedUtil.java
@@ -16,8 +16,6 @@
 
 package com.google.ipc.invalidation.util;
 
-import com.google.common.base.Objects;
-
 import java.util.Collection;
 import java.util.Map;
 import java.util.Set;
@@ -65,10 +63,13 @@
   }
 
   /**
-   * A wrapper around {@link Objects#equal(Object, Object)} that ensures the objects
-   * have the same type.
+   * Typed equals operator (useful to ensure at compile time that the expected types are being
+   * compared). Returns {@code true} if both arguments are {@code null}, if they reference the same
+   * object, or if {@code o1.equals(o2)}.
    */
   public static <T> boolean equals(T o1, T o2) {
-    return Objects.equal(o1, o2);
+    // Not using java.util.Objects, which is not supported by earlier version of Android, and not
+    // using com.google.common.base.Objects since we're avoiding a Guava dependency for client code.
+    return (o1 == o2) || ((o1 != null) && o1.equals(o2));
   }
 }
diff --git a/src/javaexample/com/google/ipc/invalidation/examples/android2/ExampleListener.java b/src/javaexample/com/google/ipc/invalidation/examples/android2/ExampleListener.java
index 0e6f56c..3510c13 100644
--- a/src/javaexample/com/google/ipc/invalidation/examples/android2/ExampleListener.java
+++ b/src/javaexample/com/google/ipc/invalidation/examples/android2/ExampleListener.java
@@ -15,7 +15,6 @@
  */
 package com.google.ipc.invalidation.examples.android2;
 
-import com.google.common.base.Preconditions;
 import com.google.ipc.invalidation.examples.android2.ExampleListenerProto.ExampleListenerStateProto.ObjectIdProto;
 import com.google.ipc.invalidation.external.client.InvalidationClientConfig;
 import com.google.ipc.invalidation.external.client.InvalidationListener.RegistrationState;
@@ -274,7 +273,9 @@
 
   /** Returns any Google account enabled on the device. */
   private static Account getAccount(AccountManager accountManager) {
-    Preconditions.checkNotNull(accountManager);
+    if (accountManager == null) {
+      throw new NullPointerException();
+    }
     for (Account acct : accountManager.getAccounts()) {
       if (GOOGLE_ACCOUNT_TYPE.equals(acct.type)) {
         return acct;
diff --git a/src/javaexample/com/google/ipc/invalidation/examples/android2/ExampleListenerState.java b/src/javaexample/com/google/ipc/invalidation/examples/android2/ExampleListenerState.java
index 1d4a33e..12ce9be 100644
--- a/src/javaexample/com/google/ipc/invalidation/examples/android2/ExampleListenerState.java
+++ b/src/javaexample/com/google/ipc/invalidation/examples/android2/ExampleListenerState.java
@@ -15,7 +15,6 @@
  */
 package com.google.ipc.invalidation.examples.android2;
 
-import com.google.common.base.Preconditions;
 import com.google.ipc.invalidation.examples.android2.ExampleListenerProto.ExampleListenerStateProto;
 import com.google.ipc.invalidation.examples.android2.ExampleListenerProto.ExampleListenerStateProto.ObjectIdProto;
 import com.google.ipc.invalidation.examples.android2.ExampleListenerProto.ExampleListenerStateProto.ObjectStateProto;
@@ -136,7 +135,10 @@
 
   private ExampleListenerState(Map<ObjectId, ObjectState> trackedObjects,
       byte[] clientId) {
-    this.trackedObjects = Preconditions.checkNotNull(trackedObjects);
+    if (trackedObjects == null) {
+      throw new NullPointerException();
+    }
+    this.trackedObjects = trackedObjects;
     this.clientId = clientId;
   }