Merge "Tests for Contact Lookup Uri Methods"
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index 86e709b..ca2ad26 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -33,6 +33,7 @@
 	CtsDeviceAdmin \
 	CtsTestStubs \
 	SignatureTest \
+	replicaisland \
 	$(CTS_SECURITY_APPS_LIST)
 
 # Test packages that require an associated test package XML.
diff --git a/tests/tests/openglperf/Android.mk b/tests/tests/openglperf/Android.mk
index 571bbd7..2ea0171 100644
--- a/tests/tests/openglperf/Android.mk
+++ b/tests/tests/openglperf/Android.mk
@@ -27,6 +27,10 @@
 
 LOCAL_PACKAGE_NAME := CtsOpenGlPerfTestCases
 
+LOCAL_INSTRUMENTATION_FOR := replicaisland
+
 LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_PACKAGE)
+
+#include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/openglperf/AndroidManifest.xml b/tests/tests/openglperf/AndroidManifest.xml
index 95a7cd1..8e48eb0 100644
--- a/tests/tests/openglperf/AndroidManifest.xml
+++ b/tests/tests/openglperf/AndroidManifest.xml
@@ -13,16 +13,24 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.cts.openglperf"
     android:versionCode="1"
     android:versionName="1.0" >
 
     <uses-feature android:glEsVersion="0x00020000" android:required="true" />
+    <uses-permission android:name="android.permission.GET_TASKS" />
+    <uses-permission android:name="android.permission.REORDER_TASKS" />
+    <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
+
+    <!-- Two activities are used -->
+    <instrumentation
+        android:targetPackage="replicaisland"
+        android:name="android.test.InstrumentationTestRunner" />
     <instrumentation
         android:targetPackage="com.android.cts.openglperf"
         android:name="android.test.InstrumentationTestRunner" />
+
     <application
         android:label="@string/app_name" >
         <uses-library android:name="android.test.runner" />
