Merge "Add CTS for enterprise SIP lookup" into mnc-dev
diff --git a/tests/tests/dreams/Android.mk b/tests/tests/dreams/Android.mk
index eca3d83..87bd357 100644
--- a/tests/tests/dreams/Android.mk
+++ b/tests/tests/dreams/Android.mk
@@ -26,6 +26,8 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
+LOCAL_JAVA_LIBRARIES :=  android.test.runner
+
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 # Need access to ServiceManager - see b/13307221
diff --git a/tests/tests/dreams/src/android/service/dreams/cts/DreamServiceTest.java b/tests/tests/dreams/src/android/service/dreams/cts/DreamServiceTest.java
new file mode 100644
index 0000000..fcf6558
--- /dev/null
+++ b/tests/tests/dreams/src/android/service/dreams/cts/DreamServiceTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 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.service.dreams.cts;
+
+import android.service.dreams.DreamService;
+import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
+import android.view.ActionMode;
+
+public class DreamServiceTest extends InstrumentationTestCase {
+    @UiThreadTest
+    public void testOnWindowStartingActionMode() {
+        DreamService dreamService = new DreamService();
+
+        ActionMode actionMode = dreamService.onWindowStartingActionMode(null);
+
+        assertNull(actionMode);
+    }
+
+    @UiThreadTest
+    public void testOnWindowStartingActionModeTyped() {
+        DreamService dreamService = new DreamService();
+
+        ActionMode actionMode = dreamService.onWindowStartingActionMode(
+                null, ActionMode.TYPE_FLOATING);
+
+        assertNull(actionMode);
+    }
+}
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_random_path_1_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_random_path_1_golden.png
index 91776a9..67f5746 100644
--- a/tests/tests/graphics/res/drawable-nodpi/vector_icon_random_path_1_golden.png
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_random_path_1_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_random_path_2_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_random_path_2_golden.png
index 9af40a3..c60dfba 100644
--- a/tests/tests/graphics/res/drawable-nodpi/vector_icon_random_path_2_golden.png
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_random_path_2_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_1_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_1_golden.png
index b3acfe7..e7cc4d1 100644
--- a/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_1_golden.png
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_1_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_2_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_2_golden.png
index bbc84b9..c7c049b 100644
--- a/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_2_golden.png
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_2_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_cq_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_cq_golden.png
index 8d73cfd..5880467 100644
--- a/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_cq_golden.png
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_cq_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_st_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_st_golden.png
index 6094a9a..93fb1d0 100644
--- a/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_st_golden.png
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_st_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_scale_1_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_scale_1_golden.png
index f8b660a..899a235 100644
--- a/tests/tests/graphics/res/drawable-nodpi/vector_icon_scale_1_golden.png
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_scale_1_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_scale_2_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_scale_2_golden.png
index e86e1b0..ba6d8c7 100644
--- a/tests/tests/graphics/res/drawable-nodpi/vector_icon_scale_2_golden.png
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_scale_2_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_transformation_1_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_transformation_1_golden.png
index baf418d..1703878 100644
--- a/tests/tests/graphics/res/drawable-nodpi/vector_icon_transformation_1_golden.png
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_transformation_1_golden.png
Binary files differ
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java
index d266efd..fdb8dae 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java
@@ -101,7 +101,8 @@
     // exactly with the golden image.
     // We can increase the threshold if the Skia is drawing with some variance
     // on different devices. So far, the tests show they are matching correctly.
-    private static final float PIXEL_ERROR_THRESHOLD = 0.00001f;
+    private static final float PIXEL_ERROR_THRESHOLD = 0.02f;
+    private static final float PIXEL_ERROR_COUNT_THRESHOLD = 0.005f;
 
     private static final boolean DBG_DUMP_PNG = false;
 
@@ -220,7 +221,7 @@
                 totalDiffPixelCount++;
             }
         }
