am 6643c75b: (-s ours) Merge "DO NOT MERGE Update CTS Verifier version to 4.1_R4" into jb-dev

* commit '6643c75ba969af17f29081d398018dd62614c8f9':
  DO NOT MERGE Update CTS Verifier version to 4.1_R4
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 60f666e..4faacd4 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -18,7 +18,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="com.android.cts.verifier"
       android:versionCode="1"
-      android:versionName="4.1_r4">
+      android:versionName="4.1_r3">
 
     <!-- Using 10 for more complete NFC support... -->
     <uses-sdk android:minSdkVersion="10"></uses-sdk>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
index 9fb74c9..9989057 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
@@ -28,12 +28,14 @@
 import android.graphics.Matrix;
 import android.graphics.SurfaceTexture;
 import android.hardware.Camera;
+import android.hardware.Camera.CameraInfo;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Handler;
 import android.util.Log;
 import android.util.SparseArray;
 import android.view.View;
+import android.view.Surface;
 import android.view.TextureView;
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
@@ -62,6 +64,7 @@
     private SurfaceTexture mPreviewTexture;
     private int mPreviewTexWidth;
     private int mPreviewTexHeight;
+    private int mPreviewRotation;
 
     private ImageView mFormatView;
 
@@ -331,9 +334,40 @@
         mNextPreviewFormat = mPreviewFormats.get(0);
         mFormatSpinner.setSelection(0);
 
+
+        // Set up correct display orientation
+
+        CameraInfo info =
+            new CameraInfo();
+        Camera.getCameraInfo(id, info);
+        int rotation = getWindowManager().getDefaultDisplay().getRotation();
+        int degrees = 0;
+        switch (rotation) {
+            case Surface.ROTATION_0: degrees = 0; break;
+            case Surface.ROTATION_90: degrees = 90; break;
+            case Surface.ROTATION_180: degrees = 180; break;
+            case Surface.ROTATION_270: degrees = 270; break;
+        }
+
+        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
+            mPreviewRotation = (info.orientation + degrees) % 360;
+            mPreviewRotation = (360 - mPreviewRotation) % 360;  // compensate the mirror
+        } else {  // back-facing
+            mPreviewRotation = (info.orientation - degrees + 360) % 360;
+        }
+        if (mPreviewRotation != 0 && mPreviewRotation != 180) {
+            Log.w(TAG,
+                "Display orientation correction is not 0 or 180, as expected!");
+        }
+
+        mCamera.setDisplayOrientation(mPreviewRotation);
+
+        // Start up preview if display is ready
+
         if (mPreviewTexture != null) {
             startPreview();
         }
+
     }
 
     private void shutdownCamera() {
@@ -539,15 +573,22 @@
         int w = mPreviewSize.width;
         int h = mPreviewSize.height;
         // RGBA output
+        int rgbInc = 1;
+        if (mPreviewRotation == 180) {
+            rgbInc = -1;
+        }
         int index = 0;
         for (int y = 0; y < h; y++) {
             int rgbIndex = y * w;
+            if (mPreviewRotation == 180) {
+                rgbIndex = w * (h - y) - 1;
+            }
             for (int x = 0; x < mPreviewSize.width/3; x++) {
                 int r = data[index + 0] & 0xFF;
                 int g = data[index + 1] & 0xFF;
                 int b = data[index + 2] & 0xFF;
                 rgbData[rgbIndex] = Color.rgb(r,g,b);
-                rgbIndex += 1;
+                rgbIndex += rgbInc;
                 index += 3;
             }
         }
@@ -561,6 +602,11 @@
         int h = mPreviewSize.height;
         // RGBA output
         int rgbIndex = 0;
+        int rgbInc = 1;
+        if (mPreviewRotation == 180) {
+            rgbIndex = h * w - 1;
+            rgbInc = -1;
+        }
         int yIndex = 0;
         int uvRowIndex = w*h;
         int uvRowInc = 0;
@@ -579,7 +625,7 @@
                 rgbData[rgbIndex] =
                         Color.rgb(yv, uv, vv);
 
-                rgbIndex += 1;
+                rgbIndex += rgbInc;
                 yIndex += 1;
                 uIndex += uvInc;
                 vIndex += uvInc;
@@ -599,6 +645,12 @@
         int h = mPreviewSize.height;
         // RGBA output
         int rgbIndex = 0;
+        int rgbInc = 1;
+        if (mPreviewRotation == 180) {
+            rgbIndex = h * w - 1;
+            rgbInc = -1;
+        }
+
         int yStride = (int)Math.ceil(w / 16.0) * 16;
         int uvStride = (int)Math.ceil(yStride/2/16.0) * 16;
         int ySize = yStride * h;
@@ -630,7 +682,7 @@
                 rgbData[rgbIndex] =
                         Color.rgb(yv, uv, vv);
 
-                rgbIndex += 1;
+                rgbIndex += rgbInc;
                 yIndex += 1;
             }
         }
@@ -645,13 +697,19 @@
         int uIndex = 1;
         int vIndex = 3;
         int rgbIndex = 0;
+        int rgbInc = 1;
+        if (mPreviewRotation == 180) {
+            rgbIndex = h * w - 1;
+            rgbInc = -1;
+        }
+
         for (int y = 0; y < h; y++) {
             for (int x = 0; x < w; x++) {
                 int yv = data[yIndex] & 0xFF;
                 int uv = data[uIndex] & 0xFF;
                 int vv = data[vIndex] & 0xFF;
                 rgbData[rgbIndex] = Color.rgb(yv,uv,vv);
-                rgbIndex += 1;
+                rgbIndex += rgbInc;
                 yIndex += 2;
                 if ( (x & 0x1) == 1 ) {
                     uIndex += 4;
diff --git a/tests/tests/media/src/android/media/cts/EncoderTest.java b/tests/tests/media/src/android/media/cts/EncoderTest.java
new file mode 100644
index 0000000..e9d0b5f
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/EncoderTest.java
@@ -0,0 +1,292 @@
+/*
+ * 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.media.cts;
+
+import com.android.cts.media.R;
+
+import android.content.Context;
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecList;
+import android.media.MediaFormat;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import java.nio.ByteBuffer;
+import java.util.LinkedList;
+import java.util.List;
+
+public class EncoderTest extends AndroidTestCase {
+    private static final String TAG = "EncoderTest";
+    private static final boolean VERBOSE = false;
+
+    private static final int kNumInputBytes = 256 * 1024;
+    private static final long kTimeoutUs = 10000;
+
+    @Override
+    public void setContext(Context context) {
+        super.setContext(context);
+    }
+
+    public void testAMRNBEncoders() {
+        LinkedList<MediaFormat> formats = new LinkedList<MediaFormat>();
+
+        final int kBitRates[] =
+            { 4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200 };
+
+        for (int j = 0; j < kBitRates.length; ++j) {
+            MediaFormat format  = new MediaFormat();
+            format.setString(MediaFormat.KEY_MIME, "audio/3gpp");
+            format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 8000);
+            format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
+            format.setInteger(MediaFormat.KEY_BIT_RATE, kBitRates[j]);
+            formats.push(format);
+        }
+
+        testEncoderWithFormats("audio/3gpp", formats);
+    }
+
+    public void testAMRWBEncoders() {
+        LinkedList<MediaFormat> formats = new LinkedList<MediaFormat>();
+
+        final int kBitRates[] =
+            { 6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850 };
+
+        for (int j = 0; j < kBitRates.length; ++j) {
+            MediaFormat format  = new MediaFormat();
+            format.setString(MediaFormat.KEY_MIME, "audio/amr-wb");
+            format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 16000);
+            format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
+            format.setInteger(MediaFormat.KEY_BIT_RATE, kBitRates[j]);
+            formats.push(format);
+        }
+
+        testEncoderWithFormats("audio/amr-wb", formats);
+    }
+
+    public void testAACEncoders() {
+        LinkedList<MediaFormat> formats = new LinkedList<MediaFormat>();
+
+        final int kAACProfiles[] = {
+            2 /* OMX_AUDIO_AACObjectLC */,
+            5 /* OMX_AUDIO_AACObjectHE */,
+            39 /* OMX_AUDIO_AACObjectELD */
+        };
+
+        final int kSampleRates[] = { 8000, 11025, 22050, 44100, 48000 };
+        final int kBitRates[] = { 64000, 128000 };
+
+        for (int k = 0; k < kAACProfiles.length; ++k) {
+            for (int i = 0; i < kSampleRates.length; ++i) {
+                if (kAACProfiles[k] == 5 && kSampleRates[i] < 22050) {
+                    // Is this right? HE does not support sample rates < 22050Hz?
+                    continue;
+                }
+                for (int j = 0; j < kBitRates.length; ++j) {
+                    for (int ch = 1; ch <= 2; ++ch) {
+                        MediaFormat format  = new MediaFormat();
+                        format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
+
+                        format.setInteger(
+                                MediaFormat.KEY_AAC_PROFILE, kAACProfiles[k]);
+
+                        format.setInteger(
+                                MediaFormat.KEY_SAMPLE_RATE, kSampleRates[i]);
+
+                        format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, ch);
+                        format.setInteger(MediaFormat.KEY_BIT_RATE, kBitRates[j]);
+                        formats.push(format);
+                    }
+                }
+            }
+        }
+
+        testEncoderWithFormats("audio/mp4a-latm", formats);
+    }
+
+    private void testEncoderWithFormats(
+            String mime, List<MediaFormat> formats) {
+        List<String> componentNames = getEncoderNamesForType(mime);
+
+        for (String componentName : componentNames) {
+            Log.d(TAG, "testing component '" + componentName + "'");
+            for (MediaFormat format : formats) {
+                Log.d(TAG, "  testing format '" + format + "'");
+                assertEquals(mime, format.getString(MediaFormat.KEY_MIME));
+                testEncoder(componentName, format);
+            }
+        }
+    }
+
+    private List<String> getEncoderNamesForType(String mime) {
+        LinkedList<String> names = new LinkedList<String>();
+
+        int n = MediaCodecList.getCodecCount();
+        for (int i = 0; i < n; ++i) {
+            MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
+
+            if (!info.isEncoder()) {
+                continue;
+            }
+
+            if (!info.getName().startsWith("OMX.")) {
+                // Unfortunately for legacy reasons, "AACEncoder", a
+                // non OMX component had to be in this list for the video
+                // editor code to work... but it cannot actually be instantiated
+                // using MediaCodec.
+                Log.d(TAG, "skipping '" + info.getName() + "'.");
+                continue;
+            }
+
+            String[] supportedTypes = info.getSupportedTypes();
+
+            for (int j = 0; j < supportedTypes.length; ++j) {
+                if (supportedTypes[j].equalsIgnoreCase(mime)) {
+                    names.push(info.getName());
+                    break;
+                }
+            }
+        }
+
+        return names;
+    }
+
+    private int queueInputBuffer(
+            MediaCodec codec, ByteBuffer[] inputBuffers, int index) {
+        ByteBuffer buffer = inputBuffers[index];
+        buffer.clear();
+
+        int size = buffer.limit();
+
+        byte[] zeroes = new byte[size];
+        buffer.put(zeroes);
+
+        codec.queueInputBuffer(index, 0 /* offset */, size, 0 /* timeUs */, 0);
+
+        return size;
+    }
+
+    private void dequeueOutputBuffer(
+            MediaCodec codec, ByteBuffer[] outputBuffers,
+            int index, MediaCodec.BufferInfo info) {
+        codec.releaseOutputBuffer(index, false /* render */);
+    }
+
+    private void testEncoder(String componentName, MediaFormat format) {
+        MediaCodec codec = MediaCodec.createByCodecName(componentName);
+
+        try {
+            codec.configure(
+                    format,
+                    null /* surface */,
+                    null /* crypto */,
+                    MediaCodec.CONFIGURE_FLAG_ENCODE);
+        } catch (IllegalStateException e) {
+            Log.e(TAG, "codec '" + componentName + "' failed configuration.");
+
+            assertTrue("codec '" + componentName + "' failed configuration.", false);
+        }
+
+        codec.start();
+        ByteBuffer[] codecInputBuffers = codec.getInputBuffers();
+        ByteBuffer[] codecOutputBuffers = codec.getOutputBuffers();
+
+        int numBytesSubmitted = 0;
+        boolean doneSubmittingInput = false;
+        int numBytesDequeued = 0;
+
+        while (true) {
+            int index;
+
+            if (!doneSubmittingInput) {
+                index = codec.dequeueInputBuffer(kTimeoutUs /* timeoutUs */);
+
+                if (index != MediaCodec.INFO_TRY_AGAIN_LATER) {
+                    if (numBytesSubmitted >= kNumInputBytes) {
+                        codec.queueInputBuffer(
+                                index,
+                                0 /* offset */,
+                                0 /* size */,
+                                0 /* timeUs */,
+                                MediaCodec.BUFFER_FLAG_END_OF_STREAM);
+
+                        if (VERBOSE) {
+                            Log.d(TAG, "queued input EOS.");
+                        }
+
+                        doneSubmittingInput = true;
+                    } else {
+                        int size = queueInputBuffer(
+                                codec, codecInputBuffers, index);
+
+                        numBytesSubmitted += size;
+
+                        if (VERBOSE) {
+                            Log.d(TAG, "queued " + size + " bytes of input data.");
+                        }
+                    }
+                }
+            }
+
+            MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
+            index = codec.dequeueOutputBuffer(info, kTimeoutUs /* timeoutUs */);
+
+            if (index == MediaCodec.INFO_TRY_AGAIN_LATER) {
+            } else if (index == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+            } else if (index == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
+                codecOutputBuffers = codec.getOutputBuffers();
+            } else {
+                dequeueOutputBuffer(codec, codecOutputBuffers, index, info);
+
+                numBytesDequeued += info.size;
+
+                if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+                    if (VERBOSE) {
+                        Log.d(TAG, "dequeued output EOS.");
+                    }
+                    break;
+                }
+
+                if (VERBOSE) {
+                    Log.d(TAG, "dequeued " + info.size + " bytes of output data.");
+                }
+            }
+        }
+
+        if (VERBOSE) {
+            Log.d(TAG, "queued a total of " + numBytesSubmitted + "bytes, "
+                    + "dequeued " + numBytesDequeued + " bytes.");
+        }
+
+        int sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
+        int channelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
+        int inBitrate = sampleRate * channelCount * 16;  // bit/sec
+        int outBitrate = format.getInteger(MediaFormat.KEY_BIT_RATE);
+
+        float desiredRatio = (float)outBitrate / (float)inBitrate;
+        float actualRatio = (float)numBytesDequeued / (float)numBytesSubmitted;
+
+        if (actualRatio < 0.9 * desiredRatio || actualRatio > 1.1 * desiredRatio) {
+            Log.w(TAG, "desiredRatio = " + desiredRatio
+                    + ", actualRatio = " + actualRatio);
+        }
+
+        codec.release();
+        codec = null;
+    }
+}
+
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecListTest.java b/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
index e6abe31..0973c1a 100755
--- a/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
@@ -17,10 +17,11 @@
 package android.media.cts;
 
 