diff --git a/tests/tests/openglperf/src/android/openglperf/cts/GlAppSwitchTest.java b/tests/tests/openglperf/src/android/openglperf/cts/GlAppSwitchTest.java
new file mode 100644
index 0000000..2d7df8a
--- /dev/null
+++ b/tests/tests/openglperf/src/android/openglperf/cts/GlAppSwitchTest.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2012 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 android.openglperf.cts;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.Instrumentation;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.test.ActivityInstrumentationTestCase2;
+
+import java.util.List;
+
+/**
+ * Tests OpenGl rendering after task switching to other GL-using application
+ * This test needs to control two applications and task switch between them to
+ * force losing and reclaiming GL context
+ */
+public class GlAppSwitchTest extends
+        ActivityInstrumentationTestCase2<GlPlanetsActivity> {
+
+    private static final String REPLICA_ISLAND_PACKAGE = "com.replica.replicaisland";
+    private static final String REPLICA_ISLAND_ACTIVITY = "AndouKun";
+    private static final long TASK_SWITCH_SLOW_WAIT_TIME_MS = 15 * 1000;
+    private static final int NUMBER_OF_TASK_SWITCHES_SLOW = 10;
+    private static final long TASK_SWITCH_FAST_WAIT_TIME_MS = 2000;
+    private static final int NUMBER_OF_TASK_SWITCHES_FAST = 50;
+    private static final String ERROR_REPLICA_ISLAND_DEAD = "replica island not running";
+    private static final int MAX_RUNNING_TASKS = 1000;
+
+    private ActivityManager mActivityManager;
+
+    private int mTaskIdSelf;
+    private int mTaskIdReplica;
+
+    public GlAppSwitchTest() {
+        super(GlPlanetsActivity.class);
+    }
+
+    public void testGlActivitySwitchingFast() throws InterruptedException {
+        runTaskSwitchTest(TASK_SWITCH_FAST_WAIT_TIME_MS, NUMBER_OF_TASK_SWITCHES_FAST);
+        // wait for more time at the last run to allow watch dog timer in replica island to kick
+        Thread.sleep(TASK_SWITCH_SLOW_WAIT_TIME_MS);
+        assertTrue(ERROR_REPLICA_ISLAND_DEAD, isReplicaIslandRunning());
+    }
+
+    public void testGlActivitySwitchingSlow() throws InterruptedException {
+        runTaskSwitchTest(TASK_SWITCH_SLOW_WAIT_TIME_MS, NUMBER_OF_TASK_SWITCHES_SLOW);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        Instrumentation instrument = getInstrumentation();
+        Context context = instrument.getContext();
+
+        mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+
+        Intent intentPlanets = new Intent();
+        intentPlanets.putExtra(GlPlanetsActivity.INTENT_EXTRA_NUM_FRAMES, 0); //runs forever
+        intentPlanets.putExtra(GlPlanetsActivity.INTENT_EXTRA_NUM_PLANETS, 4); // max load
+        setActivityIntent(intentPlanets);
+        Activity activity = getActivity();
+        instrument.waitForIdleSync();
+        mTaskIdSelf = activity.getTaskId();
+        // wait further to render some frames
+        Thread.sleep(1000);
+        // terminate if it is already running
+        terminateReplicaIsland();
+
+        Intent intentIsland = new Intent(Intent.ACTION_MAIN);
+        intentIsland.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intentIsland.addCategory(Intent.CATEGORY_LAUNCHER);
+        intentIsland.setComponent(new ComponentName(REPLICA_ISLAND_PACKAGE,
+                REPLICA_ISLAND_PACKAGE + "." + REPLICA_ISLAND_ACTIVITY));
+        context.startActivity(intentIsland);
+        // wait to render some frames
+        Thread.sleep(5000);
+
+        setReplicaIslandTask();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        showOrHideReplicaIsland(false);
+        terminateReplicaIsland();
+        super.tearDown();
+    }
+
+    /**
+     * run foreground / background task switching between replica island and GlPlanetsActivity.
+     * @param waitTimeMs time to wait after each task switching
+     * @param numberOfSwitches number of task switches to run
+     * @throws InterruptedException
+     */
+    private void runTaskSwitchTest(long waitTimeMs, int numberOfSwitches)
+            throws InterruptedException {
+        boolean replicaForeground = false;
+        assertTrue(ERROR_REPLICA_ISLAND_DEAD, isReplicaIslandRunning());
+        for (int i = 0; i < numberOfSwitches; i++ ) {
+            showOrHideReplicaIsland(replicaForeground);
+            replicaForeground = !replicaForeground;
+            Thread.sleep(waitTimeMs);
+            assertTrue(ERROR_REPLICA_ISLAND_DEAD, isReplicaIslandRunning());
+        }
+    }
+
+    private void setReplicaIslandTask() {
+        boolean foundReplica = false;
+        List<ActivityManager.RunningTaskInfo> tasks =
+                mActivityManager.getRunningTasks(MAX_RUNNING_TASKS);
+        for (ActivityManager.RunningTaskInfo info : tasks) {
+            String packageName = info.baseActivity.getPackageName();
+            if (packageName.contentEquals(REPLICA_ISLAND_PACKAGE)) {
+                foundReplica = true;
+                mTaskIdReplica = info.id;
+                break;
+            }
+        }
+        assertTrue("cannot find replica island running", foundReplica);
+    }
+
+    private boolean isReplicaIslandRunning() {
+        boolean foundReplica = false;
+        List<ActivityManager.RunningTaskInfo> tasks =
+                mActivityManager.getRunningTasks(MAX_RUNNING_TASKS);
+        for (ActivityManager.RunningTaskInfo info : tasks) {
+            if (info.id == mTaskIdReplica) {
+                foundReplica = true;
+                break;
+            }
+        }
+        return foundReplica;
+    }
+
+    /**
+     * send replica island to foreground (when show = true) or background
+     * requires both replica island and GlPlanetsActivity to be alive.
+     * @param show
+     */
+    private void showOrHideReplicaIsland(boolean show) {
+        mActivityManager.moveTaskToFront(show ? mTaskIdReplica : mTaskIdSelf, 0);
+    }
+
+    /**
+     * this API works only when the replica island is in background.
+     */
+    private void terminateReplicaIsland() {
+        mActivityManager.killBackgroundProcesses(REPLICA_ISLAND_PACKAGE);
+        getInstrumentation().waitForIdleSync();
+    }
+}
diff --git a/tests/tests/openglperf/src/android/openglperf/cts/PlanetsRenderer.java b/tests/tests/openglperf/src/android/openglperf/cts/PlanetsRenderer.java
index 59a7782..5b90089 100644
--- a/tests/tests/openglperf/src/android/openglperf/cts/PlanetsRenderer.java
+++ b/tests/tests/openglperf/src/android/openglperf/cts/PlanetsRenderer.java
@@ -45,6 +45,7 @@
     private final Context mContext;
     private final PlanetsRenderingParam mParam;
     private final RenderCompletionListener mListener;