-        if ((totalDiffPixelCount / totalPixelCount) >= PIXEL_ERROR_THRESHOLD) {
+        if ((totalDiffPixelCount / totalPixelCount) >= PIXEL_ERROR_COUNT_THRESHOLD) {
             fail((filename +": totalDiffPixelCount is " + totalDiffPixelCount));
         }
 
diff --git a/tests/tests/media/AndroidManifest.xml b/tests/tests/media/AndroidManifest.xml
index e4b6f6b..cdc0e60 100644
--- a/tests/tests/media/AndroidManifest.xml
+++ b/tests/tests/media/AndroidManifest.xml
@@ -80,6 +80,11 @@
                 <action android:name="android.intent.action.MAIN"/>
             </intent-filter>
         </service>
+        <service android:name="android.media.cts.StubMediaBrowserService">
+            <intent-filter>
+                <action android:name="android.media.browse.MediaBrowserService" />
+            </intent-filter>
+        </service>
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/media/src/android/media/cts/MediaBrowserTest.java b/tests/tests/media/src/android/media/cts/MediaBrowserTest.java
new file mode 100644
index 0000000..b53aa92
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaBrowserTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2015 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 android.content.ComponentName;
+import android.cts.util.PollingCheck;
+import android.media.browse.MediaBrowser;
+import android.test.InstrumentationTestCase;
+
+/**
+ * Test {@link android.media.browse.MediaBrowser}.
+ */
+public class MediaBrowserTest extends InstrumentationTestCase {
+    // The maximum time to wait for an operation.
+    private static final long TIME_OUT_MS = 1000L;
+    private static final ComponentName TEST_BROWSER_SERVICE = new ComponentName(
+            "com.android.cts.media", "android.media.cts.StubMediaBrowserService");
+    private final StubConnectionCallback mConnectionCallback = new StubConnectionCallback();
+
+    private MediaBrowser mMediaBrowser;
+
+    public void testMediaBrowser() {
+        mConnectionCallback.resetCounts();
+        createMediaBrowser(TEST_BROWSER_SERVICE);
+        assertEquals(false, mMediaBrowser.isConnected());
+
+        connectMediaBrowserService();
+        assertEquals(true, mMediaBrowser.isConnected());
+
+        assertEquals(TEST_BROWSER_SERVICE, mMediaBrowser.getServiceComponent());
+        assertEquals(StubMediaBrowserService.MEDIA_ID_ROOT, mMediaBrowser.getRoot());
+        assertEquals(StubMediaBrowserService.EXTRAS_VALUE,
+                mMediaBrowser.getExtras().getString(StubMediaBrowserService.EXTRAS_KEY));
+        assertEquals(StubMediaBrowserService.sSession.getSessionToken(),
+                mMediaBrowser.getSessionToken());
+
+        mMediaBrowser.disconnect();
+        assertEquals(false, mMediaBrowser.isConnected());
+    }
+
+    public void testConnectTwice() {
+        mConnectionCallback.resetCounts();
+        createMediaBrowser(TEST_BROWSER_SERVICE);
+        connectMediaBrowserService();
+        try {
+            mMediaBrowser.connect();
+            fail();
+        } catch (IllegalStateException e) {
+            // expected
+        }
+    }
+
+    public void testGetServiceComponentBeforeConnection() {
+        mConnectionCallback.resetCounts();
+        createMediaBrowser(TEST_BROWSER_SERVICE);
+        try {
+            ComponentName serviceComponent = mMediaBrowser.getServiceComponent();
+            fail();
+        } catch (IllegalStateException e) {
+            // expected
+        }
+    }
+
+    private void createMediaBrowser(final ComponentName component) {
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mMediaBrowser = new MediaBrowser(getInstrumentation().getTargetContext(),
+                        component, mConnectionCallback, null);
+            }
+        });
+    }
+
+    private void connectMediaBrowserService() {
+        mMediaBrowser.connect();
+        new PollingCheck(TIME_OUT_MS) {
+            @Override
+            protected boolean check() {
+                return mConnectionCallback.mConnectedCount > 0;
+            }
+        }.run();
+    }
+
+    private static class StubConnectionCallback extends MediaBrowser.ConnectionCallback {
+        volatile int mConnectedCount;
+        volatile int mConnectionFailedCount;
+        volatile int mConnectionSuspendedCount;
+
+        public void resetCounts() {
+            mConnectedCount = 0;
+            mConnectionFailedCount = 0;
+            mConnectionSuspendedCount = 0;
+        }
+
+        @Override
+        public void onConnected() {
+            mConnectedCount++;
+        }
+
+        @Override
+        public void onConnectionFailed() {
+            mConnectionFailedCount++;
+        }
+
+        @Override
+        public void onConnectionSuspended() {
+            mConnectionSuspendedCount++;
+        }
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaItemTest.java b/tests/tests/media/src/android/media/cts/MediaItemTest.java
new file mode 100644
index 0000000..4eefaa7
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaItemTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2015 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 android.media.MediaDescription;
+import android.media.browse.MediaBrowser.MediaItem;
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+
+/**
+ * Test {@link android.media.browse.MediaBrowser.MediaItem}.
+ */
+public class MediaItemTest extends AndroidTestCase {
+    private static final String DESCRIPTION = "test_description";
+    private static final String MEDIA_ID = "test_media_id";
+    private static final String TITLE = "test_title";
+    private static final String SUBTITLE = "test_subtitle";
+
+    public void testBrowsableMediaItem() {
+        MediaDescription description = new MediaDescription.Builder()
+                .setDescription(DESCRIPTION).setMediaId(MEDIA_ID)
+                .setTitle(TITLE).setSubtitle(SUBTITLE).build();
+        MediaItem mediaItem = new MediaItem(description, MediaItem.FLAG_BROWSABLE);
+
+        assertEquals(description.toString(), mediaItem.getDescription().toString());
+        assertEquals(MEDIA_ID, mediaItem.getMediaId());
+        assertEquals(MediaItem.FLAG_BROWSABLE, mediaItem.getFlags());
+        assertTrue(mediaItem.isBrowsable());
+        assertFalse(mediaItem.isPlayable());
+
+        // Test writeToParcel
+        Parcel p = Parcel.obtain();
+        mediaItem.writeToParcel(p, 0);
+        p.setDataPosition(0);
+        assertEquals(mediaItem.getFlags(), p.readInt());
+        assertEquals(description.toString(),
+                MediaDescription.CREATOR.createFromParcel(p).toString());
+        p.recycle();
+    }
+
+    public void testPlayableMediaItem() {
+        MediaDescription description = new MediaDescription.Builder()
+                .setDescription(DESCRIPTION).setMediaId(MEDIA_ID)
+                .setTitle(TITLE).setSubtitle(SUBTITLE).build();
+        MediaItem mediaItem = new MediaItem(description, MediaItem.FLAG_PLAYABLE);
+
+        assertEquals(description.toString(), mediaItem.getDescription().toString());
+        assertEquals(MEDIA_ID, mediaItem.getMediaId());
+        assertEquals(MediaItem.FLAG_PLAYABLE, mediaItem.getFlags());
+        assertFalse(mediaItem.isBrowsable());
+        assertTrue(mediaItem.isPlayable());
+
+        // Test writeToParcel
+        Parcel p = Parcel.obtain();
+        mediaItem.writeToParcel(p, 0);
+        p.setDataPosition(0);
+        assertEquals(mediaItem.getFlags(), p.readInt());
+        assertEquals(description.toString(),
+                MediaDescription.CREATOR.createFromParcel(p).toString());
+        p.recycle();
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerFlakyNetworkTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerFlakyNetworkTest.java
index 32fbfb5..640083f 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerFlakyNetworkTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerFlakyNetworkTest.java
@@ -23,6 +23,8 @@
 import android.os.SystemClock;
 import android.webkit.cts.CtsTestServer;
 
+import com.android.cts.util.TimeoutReq;
+
 import org.apache.http.HttpServerConnection;
 
 import org.apache.http.impl.DefaultHttpServerConnection;
@@ -67,30 +69,37 @@
         super.tearDown();
     }
 
+    @TimeoutReq(minutes = 5)
     public void test_S0P0() throws Throwable {
         doPlayStreams(0, 0);
     }
 
+    @TimeoutReq(minutes = 10)
     public void test_S1P000005() throws Throwable {
         doPlayStreams(1, 0.000005f);
     }
 
+    @TimeoutReq(minutes = 10)
     public void test_S2P00001() throws Throwable {
         doPlayStreams(2, 0.00001f);
     }
 
+    @TimeoutReq(minutes = 10)
     public void test_S3P00001() throws Throwable {
         doPlayStreams(3, 0.00001f);
     }
 
+    @TimeoutReq(minutes = 10)
     public void test_S4P00001() throws Throwable {
         doPlayStreams(4, 0.00001f);
     }
 
+    @TimeoutReq(minutes = 10)
     public void test_S5P00001() throws Throwable {
         doPlayStreams(5, 0.00001f);
     }
 
+    @TimeoutReq(minutes = 10)
     public void test_S6P00002() throws Throwable {
         doPlayStreams(6, 0.00002f);
     }
diff --git a/tests/tests/media/src/android/media/cts/StubMediaBrowserService.java b/tests/tests/media/src/android/media/cts/StubMediaBrowserService.java
new file mode 100644
index 0000000..d559c72
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/StubMediaBrowserService.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 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 android.media.browse.MediaBrowser.MediaItem;
+import android.media.session.MediaSession;
+import android.os.Bundle;
+import android.service.media.MediaBrowserService;
+
+import java.util.List;
+
+/**
+ * Stub implementation of (@link android.service.media.MediaBrowserService}.
+ */
+public class StubMediaBrowserService extends MediaBrowserService {
+    static final String MEDIA_ID_ROOT = "test_media_id_root";
+    static final String EXTRAS_KEY = "test_extras_key";
+    static final String EXTRAS_VALUE = "test_extras_value";
+
+    /* package private */ static MediaSession sSession;
+    private Bundle mExtras;
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        sSession = new MediaSession(this, "MediaBrowserStubService");
+        setSessionToken(sSession.getSessionToken());
+    }
+
+    @Override
+    public BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) {
+        mExtras = new Bundle();
+        mExtras.putString(EXTRAS_KEY, EXTRAS_VALUE);
+        return new BrowserRoot(MEDIA_ID_ROOT, mExtras);
+    }
+
+    @Override
+    public void onLoadChildren(final String parentMediaId, final Result<List<MediaItem>> result) {
+    }
+}
diff --git a/tests/tests/view/src/android/view/cts/ActionModeCallback2Test.java b/tests/tests/view/src/android/view/cts/ActionModeCallback2Test.java
new file mode 100644
index 0000000..e75b7ae
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/ActionModeCallback2Test.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2015 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.view.cts;
+
+import android.graphics.Rect;
+import android.test.AndroidTestCase;
+import android.view.ActionMode;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+
+public class ActionModeCallback2Test extends AndroidTestCase {
+    private static final int VIEW_WIDTH = 123;
+    private static final int VIEW_HEIGHT = 456;
+
+    public void testCallbackOnGetContentRectDefaultWithView() {
+        View view = new View(mContext);
+        view.setLeft(0);
+        view.setRight(VIEW_WIDTH);
+        view.setTop(0);
+        view.setBottom(VIEW_HEIGHT);
+
+        Rect outRect = new Rect();
+        MockActionModeCallback2 callback = new MockActionModeCallback2();
+        callback.onGetContentRect(null, view, outRect);
+
+        assertEquals(0, outRect.top);
+        assertEquals(0, outRect.left);
+        assertEquals(VIEW_HEIGHT, outRect.bottom);
+        assertEquals(VIEW_WIDTH, outRect.right);
+    }
+
+    public void testCallbackOnGetContentRectDefaultWithoutView() {
+        Rect outRect = new Rect();
+        MockActionModeCallback2 callback = new MockActionModeCallback2();
+        callback.onGetContentRect(null, null, outRect);
+
+        assertEquals(0, outRect.top);
+        assertEquals(0, outRect.left);
+        assertEquals(0, outRect.bottom);
+        assertEquals(0, outRect.right);
+    }
+
+    private static class MockActionModeCallback2 extends ActionMode.Callback2 {
+        @Override
+        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+            return false;
+        }
+
+        @Override
+        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+            return false;
+        }
+
+        @Override
+        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+            return false;
+        }
+
+        @Override
+        public void onDestroyActionMode(ActionMode mode) {}
+    }
+
+}
diff --git a/tests/tests/view/src/android/view/cts/ActionModeTest.java b/tests/tests/view/src/android/view/cts/ActionModeTest.java
new file mode 100644
index 0000000..61df9fe
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/ActionModeTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2015 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.view.cts;
+
+import android.test.AndroidTestCase;
+import android.view.ActionMode;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.View;
+
+public class ActionModeTest extends AndroidTestCase {
+
+    public void testSetType() {
+        ActionMode actionMode = new MockActionMode();
+        assertEquals(ActionMode.TYPE_PRIMARY, actionMode.getType());
+
+        actionMode.setType(ActionMode.TYPE_FLOATING);
+        assertEquals(ActionMode.TYPE_FLOATING, actionMode.getType());
+
+        actionMode.setType(ActionMode.TYPE_PRIMARY);
+        assertEquals(ActionMode.TYPE_PRIMARY, actionMode.getType());
+    }
+
+    public void testInvalidateContentRectDoesNotInvalidateFull() {
+        MockActionMode actionMode = new MockActionMode();
+
+        actionMode.invalidateContentRect();
+
+        assertFalse(actionMode.mInvalidateWasCalled);
+    }
+
+    private static class MockActionMode extends ActionMode {
+        boolean mInvalidateWasCalled = false;
+
+        @Override
+        public void setTitle(CharSequence title) {}
+
+        @Override
+        public void setTitle(int resId) {}
+
+        @Override
+        public void setSubtitle(CharSequence subtitle) {}
+
+        @Override
+        public void setSubtitle(int resId) {}
+
+        @Override
+        public void setCustomView(View view) {}
+
+        @Override
+        public void invalidate() {
+            mInvalidateWasCalled = true;
+        }
+
+        @Override
+        public void finish() {}
+
+        @Override
+        public Menu getMenu() {
+            return null;
+        }
+
+        @Override
+        public CharSequence getTitle() {
+            return null;
+        }
+
+        @Override
+        public CharSequence getSubtitle() {
+            return null;
+        }
+
+        @Override
+        public View getCustomView() {
+            return null;
+        }
+
+        @Override
+        public MenuInflater getMenuInflater() {
+            return null;
+        }
+    }
+}
diff --git a/tools/tradefed-host/Android.mk b/tools/tradefed-host/Android.mk
index bd28575..1f73e95 100644
--- a/tools/tradefed-host/Android.mk
+++ b/tools/tradefed-host/Android.mk
@@ -27,6 +27,8 @@
 LOCAL_JAVA_LIBRARIES := tradefed-prebuilt hosttestlib
 LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceinfolib
 