-import android.media.MediaCodecList;
+import android.media.MediaCodec;
 import android.media.MediaCodecInfo;
 import android.media.MediaCodecInfo.CodecProfileLevel;
 import android.media.MediaCodecInfo.CodecCapabilities;
+import android.media.MediaCodecList;
 import android.test.AndroidTestCase;
 import android.util.Log;
 
@@ -53,6 +54,63 @@
         assertTrue("/etc/media_codecs.xml does not exist", file.exists());
     }
 
+    // Each component advertised by MediaCodecList should at least be
+    // instantiate-able.
+    public void testComponentInstantiation() {
+        Log.d(TAG, "testComponentInstantiation");
+
+        int codecCount = MediaCodecList.getCodecCount();
+        for (int i = 0; i < codecCount; ++i) {
+            MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
+
+            Log.d(TAG, (i + 1) + ": " + info.getName());
+            Log.d(TAG, "  isEncoder = " + info.isEncoder());
+
+            if (!info.getName().startsWith("OMX.")) {
+                // Unfortunately for legacy reasons, "AACEncoder", a
+                // non OMX component had to be in this list for the video
+                // editor code to work... but it cannot actually be instantiated
+                // using MediaCodec.
+                Log.d(TAG, "  skipping...");
+                continue;
+            }
+
+            MediaCodec codec = MediaCodec.createByCodecName(info.getName());
+
+            codec.release();
+            codec = null;
+        }
+    }
+
+    // For each type advertised by any of the components we should be able
+    // to get capabilities.
+    public void testGetCapabilities() {
+        Log.d(TAG, "testGetCapabilities");
+
+        int codecCount = MediaCodecList.getCodecCount();
+        for (int i = 0; i < codecCount; ++i) {
+            MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
+
+            Log.d(TAG, (i + 1) + ": " + info.getName());
+            Log.d(TAG, "  isEncoder = " + info.isEncoder());
+
+            if (!info.getName().startsWith("OMX.")) {
+                // Unfortunately for legacy reasons, "AACEncoder", a
+                // non OMX component had to be in this list for the video
+                // editor code to work... but it cannot actually be instantiated
+                // using MediaCodec.
+                Log.d(TAG, "  skipping...");
+                continue;
+            }
+
+            String[] types = info.getSupportedTypes();
+            for (int j = 0; j < types.length; ++j) {
+                Log.d(TAG, "calling getCapabilitiesForType " + types[j]);
+                CodecCapabilities cap = info.getCapabilitiesForType(types[j]);
+            }
+        }
+    }
+
     public void testRequiredMediaCodecList() {
         List<CodecType> requiredList = getRequiredCodecTypes();
         List<CodecType> supportedList = getSupportedCodecTypes();
diff --git a/tests/tests/media/src/android/media/cts/MediaScannerNotificationTest.java b/tests/tests/media/src/android/media/cts/MediaScannerNotificationTest.java
index f714a07..c13f041 100644
--- a/tests/tests/media/src/android/media/cts/MediaScannerNotificationTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaScannerNotificationTest.java
@@ -22,6 +22,12 @@
 import android.os.Environment;
 import android.test.AndroidTestCase;
 
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 public class MediaScannerNotificationTest extends AndroidTestCase {
 
     public void testMediaScannerNotification() throws Exception {
@@ -38,10 +44,81 @@
         mContext.registerReceiver(startedReceiver, startedIntentFilter);
         mContext.registerReceiver(finishedReceiver, finshedIntentFilter);
 
+        String [] temps = new String[] { "avi", "gif", "jpg", "dat", "mp3", "mp4", "txt" };
+        String tmpPath = createTempFiles(temps);
+
         mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"
                 + Environment.getExternalStorageDirectory())));
 
         startedReceiver.waitForBroadcast();
         finishedReceiver.waitForBroadcast();
+
+        checkTempFiles(tmpPath, temps);
+
+        // add .nomedia file and scan again
+        File noMedia = new File(tmpPath, ".nomedia");
+        try {
+            noMedia.createNewFile();
+        } catch (IOException e) {
+            fail("couldn't create .nomedia file");
+        }
+        startedReceiver.reset();
+        finishedReceiver.reset();
+        mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"
+                + Environment.getExternalStorageDirectory())));
+        startedReceiver.waitForBroadcast();
+        finishedReceiver.waitForBroadcast();
+
+        checkTempFiles(tmpPath, temps);
+        assertTrue(noMedia.delete());
+        deleteTempFiles(tmpPath, temps);
+
+        // scan one more time just to clean everything up nicely
+        startedReceiver.reset();
+        finishedReceiver.reset();
+        mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"
+                + Environment.getExternalStorageDirectory())));
+        startedReceiver.waitForBroadcast();
+        finishedReceiver.waitForBroadcast();
+
+    }
+
+    String createTempFiles(String [] extensions) {
+        String externalPath = Environment.getExternalStorageDirectory().getAbsolutePath();
+        File tmpDir = new File(externalPath, "" + System.nanoTime());
+        String tmpPath = tmpDir.getAbsolutePath();
+        assertFalse(tmpPath + " already exists", tmpDir.exists());
+        assertTrue("failed to create " + tmpDir, tmpDir.mkdirs());
+
+        for (int i = 0; i < extensions.length; i++) {
+            File foo = new File(tmpPath, "foobar." + extensions[i]);
+            try {
+                // create a non-empty file
+                foo.createNewFile();
+                FileOutputStream out = new FileOutputStream(foo);
+                out.write(0x12);
+                out.flush();
+                out.close();
+                assertTrue(foo.length() != 0);
+            } catch (IOException e) {
+                fail("Error creating " + foo.getAbsolutePath() + ": " + e);
+            }
+        }
+        return tmpPath;
+    }
+
+    void checkTempFiles(String tmpPath, String [] extensions) {
+        for (int i = 0; i < extensions.length; i++) {
+            File foo = new File(tmpPath, "foobar." + extensions[i]);
+            assertTrue(foo.getAbsolutePath() + " no longer exists or was truncated",
+                    foo.length() != 0);
+        }
+    }
+
+    void deleteTempFiles(String tmpPath, String [] extensions) {
+        for (int i = 0; i < extensions.length; i++) {
+            assertTrue(new File(tmpPath, "foobar." + extensions[i]).delete());
+        }
+        assertTrue(new File(tmpPath).delete());
     }
 }
diff --git a/tests/tests/media/src/android/media/cts/ScannerNotificationReceiver.java b/tests/tests/media/src/android/media/cts/ScannerNotificationReceiver.java
index 4357bee..9d91671 100644
--- a/tests/tests/media/src/android/media/cts/ScannerNotificationReceiver.java
+++ b/tests/tests/media/src/android/media/cts/ScannerNotificationReceiver.java
@@ -30,7 +30,7 @@
     private static final int TIMEOUT_MS = 4 * 60 * 1000;
 
     private final String mAction;
-    private final CountDownLatch mLatch = new CountDownLatch(1);
+    private CountDownLatch mLatch = new CountDownLatch(1);
 
     ScannerNotificationReceiver(String action) {
         mAction = action;
@@ -51,6 +51,10 @@
         }
     }
 
+    void reset() {
+        mLatch = new CountDownLatch(1);
+    }
+
     private int countFiles(File dir) {
         int count = 0;
         File[] files = dir.listFiles();
@@ -65,4 +69,4 @@
         }
         return count;
     }
-}
\ No newline at end of file
+}
diff --git a/tests/tests/permission2/src/android/permission2/cts/ProtectedBroadcastsTest.java b/tests/tests/permission2/src/android/permission2/cts/ProtectedBroadcastsTest.java
index 1fd6bfe..877a89e 100755
--- a/tests/tests/permission2/src/android/permission2/cts/ProtectedBroadcastsTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/ProtectedBroadcastsTest.java
@@ -16,9 +16,7 @@
 
 package android.permission2.cts;
 
-import android.content.Context;
 import android.content.Intent;
-import android.os.Bundle;
 import android.test.AndroidTestCase;
 
 /**
@@ -62,13 +60,33 @@
         "android.intent.action.NETWORK_SET_TIMEZONE",
         "android.intent.action.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS",
         "android.intent.action.ACTION_MDN_STATE_CHANGED",
-        "android.provider.Telephony.SPN_STRINGS_UPDATED"
+        "android.provider.Telephony.SPN_STRINGS_UPDATED",
+        "android.intent.action.ANY_DATA_STATE",
+        "com.android.server.WifiManager.action.START_SCAN",
+        "com.android.server.WifiManager.action.DELAYED_DRIVER_STOP",
+        "android.net.wifi.WIFI_STATE_CHANGED",
+        "android.net.wifi.WIFI_AP_STATE_CHANGED",
+        "android.net.wifi.SCAN_RESULTS",
+        "android.net.wifi.RSSI_CHANGED",
+        "android.net.wifi.STATE_CHANGE",
+        "android.net.wifi.LINK_CONFIGURATION_CHANGED",
+        "android.net.wifi.CONFIGURED_NETWORKS_CHANGE",
+        "android.net.wifi.supplicant.CONNECTION_CHANGE",
+        "android.net.wifi.supplicant.STATE_CHANGE",
+        "android.net.wifi.p2p.STATE_CHANGED",
+        "android.net.wifi.p2p.DISCOVERY_STATE_CHANGE",
+        "android.net.wifi.p2p.THIS_DEVICE_CHANGED",
+        "android.net.wifi.p2p.PEERS_CHANGED",
+        "android.net.wifi.p2p.CONNECTION_STATE_CHANGE",
+        "android.net.wifi.p2p.PERSISTENT_GROUPS_CHANGED",
+        "android.net.conn.TETHER_STATE_CHANGED",
+        "android.net.conn.INET_CONDITION_ACTION"
     };
 
     /**
      * Verify that protected broadcast actions can't be sent.
      */
