Merge change I5126e183 into eclair-mr2

* changes:
  Fix MP3Extractor duration overflows...
diff --git a/api/current.xml b/api/current.xml
index 875d50c..c84f13e 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -158874,6 +158874,17 @@
  visibility="public"
 >
 </method>
+<method name="isOpaque"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isPaddingOffsetRequired"
  return="boolean"
  abstract="false"
diff --git a/core/java/android/pim/vcard/VCardComposer.java b/core/java/android/pim/vcard/VCardComposer.java
index aff3831..b8f4cfd 100644
--- a/core/java/android/pim/vcard/VCardComposer.java
+++ b/core/java/android/pim/vcard/VCardComposer.java
@@ -392,7 +392,9 @@
      * Must call before {{@link #init()}.
      */
     public void addHandler(OneEntryHandler handler) {
-        mHandlerList.add(handler);
+        if (handler != null) {
+            mHandlerList.add(handler);
+        }
     }
 
     /**
@@ -1865,11 +1867,11 @@
         switch (typeAsPrimitive) {
         case Phone.TYPE_HOME:
             parameterList.addAll(
-                    Arrays.asList(Constants.PARAM_TYPE_HOME, Constants.PARAM_TYPE_VOICE));
+                    Arrays.asList(Constants.PARAM_TYPE_HOME));
             break;
         case Phone.TYPE_WORK:
             parameterList.addAll(
-                    Arrays.asList(Constants.PARAM_TYPE_WORK, Constants.PARAM_TYPE_VOICE));
+                    Arrays.asList(Constants.PARAM_TYPE_WORK));
             break;
         case Phone.TYPE_FAX_HOME:
             parameterList.addAll(
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index eb3e523..ef306fe 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4956,8 +4956,6 @@
      * invalidate/draw passes.
      *
      * @return True if this View is guaranteed to be fully opaque, false otherwise.
-     *
-     * @hide Pending API council approval
      */
     @ViewDebug.ExportedProperty
     public boolean isOpaque() {
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index f9dec7f..e405cf2 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -251,8 +251,10 @@
                 break;
 
             case PAGE_FINISHED:
+                String finishedUrl = (String) msg.obj;
+                mWebView.onPageFinished(finishedUrl);
                 if (mWebViewClient != null) {
-                    mWebViewClient.onPageFinished(mWebView, (String) msg.obj);
+                    mWebViewClient.onPageFinished(mWebView, finishedUrl);
                 }
                 break;
                 
@@ -777,11 +779,6 @@
     }
 
     public void onPageFinished(String url) {
-        // Do an unsynchronized quick check to avoid posting if no callback has
-        // been set.
-        if (mWebViewClient == null) {
-            return;
-        }
         // Performance probe
         if (PERF_PROBE) {
             // un-comment this if PERF_PROBE is true
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 98a6c2c..630450d 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2548,6 +2548,41 @@
         }
     }
 
+    /**
+     * Called by CallbackProxy when the page finishes loading.
+     * @param url The URL of the page which has finished loading.
+     */
+    /* package */ void onPageFinished(String url) {
+        if (mPageThatNeedsToSlideTitleBarOffScreen != null) {
+            // If the user is now on a different page, or has scrolled the page
+            // past the point where the title bar is offscreen, ignore the
+            // scroll request.
+            if (mPageThatNeedsToSlideTitleBarOffScreen.equals(url)
+                    && mScrollX == 0 && mScrollY == 0) {
+                pinScrollTo(0, mYDistanceToSlideTitleOffScreen, true,
+                        SLIDE_TITLE_DURATION);
+            }
+            mPageThatNeedsToSlideTitleBarOffScreen = null;
+        }
+    }
+
+    /**
+     * The URL of a page that sent a message to scroll the title bar off screen.
+     *
+     * Many mobile sites tell the page to scroll to (0,1) in order to scroll the
+     * title bar off the screen.  Sometimes, the scroll position is set before
+     * the page finishes loading.  Rather than scrolling while the page is still
+     * loading, keep track of the URL and new scroll position so we can perform
+     * the scroll once the page finishes loading.
+     */
+    private String mPageThatNeedsToSlideTitleBarOffScreen;
+
+    /**
+     * The destination Y scroll position to be used when the page finishes
+     * loading.  See mPageThatNeedsToSlideTitleBarOffScreen.
+     */
+    private int mYDistanceToSlideTitleOffScreen;
+
     // scale from content to view coordinates, and pin
     // return true if pin caused the final x/y different than the request cx/cy,
     // and a future scroll may reach the request cx/cy after our size has
@@ -2582,8 +2617,18 @@
         // page, assume this is an attempt to scroll off the title bar, and
         // animate the title bar off screen slowly enough that the user can see
         // it.
-        if (cx == 0 && cy == 1 && mScrollX == 0 && mScrollY == 0) {
-            pinScrollTo(vx, vy, true, SLIDE_TITLE_DURATION);
+        if (cx == 0 && cy == 1 && mScrollX == 0 && mScrollY == 0
+                && mTitleBar != null) {
+            // FIXME: 100 should be defined somewhere as our max progress.
+            if (getProgress() < 100) {
+                // Wait to scroll the title bar off screen until the page has
+                // finished loading.  Keep track of the URL and the destination
+                // Y position
+                mPageThatNeedsToSlideTitleBarOffScreen = getUrl();
+                mYDistanceToSlideTitleOffScreen = vy;
+            } else {
+                pinScrollTo(vx, vy, true, SLIDE_TITLE_DURATION);
+            }
             // Since we are animating, we have not yet reached the desired
             // scroll position.  Do not return true to request another attempt
             return false;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 3ed995bc..f55ca3f 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3964,8 +3964,7 @@
                     mHighlightPath = new Path();
 
                 if (selStart == selEnd) {
-                    if ((SystemClock.uptimeMillis() - mShowCursor) % (2 * BLINK)
-                        < BLINK) {
+                    if ((SystemClock.uptimeMillis() - mShowCursor) % (2 * BLINK) < BLINK) {
                         if (mHighlightPathBogus) {
                             mHighlightPath.reset();
                             mLayout.getCursorPath(selStart, mHighlightPath, mText);
@@ -5344,21 +5343,24 @@
              * will happen at measure).
              */
             makeNewLayout(want, hintWant, UNKNOWN_BORING, UNKNOWN_BORING,
-                          mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight(), false);
+                          mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight(),
+                          false);
 
-            // In a fixed-height view, so use our new text layout.
-            if (mLayoutParams.height != LayoutParams.WRAP_CONTENT &&
-                mLayoutParams.height != LayoutParams.FILL_PARENT) {
-                invalidate();
-                return;
-            }
-
-            // Dynamic height, but height has stayed the same,
-            // so use our new text layout.
-            if (mLayout.getHeight() == oldht &&
-                (mHintLayout == null || mHintLayout.getHeight() == oldht)) {
-                invalidate();
-                return;
+            if (mEllipsize != TextUtils.TruncateAt.MARQUEE) {
+                // In a fixed-height view, so use our new text layout.
+                if (mLayoutParams.height != LayoutParams.WRAP_CONTENT &&
+                    mLayoutParams.height != LayoutParams.FILL_PARENT) {
+                    invalidate();
+                    return;
+                }
+    
+                // Dynamic height, but height has stayed the same,
+                // so use our new text layout.
+                if (mLayout.getHeight() == oldht &&
+                    (mHintLayout == null || mHintLayout.getHeight() == oldht)) {
+                    invalidate();
+                    return;
+                }
             }
 
             // We lose: the height has changed and we have a dynamic height.
diff --git a/graphics/java/android/renderscript/RSSurfaceView.java b/graphics/java/android/renderscript/RSSurfaceView.java
index 53466cc..1bc03ac 100644
--- a/graphics/java/android/renderscript/RSSurfaceView.java
+++ b/graphics/java/android/renderscript/RSSurfaceView.java
@@ -80,6 +80,9 @@
      */
     public void surfaceDestroyed(SurfaceHolder holder) {
         // Surface will be destroyed when we return
+        if (mRS != null) {
+            mRS.contextSetSurface(null);
+        }
         //Log.v(RenderScript.LOG_TAG, "surfaceDestroyed");
     }
 
@@ -88,6 +91,9 @@
      * not normally called or subclassed by clients of RSSurfaceView.
      */
     public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+        if (mRS != null) {
+            mRS.contextSetSurface(holder.getSurface());
+        }
         //Log.v(RenderScript.LOG_TAG, "surfaceChanged");
     }
 
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 1f2ea38..f1e5af1 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -64,6 +64,7 @@
     native void nDeviceSetConfig(int dev, int param, int value);
     native int  nContextCreate(int dev, Surface sur, int ver, boolean useDepth);
     native void nContextDestroy(int con);
+    native void nContextSetSurface(Surface sur);
 
     native void nContextBindRootScript(int script);
     native void nContextBindSampler(int sampler, int slot);
@@ -276,6 +277,11 @@
         mMessageThread.start();
     }
 
+    public void contextSetSurface(Surface sur) {
+        mSurface = sur;
+        nContextSetSurface(mSurface);
+    }
+
     public void destroy() {
         nContextDeinitToClient();
         mMessageThread.mRun = false;
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index fa3baa20..f3dda41 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -171,6 +171,24 @@
 }
 
 static void
+nContextSetSurface(JNIEnv *_env, jobject _this, jobject wnd)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nContextSetSurface, con(%p), surface(%p)", con, (Surface *)wnd);
+
+    Surface * window = NULL;
+    if (wnd == NULL) {
+
+    } else {
+        jclass surface_class = _env->FindClass("android/view/Surface");
+        jfieldID surfaceFieldID = _env->GetFieldID(surface_class, "mSurface", "I");
+        window = (Surface*)_env->GetIntField(wnd, surfaceFieldID);
+    }
+
+    rsContextSetSurface(con, window);
+}
+
+static void
 nContextDestroy(JNIEnv *_env, jobject _this, jint con)
 {
     LOG_API("nContextDestroy, con(%p)", (RsContext)con);
@@ -1328,6 +1346,7 @@
 {"nDeviceDestroy",                 "(I)V",                                 (void*)nDeviceDestroy },
 {"nDeviceSetConfig",               "(III)V",                               (void*)nDeviceSetConfig },
 {"nContextCreate",                 "(ILandroid/view/Surface;IZ)I",         (void*)nContextCreate },
+{"nContextSetSurface",             "(Landroid/view/Surface;)V",            (void*)nContextSetSurface },
 {"nContextDestroy",                "(I)V",                                 (void*)nContextDestroy },
 {"nContextPause",                  "()V",                                  (void*)nContextPause },
 {"nContextResume",                 "()V",                                  (void*)nContextResume },
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index c371a23..86c3df6 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -14,10 +14,13 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "IPCThreadState"
+
 #include <binder/IPCThreadState.h>
 
 #include <binder/Binder.h>
 #include <binder/BpBinder.h>
+#include <cutils/sched_policy.h>
 #include <utils/Debug.h>
 #include <utils/Log.h>
 #include <utils/TextOutput.h>
@@ -418,7 +421,32 @@
                 alog << "Processing top-level Command: "
                     << getReturnString(cmd) << endl;
             }
+
+            bool isTainted = false;
+
+            {
+                SchedPolicy policy;
+                get_sched_policy(getpid(), &policy);
+
+                if (policy == SP_BACKGROUND) {
+                    isTainted = true;
+                }
+            }
+
             result = executeCommand(cmd);
+
+            // Make sure that after executing the commands that we put the thread back into the
+            // default cgroup.
+            {
+                int pid = getpid();
+                SchedPolicy policy;
+                get_sched_policy(pid, &policy);
+
+                if (!isTainted && policy == SP_BACKGROUND) {
+                    LOGW("*** THREAD %p (PID %p) was left in SP_BACKGROUND with a priority of %d\n",
+                        (void*)pthread_self(), pid, getpriority(PRIO_PROCESS, pid));
+                }
+            }
         }
         
         // Let this thread exit the thread pool if it is no longer
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index a393e2f..865e435 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -36,6 +36,10 @@
 ContextResume {
 	}
 
+ContextSetSurface {
+	param void *sur
+	}
+
 AssignName {
 	param void *obj
 	param const char *name
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index 2cbfe17..38cec64 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -54,6 +54,17 @@
 {
     free(mPtr);
     mPtr = NULL;
+
+    if (mBufferID) {
+        // Causes a SW crash....
+        //LOGV(" mBufferID %i", mBufferID);
+        //glDeleteBuffers(1, &mBufferID);
+        //mBufferID = 0;
+    }
+    if (mTextureID) {
+        glDeleteTextures(1, &mTextureID);
+        mTextureID = 0;
+    }
 }
 
 void Allocation::setCpuWritable(bool)
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 961ec0b..3e4cc36 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -85,17 +85,6 @@
     }
     //eglChooseConfig(mEGL.mDisplay, configAttribs, &mEGL.mConfig, 1, &mEGL.mNumConfigs);
 
-    if (mWndSurface) {
-        mEGL.mSurface = eglCreateWindowSurface(mEGL.mDisplay, mEGL.mConfig, mWndSurface, NULL);
-    } else {
-        mEGL.mSurface = eglCreateWindowSurface(mEGL.mDisplay, mEGL.mConfig,
-             android_createDisplaySurface(),
-             NULL);
-    }
-    checkEglError("eglCreateWindowSurface");
-    if (mEGL.mSurface == EGL_NO_SURFACE) {
-        LOGE("eglCreateWindowSurface returned EGL_NO_SURFACE");
-    }
 
     mEGL.mContext = eglCreateContext(mEGL.mDisplay, mEGL.mConfig, EGL_NO_CONTEXT, NULL);
     checkEglError("eglCreateContext");
@@ -104,10 +93,10 @@
     }
     gGLContextCount++;
 
-    EGLBoolean ret = eglMakeCurrent(mEGL.mDisplay, mEGL.mSurface, mEGL.mSurface, mEGL.mContext);
-    checkEglError("eglCreateContext", ret);
-    if (mEGL.mContext == EGL_NO_CONTEXT) {
-        LOGE("eglCreateContext returned EGL_NO_CONTEXT");
+    if (mWndSurface) {
+        setSurface(mWndSurface);
+    } else {
+        setSurface((Surface *)android_createDisplaySurface());
     }
 
     eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_WIDTH, &mEGL.mWidth);
@@ -134,12 +123,7 @@
 
 void Context::deinitEGL()
 {
-    EGLBoolean ret = eglMakeCurrent(mEGL.mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-    checkEglError("eglCreateContext", ret);
-    if (mEGL.mContext == EGL_NO_CONTEXT) {
-        LOGE("eglCreateContext returned EGL_NO_CONTEXT");
-    }
-
+    setSurface(NULL);
     eglDestroyContext(mEGL.mDisplay, mEGL.mContext);
     checkEglError("eglDestroyContext");
 
@@ -311,6 +295,7 @@
      while (!rsc->mExit) {
          mDraw |= rsc->mIO.playCoreCommands(rsc, !mDraw);
          mDraw &= (rsc->mRootScript.get() != NULL);
+         mDraw &= (rsc->mWndSurface != NULL);
 
          if (mDraw) {
              mDraw = rsc->runRootScript() && !rsc->mPaused;
@@ -342,6 +327,9 @@
      rsc->mStateFragmentStore.deinit(rsc);
      ObjectBase::zeroAllUserRef(rsc);
 
+     rsc->mObjDestroy.mNeedToEmpty = true;
+     rsc->objDestroyOOBRun();
+
      glClearColor(0,0,0,0);
      glClear(GL_COLOR_BUFFER_BIT);
      eglSwapBuffers(rsc->mEGL.mDisplay, rsc->mEGL.mSurface);
@@ -350,8 +338,6 @@
      rsc->deinitEGL();
      pthread_mutex_unlock(&gInitMutex);
 
-     rsc->mObjDestroy.mNeedToEmpty = true;
-     rsc->objDestroyOOBRun();
      LOGV("RS Thread exited");
      return NULL;
 }
@@ -440,6 +426,32 @@
     objDestroyOOBDestroy();
 }
 
+void Context::setSurface(Surface *sur)
+{
+    EGLBoolean ret;
+    if (mEGL.mSurface != NULL) {
+        ret = eglMakeCurrent(mEGL.mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+        checkEglError("eglMakeCurrent", ret);
+
+        ret = eglDestroySurface(mEGL.mDisplay, mEGL.mSurface);
+        checkEglError("eglDestroySurface", ret);
+
+        mEGL.mSurface = NULL;
+    }
+
+    mWndSurface = sur;
+    if (mWndSurface != NULL) {
+        mEGL.mSurface = eglCreateWindowSurface(mEGL.mDisplay, mEGL.mConfig, mWndSurface, NULL);
+        checkEglError("eglCreateWindowSurface");
+        if (mEGL.mSurface == EGL_NO_SURFACE) {
+            LOGE("eglCreateWindowSurface returned EGL_NO_SURFACE");
+        }
+
+        ret = eglMakeCurrent(mEGL.mDisplay, mEGL.mSurface, mEGL.mSurface, mEGL.mContext);
+        checkEglError("eglMakeCurrent", ret);
+    }
+}
+
 void Context::pause()
 {
     mPaused = true;
@@ -755,6 +767,11 @@
     rsc->resume();
 }
 
+void rsi_ContextSetSurface(Context *rsc, void *sur)
+{
+    rsc->setSurface((Surface *)sur);
+}
+
 }
 }
 
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index c80fd5a..bffc55b 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -94,6 +94,7 @@
 
     void pause();
     void resume();
+    void setSurface(Surface *sur);
 
     void assignName(ObjectBase *obj, const char *name, uint32_t len);
     void removeName(ObjectBase *obj);
diff --git a/libs/rs/rsObjectBase.cpp b/libs/rs/rsObjectBase.cpp
index 1b442ba..b7d67cc 100644
--- a/libs/rs/rsObjectBase.cpp
+++ b/libs/rs/rsObjectBase.cpp
@@ -113,12 +113,7 @@
 
 void ObjectBase::setName(const char *name)
 {
-    delete mName;
-    mName = NULL;
-    if (name) {
-        mName = new char[strlen(name) +1];
-        strcpy(mName, name);
-    }
+    setName(name, strlen(name));
 }
 
 void ObjectBase::setName(const char *name, uint32_t len)
diff --git a/libs/rs/rsScript.h b/libs/rs/rsScript.h
index 8aa4542..bc40854 100644
--- a/libs/rs/rsScript.h
+++ b/libs/rs/rsScript.h
@@ -54,7 +54,7 @@
         ObjectBaseRef<ProgramRaster> mRaster;
         ObjectBaseRef<ProgramFragmentStore> mFragmentStore;
         InvokeFunc_t mInvokables[MAX_SCRIPT_BANKS];
-        const char * mScriptText;
+        char * mScriptText;
         uint32_t mScriptTextLength;
     };
     Enviroment_t mEnviroment;
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index 9da7766..073d98b 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -46,6 +46,8 @@
     if (mAccScript) {
         accDeleteScript(mAccScript);
     }
+    free(mEnviroment.mScriptText);
+    mEnviroment.mScriptText = NULL;
 }
 
 void ScriptC::setupScript()
@@ -404,7 +406,11 @@
 void rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len)
 {
     ScriptCState *ss = &rsc->mScriptC;
-    ss->mScript->mEnviroment.mScriptText = text;
+
+    char *t = (char *)malloc(len + 1);
+    memcpy(t, text, len);
+    t[len] = 0;
+    ss->mScript->mEnviroment.mScriptText = t;
     ss->mScript->mEnviroment.mScriptTextLength = len;
 }
 