+    private final RenderingWatchDog mWatchDog;
 
     private final Sphere[] mSpheres;
     private final int mNumSpheres;
@@ -94,10 +95,11 @@
      * @param listener
      */
     public PlanetsRenderer(Context context, PlanetsRenderingParam param,
-            RenderCompletionListener listener) {
+            RenderCompletionListener listener, RenderingWatchDog watchDog) {
         resetTimer();
         mContext = context;
         mParam = param;
+        mWatchDog = watchDog;
         mNumSpheres = mParam.mNumPlanets + 1; // 1 for sun
         mNumIndices = mNumSpheres * mParam.mNumIndicesPerVertex;
         mSpheres = new Sphere[mNumSpheres];
@@ -136,12 +138,14 @@
     }
 
     public void onDrawFrame(GL10 glUnused) {
+        mWatchDog.reset();
         long currentTime = System.currentTimeMillis();
 
         mFrameCount++;
         if ((mFrameCount % FPS_DISPLAY_INTERVAL == 0) && (mFrameCount != 0)) {
             float fps = (((float) FPS_DISPLAY_INTERVAL)
                     / ((float) (currentTime - mLastFPSTime)) * 1000.0f);
+            // FPS is not correct if activity is paused/resumed.
             Log.i(TAG, "FPS " + fps);
             mLastFPSTime = currentTime;
         }
@@ -370,11 +374,11 @@
             checkGlError("glGenBuffers Vertex");
             for (int i = 0; i < mNumSpheres; i++) {
                 GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVboVertices[i]);
+                checkGlError("glBindBuffer Vertex");
                 FloatBuffer vertices = mSpheres[i].getVertices();
                 GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertices.limit()
                         * Sphere.FLOAT_SIZE, vertices, GLES20.GL_STATIC_DRAW);
                 checkGlError("glBufferData Vertex");
-                mSpheres[i].releaseVertexBuffer(); // release memory
             }
         }
         if (mParam.mUseVboForIndices) {
@@ -393,7 +397,6 @@
                     checkGlError("glBufferData Index");
 
                 }
-                mSpheres[i].releaseIndexBuffer(); // release memory
             }
         }
         GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