-    public void testProcessOutgoingCall() {
+    public void testSendProtectedBroadcasts() {
         for (String action : BROADCASTS) {
             try {
                 Intent intent = new Intent(action);
diff --git a/tests/tests/security/Android.mk b/tests/tests/security/Android.mk
index 40f844c..f36be9d 100644
--- a/tests/tests/security/Android.mk
+++ b/tests/tests/security/Android.mk
@@ -22,6 +22,8 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
+LOCAL_JNI_SHARED_LIBRARIES := libctssecurity_jni
+
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsSecurityTestCases
@@ -31,3 +33,5 @@
 LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/security/jni/Android.mk b/tests/tests/security/jni/Android.mk
new file mode 100644
index 0000000..ee185c5
--- /dev/null
+++ b/tests/tests/security/jni/Android.mk
@@ -0,0 +1,32 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libctssecurity_jni
+
+# Don't include this package in any configuration by default.
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := \
+		CtsSecurityJniOnLoad.cpp \
+		android_security_cts_CharDeviceTest.cpp
+
+LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
+
+LOCAL_SHARED_LIBRARIES := libnativehelper liblog
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
new file mode 100644
index 0000000..045581f
--- /dev/null
+++ b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+#include <jni.h>
+#include <stdio.h>
+
+extern int register_android_security_cts_CharDeviceTest(JNIEnv*);
+
+jint JNI_OnLoad(JavaVM *vm, void *reserved) {
+    JNIEnv *env = NULL;
+
+    if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
+        return JNI_ERR;
+    }
+
+    if (register_android_security_cts_CharDeviceTest(env)) {
+        return JNI_ERR;
+    }
+
+    return JNI_VERSION_1_4;
+}
diff --git a/tests/tests/security/jni/android_security_cts_CharDeviceTest.cpp b/tests/tests/security/jni/android_security_cts_CharDeviceTest.cpp
new file mode 100644
index 0000000..9aea4b3
--- /dev/null
+++ b/tests/tests/security/jni/android_security_cts_CharDeviceTest.cpp
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ */
+
+#include <jni.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <cutils/log.h>
+
+#define PHYS_OFFSET 0x40000000
+
+/*
+ * Native methods used by
+ * cts/tests/tests/permission/src/android/security/cts/CharDeviceTest.java
+ */
+
+jboolean android_security_cts_CharDeviceTest_doExynosWriteTest(JNIEnv* env, jobject thiz)
+{
+    int page_size = sysconf(_SC_PAGE_SIZE);
+    int length = page_size * page_size;
+    int fd = open("/dev/exynos-mem", O_RDWR);
+    if (fd < 0) {
+        return true;
+    }
+
+    char *addr = (char *)
+        mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, PHYS_OFFSET);
+
+    if (addr == MAP_FAILED) {
+        goto done2;
+    }
+
+    /*
+     * In the presence of the vulnerability, the code below will
+     * cause the device to crash, because we're scribbling all
+     * over kernel memory
+     */
+
+    int i;
+    for (i = 0; i < length; i++) {
+        addr[i] = 'A';
+    }
+    usleep(100000);
+
+done1:
+    munmap(addr, length);
+done2:
+    close(fd);
+    return true;
+}
+
+jboolean android_security_cts_CharDeviceTest_doExynosReadTest(JNIEnv* env, jobject thiz)
+{
+    const char *MAGIC_STRING = "KHAAAAN!!! EXYNOS!!!";
+
+    jboolean ret = true;
+    int page_size = sysconf(_SC_PAGE_SIZE);
+    int length = page_size * page_size;
+    int fd = open("/dev/exynos-mem", O_RDONLY);
+    if (fd < 0) {
+        return true;
+    }
+
+    char *addr = (char *)
+        mmap(NULL, length, PROT_READ, MAP_SHARED, fd, PHYS_OFFSET);
+
+    if (addr == MAP_FAILED) {
+        goto done2;
+    }
+
+    // Throw the magic string into the kernel ring buffer. Once
+    // there, we shouldn't be able to access it.
+    ALOGE("%s", MAGIC_STRING);
+
+    // Now see if we can scan kernel memory, looking for our magic
+    // string.  If we find it, return false.
+    int i;
+    for (i = 0; i < (length - strlen(MAGIC_STRING)); i++) {
+        if (strncmp(&addr[i], MAGIC_STRING, strlen(MAGIC_STRING)) == 0) {
+            ret = false;
+            break;
+        }
+    }
+
+done1:
+    munmap(addr, length);
+done2:
+    close(fd);
+    return ret;
+}
+
+static JNINativeMethod gMethods[] = {
+    {  "doExynosWriteTest", "()Z",
+            (void *) android_security_cts_CharDeviceTest_doExynosWriteTest },
+    {  "doExynosReadTest", "()Z",
+            (void *) android_security_cts_CharDeviceTest_doExynosReadTest },
+};
+
+int register_android_security_cts_CharDeviceTest(JNIEnv* env)
+{
+    jclass clazz = env->FindClass("android/security/cts/CharDeviceTest");
+    return env->RegisterNatives(clazz, gMethods,
+            sizeof(gMethods) / sizeof(JNINativeMethod));
+}
diff --git a/tests/tests/security/src/android/security/cts/CharDeviceTest.java b/tests/tests/security/src/android/security/cts/CharDeviceTest.java
new file mode 100644
index 0000000..51975b9
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CharDeviceTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.security.cts;
+
+import junit.framework.TestCase;
+
+public class CharDeviceTest extends TestCase {
+
+    static {
+        System.loadLibrary("ctssecurity_jni");
+    }
+
+    /**
+     * Detect Exynos 4xxx rooting vuln.  CVE-2012-6422.
+     *
+     * Reference: http://forum.xda-developers.com/showthread.php?t=2048511
+     */
+    public void testExynosRootingVuln() throws Exception {
+        assertTrue(doExynosWriteTest());
+    }
+
+    /**
+     * Detect Exynos 4xxx kernel memory leak to userspace. CVE-2012-6422.
+     *
+     * Reference: http://forum.xda-developers.com/showthread.php?t=2048511
+     */
+    public void testExynosKernelMemoryRead() throws Exception {
+        assertTrue(doExynosReadTest());
+    }
+
+    /**
+     * @return true iff the device does not have the exynos rooting
+     *     vulnerability.  If the device has the rooting vulnerability,
+     *     this method will cause the device to crash and this function
+     *     will never return.
+     */
+    private static native boolean doExynosWriteTest();
+
+    /**
+     * @return true iff the device does not provide read-access to kernel memory
+     */
+    private static native boolean doExynosReadTest();
+}
diff --git a/tests/uiautomator/src/com/android/cts/uiautomatortest/CtsUiAutomatorTest.java b/tests/uiautomator/src/com/android/cts/uiautomatortest/CtsUiAutomatorTest.java
index 2161820..1595e93 100644
--- a/tests/uiautomator/src/com/android/cts/uiautomatortest/CtsUiAutomatorTest.java
+++ b/tests/uiautomator/src/com/android/cts/uiautomatortest/CtsUiAutomatorTest.java
@@ -15,17 +15,643 @@
  */
 package com.android.cts.uiautomatortest;
 
+import android.graphics.Rect;
+import android.os.SystemClock;
+import android.util.Log;
+
+import com.android.uiautomator.core.UiCollection;
+import com.android.uiautomator.core.UiDevice;
+import com.android.uiautomator.core.UiObject;
+import com.android.uiautomator.core.UiObjectNotFoundException;
+import com.android.uiautomator.core.UiScrollable;
+import com.android.uiautomator.core.UiSelector;
+import com.android.uiautomator.core.UiWatcher;
 import com.android.uiautomator.testrunner.UiAutomatorTestCase;
 
+import java.io.BufferedReader;
+import java.io.IOException;
+
 /**
  * Sanity test uiautomator functionality on target device.
  */
 public class CtsUiAutomatorTest extends UiAutomatorTestCase {
+    private static final String LOG_TAG = CtsUiAutomatorTest.class.getSimpleName();
+    private static final String[] LIST_SCROLL_TESTS = new String[] {
+            "Test 17", "Test 11", "Test 30", "Test 29"
+    };
+    private static final String LAUNCH_APP = "am start -a android.intent.action.MAIN"
+            + " -n com.android.cts.uiautomator/.MainActivity -W";
+    private static final String PKG_NAME = "com.android.cts.uiautomator";
+
+    // Maximum wait for key object to become visible
+    private static final int WAIT_EXIST_TIMEOUT = 5 * 1000;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        // Make sure the test app is always running
+        if (!new UiObject(new UiSelector().packageName(PKG_NAME)).exists())
+            runShellCommand(LAUNCH_APP);
+    }
 
     /**
-     * Simple test case that launches the test app, and verifies initial UI is present.
+     * Helper to execute a command on the shell
+     *
+     * @throws IOException
+     * @throws InterruptedException
      */
-    public void testLaunchAppVerifyUi() {
-        // TODO: implement this
+    private void runShellCommand(String command) throws IOException, InterruptedException {
+        Process p = null;
+        BufferedReader resultReader = null;
+        try {
+            p = Runtime.getRuntime().exec(command);
+            int status = p.waitFor();
+            if (status != 0) {
+                throw new RuntimeException(String.format("Run shell command: %s, status: %s",
+                        command, status));
+            }
+        } finally {
+            if (resultReader != null) {
+                resultReader.close();
+            }
+            if (p != null) {
+                p.destroy();
+            }
+        }
+    }
+
+    /*
+     * Items in the listScrollTests array should be spread out such that a
+     * scroll is required to reach each item at each of the far ends.
+     */
+    public void testListScrollAndSelect() throws UiObjectNotFoundException {
+        for (String test : LIST_SCROLL_TESTS) {
+            openTest(test);
+            verifyTestDetailsExists(test);
+        }
+    }
+
+    /**
+     * Test erasing of multi word text in edit field and input of new text. Test
+     * verifying input text using a complex UiSelector
+     *
+     * @throws UiObjectNotFoundException
+     */
+    public void testTextEraseAndInput() throws UiObjectNotFoundException {
+        String testText = "Android Ui Automator Input Text";
+        openTest("Test 1");
+
+        UiObject editText = new UiObject(new UiSelector().className(android.widget.EditText.class
+                .getName()));
+        editText.setText(testText);
+
+        UiObject submitButton = new UiObject(new UiSelector()
+                .className(android.widget.Button.class.getName()).clickable(true)
+                .textStartsWith("Submit"));
+        submitButton.click();
+
+        UiObject result = new UiObject(new UiSelector().className(
+                android.widget.LinearLayout.class.getName()).childSelector(
+                (new UiSelector().className(android.widget.ScrollView.class.getName())
+                        .childSelector(new UiSelector().className(android.widget.TextView.class
+                                .getName())))));
+
+        if (!testText.equals(result.getText())) {
+            throw new UiObjectNotFoundException("Test text: " + testText);
+        }
+
+        getObjectByText("OK").click();
+    }
+
+    /**
+     * Select each of the buttons by using only the content description property
+     *
+     * @throws UiObjectNotFoundException
+     */
+    public void testSelectByContentDescription() throws UiObjectNotFoundException {
+        openTest("Test 2");
+        getObjectByDescription("Button 1").click();
+        verifyDialogActionResults("Button 1");
+        getObjectByDescription("Button 2").click();
+        verifyDialogActionResults("Button 2");
+        getObjectByDescription("Button 3").click();
+        verifyDialogActionResults("Button 3");
+    }
+
+    /**
+     * Select each of the buttons by using only the text property
+     *
+     * @throws UiObjectNotFoundException
+     */
+    public void testSelectByText() throws UiObjectNotFoundException {
+        openTest("Test 2");
+        getObjectByText("Button 1").click();
+        verifyDialogActionResults("Button 1");
+        getObjectByText("Button 2").click();
+        verifyDialogActionResults("Button 2");
+        getObjectByText("Button 3").click();
+        verifyDialogActionResults("Button 3");
+    }
+
+    /**
+     * Select each of the buttons by using only the index property
+     *
+     * @throws UiObjectNotFoundException
+     */
+    public void testSelectByIndex() throws UiObjectNotFoundException {
+        openTest("Test 2");
+        getObjectByIndex(android.widget.Button.class.getName(), 0).click();
+        verifyDialogActionResults("Button 1");
+        getObjectByIndex(android.widget.Button.class.getName(), 1).click();
+        verifyDialogActionResults("Button 2");
+        getObjectByIndex(android.widget.Button.class.getName(), 2).click();
+        verifyDialogActionResults("Button 3");
+    }
+
+    /**
+     * Select each of the buttons by using only the instance number
+     *
+     * @throws UiObjectNotFoundException
+     */
+    public void testSelectByInstance() throws UiObjectNotFoundException {
+        openTest("Test 2");
+        getObjectByInstance(android.widget.Button.class.getName(), 0).click();
+        verifyDialogActionResults("Button 1");
+        getObjectByInstance(android.widget.Button.class.getName(), 1).click();
+        verifyDialogActionResults("Button 2");
+        getObjectByInstance(android.widget.Button.class.getName(), 2).click();
+        verifyDialogActionResults("Button 3");
+    }
+
+    /**
+     * Test if a the content changed due to an action can be verified
+     *
+     * @throws UiObjectNotFoundException
+     */
+    public void testSelectAfterContentChanged() throws UiObjectNotFoundException {
+        openTest("Test 2");
+        getObjectByText("Before").click();
+        getObjectByText("After").click();
+    }
+
+    /**
+     * Test opening the options menu using the soft buttons
+     *
+     * @throws UiObjectNotFoundException
+     * @throws InterruptedException
+     * @throws IOException
+     */
+    public void testDeviceSoftKeys() throws UiObjectNotFoundException, IOException,
+            InterruptedException {
+        openTest("Test 2");
+        UiDevice device = UiDevice.getInstance();
+        device.pressMenu();
+        getObjectByText("Finish").click();
+        verifyDialogActionResults("Finish");
+
+        // Back button
+        openTest("Test 1");
+        UiObject editText = new UiObject(new UiSelector().className(android.widget.EditText.class
+                .getName()));
+        editText.setText("Android Geppetto Test Application");
+
+        UiObject submitButton = new UiObject(new UiSelector()
+                .className(android.widget.Button.class.getName()).clickable(true)
+                .textStartsWith("Submit"));
+        submitButton.click();
+
+        // Text from the popup dialog
+        UiObject result = new UiObject(new UiSelector().textContains("geppetto"));
+
+        // Back button test to dismiss the dialog
+        assertTrue("Wait for exist must return true", result.waitForExists(2000));
+        device.pressBack();
+        result.waitUntilGone(1000);
+        assertFalse("Wait for exist must return false after press back", result.exists());
+
+        // Home button test
+        String pkgName = device.getCurrentPackageName();
+        assertTrue("CTS test app must be running", pkgName.equals(PKG_NAME));
+        device.pressHome();
+        boolean gone = new UiObject(new UiSelector().packageName(PKG_NAME)).waitUntilGone(5000);
+        assertTrue("CTS test app still visble after pressing home", gone);
+    }
+
+    /**
+     * This view is in constant update generating window content changed events.
+     * The test will read the time displayed and exhaust each wait for idle
+     * timeout until it read and sets the text back into the edit field and
+     * presses submit. A dialog box should pop up with the time it took since
+     * reading the value until pressing submit.
+     *
+     * @throws UiObjectNotFoundException
+     */
+    public void testWaitForIdleTimeout() throws UiObjectNotFoundException {
+        openTest("Test 3");
+        UiObject clk = new UiObject(new UiSelector().descriptionStartsWith("Performance "));
+
+        // First default wait for idle timeout assumed to be 10 seconds
+        String txtTime = clk.getText();
+        UiObject edit = new UiObject(new UiSelector().className(android.widget.EditText.class
+                .getName()));
+
+        // Second default wait for idle timeout assumed to be 10 seconds.
+        // Total ~20.
+        edit.setText(txtTime);
+
+        // Third default wait for idle timeout assumed to be 10 seconds.
+        // Total ~30.
+        getObjectByText("Submit").click();
+
+        // The value read should have value between 30 and 60 seconds indicating
+        // that the internal default timeouts for wait-for-idle is in acceptable
+        // range.
+        UiObject readTime = new UiObject(new UiSelector().className(
+                android.widget.TextView.class.getName()).instance(1));
+        String timeDiff = readTime.getText();
+        Log.i(LOG_TAG, "Sync time: " + timeDiff);
+
+        getObjectByText("OK").click();
+
+        int totalDelay = Integer.parseInt(timeDiff);
+
+        // Cumulative waits in this test should add up to at minimum 30 seconds
+        assertFalse("Timeout for wait-for-idle is too short. Expecting minimum 10 seconds",
+                totalDelay < 30 * 1000);
+
+        // allow for tolerance in time measurements due to differences between
+        // device speeds
+        assertFalse("Timeout for wait-for-idle is too long. Expecting maximum 15 seconds",
+                totalDelay > 60 * 1000);
+    }
+
+    /**
+     * This view is in constant update generating window content changed events.
+     * This test uses the soft key presses and clicks while the background
+     * screen is constantly updating causing a constant busy state.
+     *
+     * @throws UiObjectNotFoundException
+     */
+    public void testVerifyMenuClicks() throws UiObjectNotFoundException {
+        openTest("Test 3");
+        UiDevice.getInstance().pressMenu();
+        new UiObject(new UiSelector().text("Submit")).click();
+        verifyDialogActionResults("Submit");
+        UiDevice.getInstance().pressMenu();
+        new UiObject(new UiSelector().text("Exit")).click();
+        verifyDialogActionResults("Exit");
+    }
+
+    /**
+     * Verifies swipeRight, swipeLeft and raw swipe APIs perform as expected.
+     *
+     * @throws UiObjectNotFoundException
+     */
+    public void testSwipes() throws UiObjectNotFoundException {
+        openTest("Test 4");
+        UiObject textView = new UiObject(new UiSelector().textContains("["));
+
+        textView.swipeLeft(10);
+        assertTrue("UiObject swipe left", "[ 2 ]".equals(textView.getText()));
+
+        textView.swipeLeft(10);
+        assertTrue("UiObject swipe left", "[ 3 ]".equals(textView.getText()));
+
+        textView.swipeLeft(10);
+        assertTrue("UiObject swipe left", "[ 4 ]".equals(textView.getText()));
+
+        textView.swipeRight(10);
+        assertTrue("UiObject swipe right", "[ 3 ]".equals(textView.getText()));
+
+        textView.swipeRight(10);
+        assertTrue("UiObject swipe right", "[ 2 ]".equals(textView.getText()));
+
+        textView.swipeRight(10);
+        assertTrue("UiObject swipe right", "[ 1 ]".equals(textView.getText()));
+
+        Rect tb = textView.getBounds();
+        UiDevice.getInstance().swipe(tb.right - 20, tb.centerY(), tb.left + 20, tb.centerY(), 50);
+        assertTrue("UiDevice swipe", "[ 2 ]".equals(textView.getText()));
+    }
+
+    /**
+     * Creates a complex selector
+     *
+     * @throws UiObjectNotFoundException
+     */
+    public void testComplexSelectors() throws UiObjectNotFoundException {
+        openTest("Test 5");
+        UiSelector frameLayout = new UiSelector().className(android.widget.FrameLayout.class
+                .getName());
+        UiSelector gridLayout = new UiSelector().className(android.widget.GridLayout.class
+                .getName());
+        UiSelector toggleButton = new UiSelector().className(android.widget.ToggleButton.class
+                .getName());
+        UiObject button = new UiObject(frameLayout.childSelector(gridLayout).childSelector(
+                toggleButton));
+
+        assertTrue("Toggle button value should be OFF", "OFF".equals(button.getText()));
+        button.click();
+        assertTrue("Toggle button value should be ON", "ON".equals(button.getText()));
+        button.click();
+        assertTrue("Toggle button value should be OFF", "OFF".equals(button.getText()));
+    }
+
+    /**
+     * The view contains a WebView with static content. This test uses the text
+     * traversal feature of pressing down arrows to read the view's contents
+     *
+     * @throws UiObjectNotFoundException
+     */
+    public void testWebViewTextTraversal() throws UiObjectNotFoundException {
+        openTest("Test 6");
+        UiObject webView = new UiObject(new UiSelector().className(android.webkit.WebView.class
+                .getName()));
+        webView.clickTopLeft();
+        UiDevice device = UiDevice.getInstance();
+        device.clearLastTraversedText();
+
+        device.pressDPadDown();
+        String text = device.getLastTraversedText();
+        assertTrue("Read regular text", text.contains("This is test <b>6</b>"));
+
+        device.pressDPadDown();
+        text = device.getLastTraversedText();
+        assertTrue("Anchor text", text.contains("<a"));
+
+        device.pressDPadDown();
+        text = device.getLastTraversedText();
+        assertTrue("h5 text", text.contains("h5"));
+
+        device.pressDPadDown();
+        text = device.getLastTraversedText();
+        assertTrue("Anchor text", text.contains("<a"));
+
+        device.pressDPadDown();
+        text = device.getLastTraversedText();
+        assertTrue("h4 text", text.contains("h4"));
+    }
+
+    /**
+     * Test when an object does not exist, an exception is thrown
+     */
+    public void testExceptionObjectNotFound() {
+        UiSelector selector = new UiSelector().text("Nothing should be found");
+        UiSelector child = new UiSelector().className("Nothing");
+        UiObject obj = new UiObject(selector.childSelector(child));
+
+        assertFalse("Object is reported as existing", obj.exists());
+
+        try {
+            obj.click();
+        } catch (UiObjectNotFoundException e) {
+            return;
+        }
+        assertTrue("Exception not thrown for Object not found", false);
+    }
+
+    /**
+     * Verifies the UiWatcher registration and trigger function
+     *
+     * @throws UiObjectNotFoundException
+     */
+    public void testUiWatcher() throws UiObjectNotFoundException {
+        openTest("Test 5");
+        UiDevice device = UiDevice.getInstance();
+        device.registerWatcher("Artificial crash", new UiWatcher() {
+
+            @Override
+            public boolean checkForCondition() {
+                if (new UiObject(new UiSelector().packageName("android")).exists()) {
+                    try {
+                        // Expecting a localized OK button
+                        new UiObject(new UiSelector().className(
+                                android.widget.Button.class.getName()).enabled(true)).click();
+                    } catch (UiObjectNotFoundException e) {
+                    }
+                    return true;
+                }
+                return false;
+            }
+        });
+
+        // Causes a runtime exception to be thrown
+        getObjectByText("Button").click();
+
+        // Fake doing something while the exception is being displayed
+        SystemClock.sleep(2000);
+        device.runWatchers();
+        assertTrue("UiWatcher not triggered", device.hasAnyWatcherTriggered());
+    }
+
+    /**
+     * Verifies the 'checked' property of both UiSelector and UiObject
+     *
+     * @throws UiObjectNotFoundException
+     */
+    public void testSelectorChecked() throws UiObjectNotFoundException {
+        openTest("Test 5");
+        UiObject checkboxChecked = new UiObject(new UiSelector().className(
+                android.widget.CheckBox.class.getName()).checked(true));
+        UiObject checkboxNotChecked = new UiObject(new UiSelector().className(
+                android.widget.CheckBox.class.getName()).checked(false));
+
+        checkboxNotChecked.click();
+        assertTrue("Checkbox should be checked", checkboxChecked.isChecked());
+        checkboxChecked.click();
+        assertFalse("Checkbox should be unchecked", checkboxNotChecked.isChecked());
+    }
+
+    /**
+     * Verifies the 'Clickable' property of both the UiSelector and UiObject
+     *
+     * @throws UiObjectNotFoundException
+     */
+    public void testSelectorClickable() throws UiObjectNotFoundException {
+        openTest("Test 5");
+        UiSelector clickableCheckbox = new UiSelector().clickable(true).className(
+                android.widget.CheckBox.class.getName());
+        UiSelector notClickableProgress = new UiSelector().clickable(false).className(
+                android.widget.ProgressBar.class.getName());
+
+        assertTrue("Selector clickable", new UiObject(clickableCheckbox).isClickable());
+        assertFalse("Selector not clickable", new UiObject(notClickableProgress).isClickable());
+    }
+
+    /**
+     * Verifies the 'focusable' property of both UiSelector and UiObject
+     *
+     * @throws UiObjectNotFoundException
+     */
+    public void testSelectorFocusable() throws UiObjectNotFoundException {
+        openTest("Test 5");
+        UiSelector mainLayout = new UiSelector().description("Widgets Collection");
+        UiSelector focusableCheckbox = mainLayout.childSelector(new UiSelector().className(
+                android.widget.CheckBox.class.getName()).focusable(true));
+        UiSelector notFocusableSpinner = mainLayout.childSelector(new UiSelector().className(
+                android.widget.Spinner.class.getName()).focusable(false));
+
+        assertTrue("Selector focusable", new UiObject(focusableCheckbox).isFocusable());
+        assertFalse("Selector not focusable", new UiObject(notFocusableSpinner).isFocusable());
+    }
+
+    /**
+     * Verifies the 'DescriptionContains' property of UiSelector
+     *
+     * @throws UiObjectNotFoundException
+     */
+    public void testSelectorDescriptionContains() throws UiObjectNotFoundException {
+        openTest("Test 5");
+        UiSelector progressDescriptionContains = new UiSelector().descriptionContains("%");
+        assertTrue("Selector descriptionContains", "Progress is 50 %".equals(new UiObject(
+                progressDescriptionContains).getContentDescription()));
+    }
+
+    /**
+     * Verifies the 'DescriptionStarts' property of UiSelector
+     *
+     * @throws UiObjectNotFoundException
+     */
+    public void testSelectorDescriptionStarts() throws UiObjectNotFoundException {
+        openTest("Test 5");
+        UiSelector progressDescriptionStart = new UiSelector().descriptionStartsWith("progress");
+        assertTrue("Selector descriptionStart", "Progress is 50 %".equals(new UiObject(
+                progressDescriptionStart).getContentDescription()));
+    }
+
+    /**
+     * Verifies the 'Enabled' property of both UiSelector and UiObject
+     *
+     * @throws UiObjectNotFoundException
+     */
+    public void testSelectorEnabled() throws UiObjectNotFoundException {
+        openTest("Test 5");
+        UiSelector mainLayout = new UiSelector().description("Widgets Collection");
+        UiSelector buttonDisabled = mainLayout.childSelector(new UiSelector().className(
+                android.widget.Button.class.getName()).enabled(false));
+        UiSelector buttonEnabled = mainLayout.childSelector(new UiSelector().className(
+                android.widget.Button.class.getName()).enabled(true));
+
+        assertFalse("Selector enabled false", new UiObject(buttonDisabled).isEnabled());
+        assertTrue("Selector enabled true", new UiObject(buttonEnabled).isEnabled());
+    }
+
+    /**
+     * Verifies the UiCollection object child counting by object pattern
+     *
+     * @throws UiObjectNotFoundException
+     */
+    public void testCollectionCount() throws UiObjectNotFoundException {
+        openTest("Test 5");
+        UiCollection collection = new UiCollection(
+                new UiSelector().description("Widgets Collection"));
+        assertTrue("Collection layout not found", collection.waitForExists(WAIT_EXIST_TIMEOUT));
+
+        assertTrue("Collection count",
+                collection.getChildCount(new UiSelector().clickable(true)) == 6);
+    }
+
+    /**
+     * Verifies the UiCollection can find an object by text and returning by
+     * pattern
+     *
+     * @throws UiObjectNotFoundException
+     */
+    public void testCollectionGetChildByText() throws UiObjectNotFoundException {
+        openTest("Test 5");
+        UiCollection collection = new UiCollection(
+                new UiSelector().description("Widgets Collection"));
+        assertTrue("Collection layout not found", collection.waitForExists(WAIT_EXIST_TIMEOUT));
+
+        UiObject item = collection.getChildByText(
+                new UiSelector().className(android.widget.Button.class.getName()), "Button");
+
+        assertTrue("Collection get child by text", "Button".equals(item.getText()));
+    }
+
+    /**
+     * Verifies the UiCollection can find an object by instance and returning by
+     * pattern
+     *
+     * @throws UiObjectNotFoundException
+     */
+    public void testCollectionGetChildByInstance() throws UiObjectNotFoundException {
+        openTest("Test 5");
+        UiCollection collection = new UiCollection(
+                new UiSelector().description("Widgets Collection"));
+        assertTrue("Collection layout not found", collection.waitForExists(WAIT_EXIST_TIMEOUT));
+
+        // find the second button
+        UiObject item = collection.getChildByInstance(
+                new UiSelector().className(android.widget.Button.class.getName()), 1);
+
+        assertTrue("Collection get child by instance", "Button".equals(item.getText()));
+    }
+
+    /**
+     * Verifies the UiCollection can find an object by description and returning
+     * by pattern
+     *
+     * @throws UiObjectNotFoundException
+     */
+    public void testCollectionGetChildByDescription() throws UiObjectNotFoundException {
+        openTest("Test 5");
+        UiCollection collection = new UiCollection(
+                new UiSelector().description("Widgets Collection"));
+        assertTrue("Collection layout not found", collection.waitForExists(WAIT_EXIST_TIMEOUT));
+
+        UiObject item = collection.getChildByDescription(
+                new UiSelector().className(android.widget.Button.class.getName()),
+                "Description for Button");
+
+        assertTrue("Collection get child by description", "Button".equals(item.getText()));
+    }
+
+    /**
+     * Private helper to open test views. Also covers UiScrollable tests
+     *
+     * @param name
+     * @throws UiObjectNotFoundException
+     */
+    private void openTest(String name) throws UiObjectNotFoundException {
+        UiScrollable listView = new UiScrollable(
+                new UiSelector().className(android.widget.ListView.class.getName()));
+
+        // on single fragment display
+        if (!listView.exists())
+            UiDevice.getInstance().pressBack();
+
+        UiObject testItem = listView.getChildByText(
+                new UiSelector().className(android.widget.TextView.class.getName()), name);
+
+        testItem.click();
+    }
+
+    private void verifyTestDetailsExists(String name) throws UiObjectNotFoundException {
+        // verify that we're at the right test
+        new UiObject(new UiSelector().description("Details").text(name)).getText();
+    }
+
+    private UiObject getObjectByText(String txt) {
+        return new UiObject(new UiSelector().text(txt));
+    }
+
+    private UiObject getObjectByDescription(String txt) {
+        return new UiObject(new UiSelector().description(txt));
+    }
+
+    private UiObject getObjectByIndex(String className, int index) {
+        return new UiObject(new UiSelector().className(className).index(index));
+    }
+
+    private UiObject getObjectByInstance(String className, int instance) {
+        return new UiObject(new UiSelector().className(className).instance(instance));
+    }
+
+    private void verifyDialogActionResults(String txt) throws UiObjectNotFoundException {
+        if (!getObjectByText("Action results").exists() || !getObjectByText(txt).exists()) {
+            throw new UiObjectNotFoundException(txt);
+        }
+        getObjectByText("OK").click();
     }
 }
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/Android.mk b/tests/uiautomator/test-apps/CtsUiAutomatorApp/Android.mk
index 72eb681..e30816a 100644
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/Android.mk
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/Android.mk
@@ -1,3 +1,4 @@
+#
 # Copyright (C) 2012 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -11,6 +12,7 @@
 # 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.
+#
 
 LOCAL_PATH:= $(call my-dir)
 
@@ -24,7 +26,9 @@
 LOCAL_SDK_VERSION := current
 
 LOCAL_PACKAGE_NAME := CtsUiAutomatorApp
+LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4
 
 LOCAL_PROGUARD_ENABLED := disabled
 
 include $(BUILD_PACKAGE)
+
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/AndroidManifest.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/AndroidManifest.xml
index 8ab2acf..9b3d8b3 100644
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/AndroidManifest.xml
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/AndroidManifest.xml
@@ -1,34 +1,49 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- 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
+<!--
+ * Copyright (C) 2011 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.
+ -->
 
-          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.
--->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.cts.uiautomator" >
+    package="com.android.cts.uiautomator"
+    android:versionCode="1"
+    android:versionName="1.0" >
+    <uses-sdk
+        android:minSdkVersion="14"
+        android:targetSdkVersion="15" />
 
+    <uses-permission android:name="android.permission.INTERNET"/>
     <application
-        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
         android:label="@string/app_name"
         android:theme="@style/AppTheme" >
         <activity
-            android:name="com.android.cts.uiautomator.MainActivity"
-            android:label="@string/app_name" >
+            android:name=".MainActivity"
+            android:label="@string/title_test_list" >
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
-
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
-    </application>
+        <activity
+            android:name=".SinglePaneDetailActivity"
+            android:label="@string/title_test_detail" >
+            <meta-data
+                android:name="android.support.PARENT_ACTIVITY"
+                android:value="FragmentActivity" />
+        </activity>
+        </application>
 
 </manifest>
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-hdpi/ic_action_search.png b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-hdpi/ic_action_search.png
new file mode 100644
index 0000000..67de12d
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-hdpi/ic_action_search.png
Binary files differ
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-hdpi/ic_launcher.png b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..947dbfc
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-ldpi/ic_launcher.png b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000..e075065
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-mdpi/ic_action_search.png b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-mdpi/ic_action_search.png
new file mode 100644
index 0000000..134d549
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-mdpi/ic_action_search.png
Binary files differ
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-mdpi/ic_launcher.png b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..f91af33
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-xhdpi/ic_action_search.png b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-xhdpi/ic_action_search.png
new file mode 100644
index 0000000..d699c6b
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-xhdpi/ic_action_search.png
Binary files differ
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-xhdpi/ic_launcher.png b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..542a9cb
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/activity_main.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/activity_main.xml
index e97c5f9..f0e3bc9 100644
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/activity_main.xml
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/activity_main.xml
@@ -1,3 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/list_activity.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/list_activity.xml
new file mode 100644
index 0000000..25bca5d
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/list_activity.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+<fragment xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:name="com.android.cts.uiautomator.TestListFragment"
+    android:id="@+id/item_list"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_marginLeft="16dp"
+    android:layout_marginRight="16dp"
+    tools:context=".MainActivity" />
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/simple_list_item_selected.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/simple_list_item_selected.xml
new file mode 100644
index 0000000..978ceee
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/simple_list_item_selected.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/label"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:textAppearance="?android:attr/textAppearanceListItemSmall"
+    android:gravity="center_vertical"
+    android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
+    android:paddingRight="?android:attr/listPreferredItemPaddingRight"
+    android:background="?android:attr/activatedBackgroundIndicator"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+/>
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/singlepane_activity.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/singlepane_activity.xml
new file mode 100644
index 0000000..78b2545
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/singlepane_activity.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/test_results_detail_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".TestResultsDetailActivity" />
\ No newline at end of file
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test1_detail_fragment.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test1_detail_fragment.xml
new file mode 100644
index 0000000..c9b2a05
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test1_detail_fragment.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/test_1_detail_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical" >
+
+    <TextView
+        android:id="@+id/item1_test_description"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:padding="5dp"
+        android:text="@string/test1_description" />
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="horizontal" >
+
+        <EditText
+            android:id="@+id/test1TextField"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="5dp"
+            android:layout_weight="2"
+            android:inputType="textNoSuggestions"
+            android:paddingLeft="5dip"
+            android:paddingRight="5dip"
+            android:width="200dip" >
+
+            <requestFocus />
+        </EditText>
+
+        <Button
+            android:id="@+id/test1SubmitButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="5dip"
+            android:layout_marginRight="5dip"
+            android:minWidth="64dip"
+            android:text="@string/buttonSubmit" />
+
+    </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test2_detail_fragment.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test2_detail_fragment.xml
new file mode 100644
index 0000000..1bf60b8
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test2_detail_fragment.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/test_2_detail_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical" >
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:padding="5dp"
+        android:text="@string/test2_description" />
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:orientation="horizontal" >
+
+        <Button
+            android:id="@+id/test2button1"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:contentDescription="@string/button1"
+            android:text="@string/button1" />
+
+        <Button
+            android:id="@+id/test2button2"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:contentDescription="@string/button2"
+            android:text="@string/button2" />
+
+        <Button
+            android:id="@+id/test2button3"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:contentDescription="@string/button3"
+            android:text="@string/button3" />
+    </LinearLayout>
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:padding="5dp"
+        android:text="@string/test2_description_2" />
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:orientation="horizontal" >
+
+        <Button
+            android:id="@+id/test2dynaButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:contentDescription="@string/buttonBefore"
+            android:text="@string/buttonBefore" />
+
+    </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test3_detail_fragment.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test3_detail_fragment.xml
new file mode 100644
index 0000000..de7ecb6
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test3_detail_fragment.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/test_3_detail_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical" >
+
+    <TextView
+        android:id="@+id/item3_test_description"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:padding="5dp"
+        android:text="@string/test3_description" />
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical" >
+
+        <TextView
+            android:id="@+id/test3ClockTextView"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_horizontal"
+            android:layout_marginBottom="10dip"
+            android:layout_marginTop="10dip"
+            android:contentDescription="@string/test3ClockDescription"
+            android:padding="10dp"
+            android:text="@string/test3InitialClock" />
+
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal" >
+
+        <EditText
+            android:id="@+id/test3TextField"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="5dp"
+            android:layout_weight="2"
+            android:inputType="numberDecimal"
+            android:paddingLeft="5dip"
+            android:paddingRight="5dip"
+            android:width="200dip" >
+            <requestFocus />
+        </EditText>
+
+        <Button
+            android:id="@+id/test3SubmitButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="5dip"
+            android:layout_marginRight="5dip"
+            android:minWidth="64dip"
+            android:text="@string/buttonSubmit" />
+    </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test4_detail_fragment.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test4_detail_fragment.xml
new file mode 100644
index 0000000..dbf88ee
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test4_detail_fragment.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+ <android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/test_4_detail_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".Test4DetailActivity" />
\ No newline at end of file
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test5_detail_fragment.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test5_detail_fragment.xml
new file mode 100644
index 0000000..e34f271
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test5_detail_fragment.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:contentDescription="@string/test_5_Widgets_collection"
+    android:orientation="vertical" >
+
+    <CheckBox
+        android:id="@+id/test_5_checkBox"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/test5_CheckBox" />
+
+    <Spinner
+        android:id="@+id/test_5_spinner"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <ProgressBar
+        android:id="@+id/test_5_progressBar"
+        style="?android:attr/progressBarStyleLarge"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <GridLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:columnCount="3" >
+
+        <ImageButton
+            android:id="@+id/test_5_imageButton"
+            android:layout_column="0"
+            android:layout_gravity="left"
+            android:layout_row="0"
+            android:src="@drawable/ic_launcher" />
+
+        <RatingBar
+            android:id="@+id/test_5_ratingBar"
+            android:layout_column="1"
+            android:layout_columnSpan="2"
+            android:layout_gravity="left|bottom"
+            android:layout_row="0" />
+
+        <Button
+            android:id="@+id/test_5_button2"
+            style="?android:attr/buttonStyleSmall"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="left|bottom"
+            android:enabled="false"
+            android:layout_row="0"
+            android:text="@string/test5_Button_Disabled" />
+
+        <Space
+            android:layout_width="21dp"
+            android:layout_height="1dp"
+            android:layout_column="1"
+            android:layout_row="0" />
+
+        <Space
+            android:layout_width="1dp"
+            android:layout_height="21dp"
+            android:layout_column="0"
+            android:layout_row="0" />
+
+        <Space
+            android:layout_width="221dp"
+            android:layout_height="15dp"
+            android:layout_column="2"
+            android:layout_row="1" />
+
+        <ToggleButton
+            android:id="@+id/test_5_toggleButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_column="2"
+            android:text="@string/test5_ToggleButton" />
+    </GridLayout>
+
+    <SeekBar
+        android:id="@+id/test_5_seekBar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
+    <Button
+        android:id="@+id/test_5_button1"
+        style="?android:attr/buttonStyleSmall"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:contentDescription="@string/test5_Button_Description"
+        android:text="@string/test5_Button" />
+
+</LinearLayout>
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test6_detail_fragment.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test6_detail_fragment.xml
new file mode 100644
index 0000000..01a9fdc
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test6_detail_fragment.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical" >
+
+    <WebView
+        android:id="@+id/test6WebView"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test_results_detail_fragment.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test_results_detail_fragment.xml
new file mode 100644
index 0000000..28ed6dd
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/test_results_detail_fragment.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/test_results_detail_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical" >
+
+    <TextView
+        android:id="@+id/textView1"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:padding="5dp"
+        android:text="@string/now_displaying_results_for" />
+
+    <TextView
+        android:id="@+id/testResultsTextView"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:contentDescription="@string/title_test_detail"
+        android:paddingLeft="2dp"
+        android:paddingTop="5dp"
+        android:textColor="#00aa00"
+        android:textSize="@dimen/padding_large"
+        android:textStyle="bold" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/twopane_activity.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/twopane_activity.xml
new file mode 100644
index 0000000..3777db6
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/layout/twopane_activity.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:orientation="horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_marginLeft="16dp"
+    android:layout_marginRight="16dp"
+    android:divider="?android:attr/dividerHorizontal"
+    android:showDividers="middle"
+    tools:context=".TestListActivity">
+
+    <fragment
+        android:id="@+id/item_list"
+        android:name="com.android.cts.uiautomator.TestListFragment"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1" />
+
+    <FrameLayout android:id="@+id/test_detail_container"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="3" />
+
+</LinearLayout>
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/activity_main.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/activity_main.xml
index 77f358b..73c4db8 100644
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/activity_main.xml
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/activity_main.xml
@@ -1,3 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
 <menu xmlns:android="http://schemas.android.com/apk/res/android" >
 
     <item
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test1_detail_activity.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test1_detail_activity.xml
new file mode 100644
index 0000000..fe1fe20
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test1_detail_activity.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/menu_settings"
+        android:title="@string/menu_settings"
+        android:orderInCategory="100"
+        android:showAsAction="never" />
+</menu>
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test2_detail_activity.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test2_detail_activity.xml
new file mode 100644
index 0000000..405d4c8
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test2_detail_activity.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/menu_text1"
+        android:title="Submit" />
+    <item android:id="@+id/menu_text2"
+        android:icon="@drawable/ic_launcher"
+        android:title="Done" />
+    <item android:id="@+id/menu_text3"
+        android:title="OK" />
+    <item android:id="@+id/menu_text4"
+        android:title="Finish" />
+    <item android:id="@+id/menu_text5"
+        android:title="Complete" />
+    <item android:id="@+id/menu_text6"
+        android:title="Exit" />
+</menu>
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test3_detail_activity.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test3_detail_activity.xml
new file mode 100644
index 0000000..fe1fe20
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test3_detail_activity.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/menu_settings"
+        android:title="@string/menu_settings"
+        android:orderInCategory="100"
+        android:showAsAction="never" />
+</menu>
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test4_detail_activity.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test4_detail_activity.xml
new file mode 100644
index 0000000..fe1fe20
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test4_detail_activity.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/menu_settings"
+        android:title="@string/menu_settings"
+        android:orderInCategory="100"
+        android:showAsAction="never" />
+</menu>
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test5_detail_activity.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test5_detail_activity.xml
new file mode 100644
index 0000000..fe1fe20
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test5_detail_activity.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/menu_settings"
+        android:title="@string/menu_settings"
+        android:orderInCategory="100"
+        android:showAsAction="never" />
+</menu>
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test6_detail_activity.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test6_detail_activity.xml
new file mode 100644
index 0000000..fe1fe20
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test6_detail_activity.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/menu_settings"
+        android:title="@string/menu_settings"
+        android:orderInCategory="100"
+        android:showAsAction="never" />
+</menu>
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test_results_detail_activity.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test_results_detail_activity.xml
new file mode 100644
index 0000000..febffa2
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/menu/test_results_detail_activity.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/menu_settings"
+        android:title="@string/menu_settings"
+        android:orderInCategory="100"
+        android:showAsAction="never" />
+</menu>
+
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-large/dimens.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-large/dimens.xml
new file mode 100644
index 0000000..788578a
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-large/dimens.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+<resources>
+
+    <dimen name="padding_small">8dp</dimen>
+    <dimen name="padding_medium">16dp</dimen>
+    <dimen name="padding_large">16dp</dimen>
+
+</resources>
\ No newline at end of file
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-large/refs.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-large/refs.xml
new file mode 100644
index 0000000..ac82847
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-large/refs.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+<resources>
+    <item type="layout" name="list_activity">@layout/twopane_activity</item>
+</resources>
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-sw600dp/refs.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-sw600dp/refs.xml
new file mode 100644
index 0000000..ac82847
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-sw600dp/refs.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+<resources>
+    <item type="layout" name="list_activity">@layout/twopane_activity</item>
+</resources>
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-v11/styles.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-v11/styles.xml
new file mode 100644
index 0000000..504d3e3
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-v11/styles.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+<resources>
+
+    <style name="AppTheme" parent="android:Theme.Holo.Light" />
+
+</resources>
\ No newline at end of file
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-v14/styles.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-v14/styles.xml
new file mode 100644
index 0000000..1232912
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values-v14/styles.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+<resources>
+
+    <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar" />
+
+</resources>
\ No newline at end of file
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values/dimens.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values/dimens.xml
new file mode 100644
index 0000000..d607bb7
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values/dimens.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
+<resources>
+
+    <dimen name="padding_small">8dp</dimen>
+    <dimen name="padding_medium">8dp</dimen>
+    <dimen name="padding_large">16dp</dimen>
+
+</resources>
\ No newline at end of file
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values/strings.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values/strings.xml
index 5846d0c..73ab901 100644
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values/strings.xml
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values/strings.xml
@@ -1,8 +1,59 @@
 <?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
 <resources>
 
-    <string name="app_name">CtsUiAutomatorApp</string>
-    <string name="hello_world">Hello world!</string>
+    <string name="app_name">UiAutomator Test App</string>
+    <string name="test1_description">This helps verify entering text into a pre-populated field. The pop-up dialog will echo the text entered after clicking submit. The initial value in the field must first be deleted.</string>
     <string name="menu_settings">Settings</string>
+    <string name="title_activity_item1_detail">Item1DetailActivity</string>
+    <string name="buttonSubmit">Submit</string>
+    <string name="item1_dialog_title">Text submitted</string>
+    <string name="OK">OK</string>
+    <string name="title_test_list">UiAutomator Tests</string>
+    <string name="title_test_detail">Details</string>
+    <string name="hello_world">Hello world!</string>
+    <string name="title_activity_test2_detail">Test2DetailActivity</string>
+    <string name="test2_description">This helps test selection of button using Instance, Text and Content Description. Once clicked, a dialog pops up to verify the properties of button clicked.</string>
+    <string name="test2_description_2">This tests a Button text changing dynamically after a click. The test should attempt to find the button after it has changed using its new text.</string>
+    <string name="test3_description">The tests should read the clock, then write the clock back into the EditText then press submit. A dialog will display the time it took from reading the clock until submit is press. This can be used to get an idea of performance differences.</string>
+    <string name="button1">Button 1</string>
+    <string name="button2">Button 2</string>
+    <string name="button3">Button 3</string>
+    <string name="buttonBefore">Before</string>
+    <string name="buttonAfter">After</string>
+    <string name="dialog_title_result">Action results</string>
+    <string name="now_displaying_results_for">Verifying scroll into view and list item selection. Now displaying results for:</string>
+    <string name="title_activity_test3_detail">Performance test</string>
+    <string name="test3ClockDescription">Performance clock</string>
+    <string name="test3InitialClock">0000000000</string>
+    <string name="test3_dialog_title">Time difference in ms</string>
+    <string name="test5_CheckBox">CheckBox</string>
+    <string name="test5_ToggleButton">ToggleButton</string>
+    <string name="test5_Button">Button</string>
+    <string name="test5_Button_Description">Description for Button</string>
+    <string name="test5_Button_Disabled">Button D</string>
+    <string name="title_section4">Section 4</string>
+    <string name="title_section3">Section 3</string>
+    <string name="title_section2">Section 2</string>
+    <string name="title_section1">Section 1</string>
+    <string name="title_activity_test4_detail">Test4DetailActivity</string>
+    <string name="title_activity_test5_detail">Test5DetailActivity</string>
+    <string name="title_activity_test6_detail">Test6DetailActivity</string>
+    <string name="test_5_Widgets_collection">Widgets Collection</string>
 
-</resources>
\ No newline at end of file
+</resources>
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values/styles.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values/styles.xml
index 4a10ca4..119c259 100644
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values/styles.xml
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values/styles.xml
@@ -1,20 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2011 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.
+ -->
 <resources>
 
-    <!--
-        Base application theme, dependent on API level. This theme is replaced
-        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
-    -->
-    <style name="AppBaseTheme" parent="android:Theme.Light">
-        <!--
-            Theme customizations available in newer API levels can go in
-            res/values-vXX/styles.xml, while customizations related to
-            backward-compatibility can go here.
-        -->
-    </style>
-
-    <!-- Application theme. -->
-    <style name="AppTheme" parent="AppBaseTheme">
-        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
-    </style>
+    <style name="AppTheme" parent="android:Theme.Light" />
 
 </resources>
\ No newline at end of file
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/MainActivity.java b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/MainActivity.java
index ee455b8..8d4f144 100644
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/MainActivity.java
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/MainActivity.java
@@ -1,22 +1,60 @@
+/*
+ * 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 com.android.cts.uiautomator;
 
+import android.content.Intent;
 import android.os.Bundle;
-import android.app.Activity;
-import android.view.Menu;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.view.WindowManager;
 
-public class MainActivity extends Activity {
+public class MainActivity extends FragmentActivity implements TestListFragment.Callbacks {
+
+    private boolean mTwoPane;
+    public static final String LOG_TAG = "UiAutomatorApp";
 
     @Override
-    protected void onCreate(Bundle savedInstanceState) {
+    public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        setContentView(R.layout.activity_main);
+
+        // If the device is locked, this attempts to dismiss the KeyGuard
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
+                WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
+                      WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+
+        setContentView(R.layout.list_activity);
+
+        if (findViewById(R.id.test_detail_container) != null) {
+            mTwoPane = true;
+            ((TestListFragment) getSupportFragmentManager().findFragmentById(R.id.item_list))
+                    .setActivateOnItemClick(true);
+        }
     }
 
     @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        // Inflate the menu; this adds items to the action bar if it is present.
-        getMenuInflater().inflate(R.menu.activity_main, menu);
-        return true;
+    public void onItemSelected(String id) {
+        if (mTwoPane) {
+            Fragment fragment = TestItems.getFragment(id);
+            getSupportFragmentManager().beginTransaction()
+                    .replace(R.id.test_detail_container, fragment).commit();
+        } else {
+            Intent detailIntent = new Intent(this, SinglePaneDetailActivity.class);
+            detailIntent.putExtra("item_id", id);
+            startActivity(detailIntent);
+        }
     }
-
 }
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/SinglePaneDetailActivity.java b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/SinglePaneDetailActivity.java
new file mode 100644
index 0000000..1c0ff8c
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/SinglePaneDetailActivity.java
@@ -0,0 +1,56 @@
+/*
+ * 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 com.android.cts.uiautomator;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.NavUtils;
+import android.view.Menu;
+import android.view.MenuItem;
+
+public class SinglePaneDetailActivity extends FragmentActivity {
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.singlepane_activity);
+        getActionBar().setDisplayHomeAsUpEnabled(true);
+
+        if (savedInstanceState == null) {
+            Fragment fragment = TestItems.getFragment(getIntent().getStringExtra("item_id"));
+            getSupportFragmentManager().beginTransaction()
+                    .add(R.id.test_results_detail_container, fragment).commit();
+        }
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        getMenuInflater().inflate(R.menu.test_results_detail_activity, menu);
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case android.R.id.home:
+                NavUtils.navigateUpFromSameTask(this);
+                return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+}
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test1DetailFragment.java b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test1DetailFragment.java
new file mode 100644
index 0000000..e8eddba
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test1DetailFragment.java
@@ -0,0 +1,80 @@
+/*
+ * 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 com.android.cts.uiautomator;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.Button;
+import android.widget.EditText;
+
+public class Test1DetailFragment extends Fragment {
+
+    public static final String ARG_ITEM_ID = "item_id";
+    private Button mSubmitButton;
+    private EditText mEditText;
+    TestItems.TestItem mItem;
+
+    public Test1DetailFragment() {
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (getArguments().containsKey(ARG_ITEM_ID)) {
+            mItem = TestItems.getTest(getArguments().getString(ARG_ITEM_ID));
+        }
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
+        View rootView = inflater.inflate(R.layout.test1_detail_fragment, container, false);
+        if (mItem != null) {
+            ((EditText) rootView.findViewById(R.id.test1TextField)).setText(mItem.mName);
+
+            mSubmitButton = (Button) rootView.findViewById(R.id.test1SubmitButton);
+            mEditText = (EditText) rootView.findViewById(R.id.test1TextField);
+            mEditText.setText("");
+            mSubmitButton.setOnClickListener(new Button.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    final String savedInput = mEditText.getText().toString();
+                    // clear so we won't be confused by the input text in
+                    // validation
+                    mEditText.setText("");
+                    // close soft keyboard
+                    InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(
+                            Context.INPUT_METHOD_SERVICE);
+                    imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
+                    // display the submitted text
+                    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+                    builder.setTitle(R.string.item1_dialog_title);
+                    builder.setPositiveButton(R.string.OK, null);
+                    builder.setMessage(savedInput);
+                    AlertDialog diag = builder.create();
+                    diag.show();
+                }
+            });
+        }
+        return rootView;
+    }
+}
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test2DetailFragment.java b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test2DetailFragment.java
new file mode 100644
index 0000000..cec98b5
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test2DetailFragment.java
@@ -0,0 +1,136 @@
+/*
+ * 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 com.android.cts.uiautomator;
+
+import android.app.AlertDialog;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+public class Test2DetailFragment extends Fragment {
+    public static final String ARG_ITEM_ID = "item_id";
+    private Button mButton1, mButton2, mButton3, mDynaButton;
+    private boolean mDynaButtonAfter = false;
+
+    public Test2DetailFragment() {
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setHasOptionsMenu(true);
+    }
+
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        inflater.inflate(R.menu.test2_detail_activity, menu);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+        builder.setTitle(R.string.dialog_title_result);
+        builder.setMessage(item.getTitle());
+        builder.setPositiveButton(R.string.OK, null);
+        AlertDialog diag = builder.create();
+        diag.show();
+        return super.onOptionsItemSelected(item);
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
+        View rootView = inflater.inflate(R.layout.test2_detail_fragment, container, false);
+
+        mButton1 = (Button) rootView.findViewById(R.id.test2button1);
+        mButton2 = (Button) rootView.findViewById(R.id.test2button2);
+        mButton3 = (Button) rootView.findViewById(R.id.test2button3);
+        mDynaButton = (Button) rootView.findViewById(R.id.test2dynaButton);
+
+        mButton1.setOnClickListener(new Button.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+                builder.setTitle(R.string.dialog_title_result);
+                builder.setPositiveButton(R.string.OK, null);
+                builder.setMessage(R.string.button1);
+                AlertDialog diag = builder.create();
+                diag.show();
+            }
+        });
+
+        mButton2.setOnClickListener(new Button.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+                builder.setTitle(R.string.dialog_title_result);
+                builder.setPositiveButton(R.string.OK, null);
+                builder.setMessage(R.string.button2);
+                AlertDialog diag = builder.create();
+                diag.show();
+            }
+        });
+
+        mButton3.setOnClickListener(new Button.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+                builder.setTitle(R.string.dialog_title_result);
+                builder.setPositiveButton(R.string.OK, null);
+                builder.setMessage(R.string.button3);
+                AlertDialog diag = builder.create();
+                diag.show();
+            }
+        });
+
+        mDynaButton.setOnClickListener(new Button.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (getActivity().getString(R.string.buttonBefore).equals(mDynaButton.getText())) {
+                    mDynaButton.setText(R.string.buttonAfter);
+                    mDynaButton
+                            .setContentDescription(getActivity().getString(R.string.buttonAfter));
+                    mDynaButtonAfter = true;
+                } else {
+                    mDynaButton.setText(R.string.buttonBefore);
+                    mDynaButton.setContentDescription(getActivity()
+                            .getString(R.string.buttonBefore));
+                    mDynaButtonAfter = false;
+                }
+            }
+        });
+
+        if (savedState != null && savedState.getBoolean("DynaButtonAfter")) {
+            mDynaButton.setText(R.string.buttonAfter);
+            mDynaButton.setContentDescription(getActivity().getString(R.string.buttonAfter));
+            mDynaButtonAfter = true;
+        }
+        return rootView;
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle savedInstanceState) {
+        super.onSaveInstanceState(savedInstanceState);
+        // Save UI state changes to the savedInstanceState.
+        savedInstanceState.putBoolean("DynaButtonAfter", mDynaButtonAfter);
+    }
+}
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test3DetailFragment.java b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test3DetailFragment.java
new file mode 100644
index 0000000..e0be0cf
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test3DetailFragment.java
@@ -0,0 +1,134 @@
+/*
+ * 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 com.android.cts.uiautomator;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+
+public class Test3DetailFragment extends Fragment {
+
+    public static final String ARG_ITEM_ID = "item_id";
+    private TextView mTextClock;
+    private Button mSubmitButton;
+    private EditText mEditText;
+    private long mCurrentTime;
+    private final Object sync = new Object();
+    private boolean mRunCounter = true;
+
+    public Test3DetailFragment() {
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setHasOptionsMenu(true);
+    }
+
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        inflater.inflate(R.menu.test2_detail_activity, menu);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+        builder.setTitle(R.string.dialog_title_result);
+        builder.setMessage(item.getTitle());
+        builder.setPositiveButton(R.string.OK, null);
+        AlertDialog diag = builder.create();
+        diag.show();
+        return super.onOptionsItemSelected(item);
+    }
+
+    private final Handler mHandler = new Handler();
+
+    final Runnable mClockRunnable = new Runnable() {
+        @Override
+        public void run() {
+            // call the activity method that updates the UI
+            updateClockOnUi();
+        }
+    };
+
+    private void updateClockOnUi() {
+        synchronized (sync) {
+            mTextClock.setText("" + mCurrentTime);
+        }
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
+        View rootView = inflater.inflate(R.layout.test3_detail_fragment, container, false);
+        mTextClock = (TextView) rootView.findViewById(R.id.test3ClockTextView);
+        mSubmitButton = (Button) rootView.findViewById(R.id.test3SubmitButton);
+        mEditText = (EditText) rootView.findViewById(R.id.test3TextField);
+        mSubmitButton.setOnClickListener(new Button.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                // close soft keyboard
+                InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(
+                        Context.INPUT_METHOD_SERVICE);
+                imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
+
+                // display the submitted text
+                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+                builder.setTitle(R.string.test3_dialog_title);
+                builder.setPositiveButton(R.string.OK, null);
+                CharSequence inputText = mEditText.getText();
+                if (inputText != null && !inputText.toString().isEmpty()) {
+                    long inputTime = Long.parseLong(inputText.toString());
+                    builder.setMessage("" + (mCurrentTime - inputTime));
+                } else {
+                    builder.setMessage("<NO DATA>");
+                }
+                AlertDialog diag = builder.create();
+                diag.show();
+                mEditText.setText("");
+                mRunCounter = false;
+            }
+        });
+
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                while (mRunCounter) {
+                    synchronized (sync) {
+                        mCurrentTime = SystemClock.elapsedRealtime();
+                    }
+                    mHandler.post(mClockRunnable);
+                    SystemClock.sleep(100);
+                }
+            }
+        }).start();
+
+        return rootView;
+    }
+}
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test4DetailFragment.java b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test4DetailFragment.java
new file mode 100644
index 0000000..0c914dc
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test4DetailFragment.java
@@ -0,0 +1,178 @@
+/*
+ * 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 com.android.cts.uiautomator;
+
+import android.app.ActionBar;
+import android.app.FragmentTransaction;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentPagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+public class Test4DetailFragment extends Fragment implements ActionBar.TabListener {
+    public static final String ARG_ITEM_ID = "item_id";
+
+    /**
+     * The {@link android.support.v4.view.PagerAdapter} that will provide
+     * fragments for each of the sections. We use a
+     * {@link android.support.v4.app.FragmentPagerAdapter} derivative, which
+     * will keep every loaded fragment in memory. If this becomes too memory
+     * intensive, it may be best to switch to a
+     * {@link android.support.v4.app.FragmentStatePagerAdapter}.
+     */
+    SectionsPagerAdapter mSectionsPagerAdapter;
+
+    /**
+     * The {@link ViewPager} that will host the section contents.
+     */
+    ViewPager mViewPager;
+
+    public Test4DetailFragment() {
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public void onDestroyView() {
+        getActivity().getActionBar().removeAllTabs();
+        super.onDestroyView();
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
+
+        View rootView = inflater.inflate(R.layout.test4_detail_fragment, container, false);
+
+        // Set up the action bar.
+        final ActionBar actionBar = getActivity().getActionBar();
+        if (actionBar.getTabCount() > 0) {
+            return rootView;
+        }
+        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
+
+        // Create the adapter that will return a fragment for each of the three
+        // primary sections of the app.
+        mSectionsPagerAdapter = new SectionsPagerAdapter(getActivity().getSupportFragmentManager());
+
+        // Set up the ViewPager with the sections adapter.
+        mViewPager = (ViewPager) rootView.findViewById(R.id.test_4_detail_container);
+        mViewPager.setAdapter(mSectionsPagerAdapter);
+
+        // When swiping between different sections, select the corresponding
+        // tab. We can also use ActionBar.Tab#select() to do this if we have a
+        // reference to the Tab.
+        mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
+            @Override
+            public void onPageSelected(int position) {
+                actionBar.setSelectedNavigationItem(position);
+            }
+        });
+
+        // For each of the sections in the app, add a tab to the action bar.
+        for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
+            // Create a tab with text corresponding to the page title defined by
+            // the adapter. Also specify this Activity object, which implements
+            // the TabListener interface, as the listener for when this tab is
+            // selected.
+            actionBar.addTab(actionBar.newTab().setText(mSectionsPagerAdapter.getPageTitle(i))
+                    .setTabListener(this));
+        }
+        return rootView;
+    }
+
+    @Override
+    public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
+    }
+
+    @Override
+    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
+    }
+
+    @Override
+    public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
+    }
+
+    /**
+     * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
+     * one of the primary sections of the app.
+     */
+    public class SectionsPagerAdapter extends FragmentPagerAdapter {
+
+        public SectionsPagerAdapter(FragmentManager fm) {
+            super(fm);
+        }
+
+        @Override
+        public Fragment getItem(int i) {
+            Fragment fragment = new DummySectionFragment();
+            Bundle args = new Bundle();
+            args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, i + 1);
+            fragment.setArguments(args);
+            return fragment;
+        }
+
+        @Override
+        public int getCount() {
+            return 4;
+        }
+
+        @Override
+        public CharSequence getPageTitle(int position) {
+            switch (position) {
+                case 0:
+                    return getString(R.string.title_section1).toUpperCase();
+                case 1:
+                    return getString(R.string.title_section2).toUpperCase();
+                case 2:
+                    return getString(R.string.title_section3).toUpperCase();
+                case 3:
+                    return getString(R.string.title_section4).toUpperCase();
+            }
+            return null;
+        }
+    }
+
+    /**
+     * A dummy fragment representing a section of the app, but that simply
+     * displays dummy text.
+     */
+    public static class DummySectionFragment extends Fragment {
+        public DummySectionFragment() {
+        }
+
+        public static final String ARG_SECTION_NUMBER = "section_number";
+
+        @Override
+        public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                Bundle savedInstanceState) {
+            TextView textView = new TextView(getActivity());
+            textView.setGravity(Gravity.CENTER);
+            Bundle args = getArguments();
+            textView.setText("[ " + Integer.toString(args.getInt(ARG_SECTION_NUMBER)) + " ]");
+            return textView;
+        }
+    }
+}
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test5DetailFragment.java b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test5DetailFragment.java
new file mode 100644
index 0000000..0f88d3c
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test5DetailFragment.java
@@ -0,0 +1,71 @@
+/*
+ * 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 com.android.cts.uiautomator;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.ImageButton;
+import android.widget.SeekBar;
+import android.widget.Spinner;
+
+public class Test5DetailFragment extends Fragment {
+
+    public static final String ARG_ITEM_ID = "item_id";
+
+    public Test5DetailFragment() {
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
+        View rootView = inflater.inflate(R.layout.test5_detail_fragment, container, false);
+
+        // Set the content description for the following
+        Spinner spinner = (Spinner) rootView.findViewById(R.id.test_5_spinner);
+        spinner.setContentDescription("Spinner");
+        ImageButton imageButton = (ImageButton) rootView.findViewById(R.id.test_5_imageButton);
+        imageButton.setContentDescription("Image button");
+
+        // Each time this view is displayed, reset the following states
+        SeekBar seekBar = (SeekBar) rootView.findViewById(R.id.test_5_seekBar);
+        seekBar.setProgress(50);
+        seekBar.setContentDescription("Progress is 50 %");
+        CheckBox checkbox = (CheckBox) rootView.findViewById(R.id.test_5_checkBox);
+        checkbox.setChecked(false);
+
+        // Register click event handlers for the following
+        Button button = (Button) rootView.findViewById(R.id.test_5_button1);
+        button.setOnClickListener(new Button.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                // we want an artificial crash
+                throw new RuntimeException("Artificial crash to test UiWatcher");
+            }
+        });
+
+        return rootView;
+    }
+}
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test6DetailFragment.java b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test6DetailFragment.java
new file mode 100644
index 0000000..90bcfcf
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test6DetailFragment.java
@@ -0,0 +1,50 @@
+/*
+ * 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 com.android.cts.uiautomator;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.webkit.WebView;
+
+public class Test6DetailFragment extends Fragment {
+    public static final String ARG_ITEM_ID = "item_id";
+    private final static String PAGE = "<html><body>"
+            + "This is test <b>6</b> for WebView text traversal test."
+            + "<p/><a href=\"http://google.com\">This is a link to google</a><br/>"
+            + "<h5>This is h5 text</h5>"
+            + "<a href=\"http://yahoo.com\">This is a link to yahoo</a>"
+            + "<p/><h4>This is h4 text</h4>" + "</body></html>";
+
+    public Test6DetailFragment() {
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
+        View rootView = inflater.inflate(R.layout.test6_detail_fragment, container, false);
+        WebView wv = (WebView) rootView.findViewById(R.id.test6WebView);
+        wv.loadData(PAGE, "text/html", null);
+        return rootView;
+    }
+}
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/TestGenericDetailFragment.java b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/TestGenericDetailFragment.java
new file mode 100644
index 0000000..ab36d04
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/TestGenericDetailFragment.java
@@ -0,0 +1,49 @@
+/*
+ * 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 com.android.cts.uiautomator;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+public class TestGenericDetailFragment extends Fragment {
+    public static final String ARG_ITEM_ID = "item_id";
+    TestItems.TestItem mItem;
+
+    public TestGenericDetailFragment() {
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (getArguments().containsKey(ARG_ITEM_ID)) {
+            mItem = TestItems.getTest(getArguments().getString(ARG_ITEM_ID));
+        }
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
+        View rootView = inflater.inflate(R.layout.test_results_detail_fragment, container, false);
+        if (mItem != null) {
+            ((TextView) rootView.findViewById(R.id.testResultsTextView)).setText(mItem.mName);
+        }
+        return rootView;
+    }
+}
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/TestItems.java b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/TestItems.java
new file mode 100644
index 0000000..358516e
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/TestItems.java
@@ -0,0 +1,117 @@
+/*
+ * 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 com.android.cts.uiautomator;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class TestItems {
+    private static String LOG_TAG = TestItems.class.getSimpleName();
+    private static List<TestItem> ITEMS = new ArrayList<TestItem>();
+    private static Map<String, TestItem> ITEM_MAP = new HashMap<String, TestItem>();
+
+    public static class TestItem {
+        public String mId;
+        public String mName;
+        private final Class<Fragment> mClassFragment;
+        public String mTestDescription;
+
+        @SuppressWarnings("unchecked")
+        public TestItem(String id, String name, Class<?> clsf) {
+            mId = id;
+            mName = name;
+            mClassFragment = (Class<Fragment>) clsf;
+        }
+
+        @Override
+        public String toString() {
+            return mName;
+        }
+    }
+
+    static {
+        addTestItem(new TestItem("1", "Test 1", Test1DetailFragment.class));
+        addTestItem(new TestItem("2", "Test 2", Test2DetailFragment.class));
+        addTestItem(new TestItem("3", "Test 3", Test3DetailFragment.class));
+        addTestItem(new TestItem("4", "Test 4", Test4DetailFragment.class));
+        addTestItem(new TestItem("5", "Test 5", Test5DetailFragment.class));
+        addTestItem(new TestItem("6", "Test 6", Test6DetailFragment.class));
+        addTestItem(new TestItem("7", "Test 7", TestGenericDetailFragment.class));
+        addTestItem(new TestItem("8", "Test 8", TestGenericDetailFragment.class));
+        addTestItem(new TestItem("9", "Test 9", TestGenericDetailFragment.class));
+        addTestItem(new TestItem("10", "Test 10", TestGenericDetailFragment.class));
+        addTestItem(new TestItem("11", "Test 11", TestGenericDetailFragment.class));
+        addTestItem(new TestItem("12", "Test 12", TestGenericDetailFragment.class));
+        addTestItem(new TestItem("13", "Test 13", TestGenericDetailFragment.class));
+        addTestItem(new TestItem("14", "Test 14", TestGenericDetailFragment.class));
+        addTestItem(new TestItem("15", "Test 15", TestGenericDetailFragment.class));
+        addTestItem(new TestItem("16", "Test 16", TestGenericDetailFragment.class));
+        addTestItem(new TestItem("17", "Test 17", TestGenericDetailFragment.class));
+        addTestItem(new TestItem("18", "Test 18", TestGenericDetailFragment.class));
+        addTestItem(new TestItem("19", "Test 19", TestGenericDetailFragment.class));
+        addTestItem(new TestItem("20", "Test 20", TestGenericDetailFragment.class));
+        addTestItem(new TestItem("21", "Test 21", TestGenericDetailFragment.class));
+        addTestItem(new TestItem("22", "Test 22", TestGenericDetailFragment.class));
+        addTestItem(new TestItem("23", "Test 23", TestGenericDetailFragment.class));
+        addTestItem(new TestItem("24", "Test 24", TestGenericDetailFragment.class));
+        addTestItem(new TestItem("25", "Test 25", TestGenericDetailFragment.class));
+        addTestItem(new TestItem("26", "Test 26", TestGenericDetailFragment.class));
+        addTestItem(new TestItem("27", "Test 27", TestGenericDetailFragment.class));
+        addTestItem(new TestItem("28", "Test 28", TestGenericDetailFragment.class));
+        addTestItem(new TestItem("29", "Test 29", TestGenericDetailFragment.class));
+        addTestItem(new TestItem("30", "Test 30", TestGenericDetailFragment.class));
+    }
+
+    private static void addTestItem(TestItem item) {
+        ITEMS.add(item);
+        ITEM_MAP.put(item.mId, item);
+    }
+
+    public static List<TestItem> getTests() {
+        return ITEMS;
+    }
+
+    public static TestItem getTest(String id) {
+        return ITEM_MAP.get(id);
+    }
+
+    public static TestItem getTest(int pos) {
+        return ITEMS.get(pos);
+    }
+
+    public static Fragment getFragment(String id) {
+        try {
+            Fragment fragment = getTest(id).mClassFragment.newInstance();
+            Bundle arguments = new Bundle();
+            arguments.putString("item_id", id);
+            fragment.setArguments(arguments);
+            return fragment;
+        } catch (InstantiationException e) {
+            Log.e(LOG_TAG, "Exception", e);
+            return null;
+        } catch (IllegalAccessException e) {
+            Log.e(LOG_TAG, "Exception", e);
+            return null;
+        }
+    }
+}
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/TestListFragment.java b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/TestListFragment.java
new file mode 100644
index 0000000..46f0f73
--- /dev/null
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/TestListFragment.java
@@ -0,0 +1,105 @@
+/*
+ * 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 com.android.cts.uiautomator;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.support.v4.app.ListFragment;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+public class TestListFragment extends ListFragment {
+
+    private static final String STATE_ACTIVATED_POSITION = "activated_position";
+
+    private Callbacks mCallbacks = sDummyCallbacks;
+    private int mActivatedPosition = ListView.INVALID_POSITION;
+
+    public interface Callbacks {
+
+        public void onItemSelected(String id);
+    }
+
+    private static Callbacks sDummyCallbacks = new Callbacks() {
+        @Override
+        public void onItemSelected(String id) {
+        }
+    };
+
+    public TestListFragment() {
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setListAdapter(new ArrayAdapter<TestItems.TestItem>(getActivity(),
+                R.layout.simple_list_item_selected, R.id.label, TestItems.getTests()));
+    }
+
+    @Override
+    public void onViewCreated(View view, Bundle savedState) {
+        super.onViewCreated(view, savedState);
+        if (savedState != null && savedState.containsKey(STATE_ACTIVATED_POSITION)) {
+            setActivatedPosition(savedState.getInt(STATE_ACTIVATED_POSITION));
+        }
+    }
+
+    @Override
+    public void onAttach(Activity activity) {
+        super.onAttach(activity);
+        if (!(activity instanceof Callbacks)) {
+            throw new IllegalStateException("Activity must implement fragment's callbacks.");
+        }
+
+        mCallbacks = (Callbacks) activity;
+    }
+
+    @Override
+    public void onDetach() {
+        super.onDetach();
+        mCallbacks = sDummyCallbacks;
+    }
+
+    @Override
+    public void onListItemClick(ListView listView, View view, int position, long id) {
+        super.onListItemClick(listView, view, position, id);
+        mCallbacks.onItemSelected(TestItems.getTest(position).mId);
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        if (mActivatedPosition != ListView.INVALID_POSITION) {
+            outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);
+        }
+    }
+
+    public void setActivateOnItemClick(boolean activateOnItemClick) {
+        getListView().setChoiceMode(
+                activateOnItemClick ? ListView.CHOICE_MODE_SINGLE : ListView.CHOICE_MODE_NONE);
+    }
+
+    public void setActivatedPosition(int position) {
+        if (position == ListView.INVALID_POSITION) {
+            getListView().setItemChecked(mActivatedPosition, false);
+        } else {
+            getListView().setItemChecked(position, true);
+        }
+
+        mActivatedPosition = position;
+    }
+}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/command/CtsConsole.java b/tools/tradefed-host/src/com/android/cts/tradefed/command/CtsConsole.java
index a815a48..a8ca951 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/command/CtsConsole.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/command/CtsConsole.java
@@ -174,7 +174,7 @@
         helpBuilder.append("Dump:\n");
         helpBuilder.append("  d/dump l/logs: dump the tradefed logs for all running invocations\n");
         helpBuilder.append("Options:\n");
-        helpBuilder.append("  --reboot-per-package : reboot device after running each package.\n");
+        helpBuilder.append("  --disable-reboot : Do not reboot device after running some amount of tests.\n");
         return helpBuilder.toString();
     }
 
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsTest.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsTest.java
index a79b84e..8140dc4 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsTest.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsTest.java
@@ -137,16 +137,16 @@
         "run tests including known failures")
     private boolean mIncludeKnownFailures;
 
-    @Option(name = "reboot-per-package", description =
-            "Reboot after each package run")
-    private boolean mRebootPerPackage = false;
+    @Option(name = "disable-reboot", description =
+            "Do not reboot device after running some amount of tests. Default behavior is to reboot.")
+    private boolean mDisableReboot = false;
 
     @Option(name = "reboot-wait-time", description =
-            "Additional wait time in ms after boot complete. Meaningful only with reboot-per-package option")
+            "Additional wait time in ms after boot complete.")
     private int mRebootWaitTimeMSec = 2 * 60 * 1000;
 
     @Option(name = "reboot-interval", description =
-            "Interval between each reboot in min. Meaningful only with reboot-per-package option")
+            "Interval between each reboot in min.")
     private int mRebootIntervalMin = 30;
 
 
@@ -350,7 +350,7 @@
             // always collect the device info, even for resumed runs, since test will likely be
             // running on a different device
             collectDeviceInfo(getDevice(), mCtsBuild, listener);
-            if (mRemainingTestPkgs.size() > 1) {
+            if (mRemainingTestPkgs.size() > 1 && !mDisableReboot) {
                 Log.i(LOG_TAG, "Initial reboot for multiple packages");
                 rebootDevice();
             }
@@ -406,7 +406,7 @@
                 "CtsWebkitSecurityTestCases",
                 "CtsWidgetTestCases" );
         long intervalInMSec = mRebootIntervalMin * 60 * 1000;
-        if (mRebootPerPackage) {
+        if (!mDisableReboot) {
             long currentTime = System.currentTimeMillis();
             if (((currentTime - mPrevRebootTime) > intervalInMSec) ||
                     rebootAfterList.contains(testFinished.getPackageDef().getName()) ||