+LOCAL_JAR_MANIFEST := MANIFEST.mf
+
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
 include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tools/tradefed-host/MANIFEST.mf b/tools/tradefed-host/MANIFEST.mf
new file mode 100644
index 0000000..5528c06
--- /dev/null
+++ b/tools/tradefed-host/MANIFEST.mf
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: com.android.cts.tradefed.testtype
+Implementation-Version: %BUILD_NUMBER%
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
index 2ee649d..a33fc01 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
@@ -32,6 +32,7 @@
     private String mCtsRootDirPath = System.getProperty("CTS_ROOT");
 
     public static final String CTS_BUILD_VERSION = "5.0_r1.91";
+    public static final String CTS_PACKAGE = "com.android.cts.tradefed.testtype";
 
     /**
      * {@inheritDoc}
@@ -46,6 +47,10 @@
         return ctsBuild;
     }
 
+    public static String getBuildNumber() {
+        return Package.getPackage(CTS_PACKAGE).getImplementationVersion();
+    }
+
     /**
      * {@inheritDoc}
      */
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 ca4e050..2d6d8f2 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
@@ -56,7 +56,9 @@
 
     @Override
     public void run() {
-        printLine(String.format("Android CTS %s", CtsBuildProvider.CTS_BUILD_VERSION));
+        printLine(String.format("Android CTS %s build:%s",
+                CtsBuildProvider.CTS_BUILD_VERSION,
+                CtsBuildProvider.getBuildNumber()));
         super.run();
     }
 
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/TestResults.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestResults.java
index 8c1a5bd..68cd1c0 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/TestResults.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestResults.java
@@ -143,6 +143,7 @@
 
         serializer.startTag(ns, "Cts");
         serializer.attribute(ns, "version", CtsBuildProvider.CTS_BUILD_VERSION);
+        serializer.attribute(ns, "build", CtsBuildProvider.getBuildNumber());
         // TODO: consider outputting other tradefed options here
         serializer.startTag(ns, "IntValue");
         serializer.attribute(ns, "name", "testStatusTimeoutMs");