diff --git a/tests/tests/openglperf/src/android/openglperf/cts/PlanetsSurfaceView.java b/tests/tests/openglperf/src/android/openglperf/cts/PlanetsSurfaceView.java
index 526f706..2bfd001 100644
--- a/tests/tests/openglperf/src/android/openglperf/cts/PlanetsSurfaceView.java
+++ b/tests/tests/openglperf/src/android/openglperf/cts/PlanetsSurfaceView.java
@@ -20,23 +20,27 @@
 import android.opengl.GLSurfaceView;
 
 class PlanetsSurfaceView extends GLSurfaceView {
+    private final long RENDERING_TIMEOUT = 1900; // in msec, close to 2 secs
+    private final RenderingWatchDog mWatchDog = new RenderingWatchDog(RENDERING_TIMEOUT);
 
     public PlanetsSurfaceView(Context context, PlanetsRenderingParam param,
             RenderCompletionListener listener) {
         super(context);
 
         setEGLContextClientVersion(2);
-        setRenderer(new PlanetsRenderer(context, param, listener));
+        setRenderer(new PlanetsRenderer(context, param, listener, mWatchDog));
     }
 
     @Override
     public void onPause() {
+        mWatchDog.stop();
         super.onPause();
         setRenderMode(RENDERMODE_WHEN_DIRTY);
     }
 
     @Override
     public void onResume() {
+        mWatchDog.start();
         setRenderMode(RENDERMODE_CONTINUOUSLY);
         super.onResume();
     }
diff --git a/tests/tests/openglperf/src/android/openglperf/cts/RenderingWatchDog.java b/tests/tests/openglperf/src/android/openglperf/cts/RenderingWatchDog.java
new file mode 100644
index 0000000..4872af2
--- /dev/null
+++ b/tests/tests/openglperf/src/android/openglperf/cts/RenderingWatchDog.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2012 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 android.openglperf.cts;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import android.util.Log;
+
+import junit.framework.Assert;
+
+/**
+ * class for checking if rendering function is alive or not.
+ * panic if watch-dog is not reset over certain amount of time
+ */
+public class RenderingWatchDog implements Runnable {
+    private static final String TAG = "RenderingWatchDog";
+    private Thread mThread;
+    private Semaphore mSemaphore;
+    private volatile boolean mStopRequested;
+    private final long mTimeoutInMilliSecs;
+
+    public RenderingWatchDog(long timeoutInMilliSecs) {
+        mTimeoutInMilliSecs = timeoutInMilliSecs;
+    }
+
+    /** start watch-dog */
+    public void start() {
+        Log.i(TAG, "start");
+        mStopRequested = false;
+        mSemaphore = new Semaphore(0);
+        mThread = new Thread(this);
+        mThread.start();
+    }
+
+    /** stop watch-dog */
+    public void stop() {
+        Log.i(TAG, "stop");
+        if (mThread == null) {
+            return; // already finished
+        }
+        mStopRequested = true;
+        mSemaphore.release();
+        try {
+            mThread.join();
+        } catch (InterruptedException e) {
+            // ignore
+        }
+        mThread = null;
+        mSemaphore = null;
+    }
+
+    /** resets watch-dog, thus prevent it from panic */
+    public void reset() {
+        if (!mStopRequested) { // stop requested, but rendering still on-going
+            mSemaphore.release();
+        }
+    }
+
+    @Override
+    public void run() {
+        while (!mStopRequested) {
+            try {
+                Assert.assertTrue("Watchdog timed-out",
+                        mSemaphore.tryAcquire(mTimeoutInMilliSecs, TimeUnit.MILLISECONDS));
+            } catch (InterruptedException e) {
+                // this thread will not be interrupted,
+                // but if it happens, just check the exit condition.
+            }
+        }
+    }
+}
diff --git a/tests/tests/openglperf/src/android/openglperf/cts/Sphere.java b/tests/tests/openglperf/src/android/openglperf/cts/Sphere.java
index e8876dd..026ba97 100644
--- a/tests/tests/openglperf/src/android/openglperf/cts/Sphere.java
+++ b/tests/tests/openglperf/src/android/openglperf/cts/Sphere.java
@@ -147,14 +147,7 @@
     public int getTotalIndices() {
         return mTotalIndices;
     }
-    /** once VBO buffer is generated, model data can be dropped */
-    public void releaseVertexBuffer() {
-        mVertices = null;
-    }
 
-    public void releaseIndexBuffer() {
-        mVertices = null;
-    }
 
     private int max(int[] array) {
         int max = array[0];
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_PhotoTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_PhotoTest.java
index 68ed1b8..edab42f 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_PhotoTest.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_PhotoTest.java
@@ -22,6 +22,8 @@
 import android.content.IContentProvider;
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.CommonDataKinds.Photo;
+import android.provider.ContactsContract.Contacts;
+import android.provider.cts.ContactsContract_TestDataBuilder.TestContact;
 import android.provider.cts.ContactsContract_TestDataBuilder.TestData;
 import android.provider.cts.ContactsContract_TestDataBuilder.TestRawContact;
 import android.test.InstrumentationTestCase;
@@ -35,12 +37,13 @@
 
     private static final byte[] EMPTY_TEST_PHOTO_DATA = "".getBytes();
 
+    private ContentResolver mResolver;
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        ContentResolver contentResolver =
-                getInstrumentation().getTargetContext().getContentResolver();
-        IContentProvider provider = contentResolver.acquireProvider(ContactsContract.AUTHORITY);
+        mResolver = getInstrumentation().getTargetContext().getContentResolver();
+        IContentProvider provider = mResolver.acquireProvider(ContactsContract.AUTHORITY);
         mBuilder = new ContactsContract_TestDataBuilder(provider);
     }
 
@@ -51,7 +54,13 @@
     }
 
     public void testAddPhoto() throws Exception {
-        TestRawContact rawContact = mBuilder.newRawContact().insert();
+        TestRawContact rawContact = mBuilder.newRawContact().insert().load();
+        TestContact contact = rawContact.getContact().load();
+
+        assertNull(Contacts.openContactPhotoInputStream(mResolver, contact.getUri()));
+        assertNull(Contacts.openContactPhotoInputStream(mResolver, contact.getUri(), true));
+        assertNull(Contacts.openContactPhotoInputStream(mResolver, contact.getUri(), false));
+
         TestData photoData = rawContact.newDataRow(Photo.CONTENT_ITEM_TYPE)
                 .with(Photo.PHOTO, getTestPhotoData())
                 .insert();
@@ -59,14 +68,28 @@
         photoData.load();
         photoData.assertColumn(Photo.RAW_CONTACT_ID, rawContact.getId());
         photoData.assertBlobColumnNotNull(Photo.PHOTO);
+
+        assertPhotoStream(Contacts.openContactPhotoInputStream(mResolver, contact.getUri()));
+        assertPhotoStream(Contacts.openContactPhotoInputStream(mResolver, contact.getUri(), true));
+        assertPhotoStream(Contacts.openContactPhotoInputStream(mResolver, contact.getUri(), false));
     }
 
     public void testAddEmptyPhoto() throws Exception {
-        TestRawContact rawContact = mBuilder.newRawContact().insert();
+        TestRawContact rawContact = mBuilder.newRawContact().insert().load();
+        TestContact contact = rawContact.getContact().load();
+
+        assertNull(Contacts.openContactPhotoInputStream(mResolver, contact.getUri()));
+        assertNull(Contacts.openContactPhotoInputStream(mResolver, contact.getUri(), true));
+        assertNull(Contacts.openContactPhotoInputStream(mResolver, contact.getUri(), false));
+
         TestData photoData = rawContact.newDataRow(Photo.CONTENT_ITEM_TYPE)
                 .with(Photo.PHOTO, EMPTY_TEST_PHOTO_DATA)
                 .insert();
         assertNotNull(photoData.load());
+
+        assertNull(Contacts.openContactPhotoInputStream(mResolver, contact.getUri()));
+        assertNull(Contacts.openContactPhotoInputStream(mResolver, contact.getUri(), true));
+        assertNull(Contacts.openContactPhotoInputStream(mResolver, contact.getUri(), false));
     }
 
     private byte[] getTestPhotoData() {
@@ -89,5 +112,17 @@
         }
         return os.toByteArray();
     }