diff --git a/libs/rs/rsScriptC.h b/libs/rs/rsScriptC.h
index ae124b4..69afc18 100644
--- a/libs/rs/rsScriptC.h
+++ b/libs/rs/rsScriptC.h
@@ -41,10 +41,6 @@
     virtual ~ScriptC();
 
     struct Program_t {
-        const char * mScriptText;
-        uint32_t mScriptTextLength;
-
-
         int mVersionMajor;
         int mVersionMinor;
 
diff --git a/media/libstagefright/omx/QComHardwareRenderer.cpp b/media/libstagefright/omx/QComHardwareRenderer.cpp
index 8e78c77..837b6a4 100644
--- a/media/libstagefright/omx/QComHardwareRenderer.cpp
+++ b/media/libstagefright/omx/QComHardwareRenderer.cpp
@@ -127,7 +127,8 @@
 
     master->setDevice("/dev/pmem");
 
-    mMemoryHeap = new MemoryHeapPmem(master, 0);
+    uint32_t heap_flags = master->getFlags() & MemoryHeapBase::NO_CACHING;
+    mMemoryHeap = new MemoryHeapPmem(master, heap_flags);
     mMemoryHeap->slap();
 
     ISurface::BufferHeap bufferHeap(
diff --git a/opengl/libagl/matrix.cpp b/opengl/libagl/matrix.cpp
index 21ef50e..3c50977 100644
--- a/opengl/libagl/matrix.cpp
+++ b/opengl/libagl/matrix.cpp
@@ -741,20 +741,19 @@
 
 void point4__mvui(transform_t const* mx, vec4_t* lhs, vec4_t const* rhs) {
     // this used for transforming light positions back to object space.
-    // Lights have 3 components positions, so w is always 1.
-    // however, it is used as a switch for directional lights, so we need
+    // w is used as a switch for directional lights, so we need
     // to preserve it.
     const GLfixed* const m = mx->matrix.m;
     const GLfixed rx = rhs->x;
     const GLfixed ry = rhs->y;
     const GLfixed rz = rhs->z;
-    lhs->x = mla3a(rx, m[ 0], ry, m[ 4], rz, m[ 8], m[12]); 
-    lhs->y = mla3a(rx, m[ 1], ry, m[ 5], rz, m[ 9], m[13]);
-    lhs->z = mla3a(rx, m[ 2], ry, m[ 6], rz, m[10], m[14]);
-    lhs->w = rhs->w;
+    const GLfixed rw = rhs->w;
+    lhs->x = mla4(rx, m[ 0], ry, m[ 4], rz, m[ 8], rw, m[12]);
+    lhs->y = mla4(rx, m[ 1], ry, m[ 5], rz, m[ 9], rw, m[13]);
+    lhs->z = mla4(rx, m[ 2], ry, m[ 6], rz, m[10], rw, m[14]);
+    lhs->w = rw;
 }
 
-
 void point2__nop(transform_t const*, vec4_t* lhs, vec4_t const* rhs) {
     lhs->z = 0;
     lhs->w = 0x10000;
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index f75f7195..93b469f 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -1760,7 +1760,8 @@
         try {
             if (mScreenBrightnessOverride >= 0) {
                 return mScreenBrightnessOverride;
-            } else if (mLightSensorBrightness >= 0 && mUseSoftwareAutoBrightness) {
+            } else if (mLightSensorBrightness >= 0 && mUseSoftwareAutoBrightness
+                    && mAutoBrightessEnabled) {
                 return mLightSensorBrightness;
             }
             final int brightness = Settings.System.getInt(mContext.getContentResolver(),
diff --git a/services/java/com/android/server/status/StatusBarService.java b/services/java/com/android/server/status/StatusBarService.java
index bd7b471..8d73904 100644
--- a/services/java/com/android/server/status/StatusBarService.java
+++ b/services/java/com/android/server/status/StatusBarService.java
@@ -952,6 +952,7 @@
         
         updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
         mExpandedParams.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+        mExpandedParams.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
         mExpandedDialog.getWindow().setAttributes(mExpandedParams);
         mExpandedView.requestFocus(View.FOCUS_FORWARD);
         mTrackingView.setVisibility(View.VISIBLE);
@@ -1030,6 +1031,7 @@
         mExpandedVisible = false;
         panelSlightlyVisible(false);
         mExpandedParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+        mExpandedParams.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
         mExpandedDialog.getWindow().setAttributes(mExpandedParams);
         mTrackingView.setVisibility(View.GONE);
 
@@ -1522,7 +1524,6 @@
         lp.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
-                | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
                 | WindowManager.LayoutParams.FLAG_DITHER
                 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
         lp.format = pixelFormat;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/ContentValuesBuilder.java b/tests/AndroidTests/src/com/android/unit_tests/vcard/ContentValuesBuilder.java
new file mode 100644
index 0000000..e99e4cb
--- /dev/null
+++ b/tests/AndroidTests/src/com/android/unit_tests/vcard/ContentValuesBuilder.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.unit_tests.vcard;
+
+import android.content.ContentValues;
+
+/**
+ * ContentValues-like class which enables users to chain put() methods and restricts
+ * the other methods.
+ */
+/* package */ class ContentValuesBuilder {
+    private final ContentValues mContentValues;
+
+    public ContentValuesBuilder(final ContentValues contentValues) {
+        mContentValues = contentValues;
+    }
+
+    public ContentValuesBuilder put(String key, String value) {
+        mContentValues.put(key, value);
+        return this;
+    }
+
+    public ContentValuesBuilder put(String key, Byte value) {
+        mContentValues.put(key, value);
+        return this;
+    }
+
+    public ContentValuesBuilder put(String key, Short value) {
+        mContentValues.put(key, value);
+        return this;
+    }
+
+    public ContentValuesBuilder put(String key, Integer value) {
+        mContentValues.put(key, value);
+        return this;
+    }
+
+    public ContentValuesBuilder put(String key, Long value) {
+        mContentValues.put(key, value);
+        return this;
+    }
+
+    public ContentValuesBuilder put(String key, Float value) {
+        mContentValues.put(key, value);
+        return this;
+    }
+
+    public ContentValuesBuilder put(String key, Double value) {
+        mContentValues.put(key, value);
+        return this;
+    }
+
+    public ContentValuesBuilder put(String key, Boolean value) {
+        mContentValues.put(key, value);
+        return this;
+    }
+
+    public ContentValuesBuilder put(String key, byte[] value) {
+        mContentValues.put(key, value);
+        return this;
+    }
+
+    public ContentValuesBuilder putNull(String key) {
+        mContentValues.putNull(key);
+        return this;
+    }
+}
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/PropertyNodesVerifier.java b/tests/AndroidTests/src/com/android/unit_tests/vcard/PropertyNodesVerifier.java
index a0d6d16..933ff2a 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/PropertyNodesVerifier.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/vcard/PropertyNodesVerifier.java
@@ -17,14 +17,73 @@
 package com.android.unit_tests.vcard;
 
 import android.content.ContentValues;
+import android.pim.vcard.VCardConfig;
+import android.pim.vcard.VCardParser;
+import android.pim.vcard.VCardParser_V21;
+import android.pim.vcard.VCardParser_V30;
+import android.pim.vcard.exception.VCardException;
+import android.test.AndroidTestCase;
+import android.util.Log;
 
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 
-import junit.framework.TestCase;
+public class PropertyNodesVerifier extends VNodeBuilder {
+    private final List<PropertyNodesVerifierElem> mPropertyNodesVerifierElemList;
+    private final AndroidTestCase mAndroidTestCase;
+    private int mIndex;
+
+    public PropertyNodesVerifier(AndroidTestCase testCase) {
+        mPropertyNodesVerifierElemList = new ArrayList<PropertyNodesVerifierElem>();
+        mAndroidTestCase = testCase;
+    }
+
+    public PropertyNodesVerifierElem addPropertyNodesVerifierElem() {
+        PropertyNodesVerifierElem elem = new PropertyNodesVerifierElem(mAndroidTestCase);
+        mPropertyNodesVerifierElemList.add(elem);
+        return elem;
+    }
+
+    public void verify(int resId, int vCardType)
+            throws IOException, VCardException {
+        verify(mAndroidTestCase.getContext().getResources().openRawResource(resId), vCardType);
+    }
+
+    public void verify(InputStream is, int vCardType) throws IOException, VCardException {
+        final VCardParser vCardParser;
+        if (VCardConfig.isV30(vCardType)) {
+            vCardParser = new VCardParser_V30(true);  // use StrictParsing
+        } else {
+            vCardParser = new VCardParser_V21();
+        }
+        try {
+            vCardParser.parse(is, this);
+        } finally {
+            if (is != null) {
+                try {
+                    is.close();
+                } catch (IOException e) {
+                }
+            }
+        }
+    }
+
+    @Override
+    public void endRecord() {
+        super.endRecord();
+        mAndroidTestCase.assertTrue(mIndex < mPropertyNodesVerifierElemList.size());
+        mAndroidTestCase.assertTrue(mIndex < vNodeList.size());
+        mPropertyNodesVerifierElemList.get(mIndex).verify(vNodeList.get(mIndex));
+        mIndex++;
+    }
+}
 
 /**
  * Utility class which verifies input VNode.
@@ -34,7 +93,7 @@
  * If the node does not exist in the "ordered list", the class refers to
  * "unorderd expected property set" and checks the node is expected somewhere.
  */
-public class PropertyNodesVerifier {
+class PropertyNodesVerifierElem {
     public static class TypeSet extends HashSet<String> {
         public TypeSet(String ... array) {
             super(Arrays.asList(array));
@@ -53,7 +112,7 @@
     private final ArrayList<PropertyNode> mUnorderedNodeList;
     private final TestCase mTestCase;
 
-    public PropertyNodesVerifier(TestCase testCase) {
+    public PropertyNodesVerifierElem(TestCase testCase) {
         mOrderedNodeMap = new HashMap<String, List<PropertyNode>>();
         mUnorderedNodeList = new ArrayList<PropertyNode>();
         mTestCase = testCase;
@@ -61,16 +120,16 @@
 
     // WithOrder
 
-    public PropertyNodesVerifier addNodeWithOrder(String propName, String propValue) {
+    public PropertyNodesVerifierElem addNodeWithOrder(String propName, String propValue) {
         return addNodeWithOrder(propName, propValue, null, null, null, null, null);
     }
 
-    public PropertyNodesVerifier addNodeWithOrder(String propName, String propValue,
+    public PropertyNodesVerifierElem addNodeWithOrder(String propName, String propValue,
             List<String> propValueList) {
         return addNodeWithOrder(propName, propValue, propValueList, null, null, null, null);
     }
 
-    public PropertyNodesVerifier addNodeWithOrder(String propName, List<String> propValueList) {
+    public PropertyNodesVerifierElem addNodeWithOrder(String propName, List<String> propValueList) {
         StringBuffer buffer = new StringBuffer();
         boolean first = true;
         for (String propValueElem : propValueList) {
@@ -85,18 +144,18 @@
                 null, null, null, null);
     }
 
-    public PropertyNodesVerifier addNodeWithOrder(String propName, String propValue,
+    public PropertyNodesVerifierElem addNodeWithOrder(String propName, String propValue,
             TypeSet paramMap_TYPE) {
         return addNodeWithOrder(propName, propValue, null, null, null, paramMap_TYPE, null);
     }
 
-    public PropertyNodesVerifier addNodeWithOrder(String propName, String propValue,
+    public PropertyNodesVerifierElem addNodeWithOrder(String propName, String propValue,
             List<String> propValueList, TypeSet paramMap_TYPE) {
         return addNodeWithOrder(propName, propValue, propValueList, null, null,
                 paramMap_TYPE, null);
     }
 
-    public PropertyNodesVerifier addNodeWithOrder(String propName, String propValue,
+    public PropertyNodesVerifierElem addNodeWithOrder(String propName, String propValue,
             List<String> propValueList, byte[] propValue_bytes,
             ContentValues paramMap, TypeSet paramMap_TYPE, GroupSet propGroupSet) {
         PropertyNode propertyNode = new PropertyNode(propName,
@@ -113,16 +172,16 @@
 
     // WithoutOrder
 
-    public PropertyNodesVerifier addNodeWithoutOrder(String propName, String propValue) {
+    public PropertyNodesVerifierElem addNodeWithoutOrder(String propName, String propValue) {
         return addNodeWithoutOrder(propName, propValue, null, null, null, null, null);
     }
 
-    public PropertyNodesVerifier addNodeWithoutOrder(String propName, String propValue,
+    public PropertyNodesVerifierElem addNodeWithoutOrder(String propName, String propValue,
             List<String> propValueList) {
         return addNodeWithoutOrder(propName, propValue, propValueList, null, null, null, null);
     }
 
-    public PropertyNodesVerifier addNodeWithoutOrder(String propName, List<String> propValueList) {
+    public PropertyNodesVerifierElem addNodeWithoutOrder(String propName, List<String> propValueList) {
         StringBuffer buffer = new StringBuffer();
         boolean first = true;
         for (String propValueElem : propValueList) {
@@ -137,18 +196,18 @@
                 null, null, null, null);
     }
 
-    public PropertyNodesVerifier addNodeWithoutOrder(String propName, String propValue,
+    public PropertyNodesVerifierElem addNodeWithoutOrder(String propName, String propValue,
             TypeSet paramMap_TYPE) {
         return addNodeWithoutOrder(propName, propValue, null, null, null, paramMap_TYPE, null);
     }
 
-    public PropertyNodesVerifier addNodeWithoutOrder(String propName, String propValue,
+    public PropertyNodesVerifierElem addNodeWithoutOrder(String propName, String propValue,
             List<String> propValueList, TypeSet paramMap_TYPE) {
         return addNodeWithoutOrder(propName, propValue, propValueList, null, null,
                 paramMap_TYPE, null);
     }
 
-    public PropertyNodesVerifier addNodeWithoutOrder(String propName, String propValue,
+    public PropertyNodesVerifierElem addNodeWithoutOrder(String propName, String propValue,
             List<String> propValueList, byte[] propValue_bytes,
             ContentValues paramMap, TypeSet paramMap_TYPE, GroupSet propGroupSet) {
         mUnorderedNodeList.add(new PropertyNode(propName, propValue,
@@ -185,8 +244,7 @@
         if (size > 0) {
             for (int i = 0; i < size; i++) {
                 PropertyNode expectedNode = expectedNodeList.get(i);
-                List<PropertyNode> expectedButDifferentValueList =
-                    new ArrayList<PropertyNode>();
+                List<PropertyNode> expectedButDifferentValueList = new ArrayList<PropertyNode>();
                 if (expectedNode.propName.equals(propName)) {
                     if (expectedNode.equals(actualNode)) {
                         expectedNodeList.remove(i);
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardExporterTests.java b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardExporterTests.java
index e6a7a51..727d33b 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardExporterTests.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardExporterTests.java
@@ -17,7 +17,6 @@
 package com.android.unit_tests.vcard;
 
 import android.content.ContentValues;
-import android.pim.vcard.VCardComposer;
 import android.pim.vcard.VCardConfig;
 import android.provider.ContactsContract.CommonDataKinds.Email;
 import android.provider.ContactsContract.CommonDataKinds.Event;
@@ -31,7 +30,7 @@
 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
 import android.provider.ContactsContract.CommonDataKinds.Website;
 
-import com.android.unit_tests.vcard.PropertyNodesVerifier.TypeSet;
+import com.android.unit_tests.vcard.PropertyNodesVerifierElem.TypeSet;
 
 import java.util.Arrays;
 
@@ -44,72 +43,54 @@
     private static final byte[] sPhotoByteArray =
         VCardImporterTests.sPhotoByteArrayForComplicatedCase;
 
-    private void verifyOneComposition(ExportTestResolver resolver,
-            VCardVerificationHandler handler, int version) {
-        final boolean isV30 = (version == V30);
-
-        final int vcardType = (isV30 ? VCardConfig.VCARD_TYPE_V30_GENERIC_UTF8
-                : VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
-        VCardComposer composer = new VCardComposer(new CustomMockContext(resolver), vcardType);
-        composer.addHandler(handler);
-        if (!composer.init(VCardComposer.CONTACTS_TEST_CONTENT_URI, null, null, null)) {
-            fail("init() failed. Reason: " + composer.getErrorReason());
-        }
-        assertFalse(composer.isAfterLast());
-        assertTrue(composer.createOneEntry());
-        assertTrue(composer.isAfterLast());
-        composer.terminate();
-    }
-
     public void testSimpleV21() {
         ExportTestResolver resolver = new ExportTestResolver();
-        ContentValues contentValues = resolver.buildData(StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredName.FAMILY_NAME, "Ando");
-        contentValues.put(StructuredName.GIVEN_NAME, "Roid");
+        resolver.buildContactEntry().buildData(StructuredName.CONTENT_ITEM_TYPE)
+                .put(StructuredName.FAMILY_NAME, "Ando")
+                .put(StructuredName.GIVEN_NAME, "Roid");
 
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, V21);
-        handler.addNewVerifier()
-            .addNodeWithoutOrder("FN", "Roid Ando")
-            .addNodeWithoutOrder("N", "Ando;Roid;;;", Arrays.asList("Ando", "Roid", "", "", ""));
-
-        verifyOneComposition(resolver, handler, V21);
+        VCardVerifier verifier = new VCardVerifier(resolver, V21);
+        verifier.addPropertyNodesVerifierElem()
+                .addNodeWithoutOrder("FN", "Roid Ando")
+                .addNodeWithoutOrder("N", "Ando;Roid;;;", Arrays.asList("Ando", "Roid", "", "", ""));
+        verifier.verify();
     }
 
     private void testStructuredNameBasic(int version) {
-        final boolean isV30 = (version == V30);
+        final boolean isV30 = VCardConfig.isV30(version);
         ExportTestResolver resolver = new ExportTestResolver();
 
-        ContentValues contentValues = resolver.buildData(StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredName.FAMILY_NAME, "AppropriateFamilyName");
-        contentValues.put(StructuredName.GIVEN_NAME, "AppropriateGivenName");
-        contentValues.put(StructuredName.MIDDLE_NAME, "AppropriateMiddleName");
-        contentValues.put(StructuredName.PREFIX, "AppropriatePrefix");
-        contentValues.put(StructuredName.SUFFIX, "AppropriateSuffix");
-        contentValues.put(StructuredName.PHONETIC_FAMILY_NAME, "AppropriatePhoneticFamily");
-        contentValues.put(StructuredName.PHONETIC_GIVEN_NAME, "AppropriatePhoneticGiven");
-        contentValues.put(StructuredName.PHONETIC_MIDDLE_NAME, "AppropriatePhoneticMiddle");
+        resolver.buildContactEntry().buildData(StructuredName.CONTENT_ITEM_TYPE)
+                .put(StructuredName.FAMILY_NAME, "AppropriateFamilyName")
+                .put(StructuredName.GIVEN_NAME, "AppropriateGivenName")
+                .put(StructuredName.MIDDLE_NAME, "AppropriateMiddleName")
+                .put(StructuredName.PREFIX, "AppropriatePrefix")
+                .put(StructuredName.SUFFIX, "AppropriateSuffix")
+                .put(StructuredName.PHONETIC_FAMILY_NAME, "AppropriatePhoneticFamily")
+                .put(StructuredName.PHONETIC_GIVEN_NAME, "AppropriatePhoneticGiven")
+                .put(StructuredName.PHONETIC_MIDDLE_NAME, "AppropriatePhoneticMiddle");
 
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
-        PropertyNodesVerifier verifier = handler.addNewVerifier()
-            .addNodeWithOrder("N",
-                    "AppropriateFamilyName;AppropriateGivenName;AppropriateMiddleName;"
-                    + "AppropriatePrefix;AppropriateSuffix",
-                    Arrays.asList("AppropriateFamilyName", "AppropriateGivenName",
-                            "AppropriateMiddleName", "AppropriatePrefix", "AppropriateSuffix"))
-            .addNodeWithOrder("FN",
-                    "AppropriatePrefix AppropriateGivenName "
-                    + "AppropriateMiddleName AppropriateFamilyName AppropriateSuffix")
-            .addNodeWithoutOrder("X-PHONETIC-FIRST-NAME", "AppropriatePhoneticGiven")
-            .addNodeWithoutOrder("X-PHONETIC-MIDDLE-NAME", "AppropriatePhoneticMiddle")
-            .addNodeWithoutOrder("X-PHONETIC-LAST-NAME", "AppropriatePhoneticFamily");
+        VCardVerifier verifier = new VCardVerifier(resolver, version);
+        PropertyNodesVerifierElem elem = verifier.addPropertyNodesVerifierElem()
+                .addNodeWithOrder("N",
+                        "AppropriateFamilyName;AppropriateGivenName;AppropriateMiddleName;"
+                        + "AppropriatePrefix;AppropriateSuffix",
+                        Arrays.asList("AppropriateFamilyName", "AppropriateGivenName",
+                                "AppropriateMiddleName", "AppropriatePrefix", "AppropriateSuffix"))
+                .addNodeWithOrder("FN",
+                        "AppropriatePrefix AppropriateGivenName "
+                        + "AppropriateMiddleName AppropriateFamilyName AppropriateSuffix")
+                .addNodeWithoutOrder("X-PHONETIC-FIRST-NAME", "AppropriatePhoneticGiven")
+                .addNodeWithoutOrder("X-PHONETIC-MIDDLE-NAME", "AppropriatePhoneticMiddle")
+                .addNodeWithoutOrder("X-PHONETIC-LAST-NAME", "AppropriatePhoneticFamily");
 
         if (isV30) {
-            verifier.addNodeWithoutOrder("SORT-STRING",
+            elem.addNodeWithoutOrder("SORT-STRING",
                     "AppropriatePhoneticGiven AppropriatePhoneticMiddle "
                     + "AppropriatePhoneticFamily");
         }
 
-        verifyOneComposition(resolver, handler, version);
+        verifier.verify();
     }
 
     public void testStructuredNameBasicV21() {
@@ -130,61 +111,62 @@
         final boolean isV30 = (version == V30);
         ExportTestResolver resolver = new ExportTestResolver();
 
-        ContentValues contentValues = resolver.buildData(StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName1");
-        contentValues.put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName1");
-        contentValues.put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName1");
-        contentValues.put(StructuredName.PREFIX, "DoNotEmitPrefix1");
-        contentValues.put(StructuredName.SUFFIX, "DoNotEmitSuffix1");
-        contentValues.put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily1");
-        contentValues.put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven1");
-        contentValues.put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle1");
+        ContactEntry entry = resolver.buildContactEntry();
+        entry.buildData(StructuredName.CONTENT_ITEM_TYPE)
+                .put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName1")
+                .put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName1")
+                .put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName1")
+                .put(StructuredName.PREFIX, "DoNotEmitPrefix1")
+                .put(StructuredName.SUFFIX, "DoNotEmitSuffix1")
+                .put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily1")
+                .put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven1")
+                .put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle1");
 
         // With "IS_PRIMARY=1". This is what we should use.
-        contentValues = resolver.buildData(StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredName.FAMILY_NAME, "AppropriateFamilyName");
-        contentValues.put(StructuredName.GIVEN_NAME, "AppropriateGivenName");
-        contentValues.put(StructuredName.MIDDLE_NAME, "AppropriateMiddleName");
-        contentValues.put(StructuredName.PREFIX, "AppropriatePrefix");
-        contentValues.put(StructuredName.SUFFIX, "AppropriateSuffix");
-        contentValues.put(StructuredName.PHONETIC_FAMILY_NAME, "AppropriatePhoneticFamily");
-        contentValues.put(StructuredName.PHONETIC_GIVEN_NAME, "AppropriatePhoneticGiven");
-        contentValues.put(StructuredName.PHONETIC_MIDDLE_NAME, "AppropriatePhoneticMiddle");
-        contentValues.put(StructuredName.IS_PRIMARY, 1);
+        entry.buildData(StructuredName.CONTENT_ITEM_TYPE)
+                .put(StructuredName.FAMILY_NAME, "AppropriateFamilyName")
+                .put(StructuredName.GIVEN_NAME, "AppropriateGivenName")
+                .put(StructuredName.MIDDLE_NAME, "AppropriateMiddleName")
+                .put(StructuredName.PREFIX, "AppropriatePrefix")
+                .put(StructuredName.SUFFIX, "AppropriateSuffix")
+                .put(StructuredName.PHONETIC_FAMILY_NAME, "AppropriatePhoneticFamily")
+                .put(StructuredName.PHONETIC_GIVEN_NAME, "AppropriatePhoneticGiven")
+                .put(StructuredName.PHONETIC_MIDDLE_NAME, "AppropriatePhoneticMiddle")
+                .put(StructuredName.IS_PRIMARY, 1);
 
         // With "IS_PRIMARY=1", but we should ignore this time, since this is second, not first.
-        contentValues = resolver.buildData(StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName2");
-        contentValues.put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName2");
-        contentValues.put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName2");
-        contentValues.put(StructuredName.PREFIX, "DoNotEmitPrefix2");
-        contentValues.put(StructuredName.SUFFIX, "DoNotEmitSuffix2");
-        contentValues.put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily2");
-        contentValues.put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven2");
-        contentValues.put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle2");
-        contentValues.put(StructuredName.IS_PRIMARY, 1);
+        entry.buildData(StructuredName.CONTENT_ITEM_TYPE)
+                .put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName2")
+                .put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName2")
+                .put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName2")
+                .put(StructuredName.PREFIX, "DoNotEmitPrefix2")
+                .put(StructuredName.SUFFIX, "DoNotEmitSuffix2")
+                .put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily2")
+                .put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven2")
+                .put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle2")
+                .put(StructuredName.IS_PRIMARY, 1);
 
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
-        PropertyNodesVerifier verifier = handler.addNewVerifier()
-            .addNodeWithOrder("N",
-                    "AppropriateFamilyName;AppropriateGivenName;AppropriateMiddleName;"
-                    + "AppropriatePrefix;AppropriateSuffix",
-                    Arrays.asList("AppropriateFamilyName", "AppropriateGivenName",
-                            "AppropriateMiddleName", "AppropriatePrefix", "AppropriateSuffix"))
-            .addNodeWithOrder("FN",
-                    "AppropriatePrefix AppropriateGivenName "
-                    + "AppropriateMiddleName AppropriateFamilyName AppropriateSuffix")
-            .addNodeWithoutOrder("X-PHONETIC-FIRST-NAME", "AppropriatePhoneticGiven")
-            .addNodeWithoutOrder("X-PHONETIC-MIDDLE-NAME", "AppropriatePhoneticMiddle")
-            .addNodeWithoutOrder("X-PHONETIC-LAST-NAME", "AppropriatePhoneticFamily");
+        VCardVerifier verifier = new VCardVerifier(resolver, version);
+        PropertyNodesVerifierElem elem = verifier.addPropertyNodesVerifierElem()
+                .addNodeWithOrder("N",
+                        "AppropriateFamilyName;AppropriateGivenName;AppropriateMiddleName;"
+                        + "AppropriatePrefix;AppropriateSuffix",
+                        Arrays.asList("AppropriateFamilyName", "AppropriateGivenName",
+                                "AppropriateMiddleName", "AppropriatePrefix", "AppropriateSuffix"))
+                .addNodeWithOrder("FN",
+                        "AppropriatePrefix AppropriateGivenName "
+                        + "AppropriateMiddleName AppropriateFamilyName AppropriateSuffix")
+                .addNodeWithoutOrder("X-PHONETIC-FIRST-NAME", "AppropriatePhoneticGiven")
+                .addNodeWithoutOrder("X-PHONETIC-MIDDLE-NAME", "AppropriatePhoneticMiddle")
+                .addNodeWithoutOrder("X-PHONETIC-LAST-NAME", "AppropriatePhoneticFamily");
 
         if (isV30) {
-            verifier.addNodeWithoutOrder("SORT-STRING",
+            elem.addNodeWithoutOrder("SORT-STRING",
                     "AppropriatePhoneticGiven AppropriatePhoneticMiddle "
                     + "AppropriatePhoneticFamily");
         }
 
-        verifyOneComposition(resolver, handler, version);
+        verifier.verify();
     }
 
     public void testStructuredNameUsePrimaryV21() {
@@ -203,72 +185,73 @@
         final boolean isV30 = (version == V30);
         ExportTestResolver resolver = new ExportTestResolver();
 
-        ContentValues contentValues = resolver.buildData(StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName1");
-        contentValues.put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName1");
-        contentValues.put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName1");
-        contentValues.put(StructuredName.PREFIX, "DoNotEmitPrefix1");
-        contentValues.put(StructuredName.SUFFIX, "DoNotEmitSuffix1");
-        contentValues.put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily1");
-        contentValues.put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven1");
-        contentValues.put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle1");
+        ContactEntry entry = resolver.buildContactEntry();
+        entry.buildData(StructuredName.CONTENT_ITEM_TYPE)
+                .put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName1")
+                .put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName1")
+                .put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName1")
+                .put(StructuredName.PREFIX, "DoNotEmitPrefix1")
+                .put(StructuredName.SUFFIX, "DoNotEmitSuffix1")
+                .put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily1")
+                .put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven1")
+                .put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle1");
 
         // With "IS_PRIMARY=1", but we should ignore this time.
-        contentValues = resolver.buildData(StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName2");
-        contentValues.put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName2");
-        contentValues.put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName2");
-        contentValues.put(StructuredName.PREFIX, "DoNotEmitPrefix2");
-        contentValues.put(StructuredName.SUFFIX, "DoNotEmitSuffix2");
-        contentValues.put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily2");
-        contentValues.put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven2");
-        contentValues.put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle2");
-        contentValues.put(StructuredName.IS_PRIMARY, 1);
+        entry.buildData(StructuredName.CONTENT_ITEM_TYPE)
+                .put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName2")
+                .put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName2")
+                .put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName2")
+                .put(StructuredName.PREFIX, "DoNotEmitPrefix2")
+                .put(StructuredName.SUFFIX, "DoNotEmitSuffix2")
+                .put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily2")
+                .put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven2")
+                .put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle2")
+                .put(StructuredName.IS_PRIMARY, 1);
 
         // With "IS_SUPER_PRIMARY=1". This is what we should use.
-        contentValues = resolver.buildData(StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredName.FAMILY_NAME, "AppropriateFamilyName");
-        contentValues.put(StructuredName.GIVEN_NAME, "AppropriateGivenName");
-        contentValues.put(StructuredName.MIDDLE_NAME, "AppropriateMiddleName");
-        contentValues.put(StructuredName.PREFIX, "AppropriatePrefix");
-        contentValues.put(StructuredName.SUFFIX, "AppropriateSuffix");
-        contentValues.put(StructuredName.PHONETIC_FAMILY_NAME, "AppropriatePhoneticFamily");
-        contentValues.put(StructuredName.PHONETIC_GIVEN_NAME, "AppropriatePhoneticGiven");
-        contentValues.put(StructuredName.PHONETIC_MIDDLE_NAME, "AppropriatePhoneticMiddle");
-        contentValues.put(StructuredName.IS_SUPER_PRIMARY, 1);
+        entry.buildData(StructuredName.CONTENT_ITEM_TYPE)
+                .put(StructuredName.FAMILY_NAME, "AppropriateFamilyName")
+                .put(StructuredName.GIVEN_NAME, "AppropriateGivenName")
+                .put(StructuredName.MIDDLE_NAME, "AppropriateMiddleName")
+                .put(StructuredName.PREFIX, "AppropriatePrefix")
+                .put(StructuredName.SUFFIX, "AppropriateSuffix")
+                .put(StructuredName.PHONETIC_FAMILY_NAME, "AppropriatePhoneticFamily")
+                .put(StructuredName.PHONETIC_GIVEN_NAME, "AppropriatePhoneticGiven")
+                .put(StructuredName.PHONETIC_MIDDLE_NAME, "AppropriatePhoneticMiddle")
+                .put(StructuredName.IS_SUPER_PRIMARY, 1);
 
-        contentValues = resolver.buildData(StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName3");
-        contentValues.put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName3");
-        contentValues.put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName3");
-        contentValues.put(StructuredName.PREFIX, "DoNotEmitPrefix3");
-        contentValues.put(StructuredName.SUFFIX, "DoNotEmitSuffix3");
-        contentValues.put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily3");
-        contentValues.put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven3");
-        contentValues.put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle3");
-        contentValues.put(StructuredName.IS_PRIMARY, 1);
+        entry.buildData(StructuredName.CONTENT_ITEM_TYPE)
+                .put(StructuredName.FAMILY_NAME, "DoNotEmitFamilyName3")
+                .put(StructuredName.GIVEN_NAME, "DoNotEmitGivenName3")
+                .put(StructuredName.MIDDLE_NAME, "DoNotEmitMiddleName3")
+                .put(StructuredName.PREFIX, "DoNotEmitPrefix3")
+                .put(StructuredName.SUFFIX, "DoNotEmitSuffix3")
+                .put(StructuredName.PHONETIC_FAMILY_NAME, "DoNotEmitPhoneticFamily3")
+                .put(StructuredName.PHONETIC_GIVEN_NAME, "DoNotEmitPhoneticGiven3")
+                .put(StructuredName.PHONETIC_MIDDLE_NAME, "DoNotEmitPhoneticMiddle3")
+                .put(StructuredName.IS_PRIMARY, 1);
 
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
-        PropertyNodesVerifier verifier = handler.addNewVerifier()
-            .addNodeWithOrder("N",
-                    "AppropriateFamilyName;AppropriateGivenName;AppropriateMiddleName;"
-                    + "AppropriatePrefix;AppropriateSuffix",
-                    Arrays.asList("AppropriateFamilyName", "AppropriateGivenName",
-                            "AppropriateMiddleName", "AppropriatePrefix", "AppropriateSuffix"))
-            .addNodeWithOrder("FN",
-                    "AppropriatePrefix AppropriateGivenName "
-                    + "AppropriateMiddleName AppropriateFamilyName AppropriateSuffix")
-            .addNodeWithoutOrder("X-PHONETIC-FIRST-NAME", "AppropriatePhoneticGiven")
-            .addNodeWithoutOrder("X-PHONETIC-MIDDLE-NAME", "AppropriatePhoneticMiddle")
-            .addNodeWithoutOrder("X-PHONETIC-LAST-NAME", "AppropriatePhoneticFamily");
+        VCardVerifier verifier = new VCardVerifier(resolver, version);
+        PropertyNodesVerifierElem elem = verifier.addPropertyNodesVerifierElem()
+                .addNodeWithOrder("N",
+                        "AppropriateFamilyName;AppropriateGivenName;AppropriateMiddleName;"
+                        + "AppropriatePrefix;AppropriateSuffix",
+                        Arrays.asList("AppropriateFamilyName", "AppropriateGivenName",
+                                "AppropriateMiddleName", "AppropriatePrefix", "AppropriateSuffix"))
+                .addNodeWithOrder("FN",
+                        "AppropriatePrefix AppropriateGivenName "
+                        + "AppropriateMiddleName AppropriateFamilyName AppropriateSuffix")
+                .addNodeWithoutOrder("X-PHONETIC-FIRST-NAME", "AppropriatePhoneticGiven")
+                .addNodeWithoutOrder("X-PHONETIC-MIDDLE-NAME", "AppropriatePhoneticMiddle")
+                .addNodeWithoutOrder("X-PHONETIC-LAST-NAME", "AppropriatePhoneticFamily");
 
         if (isV30) {
-            verifier.addNodeWithoutOrder("SORT-STRING",
+            elem.addNodeWithoutOrder("SORT-STRING",
                     "AppropriatePhoneticGiven AppropriatePhoneticMiddle"
                     + " AppropriatePhoneticFamily");
         }
 
-        verifyOneComposition(resolver, handler, version);
+        verifier.verify();
     }
 
     public void testStructuredNameUseSuperPrimaryV21() {
@@ -281,28 +264,28 @@
 
     public void testNickNameV30() {
         ExportTestResolver resolver = new ExportTestResolver();
-        ContentValues contentValues = resolver.buildData(Nickname.CONTENT_ITEM_TYPE);
-        contentValues.put(Nickname.NAME, "Nicky");
+        resolver.buildContactEntry().buildData(Nickname.CONTENT_ITEM_TYPE)
+                .put(Nickname.NAME, "Nicky");
 
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, V30);
-        handler.addNewVerifierWithEmptyName()
+        VCardVerifier verifier = new VCardVerifier(resolver, V30);
+        verifier.addPropertyNodesVerifierWithEmptyName()
             .addNodeWithOrder("NICKNAME", "Nicky");
 
-        verifyOneComposition(resolver, handler, V30);
+        verifier.verify();
     }
 
     private void testPhoneBasicCommon(int version) {
         ExportTestResolver resolver = new ExportTestResolver();
 
-        ContentValues contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.NUMBER, "1");
-        contentValues.put(Phone.TYPE, Phone.TYPE_HOME);
+        resolver.buildContactEntry().buildData(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.NUMBER, "1")
+                .put(Phone.TYPE, Phone.TYPE_HOME);
 
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
-        handler.addNewVerifierWithEmptyName()
-            .addNodeWithoutOrder("TEL", "1", new TypeSet("HOME", "VOICE"));
+        VCardVerifier verifier = new VCardVerifier(resolver, version);
+        verifier.addPropertyNodesVerifierWithEmptyName()
+                .addNodeWithoutOrder("TEL", "1", new TypeSet("HOME"));
 
-        verifyOneComposition(resolver, handler, version);
+        verifier.verify();
     }
 
     public void testPhoneBasicV21() {
@@ -319,88 +302,75 @@
     private void testPhoneVariousTypeSupport(int version) {
         ExportTestResolver resolver = new ExportTestResolver();
 
-        ContentValues contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.NUMBER, "10");
-        contentValues.put(Phone.TYPE, Phone.TYPE_HOME);
+        ContactEntry entry = resolver.buildContactEntry();
+        entry.buildData(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.NUMBER, "10")
+                .put(Phone.TYPE, Phone.TYPE_HOME);
+        entry.buildData(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.NUMBER, "20")
+                .put(Phone.TYPE, Phone.TYPE_WORK);
+        entry.buildData(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.NUMBER, "30")
+                .put(Phone.TYPE, Phone.TYPE_FAX_HOME);
+        entry.buildData(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.NUMBER, "40")
+                .put(Phone.TYPE, Phone.TYPE_FAX_WORK);
+        entry.buildData(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.NUMBER, "50")
+                .put(Phone.TYPE, Phone.TYPE_MOBILE);
+        entry.buildData(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.NUMBER, "60")
+                .put(Phone.TYPE, Phone.TYPE_PAGER);
+        entry.buildData(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.NUMBER, "70")
+                .put(Phone.TYPE, Phone.TYPE_OTHER);
+        entry.buildData(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.NUMBER, "80")
+                .put(Phone.TYPE, Phone.TYPE_CAR);
+        entry.buildData(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.NUMBER, "90")
+                .put(Phone.TYPE, Phone.TYPE_COMPANY_MAIN);
+        entry.buildData(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.NUMBER, "100")
+                .put(Phone.TYPE, Phone.TYPE_ISDN);
+        entry.buildData(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.NUMBER, "110")
+                .put(Phone.TYPE, Phone.TYPE_MAIN);
+        entry.buildData(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.NUMBER, "120")
+                .put(Phone.TYPE, Phone.TYPE_OTHER_FAX);
+        entry.buildData(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.NUMBER, "130")
+                .put(Phone.TYPE, Phone.TYPE_TELEX);
+        entry.buildData(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.NUMBER, "140")
+                .put(Phone.TYPE, Phone.TYPE_WORK_MOBILE);
+        entry.buildData(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.NUMBER, "150")
+                .put(Phone.TYPE, Phone.TYPE_WORK_PAGER);
+        entry.buildData(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.NUMBER, "160")
+                .put(Phone.TYPE, Phone.TYPE_MMS);
 
-        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.NUMBER, "20");
-        contentValues.put(Phone.TYPE, Phone.TYPE_WORK);
-
-        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.NUMBER, "30");
-        contentValues.put(Phone.TYPE, Phone.TYPE_FAX_HOME);
-
-        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.NUMBER, "40");
-        contentValues.put(Phone.TYPE, Phone.TYPE_FAX_WORK);
-
-        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.NUMBER, "50");
-        contentValues.put(Phone.TYPE, Phone.TYPE_MOBILE);
-
-        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.NUMBER, "60");
-        contentValues.put(Phone.TYPE, Phone.TYPE_PAGER);
-
-        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.NUMBER, "70");
-        contentValues.put(Phone.TYPE, Phone.TYPE_OTHER);
-
-        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.NUMBER, "80");
-        contentValues.put(Phone.TYPE, Phone.TYPE_CAR);
-
-        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.NUMBER, "90");
-        contentValues.put(Phone.TYPE, Phone.TYPE_COMPANY_MAIN);
-
-        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.NUMBER, "100");
-        contentValues.put(Phone.TYPE, Phone.TYPE_ISDN);
-
-        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.NUMBER, "110");
-        contentValues.put(Phone.TYPE, Phone.TYPE_MAIN);
-
-        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.NUMBER, "120");
-        contentValues.put(Phone.TYPE, Phone.TYPE_OTHER_FAX);
-
-        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.NUMBER, "130");
-        contentValues.put(Phone.TYPE, Phone.TYPE_TELEX);
-
-        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.NUMBER, "140");
-        contentValues.put(Phone.TYPE, Phone.TYPE_WORK_MOBILE);
-
-        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.NUMBER, "150");
-        contentValues.put(Phone.TYPE, Phone.TYPE_WORK_PAGER);
-
-        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.NUMBER, "160");
-        contentValues.put(Phone.TYPE, Phone.TYPE_MMS);
-
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
-        handler.addNewVerifierWithEmptyName()
-            .addNodeWithoutOrder("TEL", "10", new TypeSet("HOME"))
-            .addNodeWithoutOrder("TEL", "20", new TypeSet("WORK"))
-            .addNodeWithoutOrder("TEL", "30", new TypeSet("HOME", "FAX"))
-            .addNodeWithoutOrder("TEL", "40", new TypeSet("WORK", "FAX"))
-            .addNodeWithoutOrder("TEL", "50", new TypeSet("CELL"))
-            .addNodeWithoutOrder("TEL", "60", new TypeSet("PAGER"))
-            .addNodeWithoutOrder("TEL", "70", new TypeSet("VOICE"))
-            .addNodeWithoutOrder("TEL", "80", new TypeSet("CAR"))
-            .addNodeWithoutOrder("TEL", "90", new TypeSet("WORK", "PREF"))
-            .addNodeWithoutOrder("TEL", "100", new TypeSet("ISDN"))
-            .addNodeWithoutOrder("TEL", "110", new TypeSet("PREF"))
-            .addNodeWithoutOrder("TEL", "120", new TypeSet("FAX"))
-            .addNodeWithoutOrder("TEL", "130", new TypeSet("TLX"))
-            .addNodeWithoutOrder("TEL", "140", new TypeSet("WORK", "MOBILE"))
-            .addNodeWithoutOrder("TEL", "150", new TypeSet("WORK", "PAGER"))
-            .addNodeWithoutOrder("TEL", "160", new TypeSet("MSG"));
+        VCardVerifier verifier = new VCardVerifier(resolver, version);
+        verifier.addPropertyNodesVerifierWithEmptyName()
+                .addNodeWithoutOrder("TEL", "10", new TypeSet("HOME"))
+                .addNodeWithoutOrder("TEL", "20", new TypeSet("WORK"))
+                .addNodeWithoutOrder("TEL", "30", new TypeSet("HOME", "FAX"))
+                .addNodeWithoutOrder("TEL", "40", new TypeSet("WORK", "FAX"))
+                .addNodeWithoutOrder("TEL", "50", new TypeSet("CELL"))
+                .addNodeWithoutOrder("TEL", "60", new TypeSet("PAGER"))
+                .addNodeWithoutOrder("TEL", "70", new TypeSet("VOICE"))
+                .addNodeWithoutOrder("TEL", "80", new TypeSet("CAR"))
+                .addNodeWithoutOrder("TEL", "90", new TypeSet("WORK", "PREF"))
+                .addNodeWithoutOrder("TEL", "100", new TypeSet("ISDN"))
+                .addNodeWithoutOrder("TEL", "110", new TypeSet("PREF"))
+                .addNodeWithoutOrder("TEL", "120", new TypeSet("FAX"))
+                .addNodeWithoutOrder("TEL", "130", new TypeSet("TLX"))
+                .addNodeWithoutOrder("TEL", "140", new TypeSet("WORK", "CELL"))
+                .addNodeWithoutOrder("TEL", "150", new TypeSet("WORK", "PAGER"))
+                .addNodeWithoutOrder("TEL", "160", new TypeSet("MSG"));
+        verifier.verify();
     }
 
     public void testPhoneVariousTypeSupportV21() {
@@ -416,33 +386,29 @@
      */
     private void testPhonePrefHandlingCommon(int version) {
         ExportTestResolver resolver = new ExportTestResolver();
+        ContactEntry entry = resolver.buildContactEntry();
+        entry.buildData(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.NUMBER, "1")
+                .put(Phone.TYPE, Phone.TYPE_HOME);
+        entry.buildData(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.NUMBER, "2")
+                .put(Phone.TYPE, Phone.TYPE_WORK)
+                .put(Phone.IS_PRIMARY, 1);
+        entry.buildData(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.NUMBER, "3")
+                .put(Phone.TYPE, Phone.TYPE_FAX_HOME)
+                .put(Phone.IS_PRIMARY, 1);
+        entry.buildData(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.NUMBER, "4")
+                .put(Phone.TYPE, Phone.TYPE_FAX_WORK);
 
-        ContentValues contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.NUMBER, "1");
-        contentValues.put(Phone.TYPE, Phone.TYPE_HOME);
-
-        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.NUMBER, "2");
-        contentValues.put(Phone.TYPE, Phone.TYPE_WORK);
-        contentValues.put(Phone.IS_PRIMARY, 1);
-
-        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.NUMBER, "3");
-        contentValues.put(Phone.TYPE, Phone.TYPE_FAX_HOME);
-        contentValues.put(Phone.IS_PRIMARY, 1);
-
-        contentValues = resolver.buildData(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.NUMBER, "4");
-        contentValues.put(Phone.TYPE, Phone.TYPE_FAX_WORK);
-
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
-        handler.addNewVerifierWithEmptyName()
-            .addNodeWithoutOrder("TEL", "4", new TypeSet("WORK", "FAX"))
-            .addNodeWithoutOrder("TEL", "3", new TypeSet("HOME", "FAX", "PREF"))
-            .addNodeWithoutOrder("TEL", "2", new TypeSet("WORK", "VOICE", "PREF"))
-            .addNodeWithoutOrder("TEL", "1", new TypeSet("HOME", "VOICE"));
-
-        verifyOneComposition(resolver, handler, version);
+        VCardVerifier verifier = new VCardVerifier(resolver, version);
+        verifier.addPropertyNodesVerifierWithEmptyName()
+                .addNodeWithoutOrder("TEL", "4", new TypeSet("WORK", "FAX"))
+                .addNodeWithoutOrder("TEL", "3", new TypeSet("HOME", "FAX", "PREF"))
+                .addNodeWithoutOrder("TEL", "2", new TypeSet("WORK", "PREF"))
+                .addNodeWithoutOrder("TEL", "1", new TypeSet("HOME"));
+        verifier.verify();
     }
 
     public void testPhonePrefHandlingV21() {
@@ -455,15 +421,15 @@
 
     private void testEmailBasicCommon(int version) {
         ExportTestResolver resolver = new ExportTestResolver();
-        ContentValues contentValues = resolver.buildData(Email.CONTENT_ITEM_TYPE);
-        contentValues.put(Email.DATA, "sample@example.com");
+        resolver.buildContactEntry().buildData(Email.CONTENT_ITEM_TYPE)
+                .put(Email.DATA, "sample@example.com");
 
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
+        VCardVerifier verifier = new VCardVerifier(resolver, version);
 
-        handler.addNewVerifierWithEmptyName()
+        verifier.addPropertyNodesVerifierWithEmptyName()
             .addNodeWithoutOrder("EMAIL", "sample@example.com");
 
-        verifyOneComposition(resolver, handler, version);
+        verifier.verify();
     }
 
     public void testEmailBasicV21() {
@@ -477,31 +443,29 @@
     private void testEmailVariousTypeSupportCommon(int version) {
         ExportTestResolver resolver = new ExportTestResolver();
 
-        ContentValues contentValues = resolver.buildData(Email.CONTENT_ITEM_TYPE);
-        contentValues.put(Email.DATA, "type_home@example.com");
-        contentValues.put(Email.TYPE, Email.TYPE_HOME);
+        ContactEntry entry = resolver.buildContactEntry();
+        entry.buildData(Email.CONTENT_ITEM_TYPE)
+                .put(Email.DATA, "type_home@example.com")
+                .put(Email.TYPE, Email.TYPE_HOME);
+        entry.buildData(Email.CONTENT_ITEM_TYPE)
+                .put(Email.DATA, "type_work@example.com")
+                .put(Email.TYPE, Email.TYPE_WORK);
+        entry.buildData(Email.CONTENT_ITEM_TYPE)
+                .put(Email.DATA, "type_mobile@example.com")
+                .put(Email.TYPE, Email.TYPE_MOBILE);
+        entry.buildData(Email.CONTENT_ITEM_TYPE)
+                .put(Email.DATA, "type_other@example.com")
+                .put(Email.TYPE, Email.TYPE_OTHER);
 
-        contentValues = resolver.buildData(Email.CONTENT_ITEM_TYPE);
-        contentValues.put(Email.DATA, "type_work@example.com");
-        contentValues.put(Email.TYPE, Email.TYPE_WORK);
+        VCardVerifier verifier = new VCardVerifier(resolver, version);
 
-        contentValues = resolver.buildData(Email.CONTENT_ITEM_TYPE);
-        contentValues.put(Email.DATA, "type_mobile@example.com");
-        contentValues.put(Email.TYPE, Email.TYPE_MOBILE);
+        verifier.addPropertyNodesVerifierWithEmptyName()
+                .addNodeWithoutOrder("EMAIL", "type_home@example.com", new TypeSet("HOME"))
+                .addNodeWithoutOrder("EMAIL", "type_work@example.com", new TypeSet("WORK"))
+                .addNodeWithoutOrder("EMAIL", "type_mobile@example.com", new TypeSet("CELL"))
+                .addNodeWithoutOrder("EMAIL", "type_other@example.com");
 
-        contentValues = resolver.buildData(Email.CONTENT_ITEM_TYPE);
-        contentValues.put(Email.DATA, "type_other@example.com");
-        contentValues.put(Email.TYPE, Email.TYPE_OTHER);
-
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
-
-        handler.addNewVerifierWithEmptyName()
-            .addNodeWithoutOrder("EMAIL", "type_home@example.com", new TypeSet("HOME"))
-            .addNodeWithoutOrder("EMAIL", "type_work@example.com", new TypeSet("WORK"))
-            .addNodeWithoutOrder("EMAIL", "type_mobile@example.com", new TypeSet("CELL"))
-            .addNodeWithoutOrder("EMAIL", "type_other@example.com");
-
-        verifyOneComposition(resolver, handler, version);
+        verifier.verify();
     }
 
     public void testEmailVariousTypeSupportV21() {
@@ -515,22 +479,22 @@
     private void testEmailPrefHandlingCommon(int version) {
         ExportTestResolver resolver = new ExportTestResolver();
 
-        ContentValues contentValues = resolver.buildData(Email.CONTENT_ITEM_TYPE);
-        contentValues.put(Email.DATA, "type_home@example.com");
-        contentValues.put(Email.TYPE, Email.TYPE_HOME);
-        contentValues.put(Email.IS_PRIMARY, 1);
+        ContactEntry entry = resolver.buildContactEntry();
+        entry.buildData(Email.CONTENT_ITEM_TYPE)
+                .put(Email.DATA, "type_home@example.com")
+                .put(Email.TYPE, Email.TYPE_HOME)
+                .put(Email.IS_PRIMARY, 1);
+        entry.buildData(Email.CONTENT_ITEM_TYPE)
+                .put(Email.DATA, "type_notype@example.com")
+                .put(Email.IS_PRIMARY, 1);
 
-        contentValues = resolver.buildData(Email.CONTENT_ITEM_TYPE);
-        contentValues.put(Email.DATA, "type_notype@example.com");
-        contentValues.put(Email.IS_PRIMARY, 1);
+        VCardVerifier verifier = new VCardVerifier(resolver, version);
 
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
+        verifier.addPropertyNodesVerifierWithEmptyName()
+                .addNodeWithoutOrder("EMAIL", "type_notype@example.com", new TypeSet("PREF"))
+                .addNodeWithoutOrder("EMAIL", "type_home@example.com", new TypeSet("HOME", "PREF"));
 
-        handler.addNewVerifierWithEmptyName()
-            .addNodeWithoutOrder("EMAIL", "type_notype@example.com", new TypeSet("PREF"))
-            .addNodeWithoutOrder("EMAIL", "type_home@example.com", new TypeSet("HOME", "PREF"));
-
-        verifyOneComposition(resolver, handler, version);
+        verifier.verify();
     }
 
     public void testEmailPrefHandlingV21() {
@@ -547,21 +511,21 @@
         // adr-value    = 0*6(text-value ";") text-value
         //              ; PO Box, Extended Address, Street, Locality, Region, Postal Code,
         //              ; Country Name
-        ContentValues contentValues = resolver.buildData(StructuredPostal.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredPostal.POBOX, "Pobox");
-        contentValues.put(StructuredPostal.NEIGHBORHOOD, "Neighborhood");
-        contentValues.put(StructuredPostal.STREET, "Street");
-        contentValues.put(StructuredPostal.CITY, "City");
-        contentValues.put(StructuredPostal.REGION, "Region");
-        contentValues.put(StructuredPostal.POSTCODE, "100");
-        contentValues.put(StructuredPostal.COUNTRY, "Country");
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
-        handler.addNewVerifierWithEmptyName()
-            .addNodeWithoutOrder("ADR", "Pobox;Neighborhood;Street;City;Region;100;Country",
-                    Arrays.asList("Pobox", "Neighborhood", "Street", "City",
-                            "Region", "100", "Country"), new TypeSet("HOME"));
+        resolver.buildContactEntry().buildData(StructuredPostal.CONTENT_ITEM_TYPE)
+                .put(StructuredPostal.POBOX, "Pobox")
+                .put(StructuredPostal.NEIGHBORHOOD, "Neighborhood")
+                .put(StructuredPostal.STREET, "Street")
+                .put(StructuredPostal.CITY, "City")
+                .put(StructuredPostal.REGION, "Region")
+                .put(StructuredPostal.POSTCODE, "100")
+                .put(StructuredPostal.COUNTRY, "Country");
+        VCardVerifier verifier = new VCardVerifier(resolver, version);
+        verifier.addPropertyNodesVerifierWithEmptyName()
+                .addNodeWithoutOrder("ADR", "Pobox;Neighborhood;Street;City;Region;100;Country",
+                        Arrays.asList("Pobox", "Neighborhood", "Street", "City",
+                                "Region", "100", "Country"), new TypeSet("HOME"));
 
-        verifyOneComposition(resolver, handler, version);
+        verifier.verify();
     }
 
     public void testPostalOnlyWithStructuredDataV21() {
@@ -575,17 +539,17 @@
     private void testPostalOnlyWithFormattedAddressCommon(int version) {
         ExportTestResolver resolver = new ExportTestResolver();
 
-        ContentValues contentValues = resolver.buildData(StructuredPostal.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredPostal.FORMATTED_ADDRESS,
+        resolver.buildContactEntry().buildData(StructuredPostal.CONTENT_ITEM_TYPE)
+                .put(StructuredPostal.FORMATTED_ADDRESS,
                 "Formatted address CA 123-334 United Statue");
 
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
-        handler.addNewVerifierWithEmptyName()
-            .addNodeWithOrder("ADR", ";Formatted address CA 123-334 United Statue;;;;;",
-                    Arrays.asList("", "Formatted address CA 123-334 United Statue",
-                            "", "", "", "", ""), new TypeSet("HOME"));
+        VCardVerifier verifier = new VCardVerifier(resolver, version);
+        verifier.addPropertyNodesVerifierWithEmptyName()
+                .addNodeWithOrder("ADR", ";Formatted address CA 123-334 United Statue;;;;;",
+                        Arrays.asList("", "Formatted address CA 123-334 United Statue",
+                                "", "", "", "", ""), new TypeSet("HOME"));
 
-        verifyOneComposition(resolver, handler, version);
+        verifier.verify();
     }
 
     public void testPostalOnlyWithFormattedAddressV21() {
@@ -603,18 +567,19 @@
     private void testPostalWithBothStructuredAndFormattedCommon(int version) {
         ExportTestResolver resolver = new ExportTestResolver();
 
-        ContentValues contentValues = resolver.buildData(StructuredPostal.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredPostal.POBOX, "Pobox");
-        contentValues.put(StructuredPostal.COUNTRY, "Country");
-        contentValues.put(StructuredPostal.FORMATTED_ADDRESS,
-                "Formatted address CA 123-334 United Statue");  // Should be ignored
+        resolver.buildContactEntry().buildData(StructuredPostal.CONTENT_ITEM_TYPE)
+                .put(StructuredPostal.POBOX, "Pobox")
+                .put(StructuredPostal.COUNTRY, "Country")
+                .put(StructuredPostal.FORMATTED_ADDRESS,
+                        "Formatted address CA 123-334 United Statue");  // Should be ignored
 
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
-        handler.addNewVerifierWithEmptyName()
-            .addNodeWithoutOrder("ADR", "Pobox;;;;;;Country",
-                    Arrays.asList("Pobox", "", "", "", "", "", "Country"), new TypeSet("HOME"));
+        VCardVerifier verifier = new VCardVerifier(resolver, version);
+        verifier.addPropertyNodesVerifierWithEmptyName()
+                .addNodeWithoutOrder("ADR", "Pobox;;;;;;Country",
+                        Arrays.asList("Pobox", "", "", "", "", "", "Country"),
+                        new TypeSet("HOME"));
 
-        verifyOneComposition(resolver, handler, version);
+        verifier.verify();
     }
 
     public void testPostalWithBothStructuredAndFormattedV21() {
@@ -627,37 +592,38 @@
 
     private void testOrganizationCommon(int version) {
         ExportTestResolver resolver = new ExportTestResolver();
-        ContentValues contentValues = resolver.buildData(Organization.CONTENT_ITEM_TYPE);
-        contentValues.put(Organization.COMPANY, "CompanyX");
-        contentValues.put(Organization.DEPARTMENT, "DepartmentY");
-        contentValues.put(Organization.TITLE, "TitleZ");
-        contentValues.put(Organization.JOB_DESCRIPTION, "Description Rambda");  // Ignored.
-        contentValues.put(Organization.OFFICE_LOCATION, "Mountain View");  // Ignored.
-        contentValues.put(Organization.PHONETIC_NAME, "PhoneticName!");  // Ignored
-        contentValues.put(Organization.SYMBOL, "(^o^)/~~");  // Ignore him (her).
+        ContactEntry entry = resolver.buildContactEntry();
+        entry.buildData(Organization.CONTENT_ITEM_TYPE)
+                .put(Organization.COMPANY, "CompanyX")
+                .put(Organization.DEPARTMENT, "DepartmentY")
+                .put(Organization.TITLE, "TitleZ")
+                .put(Organization.JOB_DESCRIPTION, "Description Rambda")  // Ignored.
+                .put(Organization.OFFICE_LOCATION, "Mountain View")  // Ignored.
+                .put(Organization.PHONETIC_NAME, "PhoneticName!")  // Ignored
+                .put(Organization.SYMBOL, "(^o^)/~~");  // Ignore him (her).
 
-        contentValues = resolver.buildData(Organization.CONTENT_ITEM_TYPE);
-        contentValues.putNull(Organization.COMPANY);
-        contentValues.put(Organization.DEPARTMENT, "DepartmentXX");
-        contentValues.putNull(Organization.TITLE);
+        entry.buildData(Organization.CONTENT_ITEM_TYPE)
+                .putNull(Organization.COMPANY)
+                .put(Organization.DEPARTMENT, "DepartmentXX")
+                .putNull(Organization.TITLE);
 
-        contentValues = resolver.buildData(Organization.CONTENT_ITEM_TYPE);
-        contentValues.put(Organization.COMPANY, "CompanyXYZ");
-        contentValues.putNull(Organization.DEPARTMENT);
-        contentValues.put(Organization.TITLE, "TitleXYZYX");
+        entry.buildData(Organization.CONTENT_ITEM_TYPE)
+                .put(Organization.COMPANY, "CompanyXYZ")
+                .putNull(Organization.DEPARTMENT)
+                .put(Organization.TITLE, "TitleXYZYX");
 
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
+        VCardVerifier verifier = new VCardVerifier(resolver, version);
 
         // Currently we do not use group but depend on the order.
-        handler.addNewVerifierWithEmptyName()
-            .addNodeWithOrder("ORG", "CompanyX;DepartmentY",
-                    Arrays.asList("CompanyX", "DepartmentY"))
-            .addNodeWithOrder("TITLE", "TitleZ")
-            .addNodeWithOrder("ORG", "DepartmentXX")
-            .addNodeWithOrder("ORG", "CompanyXYZ")
-            .addNodeWithOrder("TITLE", "TitleXYZYX");
+        verifier.addPropertyNodesVerifierWithEmptyName()
+                .addNodeWithOrder("ORG", "CompanyX;DepartmentY",
+                        Arrays.asList("CompanyX", "DepartmentY"))
+                .addNodeWithOrder("TITLE", "TitleZ")
+                .addNodeWithOrder("ORG", "DepartmentXX")
+                .addNodeWithOrder("ORG", "CompanyXYZ")
+                .addNodeWithOrder("TITLE", "TitleXYZYX");
 
-        verifyOneComposition(resolver, handler, version);
+        verifier.verify();
     }
 
     public void testOrganizationV21() {
@@ -671,57 +637,58 @@
     private void testImVariousTypeSupportCommon(int version) {
         ExportTestResolver resolver = new ExportTestResolver();
 
-        ContentValues contentValues = resolver.buildData(Im.CONTENT_ITEM_TYPE);
-        contentValues.put(Im.PROTOCOL, Im.PROTOCOL_AIM);
-        contentValues.put(Im.DATA, "aim");
+        ContactEntry entry = resolver.buildContactEntry();
+        entry.buildData(Im.CONTENT_ITEM_TYPE)
+                .put(Im.PROTOCOL, Im.PROTOCOL_AIM)
+                .put(Im.DATA, "aim");
 
-        contentValues = resolver.buildData(Im.CONTENT_ITEM_TYPE);
-        contentValues.put(Im.PROTOCOL, Im.PROTOCOL_MSN);
-        contentValues.put(Im.DATA, "msn");
+        entry.buildData(Im.CONTENT_ITEM_TYPE)
+                .put(Im.PROTOCOL, Im.PROTOCOL_MSN)
+                .put(Im.DATA, "msn");
 
-        contentValues = resolver.buildData(Im.CONTENT_ITEM_TYPE);
-        contentValues.put(Im.PROTOCOL, Im.PROTOCOL_YAHOO);
-        contentValues.put(Im.DATA, "yahoo");
+        entry.buildData(Im.CONTENT_ITEM_TYPE)
+                .put(Im.PROTOCOL, Im.PROTOCOL_YAHOO)
+                .put(Im.DATA, "yahoo");
 
-        contentValues = resolver.buildData(Im.CONTENT_ITEM_TYPE);
-        contentValues.put(Im.PROTOCOL, Im.PROTOCOL_SKYPE);
-        contentValues.put(Im.DATA, "skype");
+        entry.buildData(Im.CONTENT_ITEM_TYPE)
+                .put(Im.PROTOCOL, Im.PROTOCOL_SKYPE)
+                .put(Im.DATA, "skype");
 
-        contentValues = resolver.buildData(Im.CONTENT_ITEM_TYPE);
-        contentValues.put(Im.PROTOCOL, Im.PROTOCOL_QQ);
-        contentValues.put(Im.DATA, "qq");
+        entry.buildData(Im.CONTENT_ITEM_TYPE)
+                .put(Im.PROTOCOL, Im.PROTOCOL_QQ)
+                .put(Im.DATA, "qq");
 
-        contentValues = resolver.buildData(Im.CONTENT_ITEM_TYPE);
-        contentValues.put(Im.PROTOCOL, Im.PROTOCOL_GOOGLE_TALK);
-        contentValues.put(Im.DATA, "google talk");
+        entry.buildData(Im.CONTENT_ITEM_TYPE)
+                .put(Im.PROTOCOL, Im.PROTOCOL_GOOGLE_TALK)
+                .put(Im.DATA, "google talk");
 
-        contentValues = resolver.buildData(Im.CONTENT_ITEM_TYPE);
-        contentValues.put(Im.PROTOCOL, Im.PROTOCOL_ICQ);
-        contentValues.put(Im.DATA, "icq");
+        entry.buildData(Im.CONTENT_ITEM_TYPE)
+                .put(Im.PROTOCOL, Im.PROTOCOL_ICQ)
+                .put(Im.DATA, "icq");
 
-        contentValues = resolver.buildData(Im.CONTENT_ITEM_TYPE);
-        contentValues.put(Im.PROTOCOL, Im.PROTOCOL_JABBER);
-        contentValues.put(Im.DATA, "jabber");
+        entry.buildData(Im.CONTENT_ITEM_TYPE)
+                .put(Im.PROTOCOL, Im.PROTOCOL_JABBER)
+                .put(Im.DATA, "jabber");
 
-        contentValues = resolver.buildData(Im.CONTENT_ITEM_TYPE);
-        contentValues.put(Im.PROTOCOL, Im.PROTOCOL_NETMEETING);
-        contentValues.put(Im.DATA, "netmeeting");
+        entry.buildData(Im.CONTENT_ITEM_TYPE)
+                .put(Im.PROTOCOL, Im.PROTOCOL_NETMEETING)
+                .put(Im.DATA, "netmeeting");
 
         // No determined way to express unknown type...
 
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
-        handler.addNewVerifierWithEmptyName()
-            .addNodeWithoutOrder("X-JABBER", "jabber")
-            .addNodeWithoutOrder("X-ICQ", "icq")
-            .addNodeWithoutOrder("X-GOOGLE-TALK", "google talk")
-            .addNodeWithoutOrder("X-QQ", "qq")
-            .addNodeWithoutOrder("X-SKYPE-USERNAME", "skype")
-            .addNodeWithoutOrder("X-YAHOO", "yahoo")
-            .addNodeWithoutOrder("X-MSN", "msn")
-            .addNodeWithoutOrder("X-NETMEETING", "netmeeting")
-            .addNodeWithoutOrder("X-AIM", "aim");
+        VCardVerifier verifier = new VCardVerifier(resolver, version);
+        verifier.addPropertyNodesVerifierWithEmptyName()
+                .addNodeWithoutOrder("X-JABBER", "jabber")
+                .addNodeWithoutOrder("X-ICQ", "icq")
+                .addNodeWithoutOrder("X-GOOGLE-TALK", "google talk")
+                .addNodeWithoutOrder("X-QQ", "qq")
+                .addNodeWithoutOrder("X-SKYPE-USERNAME", "skype")
+                .addNodeWithoutOrder("X-YAHOO", "yahoo")
+                .addNodeWithoutOrder("X-MSN", "msn")
+                .addNodeWithoutOrder("X-NETMEETING", "netmeeting")
+                .addNodeWithoutOrder("X-AIM", "aim");
 
-        verifyOneComposition(resolver, handler, version);
+        verifier.verify();
     }
 
     public void testImBasiV21() {
@@ -735,22 +702,23 @@
     private void testImPrefHandlingCommon(int version) {
         ExportTestResolver resolver = new ExportTestResolver();
 
-        ContentValues contentValues = resolver.buildData(Im.CONTENT_ITEM_TYPE);
-        contentValues.put(Im.PROTOCOL, Im.PROTOCOL_AIM);
-        contentValues.put(Im.DATA, "aim1");
+        ContactEntry entry = resolver.buildContactEntry();
+        entry.buildData(Im.CONTENT_ITEM_TYPE)
+                .put(Im.PROTOCOL, Im.PROTOCOL_AIM)
+                .put(Im.DATA, "aim1");
 
-        contentValues = resolver.buildData(Im.CONTENT_ITEM_TYPE);
-        contentValues.put(Im.PROTOCOL, Im.PROTOCOL_AIM);
-        contentValues.put(Im.DATA, "aim2");
-        contentValues.put(Im.TYPE, Im.TYPE_HOME);
-        contentValues.put(Im.IS_PRIMARY, 1);
+        entry.buildData(Im.CONTENT_ITEM_TYPE)
+                .put(Im.PROTOCOL, Im.PROTOCOL_AIM)
+                .put(Im.DATA, "aim2")
+                .put(Im.TYPE, Im.TYPE_HOME)
+                .put(Im.IS_PRIMARY, 1);
 
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
-        handler.addNewVerifierWithEmptyName()
-            .addNodeWithoutOrder("X-AIM", "aim1")
-            .addNodeWithoutOrder("X-AIM", "aim2", new TypeSet("HOME", "PREF"));
+        VCardVerifier verifier = new VCardVerifier(resolver, version);
+        verifier.addPropertyNodesVerifierWithEmptyName()
+                .addNodeWithoutOrder("X-AIM", "aim1")
+                .addNodeWithoutOrder("X-AIM", "aim2", new TypeSet("HOME", "PREF"));
 
-        verifyOneComposition(resolver, handler, version);
+        verifier.verify();
     }
 
     public void testImPrefHandlingV21() {
@@ -764,21 +732,21 @@
     private void testWebsiteCommon(int version) {
         ExportTestResolver resolver = new ExportTestResolver();
 
-        ContentValues contentValues = resolver.buildData(Website.CONTENT_ITEM_TYPE);
-        contentValues.put(Website.URL, "http://website.example.android.com/index.html");
-        contentValues.put(Website.TYPE, Website.TYPE_BLOG);
+        ContactEntry entry = resolver.buildContactEntry();
+        entry.buildData(Website.CONTENT_ITEM_TYPE)
+                .put(Website.URL, "http://website.example.android.com/index.html")
+                .put(Website.TYPE, Website.TYPE_BLOG);
 
-        contentValues = resolver.buildData(Website.CONTENT_ITEM_TYPE);
-        contentValues.put(Website.URL, "ftp://ftp.example.android.com/index.html");
-        contentValues.put(Website.TYPE, Website.TYPE_FTP);
+        entry.buildData(Website.CONTENT_ITEM_TYPE)
+                .put(Website.URL, "ftp://ftp.example.android.com/index.html")
+                .put(Website.TYPE, Website.TYPE_FTP);
 
         // We drop TYPE information since vCard (especially 3.0) does not allow us to emit it.
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
-        handler.addNewVerifierWithEmptyName()
-            .addNodeWithoutOrder("URL", "ftp://ftp.example.android.com/index.html")
-            .addNodeWithoutOrder("URL", "http://website.example.android.com/index.html");
-
-        verifyOneComposition(resolver, handler, version);
+        VCardVerifier verifier = new VCardVerifier(resolver, version);
+        verifier.addPropertyNodesVerifierWithEmptyName()
+                .addNodeWithoutOrder("URL", "ftp://ftp.example.android.com/index.html")
+                .addNodeWithoutOrder("URL", "http://website.example.android.com/index.html");
+        verifier.verify();
     }
 
     public void testWebsiteV21() {
@@ -792,32 +760,29 @@
     private void testEventCommon(int version) {
         ExportTestResolver resolver = new ExportTestResolver();
 
-        ContentValues contentValues = resolver.buildData(Event.CONTENT_ITEM_TYPE);
-        contentValues.put(Event.TYPE, Event.TYPE_ANNIVERSARY);
-        contentValues.put(Event.START_DATE, "1982-06-16");
+        ContactEntry entry = resolver.buildContactEntry();
+        entry.buildData(Event.CONTENT_ITEM_TYPE)
+                .put(Event.TYPE, Event.TYPE_ANNIVERSARY)
+                .put(Event.START_DATE, "1982-06-16");
+        entry.buildData(Event.CONTENT_ITEM_TYPE)
+                .put(Event.TYPE, Event.TYPE_BIRTHDAY)
+                .put(Event.START_DATE, "2008-10-22");
+        entry.buildData(Event.CONTENT_ITEM_TYPE)
+                .put(Event.TYPE, Event.TYPE_OTHER)
+                .put(Event.START_DATE, "2018-03-12");
+        entry.buildData(Event.CONTENT_ITEM_TYPE)
+                .put(Event.TYPE, Event.TYPE_CUSTOM)
+                .put(Event.LABEL, "The last day")
+                .put(Event.START_DATE, "When the Tower of Hanoi with 64 rings is completed.");
+        entry.buildData(Event.CONTENT_ITEM_TYPE)
+                .put(Event.TYPE, Event.TYPE_BIRTHDAY)
+                .put(Event.START_DATE, "2009-05-19");
 
-        contentValues = resolver.buildData(Event.CONTENT_ITEM_TYPE);
-        contentValues.put(Event.TYPE, Event.TYPE_BIRTHDAY);
-        contentValues.put(Event.START_DATE, "2008-10-22");
+        VCardVerifier verifier = new VCardVerifier(resolver, version);
+        verifier.addPropertyNodesVerifierWithEmptyName()
+                .addNodeWithoutOrder("BDAY", "2008-10-22");
 
-        contentValues = resolver.buildData(Event.CONTENT_ITEM_TYPE);
-        contentValues.put(Event.TYPE, Event.TYPE_OTHER);
-        contentValues.put(Event.START_DATE, "2018-03-12");
-
-        contentValues = resolver.buildData(Event.CONTENT_ITEM_TYPE);
-        contentValues.put(Event.TYPE, Event.TYPE_CUSTOM);
-        contentValues.put(Event.LABEL, "The last day");
-        contentValues.put(Event.START_DATE, "When the Tower of Hanoi with 64 rings is completed.");
-
-        contentValues = resolver.buildData(Event.CONTENT_ITEM_TYPE);
-        contentValues.put(Event.TYPE, Event.TYPE_BIRTHDAY);
-        contentValues.put(Event.START_DATE, "2009-05-19");
-
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
-        handler.addNewVerifierWithEmptyName()
-            .addNodeWithoutOrder("BDAY", "2008-10-22");
-
-        verifyOneComposition(resolver, handler, version);
+        verifier.verify();
     }
 
     public void testEventV21() {
@@ -831,19 +796,19 @@
     private void testNoteCommon(int version) {
         ExportTestResolver resolver = new ExportTestResolver();
 
-        ContentValues contentValues = resolver.buildData(Note.CONTENT_ITEM_TYPE);
-        contentValues.put(Note.NOTE, "note1");
+        ContactEntry entry = resolver.buildContactEntry();
+        entry.buildData(Note.CONTENT_ITEM_TYPE)
+                .put(Note.NOTE, "note1");
+        entry.buildData(Note.CONTENT_ITEM_TYPE)
+                .put(Note.NOTE, "note2")
+                .put(Note.IS_PRIMARY, 1);  // Just ignored.
 
-        contentValues = resolver.buildData(Note.CONTENT_ITEM_TYPE);
-        contentValues.put(Note.NOTE, "note2");
-        contentValues.put(Note.IS_PRIMARY, 1);  // Just ignored.
+        VCardVerifier verifier = new VCardVerifier(resolver, version);
+        verifier.addPropertyNodesVerifierWithEmptyName()
+                .addNodeWithOrder("NOTE", "note1")
+                .addNodeWithOrder("NOTE", "note2");
 
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
-        handler.addNewVerifierWithEmptyName()
-            .addNodeWithOrder("NOTE", "note1")
-            .addNodeWithOrder("NOTE", "note2");
-
-        verifyOneComposition(resolver, handler, version);
+        verifier.verify();
     }
 
     public void testNoteV21() {
@@ -857,22 +822,23 @@
     private void testPhotoCommon(int version) {
         final boolean isV30 = version == V30;
         ExportTestResolver resolver = new ExportTestResolver();
-        ContentValues contentValues = resolver.buildData(StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredName.FAMILY_NAME, "PhotoTest");
-
-        contentValues = resolver.buildData(Photo.CONTENT_ITEM_TYPE);
-        contentValues.put(Photo.PHOTO, sPhotoByteArray);
+        ContactEntry entry = resolver.buildContactEntry();
+        entry.buildData(StructuredName.CONTENT_ITEM_TYPE)
+                .put(StructuredName.FAMILY_NAME, "PhotoTest");
+        entry.buildData(Photo.CONTENT_ITEM_TYPE)
+                .put(Photo.PHOTO, sPhotoByteArray);
 
         ContentValues contentValuesForPhoto = new ContentValues();
         contentValuesForPhoto.put("ENCODING", (isV30 ? "b" : "BASE64"));
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
-        handler.addNewVerifier()
-            .addNodeWithoutOrder("FN", "PhotoTest")
-            .addNodeWithoutOrder("N", "PhotoTest;;;;", Arrays.asList("PhotoTest", "", "", "", ""))
-            .addNodeWithOrder("PHOTO", null, null, sPhotoByteArray,
-                    contentValuesForPhoto, new TypeSet("JPEG"), null);
+        VCardVerifier verifier = new VCardVerifier(resolver, version);
+        verifier.addPropertyNodesVerifierElem()
+                .addNodeWithoutOrder("FN", "PhotoTest")
+                .addNodeWithoutOrder("N", "PhotoTest;;;;",
+                        Arrays.asList("PhotoTest", "", "", "", ""))
+                .addNodeWithOrder("PHOTO", null, null, sPhotoByteArray,
+                        contentValuesForPhoto, new TypeSet("JPEG"), null);
 
-        verifyOneComposition(resolver, handler, version);
+        verifier.verify();
     }
 
     public void testPhotoV21() {
@@ -886,21 +852,22 @@
     public void testV30HandleEscape() {
         final int version = V30;
         ExportTestResolver resolver = new ExportTestResolver();
-        ContentValues contentValues = resolver.buildData(StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredName.FAMILY_NAME, "\\");
-        contentValues.put(StructuredName.GIVEN_NAME, ";");
-        contentValues.put(StructuredName.MIDDLE_NAME, ",");
-        contentValues.put(StructuredName.PREFIX, "\n");
-        contentValues.put(StructuredName.DISPLAY_NAME, "[<{Unescaped:Asciis}>]");
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, version);
+        resolver.buildContactEntry().buildData(StructuredName.CONTENT_ITEM_TYPE)
+                .put(StructuredName.FAMILY_NAME, "\\")
+                .put(StructuredName.GIVEN_NAME, ";")
+                .put(StructuredName.MIDDLE_NAME, ",")
+                .put(StructuredName.PREFIX, "\n")
+                .put(StructuredName.DISPLAY_NAME, "[<{Unescaped:Asciis}>]");
+        VCardVerifier verifier = new VCardVerifier(resolver, version);
         // Verifies the vCard String correctly escapes each character which must be escaped.
-        handler.addExpectedLine("N:\\\\;\\;;\\,;\\n;")
-            .addExpectedLine("FN:[<{Unescaped:Asciis}>]");
-        handler.addNewVerifier()
-            .addNodeWithoutOrder("FN", "[<{Unescaped:Asciis}>]")
-            .addNodeWithoutOrder("N", Arrays.asList("\\", ";", ",", "\n", ""));
+        verifier.addLineVerifier()
+                .addExpected("N:\\\\;\\;;\\,;\\n;")
+                .addExpected("FN:[<{Unescaped:Asciis}>]");
+        verifier.addPropertyNodesVerifierElem()
+                .addNodeWithoutOrder("FN", "[<{Unescaped:Asciis}>]")
+                .addNodeWithoutOrder("N", Arrays.asList("\\", ";", ",", "\n", ""));
 
-        verifyOneComposition(resolver, handler, version);
+        verifier.verify();
     }
 
     /**
@@ -910,18 +877,16 @@
      */
     public void testNickNameV21() {
         ExportTestResolver resolver = new ExportTestResolver();
-        ContentValues contentValues = resolver.buildData(Nickname.CONTENT_ITEM_TYPE);
-        contentValues.put(Nickname.NAME, "Nicky");
+        resolver.buildContactEntry().buildData(Nickname.CONTENT_ITEM_TYPE)
+                .put(Nickname.NAME, "Nicky");
 
-        ContactStructVerifier verifier = new ContactStructVerifier();
-        contentValues = verifier.createExpected(Nickname.CONTENT_ITEM_TYPE);
-        contentValues.put(Nickname.NAME, "Nicky");
-
-        VCardVerificationHandler handler = new VCardVerificationHandler(this, verifier, V21);
-        handler.addNewVerifierWithEmptyName()
-            .addNodeWithOrder("X-ANDROID-CUSTOM",
-                    Nickname.CONTENT_ITEM_TYPE + ";Nicky;;;;;;;;;;;;;;");
-
-        verifyOneComposition(resolver, handler, V21);
+        VCardVerifier verifier = new VCardVerifier(resolver, V21);
+        verifier.addPropertyNodesVerifierWithEmptyName()
+                .addNodeWithOrder("X-ANDROID-CUSTOM",
+                        Nickname.CONTENT_ITEM_TYPE + ";Nicky;;;;;;;;;;;;;;");
+        verifier.addImportVerifier()
+                .addExpected(Nickname.CONTENT_ITEM_TYPE)
+                        .put(Nickname.NAME, "Nicky");
+        verifier.verify();
     }
 }
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardImporterTests.java b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardImporterTests.java
index 4f2fa0a..1aa334a 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardImporterTests.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardImporterTests.java
@@ -19,7 +19,6 @@
 import android.content.ContentValues;
 import android.pim.vcard.VCardConfig;
 import android.pim.vcard.VCardParser_V21;
-import android.pim.vcard.VCardParser_V30;
 import android.pim.vcard.exception.VCardException;
 import android.provider.ContactsContract.Data;
 import android.provider.ContactsContract.CommonDataKinds.Email;
@@ -33,7 +32,7 @@
 import android.provider.ContactsContract.CommonDataKinds.Website;
 
 import com.android.unit_tests.R;
-import com.android.unit_tests.vcard.PropertyNodesVerifier.TypeSet;
+import com.android.unit_tests.vcard.PropertyNodesVerifierElem.TypeSet;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -410,56 +409,52 @@
     }
 
     public void testV21SimpleCase1_Parsing() throws IOException, VCardException {
-        VCardParser_V21 parser = new VCardParser_V21();
-        VNodeBuilder builder = new VNodeBuilder();
-        InputStream is = getContext().getResources().openRawResource(R.raw.v21_simple_1);
-        assertEquals(true, parser.parse(is,"ISO-8859-1", builder));
-        is.close();
-        assertEquals(1, builder.vNodeList.size());
-        PropertyNodesVerifier verifier = new PropertyNodesVerifier(this)
-            .addNodeWithOrder("N", "Ando;Roid;", Arrays.asList("Ando", "Roid", ""));
-        verifier.verify(builder.vNodeList.get(0));
+        PropertyNodesVerifier verifier = new PropertyNodesVerifier(this);
+        verifier.addPropertyNodesVerifierElem()
+                .addNodeWithOrder("N", "Ando;Roid;", Arrays.asList("Ando", "Roid", ""));
+        verifier.verify(R.raw.v21_simple_1, V21);
     }
 
     public void testV21SimpleCase1_Type_Generic() throws IOException, VCardException {
-        ContactStructVerifier verifier = new ContactStructVerifier();
-        ContentValues contentValues =
-            verifier.createExpected(StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredName.FAMILY_NAME, "Ando");
-        contentValues.put(StructuredName.GIVEN_NAME, "Roid");
-        contentValues.put(StructuredName.DISPLAY_NAME, "Roid Ando");
+        ImportVerifier verifier = new ImportVerifier();
+        verifier.addImportVerifierElem()
+                .addExpected(StructuredName.CONTENT_ITEM_TYPE)
+                        .put(StructuredName.FAMILY_NAME, "Ando")
+                        .put(StructuredName.GIVEN_NAME, "Roid")
+                        .put(StructuredName.DISPLAY_NAME, "Roid Ando");
         verifier.verify(R.raw.v21_simple_1, VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
     }
 
     public void testV21SimpleCase1_Type_Japanese() throws IOException, VCardException {
-        ContactStructVerifier verifier = new ContactStructVerifier();
-        ContentValues contentValues =
-            verifier.createExpected(StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredName.FAMILY_NAME, "Ando");
-        contentValues.put(StructuredName.GIVEN_NAME, "Roid");
-        // If name-related strings only contains printable Ascii, the order is remained to be US's:
-        // "Prefix Given Middle Family Suffix"
-        contentValues.put(StructuredName.DISPLAY_NAME, "Roid Ando");
+        ImportVerifier verifier = new ImportVerifier();
+        verifier.addImportVerifierElem()
+                .addExpected(StructuredName.CONTENT_ITEM_TYPE)
+                        .put(StructuredName.FAMILY_NAME, "Ando")
+                        .put(StructuredName.GIVEN_NAME, "Roid")
+                        // If name-related strings only contains printable Ascii,
+                        // the order is remained to be US's:
+                        // "Prefix Given Middle Family Suffix"
+                        .put(StructuredName.DISPLAY_NAME, "Roid Ando");
         verifier.verify(R.raw.v21_simple_1, VCardConfig.VCARD_TYPE_V21_JAPANESE_SJIS);
     }
 
     public void testV21SimpleCase2() throws IOException, VCardException {
-        ContactStructVerifier verifier = new ContactStructVerifier();
-        ContentValues contentValues =
-            verifier.createExpected(StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredName.DISPLAY_NAME, "Ando Roid");
+        ImportVerifier verifier = new ImportVerifier();
+        verifier.addImportVerifierElem()
+                .addExpected(StructuredName.CONTENT_ITEM_TYPE)
+                        .put(StructuredName.DISPLAY_NAME, "Ando Roid");
         verifier.verify(R.raw.v21_simple_2, VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
     }
 
     public void testV21SimpleCase3() throws IOException, VCardException {
-        ContactStructVerifier verifier = new ContactStructVerifier();
-        ContentValues contentValues =
-            verifier.createExpected(StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredName.FAMILY_NAME, "Ando");
-        contentValues.put(StructuredName.GIVEN_NAME, "Roid");
-        // "FN" field should be prefered since it should contain the original order intended by
-        // the author of the file.
-        contentValues.put(StructuredName.DISPLAY_NAME, "Ando Roid");
+        ImportVerifier verifier = new ImportVerifier();
+        verifier.addImportVerifierElem()
+                .addExpected(StructuredName.CONTENT_ITEM_TYPE)
+                        .put(StructuredName.FAMILY_NAME, "Ando")
+                        .put(StructuredName.GIVEN_NAME, "Roid")
+                        // "FN" field should be prefered since it should contain the original
+                        // order intended by the author of the file.
+                        .put(StructuredName.DISPLAY_NAME, "Ando Roid");
         verifier.verify(R.raw.v21_simple_3, VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
     }
 
@@ -467,18 +462,13 @@
      * Tests ';' is properly handled by VCardParser implementation.
      */
     public void testV21BackslashCase_Parsing() throws IOException, VCardException {
-        VCardParser_V21 parser = new VCardParser_V21();
-        VNodeBuilder builder = new VNodeBuilder();
-        InputStream is = getContext().getResources().openRawResource(R.raw.v21_backslash);
-        assertEquals(true, parser.parse(is,"ISO-8859-1", builder));
-        is.close();
-        assertEquals(1, builder.vNodeList.size());
-        PropertyNodesVerifier verifier = new PropertyNodesVerifier(this)
-            .addNodeWithOrder("VERSION", "2.1")
-            .addNodeWithOrder("N", ";A;B\\;C\\;;D;:E;\\\\;",
-                    Arrays.asList("", "A;B\\", "C\\;", "D", ":E", "\\\\", ""))
-            .addNodeWithOrder("FN", "A;B\\C\\;D:E\\\\");
-        verifier.verify(builder.vNodeList.get(0));
+        PropertyNodesVerifier verifier = new PropertyNodesVerifier(this);
+        verifier.addPropertyNodesVerifierElem()
+                .addNodeWithOrder("VERSION", "2.1")
+                .addNodeWithOrder("N", ";A;B\\;C\\;;D;:E;\\\\;",
+                        Arrays.asList("", "A;B\\", "C\\;", "D", ":E", "\\\\", ""))
+                .addNodeWithOrder("FN", "A;B\\C\\;D:E\\\\");
+        verifier.verify(R.raw.v21_backslash, V21);
     }
 
     /**
@@ -486,43 +476,43 @@
      * inserts name related data.
      */
     public void testV21BackslashCase() throws IOException, VCardException {
-        ContactStructVerifier verifier = new ContactStructVerifier();
-        ContentValues contentValues =
-            verifier.createExpected(StructuredName.CONTENT_ITEM_TYPE);
-        // FAMILY_NAME is empty and removed in this test...
-        contentValues.put(StructuredName.GIVEN_NAME, "A;B\\");
-        contentValues.put(StructuredName.MIDDLE_NAME, "C\\;");
-        contentValues.put(StructuredName.PREFIX, "D");
-        contentValues.put(StructuredName.SUFFIX, ":E");
-        contentValues.put(StructuredName.DISPLAY_NAME, "A;B\\C\\;D:E\\\\");
+        ImportVerifier verifier = new ImportVerifier();
+        verifier.addImportVerifierElem()
+                .addExpected(StructuredName.CONTENT_ITEM_TYPE)
+                        // FAMILY_NAME is empty and removed in this test...
+                        .put(StructuredName.GIVEN_NAME, "A;B\\")
+                        .put(StructuredName.MIDDLE_NAME, "C\\;")
+                        .put(StructuredName.PREFIX, "D")
+                        .put(StructuredName.SUFFIX, ":E")
+                        .put(StructuredName.DISPLAY_NAME, "A;B\\C\\;D:E\\\\");
         verifier.verify(R.raw.v21_backslash, VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
     }
 
     public void testOrgBeforTitle() throws IOException, VCardException {
-        ContactStructVerifier verifier = new ContactStructVerifier();
-        ContentValues contentValues =
-            verifier.createExpected(StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredName.DISPLAY_NAME, "Normal Guy");
+        ImportVerifier verifier = new ImportVerifier();
+        ImportVerifierElem elem = verifier.addImportVerifierElem();
+        elem.addExpected(StructuredName.CONTENT_ITEM_TYPE)
+                .put(StructuredName.DISPLAY_NAME, "Normal Guy");
 
-        contentValues = verifier.createExpected(Organization.CONTENT_ITEM_TYPE);
-        contentValues.put(Organization.COMPANY, "Company");
-        contentValues.put(Organization.DEPARTMENT, "Organization Devision Room Sheet No.");
-        contentValues.put(Organization.TITLE, "Excellent Janitor");
-        contentValues.put(Organization.TYPE, Organization.TYPE_WORK);
+        elem.addExpected(Organization.CONTENT_ITEM_TYPE)
+                .put(Organization.COMPANY, "Company")
+                .put(Organization.DEPARTMENT, "Organization Devision Room Sheet No.")
+                .put(Organization.TITLE, "Excellent Janitor")
+                .put(Organization.TYPE, Organization.TYPE_WORK);
         verifier.verify(R.raw.v21_org_before_title, VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
     }
 
     public void testTitleBeforOrg() throws IOException, VCardException {
-        ContactStructVerifier verifier = new ContactStructVerifier();
-        ContentValues contentValues =
-            verifier.createExpected(StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredName.DISPLAY_NAME, "Nice Guy");
+        ImportVerifier verifier = new ImportVerifier();
+        ImportVerifierElem elem = verifier.addImportVerifierElem();
+        elem.addExpected(StructuredName.CONTENT_ITEM_TYPE)
+                .put(StructuredName.DISPLAY_NAME, "Nice Guy");
 
-        contentValues = verifier.createExpected(Organization.CONTENT_ITEM_TYPE);
-        contentValues.put(Organization.COMPANY, "Marverous");
-        contentValues.put(Organization.DEPARTMENT, "Perfect Great Good Bad Poor");
-        contentValues.put(Organization.TITLE, "Cool Title");
-        contentValues.put(Organization.TYPE, Organization.TYPE_WORK);
+        elem.addExpected(Organization.CONTENT_ITEM_TYPE)
+                .put(Organization.COMPANY, "Marverous")
+                .put(Organization.DEPARTMENT, "Perfect Great Good Bad Poor")
+                .put(Organization.TITLE, "Cool Title")
+                .put(Organization.TYPE, Organization.TYPE_WORK);
         verifier.verify(R.raw.v21_title_before_org, VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
     }
 
@@ -531,49 +521,49 @@
      * The data contain three cases: one "PREF", no "PREF" and multiple "PREF", in each type.
      */
     public void testV21PrefToIsPrimary() throws IOException, VCardException {
-        ContactStructVerifier verifier = new ContactStructVerifier();
-        ContentValues contentValues =
-            verifier.createExpected(StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredName.DISPLAY_NAME, "Smith");
+        ImportVerifier verifier = new ImportVerifier();
+        ImportVerifierElem elem = verifier.addImportVerifierElem();
+        elem.addExpected(StructuredName.CONTENT_ITEM_TYPE)
+                .put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
+                .put(StructuredName.DISPLAY_NAME, "Smith");
 
-        contentValues = verifier.createExpected(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.NUMBER, "1");
-        contentValues.put(Phone.TYPE, Phone.TYPE_HOME);
+        elem.addExpected(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.NUMBER, "1")
+                .put(Phone.TYPE, Phone.TYPE_HOME);
 
-        contentValues = verifier.createExpected(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.NUMBER, "2");
-        contentValues.put(Phone.TYPE, Phone.TYPE_WORK);
-        contentValues.put(Phone.IS_PRIMARY, 1);
+        elem.addExpected(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.NUMBER, "2")
+                .put(Phone.TYPE, Phone.TYPE_WORK)
+                .put(Phone.IS_PRIMARY, 1);
 
-        contentValues = verifier.createExpected(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.NUMBER, "3");
-        contentValues.put(Phone.TYPE, Phone.TYPE_ISDN);
+        elem.addExpected(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.NUMBER, "3")
+                .put(Phone.TYPE, Phone.TYPE_ISDN);
 
-        contentValues = verifier.createExpected(Email.CONTENT_ITEM_TYPE);
-        contentValues.put(Email.DATA, "test@example.com");
-        contentValues.put(Email.TYPE, Email.TYPE_HOME);
-        contentValues.put(Email.IS_PRIMARY, 1);
+        elem.addExpected(Email.CONTENT_ITEM_TYPE)
+                .put(Email.DATA, "test@example.com")
+                .put(Email.TYPE, Email.TYPE_HOME)
+                .put(Email.IS_PRIMARY, 1);
 
-        contentValues = verifier.createExpected(Email.CONTENT_ITEM_TYPE);
-        contentValues.put(Email.DATA, "test2@examination.com");
-        contentValues.put(Email.TYPE, Email.TYPE_MOBILE);
-        contentValues.put(Email.IS_PRIMARY, 1);
+        elem.addExpected(Email.CONTENT_ITEM_TYPE)
+                .put(Email.DATA, "test2@examination.com")
+                .put(Email.TYPE, Email.TYPE_MOBILE)
+                .put(Email.IS_PRIMARY, 1);
 
-        contentValues = verifier.createExpected(Organization.CONTENT_ITEM_TYPE);
-        contentValues.put(Organization.COMPANY, "Company");
-        contentValues.put(Organization.TITLE, "Engineer");
-        contentValues.put(Organization.TYPE, Organization.TYPE_WORK);
+        elem.addExpected(Organization.CONTENT_ITEM_TYPE)
+                .put(Organization.COMPANY, "Company")
+                .put(Organization.TITLE, "Engineer")
+                .put(Organization.TYPE, Organization.TYPE_WORK);
 
-        contentValues = verifier.createExpected(Organization.CONTENT_ITEM_TYPE);
-        contentValues.put(Organization.COMPANY, "Mystery");
-        contentValues.put(Organization.TITLE, "Blogger");
-        contentValues.put(Organization.TYPE, Organization.TYPE_WORK);
+        elem.addExpected(Organization.CONTENT_ITEM_TYPE)
+                .put(Organization.COMPANY, "Mystery")
+                .put(Organization.TITLE, "Blogger")
+                .put(Organization.TYPE, Organization.TYPE_WORK);
 
-        contentValues = verifier.createExpected(Organization.CONTENT_ITEM_TYPE);
-        contentValues.put(Organization.COMPANY, "Poetry");
-        contentValues.put(Organization.TITLE, "Poet");
-        contentValues.put(Organization.TYPE, Organization.TYPE_WORK);
+        elem.addExpected(Organization.CONTENT_ITEM_TYPE)
+                .put(Organization.COMPANY, "Poetry")
+                .put(Organization.TITLE, "Poet")
+                .put(Organization.TYPE, Organization.TYPE_WORK);
         verifier.verify(R.raw.v21_pref_handling, VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
     }
 
@@ -581,62 +571,59 @@
      * Tests all the properties in a complicated vCard are correctly parsed by the VCardParser.
      */
     public void testV21ComplicatedCase_Parsing() throws IOException, VCardException {
-        VCardParser_V21 parser = new VCardParser_V21();
-        VNodeBuilder builder = new VNodeBuilder();
-        InputStream is = getContext().getResources().openRawResource(R.raw.v21_complicated);
-        assertEquals(true, parser.parse(is,"ISO-8859-1", builder));
-        is.close();
-        assertEquals(1, builder.vNodeList.size());
         ContentValues contentValuesForQP = new ContentValues();
         contentValuesForQP.put("ENCODING", "QUOTED-PRINTABLE");
         ContentValues contentValuesForPhoto = new ContentValues();
         contentValuesForPhoto.put("ENCODING", "BASE64");
-        PropertyNodesVerifier verifier = new PropertyNodesVerifier(this)
-            .addNodeWithOrder("VERSION", "2.1")
-            .addNodeWithOrder("N", "Gump;Forrest;Hoge;Pos;Tao",
-                    Arrays.asList("Gump", "Forrest", "Hoge", "Pos", "Tao"))
-            .addNodeWithOrder("FN", "Joe Due")
-            .addNodeWithOrder("ORG", "Gump Shrimp Co.;Sales Dept.;Manager;Fish keeper",
-                    Arrays.asList("Gump Shrimp Co.", "Sales Dept.;Manager", "Fish keeper"))
-            .addNodeWithOrder("ROLE", "Fish Cake Keeper!")
-            .addNodeWithOrder("TITLE", "Shrimp Man")
-            .addNodeWithOrder("X-CLASS", "PUBLIC")
-            .addNodeWithOrder("TEL", "(111) 555-1212", new TypeSet("WORK", "VOICE"))
-            .addNodeWithOrder("TEL", "(404) 555-1212", new TypeSet("HOME", "VOICE"))
-            .addNodeWithOrder("TEL", "0311111111", new TypeSet("CELL"))
-            .addNodeWithOrder("TEL", "0322222222", new TypeSet("VIDEO"))
-            .addNodeWithOrder("TEL", "0333333333", new TypeSet("VOICE"))
-            .addNodeWithOrder("ADR", ";;100 Waters Edge;Baytown;LA;30314;United States of America",
-                    Arrays.asList("", "", "100 Waters Edge", "Baytown",
-                            "LA", "30314", "United States of America"),
-                            null, null, new TypeSet("WORK"), null)
-            .addNodeWithOrder("LABEL",
-                    "100 Waters Edge\r\nBaytown, LA 30314\r\nUnited  States of America",
-                    null, null, contentValuesForQP, new TypeSet("WORK"), null)
-            .addNodeWithOrder("ADR",
-                    ";;42 Plantation St.;Baytown;LA;30314;United States of America",
-                    Arrays.asList("", "", "42 Plantation St.", "Baytown",
-                            "LA", "30314", "United States of America"), null, null,
-                    new TypeSet("HOME"), null)
-            .addNodeWithOrder("LABEL",
-                    "42 Plantation St.\r\nBaytown, LA 30314\r\nUnited  States of America",
-                    null, null, contentValuesForQP,
-                    new TypeSet("HOME"), null)
-            .addNodeWithOrder("EMAIL", "forrestgump@walladalla.com", new TypeSet("PREF", "INTERNET"))
-            .addNodeWithOrder("EMAIL", "cell@example.com", new TypeSet("CELL"))
-            .addNodeWithOrder("NOTE", "The following note is the example from RFC 2045.")
-            .addNodeWithOrder("NOTE",
-                    "Now's the time for all folk to come to the aid of their country.",
-                    null, null, contentValuesForQP, null, null)
-            .addNodeWithOrder("PHOTO", null,
-                    null, sPhotoByteArrayForComplicatedCase, contentValuesForPhoto,
-                    new TypeSet("JPEG"), null)
-            .addNodeWithOrder("X-ATTRIBUTE", "Some String")
-            .addNodeWithOrder("BDAY", "19800101")
-            .addNodeWithOrder("GEO", "35.6563854,139.6994233")
-            .addNodeWithOrder("URL", "http://www.example.com/")
-            .addNodeWithOrder("REV", "20080424T195243Z");
-        verifier.verify(builder.vNodeList.get(0));
+        PropertyNodesVerifier verifier = new PropertyNodesVerifier(this);
+        verifier.addPropertyNodesVerifierElem()
+                .addNodeWithOrder("VERSION", "2.1")
+                .addNodeWithOrder("N", "Gump;Forrest;Hoge;Pos;Tao",
+                        Arrays.asList("Gump", "Forrest", "Hoge", "Pos", "Tao"))
+                .addNodeWithOrder("FN", "Joe Due")
+                .addNodeWithOrder("ORG", "Gump Shrimp Co.;Sales Dept.;Manager;Fish keeper",
+                        Arrays.asList("Gump Shrimp Co.", "Sales Dept.;Manager", "Fish keeper"))
+                .addNodeWithOrder("ROLE", "Fish Cake Keeper!")
+                .addNodeWithOrder("TITLE", "Shrimp Man")
+                .addNodeWithOrder("X-CLASS", "PUBLIC")
+                .addNodeWithOrder("TEL", "(111) 555-1212", new TypeSet("WORK", "VOICE"))
+                .addNodeWithOrder("TEL", "(404) 555-1212", new TypeSet("HOME", "VOICE"))
+                .addNodeWithOrder("TEL", "0311111111", new TypeSet("CELL"))
+                .addNodeWithOrder("TEL", "0322222222", new TypeSet("VIDEO"))
+                .addNodeWithOrder("TEL", "0333333333", new TypeSet("VOICE"))
+                .addNodeWithOrder("ADR",
+                        ";;100 Waters Edge;Baytown;LA;30314;United States of America",
+                        Arrays.asList("", "", "100 Waters Edge", "Baytown",
+                                "LA", "30314", "United States of America"),
+                                null, null, new TypeSet("WORK"), null)
+                .addNodeWithOrder("LABEL",
+                        "100 Waters Edge\r\nBaytown, LA 30314\r\nUnited  States of America",
+                        null, null, contentValuesForQP, new TypeSet("WORK"), null)
+                .addNodeWithOrder("ADR",
+                        ";;42 Plantation St.;Baytown;LA;30314;United States of America",
+                        Arrays.asList("", "", "42 Plantation St.", "Baytown",
+                                "LA", "30314", "United States of America"), null, null,
+                                new TypeSet("HOME"), null)
+                .addNodeWithOrder("LABEL",
+                        "42 Plantation St.\r\nBaytown, LA 30314\r\nUnited  States of America",
+                        null, null, contentValuesForQP,
+                        new TypeSet("HOME"), null)
+                .addNodeWithOrder("EMAIL", "forrestgump@walladalla.com",
+                        new TypeSet("PREF", "INTERNET"))
+                .addNodeWithOrder("EMAIL", "cell@example.com", new TypeSet("CELL"))
+                .addNodeWithOrder("NOTE", "The following note is the example from RFC 2045.")
+                .addNodeWithOrder("NOTE",
+                        "Now's the time for all folk to come to the aid of their country.",
+                        null, null, contentValuesForQP, null, null)
+                .addNodeWithOrder("PHOTO", null,
+                        null, sPhotoByteArrayForComplicatedCase, contentValuesForPhoto,
+                        new TypeSet("JPEG"), null)
+                .addNodeWithOrder("X-ATTRIBUTE", "Some String")
+                .addNodeWithOrder("BDAY", "19800101")
+                .addNodeWithOrder("GEO", "35.6563854,139.6994233")
+                .addNodeWithOrder("URL", "http://www.example.com/")
+                .addNodeWithOrder("REV", "20080424T195243Z");
+        verifier.verify(R.raw.v21_complicated, V21);
     }
 
     /**
@@ -644,192 +631,174 @@
      * into ContentResolver.
      */
     public void testV21ComplicatedCase() throws IOException, VCardException {
-        ContactStructVerifier verifier = new ContactStructVerifier();
-        ContentValues contentValues =
-            verifier.createExpected(StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredName.FAMILY_NAME, "Gump");
-        contentValues.put(StructuredName.GIVEN_NAME, "Forrest");
-        contentValues.put(StructuredName.MIDDLE_NAME, "Hoge");
-        contentValues.put(StructuredName.PREFIX, "Pos");
-        contentValues.put(StructuredName.SUFFIX, "Tao");
-        contentValues.put(StructuredName.DISPLAY_NAME, "Joe Due");
+        ImportVerifier verifier = new ImportVerifier();
+        ImportVerifierElem elem = verifier.addImportVerifierElem();
+        elem.addExpected(StructuredName.CONTENT_ITEM_TYPE)
+                .put(StructuredName.FAMILY_NAME, "Gump")
+                .put(StructuredName.GIVEN_NAME, "Forrest")
+                .put(StructuredName.MIDDLE_NAME, "Hoge")
+                .put(StructuredName.PREFIX, "Pos")
+                .put(StructuredName.SUFFIX, "Tao")
+                .put(StructuredName.DISPLAY_NAME, "Joe Due");
         
-        contentValues = verifier.createExpected(Organization.CONTENT_ITEM_TYPE);
-        contentValues.put(Organization.TYPE, Organization.TYPE_WORK);
-        contentValues.put(Organization.COMPANY, "Gump Shrimp Co.");
-        contentValues.put(Organization.DEPARTMENT, "Sales Dept.;Manager Fish keeper");
-        contentValues.put(Organization.TITLE, "Shrimp Man");
+        elem.addExpected(Organization.CONTENT_ITEM_TYPE)
+                .put(Organization.TYPE, Organization.TYPE_WORK)
+                .put(Organization.COMPANY, "Gump Shrimp Co.")
+                .put(Organization.DEPARTMENT, "Sales Dept.;Manager Fish keeper")
+                .put(Organization.TITLE, "Shrimp Man");
 
-        contentValues = verifier.createExpected(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.TYPE, Phone.TYPE_WORK);
-        // Phone number is expected to be formated with NAMP format in default.
-        contentValues.put(Phone.NUMBER, "111-555-1212");
+        elem.addExpected(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.TYPE, Phone.TYPE_WORK)
+                // Phone number is expected to be formated with NAMP format in default.
+                .put(Phone.NUMBER, "111-555-1212");
 
-        contentValues = verifier.createExpected(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.TYPE, Phone.TYPE_HOME);
-        contentValues.put(Phone.NUMBER, "404-555-1212");
+        elem.addExpected(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.TYPE, Phone.TYPE_HOME)
+                .put(Phone.NUMBER, "404-555-1212");
 
-        contentValues = verifier.createExpected(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.TYPE, Phone.TYPE_MOBILE);
-        contentValues.put(Phone.NUMBER, "031-111-1111");
+        elem.addExpected(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.TYPE, Phone.TYPE_MOBILE)
+                .put(Phone.NUMBER, "031-111-1111");
 
-        contentValues = verifier.createExpected(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.TYPE, Phone.TYPE_CUSTOM);
-        contentValues.put(Phone.LABEL, "VIDEO");
-        contentValues.put(Phone.NUMBER, "032-222-2222");
+        elem.addExpected(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.TYPE, Phone.TYPE_CUSTOM)
+                .put(Phone.LABEL, "VIDEO")
+                .put(Phone.NUMBER, "032-222-2222");
 
-        contentValues = verifier.createExpected(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.TYPE, Phone.TYPE_CUSTOM);
-        contentValues.put(Phone.LABEL, "VOICE");
-        contentValues.put(Phone.NUMBER, "033-333-3333");
+        elem.addExpected(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.TYPE, Phone.TYPE_CUSTOM)
+                .put(Phone.LABEL, "VOICE")
+                .put(Phone.NUMBER, "033-333-3333");
 
-        contentValues = verifier.createExpected(StructuredPostal.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredPostal.TYPE, StructuredPostal.TYPE_WORK);
-        contentValues.put(StructuredPostal.COUNTRY, "United States of America");
-        contentValues.put(StructuredPostal.POSTCODE, "30314");
-        contentValues.put(StructuredPostal.REGION, "LA");
-        contentValues.put(StructuredPostal.CITY, "Baytown");
-        contentValues.put(StructuredPostal.STREET, "100 Waters Edge");
-        contentValues.put(StructuredPostal.FORMATTED_ADDRESS,
-                "100 Waters Edge Baytown LA 30314 United States of America");
+        elem.addExpected(StructuredPostal.CONTENT_ITEM_TYPE)
+                .put(StructuredPostal.TYPE, StructuredPostal.TYPE_WORK)
+                .put(StructuredPostal.COUNTRY, "United States of America")
+                .put(StructuredPostal.POSTCODE, "30314")
+                .put(StructuredPostal.REGION, "LA")
+                .put(StructuredPostal.CITY, "Baytown")
+                .put(StructuredPostal.STREET, "100 Waters Edge")
+                .put(StructuredPostal.FORMATTED_ADDRESS,
+                        "100 Waters Edge Baytown LA 30314 United States of America");
 
-        contentValues = verifier.createExpected(StructuredPostal.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredPostal.TYPE, StructuredPostal.TYPE_HOME);
-        contentValues.put(StructuredPostal.COUNTRY, "United States of America");
-        contentValues.put(StructuredPostal.POSTCODE, "30314");
-        contentValues.put(StructuredPostal.REGION, "LA");
-        contentValues.put(StructuredPostal.CITY, "Baytown");
-        contentValues.put(StructuredPostal.STREET, "42 Plantation St.");
-        contentValues.put(StructuredPostal.FORMATTED_ADDRESS,
-                "42 Plantation St. Baytown LA 30314 United States of America");
+        elem.addExpected(StructuredPostal.CONTENT_ITEM_TYPE)
+                .put(StructuredPostal.TYPE, StructuredPostal.TYPE_HOME)
+                .put(StructuredPostal.COUNTRY, "United States of America")
+                .put(StructuredPostal.POSTCODE, "30314")
+                .put(StructuredPostal.REGION, "LA")
+                .put(StructuredPostal.CITY, "Baytown")
+                .put(StructuredPostal.STREET, "42 Plantation St.")
+                .put(StructuredPostal.FORMATTED_ADDRESS,
+                        "42 Plantation St. Baytown LA 30314 United States of America");
 
-        contentValues = verifier.createExpected(Email.CONTENT_ITEM_TYPE);
-        // "TYPE=INTERNET" -> TYPE_CUSTOM + the label "INTERNET"
-        contentValues.put(Email.TYPE, Email.TYPE_CUSTOM);
-        contentValues.put(Email.LABEL, "INTERNET");
-        contentValues.put(Email.DATA, "forrestgump@walladalla.com");
-        contentValues.put(Email.IS_PRIMARY, 1);
+        elem.addExpected(Email.CONTENT_ITEM_TYPE)
+                // "TYPE=INTERNET" -> TYPE_CUSTOM + the label "INTERNET"
+                .put(Email.TYPE, Email.TYPE_CUSTOM)
+                .put(Email.LABEL, "INTERNET")
+                .put(Email.DATA, "forrestgump@walladalla.com")
+                .put(Email.IS_PRIMARY, 1);
 
-        contentValues = verifier.createExpected(Email.CONTENT_ITEM_TYPE);
-        contentValues.put(Email.TYPE, Email.TYPE_MOBILE);
-        contentValues.put(Email.DATA, "cell@example.com");
+        elem.addExpected(Email.CONTENT_ITEM_TYPE)
+                .put(Email.TYPE, Email.TYPE_MOBILE)
+                .put(Email.DATA, "cell@example.com");
 
-        contentValues = verifier.createExpected(Note.CONTENT_ITEM_TYPE);
-        contentValues.put(Note.NOTE, "The following note is the example from RFC 2045.");
+        elem.addExpected(Note.CONTENT_ITEM_TYPE)
+                .put(Note.NOTE, "The following note is the example from RFC 2045.");
 
-        contentValues = verifier.createExpected(Note.CONTENT_ITEM_TYPE);
-        contentValues.put(Note.NOTE,
-                "Now's the time for all folk to come to the aid of their country.");
+        elem.addExpected(Note.CONTENT_ITEM_TYPE)
+                .put(Note.NOTE,
+                        "Now's the time for all folk to come to the aid of their country.");
 
-        contentValues = verifier.createExpected(Photo.CONTENT_ITEM_TYPE);
-        // No information about its image format can be inserted.
-        contentValues.put(Photo.PHOTO, sPhotoByteArrayForComplicatedCase);
+        elem.addExpected(Photo.CONTENT_ITEM_TYPE)
+                // No information about its image format can be inserted.
+                .put(Photo.PHOTO, sPhotoByteArrayForComplicatedCase);
 
-        contentValues = verifier.createExpected(Event.CONTENT_ITEM_TYPE);
-        contentValues.put(Event.START_DATE, "19800101");
-        contentValues.put(Event.TYPE, Event.TYPE_BIRTHDAY);
+        elem.addExpected(Event.CONTENT_ITEM_TYPE)
+                .put(Event.START_DATE, "19800101")
+                .put(Event.TYPE, Event.TYPE_BIRTHDAY);
 
-        contentValues = verifier.createExpected(Website.CONTENT_ITEM_TYPE);
-        contentValues.put(Website.URL, "http://www.example.com/");
-        contentValues.put(Website.TYPE, Website.TYPE_HOMEPAGE);
+        elem.addExpected(Website.CONTENT_ITEM_TYPE)
+                .put(Website.URL, "http://www.example.com/")
+                .put(Website.TYPE, Website.TYPE_HOMEPAGE);
         verifier.verify(R.raw.v21_complicated, VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
     }
 
     public void testV30Simple_Parsing() throws IOException, VCardException {
-        VCardParser_V21 parser = new VCardParser_V30();
-        VNodeBuilder builder = new VNodeBuilder();
-        InputStream is = getContext().getResources().openRawResource(R.raw.v30_simple);
-        assertEquals(true, parser.parse(is,"ISO-8859-1", builder));
-        is.close();
-        assertEquals(1, builder.vNodeList.size());
-        PropertyNodesVerifier verifier = new PropertyNodesVerifier(this)
-            .addNodeWithOrder("VERSION", "3.0")
-            .addNodeWithOrder("FN", "And Roid")
-            .addNodeWithOrder("N", "And;Roid;;;", Arrays.asList("And", "Roid", "", "", ""))
-            .addNodeWithOrder("ORG", "Open;Handset; Alliance",
-                    Arrays.asList("Open", "Handset", " Alliance"))
-            .addNodeWithOrder("SORT-STRING", "android")
-            .addNodeWithOrder("TEL", "0300000000", new TypeSet("PREF", "VOICE"))
-            .addNodeWithOrder("CLASS", "PUBLIC")
-            .addNodeWithOrder("X-GNO", "0")
-            .addNodeWithOrder("X-GN", "group0")
-            .addNodeWithOrder("X-REDUCTION", "0")
-            .addNodeWithOrder("REV", "20081031T065854Z");
-        verifier.verify(builder.vNodeList.get(0));
+        PropertyNodesVerifier verifier = new PropertyNodesVerifier(this);
+        verifier.addPropertyNodesVerifierElem()
+                .addNodeWithOrder("VERSION", "3.0")
+                .addNodeWithOrder("FN", "And Roid")
+                .addNodeWithOrder("N", "And;Roid;;;", Arrays.asList("And", "Roid", "", "", ""))
+                .addNodeWithOrder("ORG", "Open;Handset; Alliance",
+                        Arrays.asList("Open", "Handset", " Alliance"))
+                .addNodeWithOrder("SORT-STRING", "android")
+                .addNodeWithOrder("TEL", "0300000000", new TypeSet("PREF", "VOICE"))
+                .addNodeWithOrder("CLASS", "PUBLIC")
+                .addNodeWithOrder("X-GNO", "0")
+                .addNodeWithOrder("X-GN", "group0")
+                .addNodeWithOrder("X-REDUCTION", "0")
+                .addNodeWithOrder("REV", "20081031T065854Z");
+        verifier.verify(R.raw.v30_simple, V30);
     }
 
     public void testV30Simple() throws IOException, VCardException {
-        ContactStructVerifier verifier = new ContactStructVerifier();
-        ContentValues contentValues =
-            verifier.createExpected(StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredName.FAMILY_NAME, "And");
-        contentValues.put(StructuredName.GIVEN_NAME, "Roid");
-        contentValues.put(StructuredName.DISPLAY_NAME, "And Roid");
-        contentValues.put(StructuredName.PHONETIC_GIVEN_NAME, "android");
-
-        contentValues = verifier.createExpected(Organization.CONTENT_ITEM_TYPE);
-        contentValues.put(Organization.COMPANY, "Open");
-        contentValues.put(Organization.DEPARTMENT, "Handset  Alliance");
-        contentValues.put(Organization.TYPE, Organization.TYPE_WORK);
-
-        contentValues = verifier.createExpected(Phone.CONTENT_ITEM_TYPE);
-        contentValues.put(Phone.TYPE, Phone.TYPE_CUSTOM);
-        contentValues.put(Phone.LABEL, "VOICE");
-        contentValues.put(Phone.NUMBER, "030-000-0000");
-        contentValues.put(Phone.IS_PRIMARY, 1);
+        ImportVerifier verifier = new ImportVerifier();
+        ImportVerifierElem elem = verifier.addImportVerifierElem();
+        elem.addExpected(StructuredName.CONTENT_ITEM_TYPE)
+                .put(StructuredName.FAMILY_NAME, "And")
+                .put(StructuredName.GIVEN_NAME, "Roid")
+                .put(StructuredName.DISPLAY_NAME, "And Roid")
+                .put(StructuredName.PHONETIC_GIVEN_NAME, "android");
+        elem.addExpected(Organization.CONTENT_ITEM_TYPE)
+                .put(Organization.COMPANY, "Open")
+                .put(Organization.DEPARTMENT, "Handset  Alliance")
+                .put(Organization.TYPE, Organization.TYPE_WORK);
+        elem.addExpected(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.TYPE, Phone.TYPE_CUSTOM)
+                .put(Phone.LABEL, "VOICE")
+                .put(Phone.NUMBER, "030-000-0000")
+                .put(Phone.IS_PRIMARY, 1);
         verifier.verify(R.raw.v30_simple, VCardConfig.VCARD_TYPE_V30_GENERIC_UTF8);
     }
 
     public void testV21Japanese1_Parsing() throws IOException, VCardException {
-        VCardParser_V21 parser = new VCardParser_V21();
-        VNodeBuilder builder = new VNodeBuilder();
-        InputStream is = getContext().getResources().openRawResource(R.raw.v21_japanese_1);
-        assertEquals(true, parser.parse(is,"ISO-8859-1", builder));
-        is.close();
-        assertEquals(1, builder.vNodeList.size());
-        ContentValues contentValuesForShiftJis = new ContentValues();
-        contentValuesForShiftJis.put("CHARSET", "SHIFT_JIS");
-        ContentValues contentValuesForQP = new ContentValues();
-        contentValuesForQP.put("ENCODING", "QUOTED-PRINTABLE");
-        contentValuesForQP.put("CHARSET", "SHIFT_JIS");
         // Though Japanese careers append ";;;;" at the end of the value of "SOUND",
         // vCard 2.1/3.0 specification does not allow multiple values.
         // Do not need to handle it as multiple values.
-        PropertyNodesVerifier verifier = new PropertyNodesVerifier(this)
-            .addNodeWithOrder("VERSION", "2.1", null, null, null, null, null)
-            .addNodeWithOrder("N", "\u5B89\u85E4\u30ED\u30A4\u30C9;;;;",
-                    Arrays.asList("\u5B89\u85E4\u30ED\u30A4\u30C9", "", "", "", ""),
-                    null, contentValuesForShiftJis, null, null)
-            .addNodeWithOrder("SOUND", "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E;;;;",
-                    null, null, contentValuesForShiftJis,
-                    new TypeSet("X-IRMC-N"), null)
-            .addNodeWithOrder("TEL", "0300000000", null, null, null,
-                    new TypeSet("VOICE", "PREF"), null);
-        verifier.verify(builder.vNodeList.get(0));
+        ContentValues contentValuesForShiftJis = new ContentValues();
+        contentValuesForShiftJis.put("CHARSET", "SHIFT_JIS");
+        PropertyNodesVerifier verifier = new PropertyNodesVerifier(this);
+        verifier.addPropertyNodesVerifierElem()
+                .addNodeWithOrder("VERSION", "2.1", null, null, null, null, null)
+                .addNodeWithOrder("N", "\u5B89\u85E4\u30ED\u30A4\u30C9;;;;",
+                        Arrays.asList("\u5B89\u85E4\u30ED\u30A4\u30C9", "", "", "", ""),
+                        null, contentValuesForShiftJis, null, null)
+                .addNodeWithOrder("SOUND",
+                        "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E;;;;",
+                        null, null, contentValuesForShiftJis,
+                        new TypeSet("X-IRMC-N"), null)
+                .addNodeWithOrder("TEL", "0300000000", null, null, null,
+                        new TypeSet("VOICE", "PREF"), null);
+        verifier.verify(R.raw.v21_japanese_1, VCardConfig.VCARD_TYPE_V21_JAPANESE_SJIS);
     }
 
     private void testV21Japanese1Common(int resId, int vcardType, boolean japanese)
             throws IOException, VCardException {
-        ContactStructVerifier verifier = new ContactStructVerifier();
+        ImportVerifier verifier = new ImportVerifier();
+        ImportVerifierElem elem = verifier.addImportVerifierElem();
+        elem.addExpected(StructuredName.CONTENT_ITEM_TYPE)
+                .put(StructuredName.FAMILY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9")
+                .put(StructuredName.DISPLAY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9")
+                // While vCard parser does not split "SOUND" property values,
+                // ContactStruct care it.
+                .put(StructuredName.PHONETIC_FAMILY_NAME,
+                        "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E");
 
-        ContentValues contentValues =
-            verifier.createExpected(StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredName.FAMILY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9");
-        contentValues.put(StructuredName.DISPLAY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9");
-        // While vCard parser does not split "SOUND" property values, ContactStruct care it.
-        contentValues.put(StructuredName.PHONETIC_FAMILY_NAME,
-                "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E");
-
-        contentValues = verifier.createExpected(Phone.CONTENT_ITEM_TYPE);
-        // Phone number formatting is different.
-        if (japanese) {
-            contentValues.put(Phone.NUMBER, "03-0000-0000");
-        } else {
-            contentValues.put(Phone.NUMBER, "030-000-0000");
-        }
-        contentValues.put(Phone.TYPE, Phone.TYPE_CUSTOM);
-        contentValues.put(Phone.LABEL, "VOICE");
-        contentValues.put(Phone.IS_PRIMARY, 1);
+        elem.addExpected(Phone.CONTENT_ITEM_TYPE)
+                // Phone number formatting is different.
+                .put(Phone.NUMBER, (japanese ? "03-0000-0000" : "030-000-0000"))
+                .put(Phone.TYPE, Phone.TYPE_CUSTOM)
+                .put(Phone.LABEL, "VOICE")
+                .put(Phone.IS_PRIMARY, 1);
         verifier.verify(resId, vcardType);
     }
 
@@ -862,130 +831,186 @@
     }
 
     public void testV21Japanese2_Parsing() throws IOException, VCardException {
-        VCardParser_V21 parser = new VCardParser_V21();
-        VNodeBuilder builder = new VNodeBuilder();
-        InputStream is = getContext().getResources().openRawResource(R.raw.v21_japanese_2);
-        assertEquals(true, parser.parse(is,"ISO-8859-1", builder));
-        is.close();
-        assertEquals(1, builder.vNodeList.size());
         ContentValues contentValuesForShiftJis = new ContentValues();
         contentValuesForShiftJis.put("CHARSET", "SHIFT_JIS");
-        ContentValues contentValuesForQP = new ContentValues();
-        contentValuesForQP.put("ENCODING", "QUOTED-PRINTABLE");
-        contentValuesForQP.put("CHARSET", "SHIFT_JIS");
-        PropertyNodesVerifier verifier = new PropertyNodesVerifier(this)
-            .addNodeWithOrder("VERSION", "2.1")
-            .addNodeWithOrder("N", "\u5B89\u85E4;\u30ED\u30A4\u30C9\u0031;;;",
-                    Arrays.asList("\u5B89\u85E4", "\u30ED\u30A4\u30C9\u0031",
-                            "", "", ""),
-                    null, contentValuesForShiftJis, null, null)
-            .addNodeWithOrder("FN", "\u5B89\u85E4\u0020\u30ED\u30A4\u30C9\u0020\u0031",
-                    null, null, contentValuesForShiftJis, null, null)
-            .addNodeWithOrder("SOUND",
-                    "\uFF71\uFF9D\uFF84\uFF9E\uFF73;\uFF9B\uFF72\uFF84\uFF9E\u0031;;;",
-                    null, null, contentValuesForShiftJis,
-                    new TypeSet("X-IRMC-N"), null)
-            .addNodeWithOrder("ADR",
-                    ";\u6771\u4EAC\u90FD\u6E0B\u8C37\u533A\u685C" +
-                    "\u4E18\u753A\u0032\u0036\u002D\u0031\u30BB" +
-                    "\u30EB\u30EA\u30A2\u30F3\u30BF\u30EF\u30FC\u0036" +
-                    "\u968E;;;;150-8512;",
-                    Arrays.asList("",
-                            "\u6771\u4EAC\u90FD\u6E0B\u8C37\u533A\u685C" +
-                            "\u4E18\u753A\u0032\u0036\u002D\u0031\u30BB" +
-                            "\u30EB\u30EA\u30A2\u30F3\u30BF\u30EF\u30FC" +
-                            "\u0036\u968E", "", "", "", "150-8512", ""),
-                    null, contentValuesForQP, new TypeSet("HOME"), null)
-            .addNodeWithOrder("NOTE", "\u30E1\u30E2", null, null, contentValuesForQP, null, null);
-        verifier.verify(builder.vNodeList.get(0));
+        ContentValues contentValuesForQPAndSJ = new ContentValues();
+        contentValuesForQPAndSJ.put("ENCODING", "QUOTED-PRINTABLE");
+        contentValuesForQPAndSJ.put("CHARSET", "SHIFT_JIS");
+        PropertyNodesVerifier verifier = new PropertyNodesVerifier(this);
+        verifier.addPropertyNodesVerifierElem()
+                .addNodeWithOrder("VERSION", "2.1")
+                .addNodeWithOrder("N", "\u5B89\u85E4;\u30ED\u30A4\u30C9\u0031;;;",
+                        Arrays.asList("\u5B89\u85E4", "\u30ED\u30A4\u30C9\u0031",
+                                "", "", ""),
+                        null, contentValuesForShiftJis, null, null)
+                .addNodeWithOrder("FN", "\u5B89\u85E4\u0020\u30ED\u30A4\u30C9\u0020\u0031",
+                        null, null, contentValuesForShiftJis, null, null)
+                .addNodeWithOrder("SOUND",
+                        "\uFF71\uFF9D\uFF84\uFF9E\uFF73;\uFF9B\uFF72\uFF84\uFF9E\u0031;;;",
+                        null, null, contentValuesForShiftJis,
+                        new TypeSet("X-IRMC-N"), null)
+                .addNodeWithOrder("ADR",
+                        ";\u6771\u4EAC\u90FD\u6E0B\u8C37\u533A\u685C" +
+                        "\u4E18\u753A\u0032\u0036\u002D\u0031\u30BB" +
+                        "\u30EB\u30EA\u30A2\u30F3\u30BF\u30EF\u30FC\u0036" +
+                        "\u968E;;;;150-8512;",
+                        Arrays.asList("",
+                                "\u6771\u4EAC\u90FD\u6E0B\u8C37\u533A\u685C" +
+                                "\u4E18\u753A\u0032\u0036\u002D\u0031\u30BB" +
+                                "\u30EB\u30EA\u30A2\u30F3\u30BF\u30EF\u30FC" +
+                                "\u0036\u968E", "", "", "", "150-8512", ""),
+                        null, contentValuesForQPAndSJ, new TypeSet("HOME"), null)
+                .addNodeWithOrder("NOTE", "\u30E1\u30E2", null, null,
+                        contentValuesForQPAndSJ, null, null);
+        verifier.verify(R.raw.v21_japanese_2, VCardConfig.VCARD_TYPE_V21_JAPANESE_SJIS);
     }
 
     public void testV21Japanese2_Type_Generic_Utf8() throws IOException, VCardException {
-        ContactStructVerifier verifier = new ContactStructVerifier();
-        ContentValues contentValues =
-            verifier.createExpected(StructuredName.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredName.FAMILY_NAME, "\u5B89\u85E4");
-        contentValues.put(StructuredName.GIVEN_NAME, "\u30ED\u30A4\u30C9\u0031");
-        contentValues.put(StructuredName.DISPLAY_NAME,
-                "\u5B89\u85E4\u0020\u30ED\u30A4\u30C9\u0020\u0031");
-        // ContactStruct should correctly split "SOUND" property into several elements,
-        // even though VCardParser side does not care it. 
-        contentValues.put(StructuredName.PHONETIC_FAMILY_NAME,
-                "\uFF71\uFF9D\uFF84\uFF9E\uFF73");
-        contentValues.put(StructuredName.PHONETIC_GIVEN_NAME,
-                "\uFF9B\uFF72\uFF84\uFF9E\u0031");
+        ImportVerifierElem verifier = new ImportVerifierElem();
+        verifier.addExpected(StructuredName.CONTENT_ITEM_TYPE)
+                .put(StructuredName.FAMILY_NAME, "\u5B89\u85E4")
+                .put(StructuredName.GIVEN_NAME, "\u30ED\u30A4\u30C9\u0031")
+                .put(StructuredName.DISPLAY_NAME,
+                        "\u5B89\u85E4\u0020\u30ED\u30A4\u30C9\u0020\u0031")
+                // ContactStruct should correctly split "SOUND" property into several elements,
+                // even though VCardParser side does not care it.
+                .put(StructuredName.PHONETIC_FAMILY_NAME, "\uFF71\uFF9D\uFF84\uFF9E\uFF73")
+                .put(StructuredName.PHONETIC_GIVEN_NAME, "\uFF9B\uFF72\uFF84\uFF9E\u0031");
 
-        contentValues = verifier.createExpected(StructuredPostal.CONTENT_ITEM_TYPE);
-        contentValues.put(StructuredPostal.POSTCODE, "150-8512");
-        contentValues.put(StructuredPostal.NEIGHBORHOOD,
-                "\u6771\u4EAC\u90FD\u6E0B\u8C37\u533A\u685C" +
-                "\u4E18\u753A\u0032\u0036\u002D\u0031\u30BB" +
-                "\u30EB\u30EA\u30A2\u30F3\u30BF\u30EF\u30FC" +
-                "\u0036\u968E");
-        contentValues.put(StructuredPostal.FORMATTED_ADDRESS,
-                "\u6771\u4EAC\u90FD\u6E0B\u8C37\u533A\u685C" +
-                "\u4E18\u753A\u0032\u0036\u002D\u0031\u30BB" +
-                "\u30EB\u30EA\u30A2\u30F3\u30BF\u30EF\u30FC" +
-                "\u0036\u968E 150-8512");
-        contentValues.put(StructuredPostal.TYPE, StructuredPostal.TYPE_HOME);
-        contentValues = verifier.createExpected(Note.CONTENT_ITEM_TYPE);
-        contentValues.put(Note.NOTE, "\u30E1\u30E2");
+        verifier.addExpected(StructuredPostal.CONTENT_ITEM_TYPE)
+                .put(StructuredPostal.POSTCODE, "150-8512")
+                .put(StructuredPostal.NEIGHBORHOOD,
+                        "\u6771\u4EAC\u90FD\u6E0B\u8C37\u533A\u685C" +
+                        "\u4E18\u753A\u0032\u0036\u002D\u0031\u30BB" +
+                        "\u30EB\u30EA\u30A2\u30F3\u30BF\u30EF\u30FC" +
+                        "\u0036\u968E")
+                .put(StructuredPostal.FORMATTED_ADDRESS,
+                        "\u6771\u4EAC\u90FD\u6E0B\u8C37\u533A\u685C" +
+                        "\u4E18\u753A\u0032\u0036\u002D\u0031\u30BB" +
+                        "\u30EB\u30EA\u30A2\u30F3\u30BF\u30EF\u30FC" +
+                        "\u0036\u968E 150-8512")
+                .put(StructuredPostal.TYPE, StructuredPostal.TYPE_HOME);
+        verifier.addExpected(Note.CONTENT_ITEM_TYPE)
+                .put(Note.NOTE, "\u30E1\u30E2");
         verifier.verify(R.raw.v21_japanese_2, VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
     }
 
-    // Following tests are old ones, though they still work fine.
-    
-    public void testV21MultipleEntryCase() throws IOException, VCardException {
-        VCardParser_V21 parser = new VCardParser_V21();
-        VNodeBuilder builder = new VNodeBuilder();
-        InputStream is = getContext().getResources().openRawResource(R.raw.v21_multiple_entry);
-        assertEquals(true, parser.parse(is,"ISO-8859-1", builder));
-        is.close();
-        assertEquals(3, builder.vNodeList.size());
+    public void testV21MultipleEntryCase_Parse() throws IOException, VCardException {
         ContentValues contentValuesForShiftJis = new ContentValues();
         contentValuesForShiftJis.put("CHARSET", "SHIFT_JIS");
-        PropertyNodesVerifier verifier = new PropertyNodesVerifier(this)
-            .addNodeWithOrder("VERSION", "2.1")
-            .addNodeWithOrder("N", "\u5B89\u85E4\u30ED\u30A4\u30C9\u0033;;;;",
-                    Arrays.asList("\u5B89\u85E4\u30ED\u30A4\u30C9\u0033", "", "", "", ""),
-                    null, contentValuesForShiftJis, null, null)
-            .addNodeWithOrder("SOUND",
-                    "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E\u0033;;;;",
-                    null, null, contentValuesForShiftJis,
-                    new TypeSet("X-IRMC-N"), null)
-            .addNodeWithOrder("TEL", "9", new TypeSet("X-NEC-SECRET"))
-            .addNodeWithOrder("TEL", "10", new TypeSet("X-NEC-HOTEL"))
-            .addNodeWithOrder("TEL", "11", new TypeSet("X-NEC-SCHOOL"))
-            .addNodeWithOrder("TEL", "12", new TypeSet("FAX", "HOME"));
-        verifier.verify(builder.vNodeList.get(0));
-        
-        verifier = new PropertyNodesVerifier(this)
-            .addNodeWithOrder("VERSION", "2.1")
-            .addNodeWithOrder("N", "\u5B89\u85E4\u30ED\u30A4\u30C9\u0034;;;;",
-                    Arrays.asList("\u5B89\u85E4\u30ED\u30A4\u30C9\u0034", "", "", "", ""),
-                    null, contentValuesForShiftJis, null, null)
-            .addNodeWithOrder("SOUND",
-                    "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E\u0034;;;;",
-                    null, null, contentValuesForShiftJis,
-                    new TypeSet("X-IRMC-N"), null)
-            .addNodeWithOrder("TEL", "13", new TypeSet("MODEM"))
-            .addNodeWithOrder("TEL", "14", new TypeSet("PAGER"))
-            .addNodeWithOrder("TEL", "15", new TypeSet("X-NEC-FAMILY"))
-            .addNodeWithOrder("TEL", "16", new TypeSet("X-NEC-GIRL"));
-        verifier.verify(builder.vNodeList.get(1));
-        verifier = new PropertyNodesVerifier(this)
-            .addNodeWithOrder("VERSION", "2.1")
-            .addNodeWithOrder("N", "\u5B89\u85E4\u30ED\u30A4\u30C9\u0035;;;;",
-                    Arrays.asList("\u5B89\u85E4\u30ED\u30A4\u30C9\u0035", "", "", "", ""),
-                    null, contentValuesForShiftJis, null, null)
-            .addNodeWithOrder("SOUND",
-                    "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E\u0035;;;;",
-                    null, null, contentValuesForShiftJis,
-                    new TypeSet("X-IRMC-N"), null)
-            .addNodeWithOrder("TEL", "17", new TypeSet("X-NEC-BOY"))
-            .addNodeWithOrder("TEL", "18", new TypeSet("X-NEC-FRIEND"))
-            .addNodeWithOrder("TEL", "19", new TypeSet("X-NEC-PHS"))
-            .addNodeWithOrder("TEL", "20", new TypeSet("X-NEC-RESTAURANT"));
-        verifier.verify(builder.vNodeList.get(2));
+        PropertyNodesVerifier verifier = new PropertyNodesVerifier(this);
+        verifier.addPropertyNodesVerifierElem()
+                .addNodeWithOrder("VERSION", "2.1")
+                .addNodeWithOrder("N", "\u5B89\u85E4\u30ED\u30A4\u30C9\u0033;;;;",
+                        Arrays.asList("\u5B89\u85E4\u30ED\u30A4\u30C9\u0033", "", "", "", ""),
+                        null, contentValuesForShiftJis, null, null)
+                .addNodeWithOrder("SOUND",
+                        "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E\u0033;;;;",
+                        null, null, contentValuesForShiftJis,
+                        new TypeSet("X-IRMC-N"), null)
+                .addNodeWithOrder("TEL", "9", new TypeSet("X-NEC-SECRET"))
+                .addNodeWithOrder("TEL", "10", new TypeSet("X-NEC-HOTEL"))
+                .addNodeWithOrder("TEL", "11", new TypeSet("X-NEC-SCHOOL"))
+                .addNodeWithOrder("TEL", "12", new TypeSet("FAX", "HOME"));
+
+        verifier.addPropertyNodesVerifierElem()
+                .addNodeWithOrder("VERSION", "2.1")
+                .addNodeWithOrder("N", "\u5B89\u85E4\u30ED\u30A4\u30C9\u0034;;;;",
+                        Arrays.asList("\u5B89\u85E4\u30ED\u30A4\u30C9\u0034", "", "", "", ""),
+                        null, contentValuesForShiftJis, null, null)
+                .addNodeWithOrder("SOUND",
+                        "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E\u0034;;;;",
+                        null, null, contentValuesForShiftJis,
+                        new TypeSet("X-IRMC-N"), null)
+                .addNodeWithOrder("TEL", "13", new TypeSet("MODEM"))
+                .addNodeWithOrder("TEL", "14", new TypeSet("PAGER"))
+                .addNodeWithOrder("TEL", "15", new TypeSet("X-NEC-FAMILY"))
+                .addNodeWithOrder("TEL", "16", new TypeSet("X-NEC-GIRL"));
+
+        verifier.addPropertyNodesVerifierElem()
+                .addNodeWithOrder("VERSION", "2.1")
+                .addNodeWithOrder("N", "\u5B89\u85E4\u30ED\u30A4\u30C9\u0035;;;;",
+                        Arrays.asList("\u5B89\u85E4\u30ED\u30A4\u30C9\u0035", "", "", "", ""),
+                        null, contentValuesForShiftJis, null, null)
+                .addNodeWithOrder("SOUND",
+                        "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E\u0035;;;;",
+                        null, null, contentValuesForShiftJis,
+                        new TypeSet("X-IRMC-N"), null)
+                .addNodeWithOrder("TEL", "17", new TypeSet("X-NEC-BOY"))
+                .addNodeWithOrder("TEL", "18", new TypeSet("X-NEC-FRIEND"))
+                .addNodeWithOrder("TEL", "19", new TypeSet("X-NEC-PHS"))
+                .addNodeWithOrder("TEL", "20", new TypeSet("X-NEC-RESTAURANT"));
+        verifier.verify(R.raw.v21_multiple_entry, VCardConfig.VCARD_TYPE_V21_JAPANESE_SJIS);
+    }
+
+    public void testV21MultipleEntryCase() throws IOException, VCardException {
+        ImportVerifier verifier = new ImportVerifier();
+        ImportVerifierElem elem = verifier.addImportVerifierElem();
+        elem.addExpected(StructuredName.CONTENT_ITEM_TYPE)
+                .put(StructuredName.FAMILY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9\u0033")
+                .put(StructuredName.DISPLAY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9\u0033")
+                .put(StructuredName.PHONETIC_FAMILY_NAME,
+                        "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E\u0033");
+        elem.addExpected(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.TYPE, Phone.TYPE_CUSTOM)
+                .put(Phone.LABEL, "NEC-SECRET")
+                .put(Phone.NUMBER, "9");
+        elem.addExpected(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.TYPE, Phone.TYPE_CUSTOM)
+                .put(Phone.LABEL, "NEC-HOTEL")
+                .put(Phone.NUMBER, "10");
+        elem.addExpected(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.TYPE, Phone.TYPE_CUSTOM)
+                .put(Phone.LABEL, "NEC-SCHOOL")
+                .put(Phone.NUMBER, "11");
+        elem.addExpected(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.TYPE, Phone.TYPE_FAX_HOME)
+                .put(Phone.NUMBER, "12");
+
+        elem = verifier.addImportVerifierElem();
+        elem.addExpected(StructuredName.CONTENT_ITEM_TYPE)
+                .put(StructuredName.FAMILY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9\u0034")
+                .put(StructuredName.DISPLAY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9\u0034")
+                .put(StructuredName.PHONETIC_FAMILY_NAME,
+                        "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E\u0034");
+        elem.addExpected(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.TYPE, Phone.TYPE_CUSTOM)
+                .put(Phone.LABEL, "MODEM")
+                .put(Phone.NUMBER, "13");
+        elem.addExpected(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.TYPE, Phone.TYPE_PAGER)
+                .put(Phone.NUMBER, "14");
+        elem.addExpected(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.TYPE, Phone.TYPE_CUSTOM)
+                .put(Phone.LABEL, "NEC-FAMILY")
+                .put(Phone.NUMBER, "15");
+        elem.addExpected(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.TYPE, Phone.TYPE_CUSTOM)
+                .put(Phone.LABEL, "NEC-GIRL")
+                .put(Phone.NUMBER, "16");
+
+        elem = verifier.addImportVerifierElem();
+        elem.addExpected(StructuredName.CONTENT_ITEM_TYPE)
+                .put(StructuredName.FAMILY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9\u0035")
+                .put(StructuredName.DISPLAY_NAME, "\u5B89\u85E4\u30ED\u30A4\u30C9\u0035")
+                .put(StructuredName.PHONETIC_FAMILY_NAME,
+                        "\uFF71\uFF9D\uFF84\uFF9E\uFF73\uFF9B\uFF72\uFF84\uFF9E\u0035");
+        elem.addExpected(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.TYPE, Phone.TYPE_CUSTOM)
+                .put(Phone.LABEL, "NEC-BOY")
+                .put(Phone.NUMBER, "17");
+        elem.addExpected(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.TYPE, Phone.TYPE_CUSTOM)
+                .put(Phone.LABEL, "NEC-FRIEND")
+                .put(Phone.NUMBER, "18");
+        elem.addExpected(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.TYPE, Phone.TYPE_CUSTOM)
+                .put(Phone.LABEL, "NEC-PHS")
+                .put(Phone.NUMBER, "19");
+        elem.addExpected(Phone.CONTENT_ITEM_TYPE)
+                .put(Phone.TYPE, Phone.TYPE_CUSTOM)
+                .put(Phone.LABEL, "NEC-RESTAURANT")
+                .put(Phone.NUMBER, "20");
+        verifier.verify(R.raw.v21_multiple_entry, VCardConfig.VCARD_TYPE_V21_JAPANESE_SJIS);
     }
 }
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardTestsBase.java b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardTestsBase.java
index 4c899b3..9ec6e05 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardTestsBase.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardTestsBase.java
@@ -33,7 +33,11 @@
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
+import android.pim.vcard.ContactStruct;
 import android.pim.vcard.EntryCommitter;
+import android.pim.vcard.EntryHandler;
+import android.pim.vcard.VCardBuilder;
+import android.pim.vcard.VCardBuilderCollection;
 import android.pim.vcard.VCardComposer;
 import android.pim.vcard.VCardConfig;
 import android.pim.vcard.VCardDataBuilder;
@@ -178,24 +182,24 @@
  * Please do not add each unit test here.
  */
 /* package */ class VCardTestsBase extends AndroidTestCase {
-    public static final int V21 = 0;
-    public static final int V30 = 1;
+    public static final int V21 = VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8;
+    public static final int V30 = VCardConfig.VCARD_TYPE_V30_GENERIC_UTF8;
 
-    public class ImportVerificationResolver extends MockContentResolver {
-        ImportVerificationProvider mVerificationProvider = new ImportVerificationProvider();
+    public class ImportTestResolver extends MockContentResolver {
+        ImportTestProvider mProvider = new ImportTestProvider();
         @Override
         public ContentProviderResult[] applyBatch(String authority,
                 ArrayList<ContentProviderOperation> operations) {
             equalsString(authority, RawContacts.CONTENT_URI.toString());
-            return mVerificationProvider.applyBatch(operations);
+            return mProvider.applyBatch(operations);
         }
 
         public void addExpectedContentValues(ContentValues expectedContentValues) {
-            mVerificationProvider.addExpectedContentValues(expectedContentValues);
+            mProvider.addExpectedContentValues(expectedContentValues);
         }
 
         public void verify() {
-            mVerificationProvider.verify();
+            mProvider.verify();
         }
     }
 
@@ -209,10 +213,10 @@
                 Relation.CONTENT_ITEM_TYPE, Event.CONTENT_ITEM_TYPE,
                 GroupMembership.CONTENT_ITEM_TYPE));
 
-    public class ImportVerificationProvider extends MockContentProvider {
+    public class ImportTestProvider extends MockContentProvider {
         final Map<String, Collection<ContentValues>> mMimeTypeToExpectedContentValues;
 
-        public ImportVerificationProvider() {
+        public ImportTestProvider() {
             mMimeTypeToExpectedContentValues =
                 new HashMap<String, Collection<ContentValues>>();
             for (String acceptanbleMimeType : sKnownMimeTypeSet) {
@@ -233,7 +237,7 @@
             }
 
             final Collection<ContentValues> contentValuesCollection =
-                mMimeTypeToExpectedContentValues.get(mimeType);
+                    mMimeTypeToExpectedContentValues.get(mimeType);
             contentValuesCollection.add(expectedContentValues);
         }
 
@@ -304,11 +308,11 @@
                     }
                     boolean checked = false;
                     for (ContentValues expectedContentValues : contentValuesCollection) {
-                        /* for testing
+                        /*for testing
                         Log.d("@@@", "expected: "
                                 + convertToEasilyReadableString(expectedContentValues));
                         Log.d("@@@", "actual  : "
-                                + convertToEasilyReadableString(actualContentValues)); */
+                                + convertToEasilyReadableString(actualContentValues));*/
                         if (equalsForContentValues(expectedContentValues,
                                 actualContentValues)) {
                             assertTrue(contentValuesCollection.remove(expectedContentValues));
@@ -347,19 +351,20 @@
         }
     }
 
-    public class ContactStructVerifier {
-        private final ImportVerificationResolver mResolver;
-        // private final String mCharset;
+    class ImportVerifierElem {
+        private final ImportTestResolver mResolver;
+        private final EntryHandler mHandler;
 
-        public ContactStructVerifier() {
-            mResolver = new ImportVerificationResolver();
+        public ImportVerifierElem() {
+            mResolver = new ImportTestResolver();
+            mHandler = new EntryCommitter(mResolver);
         }
 
-        public ContentValues createExpected(String mimeType) {
+        public ContentValuesBuilder addExpected(String mimeType) {
             ContentValues contentValues = new ContentValues();
             contentValues.put(Data.MIMETYPE, mimeType);
             mResolver.addExpectedContentValues(contentValues);
-            return contentValues;
+            return new ContentValuesBuilder(contentValues);
         }
 
         public void verify(int resId, int vCardType)
@@ -367,8 +372,7 @@
             verify(getContext().getResources().openRawResource(resId), vCardType);
         }
 
-        public void verify(InputStream is, int vCardType)
-                throws IOException, VCardException {
+        public void verify(InputStream is, int vCardType) throws IOException, VCardException {
             final VCardParser vCardParser;
             if (VCardConfig.isV30(vCardType)) {
                 vCardParser = new VCardParser_V30(true);  // use StrictParsing
@@ -376,8 +380,8 @@
                 vCardParser = new VCardParser_V21();
             }
             VCardDataBuilder builder =
-                new VCardDataBuilder(null, null, false, vCardType, null);
-            builder.addEntryHandler(new EntryCommitter(mResolver));
+                    new VCardDataBuilder(null, null, false, vCardType, null);
+            builder.addEntryHandler(mHandler);
             try {
                 vCardParser.parse(is, builder);
             } finally {
@@ -388,8 +392,81 @@
                     }
                 }
             }
+            verifyResolver();
+        }
+
+        public void verifyResolver() {
             mResolver.verify();
         }
+
+        public void onParsingStart() {
+            mHandler.onParsingStart();
+        }
+
+        public void onEntryCreated(ContactStruct entry) {
+            mHandler.onEntryCreated(entry);
+        }
+
+        public void onParsingEnd() {
+            mHandler.onParsingEnd();
+        }
+    }
+
+    class ImportVerifier implements EntryHandler {
+        private List<ImportVerifierElem> mImportVerifierElemList =
+            new ArrayList<ImportVerifierElem>();
+        private int mIndex;
+
+        public ImportVerifierElem addImportVerifierElem() {
+            ImportVerifierElem importVerifier = new ImportVerifierElem();
+            mImportVerifierElemList.add(importVerifier);
+            return importVerifier;
+        }
+
+        public void verify(int resId, int vCardType) throws IOException, VCardException {
+            verify(getContext().getResources().openRawResource(resId), vCardType);
+        }
+
+        public void verify(InputStream is, int vCardType) throws IOException, VCardException {
+            final VCardParser vCardParser;
+            if (VCardConfig.isV30(vCardType)) {
+                vCardParser = new VCardParser_V30(true);  // use StrictParsing
+            } else {
+                vCardParser = new VCardParser_V21();
+            }
+            VCardDataBuilder builder =
+                new VCardDataBuilder(null, null, false, vCardType, null);
+            builder.addEntryHandler(this);
+            try {
+                vCardParser.parse(is, builder);
+            } finally {
+                if (is != null) {
+                    try {
+                        is.close();
+                    } catch (IOException e) {
+                    }
+                }
+            }
+        }
+
+        public void onParsingStart() {
+            for (ImportVerifierElem elem : mImportVerifierElemList) {
+                elem.onParsingStart();
+            }
+        }
+
+        public void onEntryCreated(ContactStruct entry) {
+            assertTrue(mIndex < mImportVerifierElemList.size());
+            mImportVerifierElemList.get(mIndex).onEntryCreated(entry);
+            mIndex++;
+        }
+
+        public void onParsingEnd() {
+            for (ImportVerifierElem elem : mImportVerifierElemList) {
+                elem.onParsingEnd();
+                elem.verifyResolver();
+            }
+        }
     }
 
     public class ExportTestResolver extends MockContentResolver {
@@ -399,24 +476,23 @@
             addProvider(RawContacts.CONTENT_URI.getAuthority(), mProvider);
         }
 
-        public ContentValues buildData(String mimeType) {
-            return mProvider.buildData(mimeType);
+        public ContactEntry buildContactEntry() {
+            return mProvider.buildInputEntry();
         }
     }
 
     public static class MockEntityIterator implements EntityIterator {
-        Collection<Entity> mEntityCollection;
+        List<Entity> mEntityList;
         Iterator<Entity> mIterator;
 
-        // TODO: Support multiple vCard entries.
-        public MockEntityIterator(Collection<ContentValues> contentValuesCollection) {
-            mEntityCollection = new ArrayList<Entity>();
+        public MockEntityIterator(List<ContentValues> contentValuesList) {
+            mEntityList = new ArrayList<Entity>();
             Entity entity = new Entity(new ContentValues());
-            for (ContentValues contentValues : contentValuesCollection) {
-                entity.addSubValue(Data.CONTENT_URI, contentValues);
+            for (ContentValues contentValues : contentValuesList) {
+                    entity.addSubValue(Data.CONTENT_URI, contentValues);
             }
-            mEntityCollection.add(entity);
-            mIterator = mEntityCollection.iterator();
+            mEntityList.add(entity);
+            mIterator = mEntityList.iterator();
         }
 
         public boolean hasNext() {
@@ -428,44 +504,71 @@
         }
 
         public void reset() {
-            mIterator = mEntityCollection.iterator();
+            mIterator = mEntityList.iterator();
         }
 
         public void close() {
         }
     }
 
-    public class ExportTestProvider extends MockContentProvider {
-        List<ContentValues> mContentValuesList = new ArrayList<ContentValues>();
-        public ContentValues buildData(String mimeType) {
+    /**
+     * Represents one contact, which should contain multiple ContentValues like
+     * StructuredName, Email, etc.
+     */
+    static class ContactEntry {
+        private final List<ContentValues> mContentValuesList = new ArrayList<ContentValues>();
+
+        public ContentValuesBuilder buildData(String mimeType) {
             ContentValues contentValues = new ContentValues();
             contentValues.put(Data.MIMETYPE, mimeType);
             mContentValuesList.add(contentValues);
-            return contentValues;
+            return new ContentValuesBuilder(contentValues);
+        }
+
+        public List<ContentValues> getList() {
+            return mContentValuesList;
+        }
+    }
+
+    class ExportTestProvider extends MockContentProvider {
+        ArrayList<ContactEntry> mContactEntryList = new ArrayList<ContactEntry>();
+
+        public ContactEntry buildInputEntry() {
+            ContactEntry contactEntry = new ContactEntry();
+            mContactEntryList.add(contactEntry);
+            return contactEntry;
         }
 
         @Override
         public EntityIterator queryEntities(Uri uri, String selection, String[] selectionArgs,
                 String sortOrder) {
-            assert(uri != null);
-            assert(ContentResolver.SCHEME_CONTENT.equals(uri.getScheme()));
+            assertTrue(uri != null);
+            assertTrue(ContentResolver.SCHEME_CONTENT.equals(uri.getScheme()));
             final String authority = uri.getAuthority();
-            assert(RawContacts.CONTENT_URI.getAuthority().equals(authority));
+            assertTrue(RawContacts.CONTENT_URI.getAuthority().equals(authority));
+            assertTrue((Data.CONTACT_ID + "=?").equals(selection));
+            assertEquals(1, selectionArgs.length);
+            int id = Integer.parseInt(selectionArgs[0]);
+            assertTrue(id >= 0 && id < mContactEntryList.size());
 
-            return new MockEntityIterator(mContentValuesList);
+            return new MockEntityIterator(mContactEntryList.get(id).getList());
         }
 
         @Override
-        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
-                String sortOrder) {
-            assert(VCardComposer.CONTACTS_TEST_CONTENT_URI.equals(uri));
-            // Support multiple rows.
+        public Cursor query(Uri uri, String[] projection,
+                String selection, String[] selectionArgs, String sortOrder) {
+            assertTrue(VCardComposer.CONTACTS_TEST_CONTENT_URI.equals(uri));
+            // In this test, following arguments are not supported.
+            assertNull(selection);
+            assertNull(selectionArgs);
+            assertNull(sortOrder);
+
             return new MockCursor() {
                 int mCurrentPosition = -1;
 
                 @Override
                 public int getCount() {
-                    return 1;
+                    return mContactEntryList.size();
                 }
 
                 @Override
@@ -476,7 +579,7 @@
 
                 @Override
                 public boolean moveToNext() {
-                    if (mCurrentPosition == 0 || mCurrentPosition == -1) {
+                    if (mCurrentPosition < mContactEntryList.size()) {
                         mCurrentPosition++;
                         return true;
                     } else {
@@ -491,7 +594,7 @@
 
                 @Override
                 public boolean isAfterLast() {
-                    return mCurrentPosition > 0;
+                    return mCurrentPosition >= mContactEntryList.size();
                 }
 
                 @Override
@@ -503,7 +606,9 @@
                 @Override
                 public int getInt(int columnIndex) {
                     assertEquals(0, columnIndex);
-                    return 0;
+                    assertTrue(mCurrentPosition >= 0
+                            && mCurrentPosition < mContactEntryList.size());
+                    return mCurrentPosition;
                 }
 
                 @Override
@@ -518,128 +623,252 @@
         }
     }
 
-    public static class VCardVerificationHandler implements VCardComposer.OneEntryHandler {
-        final private TestCase mTestCase;
-        final private List<PropertyNodesVerifier> mPropertyNodesVerifierList;
-        final private boolean mIsV30;
-        // To allow duplication, use list instead of set.
-        // TODO: support multiple vCard entries.
-        final private List<String> mExpectedLineList;
-        final private ContactStructVerifier mContactStructVerifier;
-        final private int mVCardType;
-        int mCount;
+    class LineVerifierElem {
+        private final List<String> mExpectedLineList = new ArrayList<String>();
+        private final boolean mIsV30;
 
-        public VCardVerificationHandler(final TestCase testCase, final int version) {
-            this(testCase, null, version);
+        public LineVerifierElem(boolean isV30) {
+            mIsV30 = isV30;
         }
 
-        public VCardVerificationHandler(final TestCase testCase,
-                ContactStructVerifier contactStructVerifier, final int version) {
-            mTestCase = testCase;
-            mPropertyNodesVerifierList = new ArrayList<PropertyNodesVerifier>();
-            mIsV30 = (version == V30);
-            mExpectedLineList = new ArrayList<String>();
-            mContactStructVerifier = contactStructVerifier;
-            mVCardType = (version == V30 ? VCardConfig.VCARD_TYPE_V30_GENERIC_UTF8
-                    : VCardConfig.VCARD_TYPE_V21_GENERIC_UTF8);
-            mCount = 1;
-        }
-
-        public PropertyNodesVerifier addNewVerifier() {
-            PropertyNodesVerifier verifier = new PropertyNodesVerifier(mTestCase);
-            mPropertyNodesVerifierList.add(verifier);
-            verifier.addNodeWithOrder("VERSION", mIsV30 ? "3.0" : "2.1");
-            return verifier;
-        }
-
-        public PropertyNodesVerifier addNewVerifierWithEmptyName() {
-            PropertyNodesVerifier verifier = addNewVerifier();
-            if (mIsV30) {
-                verifier.addNodeWithOrder("N", "").addNodeWithOrder("FN", "");
+        public LineVerifierElem addExpected(final String line) {
+            if (!TextUtils.isEmpty(line)) {
+                mExpectedLineList.add(line);
             }
-            return verifier;
-        }
-
-        public VCardVerificationHandler addExpectedLine(String line) {
-            mExpectedLineList.add(line);
             return this;
         }
 
-        public boolean onInit(final Context context) {
-            return true;
-        }
-
-        public boolean onEntryCreated(final String vcard) {
-            if (!mExpectedLineList.isEmpty()) {
-                verifyLines(vcard);
-            }
-            verifyNodes(vcard);
-            return true;
-        }
-
-        private void verifyLines(final String vcard) {
+        public void verify(final String vcard) {
             final String[] lineArray = vcard.split("\\r?\\n");
             final int length = lineArray.length;
+            final TestCase testCase = VCardTestsBase.this;
+            boolean beginExists = false;
+            boolean endExists = false;
+            boolean versionExists = false;
+
             for (int i = 0; i < length; i++) {
                 final String line = lineArray[i];
-                // TODO: support multiple vcard entries.
-                if ("BEGIN:VCARD".equals(line) || "END:VCARD".equals(line) ||
-                        (mIsV30 ? "VERSION:3.0" : "VERSION:2.1").equals(line)) {
+                if (TextUtils.isEmpty(line)) {
                     continue;
                 }
+
+                if ("BEGIN:VCARD".equalsIgnoreCase(line)) {
+                    if (beginExists) {
+                        testCase.fail("Multiple \"BEGIN:VCARD\" line found");
+                    } else {
+                        beginExists = true;
+                        continue;
+                    }
+                } else if ("END:VCARD".equalsIgnoreCase(line)) {
+                    if (endExists) {
+                        testCase.fail("Multiple \"END:VCARD\" line found");
+                    } else {
+                        endExists = true;
+                        continue;
+                    }
+                } else if (
+                        (mIsV30 ? "VERSION:3.0" : "VERSION:2.1").equalsIgnoreCase(line)) {
+                    if (versionExists) {
+                        testCase.fail("Multiple VERSION line + found");
+                    } else {
+                        versionExists = true;
+                        continue;
+                    }
+                }
+
+                if (!beginExists) {
+                    testCase.fail(
+                            "Property other than BEGIN came before BEGIN property: " + line);
+                } else if (endExists) {
+                    testCase.fail("Property other than END came after END property: " + line);
+                }
+
                 final int index = mExpectedLineList.indexOf(line);
                 if (index >= 0) {
                     mExpectedLineList.remove(index);
                 } else {
-                    mTestCase.fail("Unexpected line: " + line);
+                    testCase.fail("Unexpected line: " + line);
                 }
             }
+
             if (!mExpectedLineList.isEmpty()) {
                 StringBuffer buffer = new StringBuffer();
                 for (String expectedLine : mExpectedLineList) {
                     buffer.append(expectedLine);
                     buffer.append("\n");
                 }
-                mTestCase.fail("Expected line(s) not found:" + buffer.toString());
+
+                testCase.fail("Expected line(s) not found:" + buffer.toString());
             }
         }
+    }
 
-        private void verifyNodes(final String vcard) {
-            if (mPropertyNodesVerifierList.size() == 0) {
-                mTestCase.fail("Too many vCard entries seems to be inserted(No."
-                        + mCount + " of the entries (No.1 is the first entry))");
+    class LineVerifier implements VCardComposer.OneEntryHandler {
+        private final ArrayList<LineVerifierElem> mLineVerifierElemList;
+        private final boolean mIsV30;
+        private int index;
+
+        public LineVerifier(final boolean isV30) {
+            mLineVerifierElemList = new ArrayList<LineVerifierElem>();
+            mIsV30 = isV30;
+        }
+
+        public LineVerifierElem addLineVerifierElem() {
+            LineVerifierElem lineVerifier = new LineVerifierElem(mIsV30);
+            mLineVerifierElemList.add(lineVerifier);
+            return lineVerifier;
+        }
+
+        public void verify(String vcard) {
+            if (index >= mLineVerifierElemList.size()) {
+                VCardTestsBase.this.fail("Insufficient number of LineVerifier (" + index + ")");
             }
-            PropertyNodesVerifier propertyNodesVerifier =
-                mPropertyNodesVerifierList.get(0);
-            mPropertyNodesVerifierList.remove(0);
-            VCardParser parser = (mIsV30 ? new VCardParser_V30(true) : new VCardParser_V21());
-            VNodeBuilder builder = new VNodeBuilder();
-            InputStream is;
-            try {
-                is = new ByteArrayInputStream(vcard.getBytes("UTF-8"));
-                mTestCase.assertEquals(true, parser.parse(is, null, builder));
-                is.close();
-                mTestCase.assertEquals(1, builder.vNodeList.size());
-                propertyNodesVerifier.verify(builder.vNodeList.get(0));
-                if (mContactStructVerifier != null) {
-                    Log.d("@@@", vcard);
-                    is = new ByteArrayInputStream(vcard.getBytes("UTF-8"));
-                    mContactStructVerifier.verify(is, mVCardType);
-                    is.close();
-                }
-            } catch (IOException e) {
-                mTestCase.fail("Unexpected IOException: " + e.getMessage());
-            } catch (VCardException e) {
-                mTestCase.fail("Unexpected VCardException: " + e.getMessage());
-            } finally {
-                mCount++;
-            }
+
+            LineVerifierElem lineVerifier = mLineVerifierElemList.get(index);
+            lineVerifier.verify(vcard);
+
+            index++;
+        }
+
+        public boolean onEntryCreated(String vcard) {
+            verify(vcard);
+            return true;
+        }
+
+        public boolean onInit(Context context) {
+            return true;
         }
 
         public void onTerminate() {
         }
     }
 
+    class VCardVerifier {
+        private class VCardVerifierInternal implements VCardComposer.OneEntryHandler {
+            public boolean onInit(Context context) {
+                return true;
+            }
+            public boolean onEntryCreated(String vcard) {
+                verifyOneVCard(vcard);
+                return true;
+            }
+            public void onTerminate() {
+            }
+        }
+
+        private final VCardVerifierInternal mVCardVerifierInternal;
+        private final ExportTestResolver mResolver;
+        private final int mVCardType;
+        private final boolean mIsV30;
+
+        // To allow duplication, use list instead of set.
+        // When null, we don't need to do the verification.
+        private PropertyNodesVerifier mPropertyNodesVerifier;
+        private LineVerifier mLineVerificationHandler;
+        private ImportVerifier mImportVerifier;
+
+        public VCardVerifier(ExportTestResolver resolver, int vcardType) {
+            mVCardVerifierInternal = new VCardVerifierInternal();
+            mResolver = resolver;
+            mIsV30 = VCardConfig.isV30(vcardType);
+            mVCardType = vcardType;
+        }
+
+        public PropertyNodesVerifierElem addPropertyNodesVerifierElem() {
+            if (mPropertyNodesVerifier == null) {
+                mPropertyNodesVerifier = new PropertyNodesVerifier(VCardTestsBase.this);
+            }
+            PropertyNodesVerifierElem elem =
+                    mPropertyNodesVerifier.addPropertyNodesVerifierElem();
+            elem.addNodeWithOrder("VERSION", (mIsV30 ? "3.0" : "2.1"));
+
+            return elem;
+        }
+
+        public PropertyNodesVerifierElem addPropertyNodesVerifierWithEmptyName() {
+            PropertyNodesVerifierElem elem = addPropertyNodesVerifierElem();
+            if (mIsV30) {
+                elem.addNodeWithOrder("N", "").addNodeWithOrder("FN", "");
+            }
+            return elem;
+        }
+
+        public LineVerifierElem addLineVerifier() {
+            if (mLineVerificationHandler == null) {
+                mLineVerificationHandler = new LineVerifier(mIsV30);
+            }
+            return mLineVerificationHandler.addLineVerifierElem();
+        }
+
+        public ImportVerifierElem addImportVerifier() {
+            if (mImportVerifier == null) {
+                mImportVerifier = new ImportVerifier();
+            }
+
+            return mImportVerifier.addImportVerifierElem();
+        }
+
+        private void verifyOneVCard(final String vcard) {
+            final VCardBuilder builder;
+            if (mImportVerifier != null) {
+                final VNodeBuilder vnodeBuilder = mPropertyNodesVerifier;
+                final VCardDataBuilder vcardDataBuilder = new VCardDataBuilder();
+                vcardDataBuilder.addEntryHandler(mImportVerifier);
+                if (mPropertyNodesVerifier != null) {
+                    builder = new VCardBuilderCollection(Arrays.asList(
+                            vcardDataBuilder, mPropertyNodesVerifier));
+                } else {
+                    builder = vnodeBuilder;
+                }
+            } else {
+                if (mPropertyNodesVerifier != null) {
+                    builder = mPropertyNodesVerifier;
+                } else {
+                    return;
+                }
+            }
+
+            final VCardParser parser =
+                    (mIsV30 ? new VCardParser_V30(true) : new VCardParser_V21());
+            final TestCase testCase = VCardTestsBase.this;
+
+            InputStream is = null;
+            try {
+                is = new ByteArrayInputStream(vcard.getBytes("UTF-8"));
+                testCase.assertEquals(true, parser.parse(is, null, builder));
+            } catch (IOException e) {
+                testCase.fail("Unexpected IOException: " + e.getMessage());
+            } catch (VCardException e) {
+                testCase.fail("Unexpected VCardException: " + e.getMessage());
+            } finally {
+                if (is != null) {
+                    try {
+                        is.close();
+                    } catch (IOException e) {
+                    }
+                }
+            }
+        }
+
+        public void verify() {
+            VCardComposer composer =
+                    new VCardComposer(new CustomMockContext(mResolver), mVCardType);
+            composer.addHandler(mLineVerificationHandler);
+            composer.addHandler(mVCardVerifierInternal);
+            if (!composer.init(VCardComposer.CONTACTS_TEST_CONTENT_URI, null, null, null)) {
+                fail("init() failed. Reason: " + composer.getErrorReason());
+            }
+            assertFalse(composer.isAfterLast());
+            try {
+                while (!composer.isAfterLast()) {
+                    assertTrue(composer.createOneEntry());
+                }
+            } finally {
+                composer.terminate();
+            }
+        }
+    }
+
     /**
      * Utility method to print ContentValues whose content is printed with sorted keys.
      */
@@ -682,6 +911,7 @@
         } else if (expected == null || actual == null || expected.size() != actual.size()) {
             return false;
         }
+
         for (Entry<String, Object> entry : expected.valueSet()) {
             final String key = entry.getKey();
             final Object value = entry.getValue();