+
+    private void assertPhotoStream(InputStream photoStream) throws IOException {
+        try {
+            assertNotNull(photoStream);
+            byte[] actualBytes = readInputStreamFully(photoStream);
+            assertTrue(actualBytes.length > 0);
+        } finally {
+            if (photoStream != null) {
+                photoStream.close();
+            }
+        }
+    }
 }
 
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java
index db95aba..d6e9ec6 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java
@@ -41,6 +41,10 @@
  */
 class TestPackageDef implements ITestPackageDef {
 
+    public static final String HOST_SIDE_ONLY_TEST = "hostSideOnly";
+    public static final String NATIVE_TEST = "native";
+    public static final String VM_HOST_TEST = "vmHostTest";
+
     private static final String SIGNATURE_TEST_METHOD = "testSignature";
     private static final String SIGNATURE_TEST_CLASS = "android.tests.sigtest.SimpleSignatureTest";
 
@@ -108,19 +112,14 @@
         return mRunner;
     }
 
-    void setIsVMHostTest(boolean vmHostTest) {
-        mIsVMHostTest = vmHostTest;
-
-    }
-
-    boolean isVMHostTest() {
-        return mIsVMHostTest;
-    }
-
     void setTestType(String testType) {
         mTestType = testType;
     }
 
+    String getTestType() {
+        return mTestType;
+    }
+
     void setJarPath(String jarPath) {
         mJarPath = jarPath;
     }
@@ -190,7 +189,7 @@
         mExcludedTestFilter.setTestInclusion(mClassName, mMethodName);
         mTests = filterTests();
 
-        if ("hostSideOnly".equals(mTestType)) {
+        if (HOST_SIDE_ONLY_TEST.equals(mTestType)) {
             CLog.d("Creating host test for %s", mName);
             JarHostTest hostTest = new JarHostTest();
             hostTest.setRunName(getUri());
@@ -198,7 +197,7 @@
             hostTest.setTests(mTests);
             mDigest = generateDigest(testCaseDir, mJarPath);
             return hostTest;
-        } else if (mIsVMHostTest) {
+        } else if (VM_HOST_TEST.equals(mTestType)) {
             CLog.d("Creating vm host test for %s", mName);
             VMHostTest vmHostTest = new VMHostTest();
             vmHostTest.setRunName(getUri());
@@ -206,7 +205,7 @@
             vmHostTest.setTests(mTests);
             mDigest = generateDigest(testCaseDir, mJarPath);
             return vmHostTest;
-        } else if ("native".equals(mTestType)) {
+        } else if (NATIVE_TEST.equals(mTestType)) {
             return new GeeTest(mUri, mName);
         } else if (mIsSignatureTest) {
             // TODO: hardcode the runner/class/method for now, since current package xml points to
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageXmlParser.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageXmlParser.java
index 65fc87d..d24c5bf 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageXmlParser.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageXmlParser.java
@@ -64,8 +64,6 @@
                 final String testPackageNameSpace = attributes.getValue("appNameSpace");
                 final String packageName = attributes.getValue("name");
                 final String runnerName = attributes.getValue("runner");
-                final String vmHostTest = attributes.getValue("vmHostTest");
-                final String testType = attributes.getValue("testType");
                 final String jarPath = attributes.getValue("jarPath");
                 final String signatureCheck = attributes.getValue("signatureCheck");
                 final String javaPackageFilter = attributes.getValue("javaPackageFilter");
@@ -77,8 +75,7 @@
                 mPackageDef.setAppNameSpace(testPackageNameSpace);
                 mPackageDef.setName(packageName);
                 mPackageDef.setRunner(runnerName);
-                mPackageDef.setIsVMHostTest(parseBoolean(vmHostTest));
-                mPackageDef.setTestType(testType);
+                mPackageDef.setTestType(getTestType(attributes));
                 mPackageDef.setJarPath(jarPath);
                 mPackageDef.setIsSignatureCheck(parseBoolean(signatureCheck));
                 mPackageDef.setTestPackageName(javaPackageFilter);
@@ -129,6 +126,16 @@
 
         }
 
+        private String getTestType(Attributes attributes) {
+            if (parseBoolean(attributes.getValue("hostSideOnly"))) {
+                return TestPackageDef.HOST_SIDE_ONLY_TEST;
+            } else if (parseBoolean(attributes.getValue("vmHostTest"))) {
+                return TestPackageDef.VM_HOST_TEST;
+            } else {
+                return attributes.getValue("testType");
+            }
+        }
+
         @Override
         public void endElement (String uri, String localName, String qName) {
             if (TEST_SUITE_TAG.equals(localName) || TEST_CASE_TAG.equals(localName)) {
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/TestPackageXmlParserTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/TestPackageXmlParserTest.java
index 482844c..7861449 100644
--- a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/TestPackageXmlParserTest.java
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/TestPackageXmlParserTest.java
@@ -57,6 +57,10 @@
         "<TestPackage hostSideOnly=\"blah\" >" +
         "</TestPackage>";
 
+    private static String VM_HOST_TEST_XML = "<TestPackage vmHostTest=\"true\"></TestPackage>";
+
+    private static String NATIVE_TEST_XML = "<TestPackage testType=\"native\"></TestPackage>";
+
     private static String NO_TEST_DATA =
         "<invalid />";
 
@@ -79,7 +83,7 @@
         TestPackageXmlParser parser = new TestPackageXmlParser();
         parser.parse(getStringAsStream(HOST_TEST_DATA));
         TestPackageDef def = parser.getTestPackageDef();
-        // assertTrue(def.isHostSideTest());
+        assertEquals(TestPackageDef.HOST_SIDE_ONLY_TEST, def.getTestType());
         assertEquals(3, def.getTests().size());
         Iterator<TestIdentifier> iterator = def.getTests().iterator();
 
@@ -103,7 +107,22 @@
         TestPackageXmlParser parser = new TestPackageXmlParser();
         parser.parse(getStringAsStream(BAD_HOST_TEST_DATA));
         TestPackageDef def = parser.getTestPackageDef();
-        // assertFalse(def.isHostSideTest());
+        assertFalse(TestPackageDef.HOST_SIDE_ONLY_TEST.equals(def.getTestType()));
+    }
+
+    public void testParse_vmHostTest() throws ParseException  {
+        assertTestType(TestPackageDef.VM_HOST_TEST, VM_HOST_TEST_XML);
+    }
+
+    public void testParse_nativeTest() throws ParseException  {
+        assertTestType(TestPackageDef.NATIVE_TEST, NATIVE_TEST_XML);
+    }
+
+    private void assertTestType(String expectedType, String xml) throws ParseException {
+        TestPackageXmlParser parser = new TestPackageXmlParser();
+        parser.parse(getStringAsStream(xml));
+        TestPackageDef def = parser.getTestPackageDef();
+        assertEquals(expectedType, def.getTestType());
     }
 
     /**