auto import from //depot/cupcake/@135843
diff --git a/tests/FrameworkTest/Android.mk b/tests/FrameworkTest/Android.mk
new file mode 100644
index 0000000..61cdbfa
--- /dev/null
+++ b/tests/FrameworkTest/Android.mk
@@ -0,0 +1,15 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_PACKAGE_NAME := FrameworkTest
+
+include $(BUILD_PACKAGE)
+# Use the following include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/FrameworkTest/AndroidManifest.xml b/tests/FrameworkTest/AndroidManifest.xml
new file mode 100644
index 0000000..c70302b
--- /dev/null
+++ b/tests/FrameworkTest/AndroidManifest.xml
@@ -0,0 +1,952 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.frameworktest">
+
+    <uses-permission android:name="android.permission.READ_CONTACTS" />
+    <uses-permission android:name="android.permission.HARDWARE_TEST" />
+    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+
+    <application android:theme="@style/Theme">
+        <uses-library android:name="android.test.runner" />
+
+        <activity android:name=".FrameworkTestApplication" android:label="FrameworkTestApplication">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".performance.InvalidateCycle" android:label="InvalidateCycle">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".focus.DescendantFocusability" android:label="DescendantFocusability">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>            
+        </activity>
+
+        <activity android:name=".focus.FocusAfterRemoval" android:label="FocusAfterRemoval">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".focus.RequestFocus" android:label="RequestFocus">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />V
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".focus.ListOfButtons" android:label="ListOfButtons">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".focus.LinearLayoutGrid" android:label="LinearLayoutGrid">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>            
+        </activity>
+
+        <activity android:name=".focus.ListOfEditTexts" android:label="ListOfEditTexts">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>            
+        </activity>
+
+        <activity android:name=".focus.ListOfInternalSelectionViews" android:label="ListOfInternalSelectionViews">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>                        
+        </activity>
+
+        <activity android:name=".focus.ListWithFooterViewAndNewLabels" android:label="FocusListWithFooter">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>            
+        </activity>
+
+        <activity android:name=".focus.ListWithMailMessages" android:label="ListWithMailMessages">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".focus.HorizontalFocusSearch" android:label="HorizontalFocusSearch">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>            
+        </activity>
+
+        <activity android:name=".focus.VerticalFocusSearch" android:label="VerticalFocusSearch">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".focus.AdjacentVerticalRectLists" android:label="AdjacentVerticalRectLists">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".focus.GoneParentFocusedChild" android:label="GoneParentFocusedChild">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".layout.frame.FrameLayoutGravity" android:label="FrameLayoutGravity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".layout.frame.FrameLayoutMargin" android:label="FrameLayoutMargin">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".layout.linear.BaselineAlignmentCenterGravity" android:label="BaselineAlignmentCenterGravity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".layout.linear.BaselineButtons" android:label="BaselineButtons">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".layout.linear.FillInWrap" android:label="FillInWrap">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".layout.linear.BaselineAlignmentZeroWidthAndWeight" android:label="Baseline0WidthAndWeight">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".layout.linear.HorizontalOrientationVerticalAlignment" android:label="HorizontalOrientationVerticalAlignment">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".layout.linear.LLEditTextThenButton" android:label="LLEditTextThenButton">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>            
+        </activity>
+
+        <activity android:name=".layout.linear.LLOfButtons1" android:label="LLOfButtons1">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".layout.linear.LinearLayoutEditTexts" android:label="LinearLayoutEditTexts">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".layout.linear.LLOfButtons2" android:label="LLOfButtons2">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".layout.linear.LLOfTwoFocusableInTouchMode" android:label="LLOfTwoFocusableInTouchMode">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>            
+        </activity>
+
+        <activity android:name=".layout.linear.Weight" android:label="Weight">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".layout.linear.WeightSum" android:label="WeightSum">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".listview.AdjacentListsWithAdjacentISVsInside" android:label="AdjacentListsWithAdjacentISVsInside">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".listview.ListDividers" android:label="ListDividers">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".listview.ListViewHeight" android:label="ListViewHeight">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".layout.table.FixedWidth" android:label="CellFixedWidth">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".layout.table.Weight" android:label="CellWeight">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".layout.table.HorizontalGravity" android:label="CellHorizontalGravity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".layout.table.VerticalGravity" android:label="CellVerticalGravity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".layout.table.AddColumn" android:label="AddColumnInTable">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".layout.table.CellSpan" android:label="CellSpan">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".scroll.ButtonAboveTallInternalSelectionView" android:label="ButtonAboveTallInternalSelectionView">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".scroll.ButtonsWithTallTextViewInBetween" android:label="scrollButtonsWithTallTextViewInBetween">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".scroll.RequestRectangleVisible" android:label="ScrollToChildRect">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".scroll.RequestRectangleVisibleWithInternalScroll" android:label="ScrollToChildRectWithInternalScroll">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".scroll.ScrollViewButtonsAndLabels" android:label="ScrollViewButtonsAndLabels">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".scroll.ShortButtons" android:label="scrollShortButtons">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".scroll.TallTextAboveButton" android:label="scrollTallTextAboveButton">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".view.Include" android:label="IncludeTag">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".view.Merge" android:label="MergeTag">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".view.StubbedView" android:label="ViewStub">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".view.RunQueue" android:label="RunQueue">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".view.Visibility" android:label="Visibility">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".view.BigCache" android:label="BigCache">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".view.ZeroSized" android:label="ZeroSized">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".view.Disabled" android:label="Disabled">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".view.PopupWindowVisibility" android:label="PopupWindowVisibility">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+        
+        <activity android:name=".view.PreDrawListener" android:label="PreDrawListener">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".view.GlobalFocusChange" android:label="GlobalFocusChange">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".listview.ListSetSelection" android:label="ListSetSelection">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".listview.ListSimple" android:label="ListSimple">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".listview.ListFilter" android:label="ListFilter">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+        
+        <activity android:name=".listview.ListScrollListener" android:label="ListScrollListener">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".listview.ListThrasher" android:label="ListThrasher">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+        
+        <activity android:name=".listview.ListTakeFocusFromSide" android:label="ListTakeFocusFromSide">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+        
+        <activity android:name=".listview.ListBottomGravity" android:label="ListBottomGravity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+        
+        <activity android:name=".listview.ListBottomGravityMany" android:label="ListBottomGravityMany">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+
+        <activity android:name=".listview.ListButtonsDiagonalAcrossItems" android:label="ListButtonsDiagonalAcrossItems">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".listview.ListTopGravity" android:label="ListTopGravity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+        
+        <activity android:name=".listview.ListTopGravityMany" android:label="ListTopGravityMany">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+        
+        <activity android:name=".listview.ListEndingWithMultipleSeparators" android:label="ListEndingWithMultipleSeparators">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>                        
+        </activity>
+
+        <activity android:name=".listview.ListGetSelectedView" android:label="ListGetSelectedView">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".listview.ListInHorizontal" android:label="ListInHorizontal">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".listview.ListInVertical" android:label="ListInVertical">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".listview.ListInterleaveFocusables" android:label="ListInterleaveFocusables">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+             <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+         </intent-filter>
+        </activity>
+
+        <activity android:name=".listview.ListOfItemsShorterThanScreen" android:label="ListOfItemsShorterThanScreen">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>            
+        </activity>
+
+        <activity android:name=".listview.ListOfItemsTallerThanScreen" android:label="ListOfItemsTallerThanScreen">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>            
+        </activity>
+
+        <activity android:name=".listview.ListOfThinItems" android:label="ListOfThinItems">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>                        
+        </activity>
+
+        <activity android:name=".listview.ListOfShortTallShort" android:label="ListOfShortTallShort">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".listview.ListOfShortShortTallShortShort" android:label="ListOfShortShortTallShortShort">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>            
+        </activity>
+
+        <activity android:name=".listview.ListWithOffScreenNextSelectable" android:label="ListWithOffScreenNextSelectable">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>                                    
+        </activity>
+
+        <activity android:name=".listview.ListWithFirstScreenUnSelectable" android:label="ListWithFirstScreenUnSelectable">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+
+        <activity android:name=".listview.ListWithSeparators" android:label="ListWithSeparators">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>            
+        </activity>
+
+        <activity android:name=".listview.ListWithHeaders" android:label="ListWithHeaders">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".listview.ListWithEditTextHeader" android:label="ListWithEditTextHeader">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+
+        <activity android:name=".listview.ListWithNoFadingEdge" android:label="ListWithNoFadingEdge">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>            
+        </activity>
+
+        <activity android:name=".listview.ListWithScreenOfNoSelectables" android:label="ListWithScreenOfNoSelectables">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>            
+        </activity>
+
+        <activity android:name=".listview.ListItemFocusablesFarApart" android:label="ListItemFocusablesFarApart">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".listview.ListItemFocusableAboveUnfocusable" android:label="ListItemFocusableAboveUnfocusable">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".listview.ListItemFocusablesClose" android:label="ListItemFocusablesClose">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".listview.ListLastItemPartiallyVisible" android:label="ListLastItemPartiallyVisible">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>            
+        </activity>
+
+        <activity android:name=".listview.ListItemsExpandOnSelection" android:label="ListItemsExpandOnSelection">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>            
+        </activity>
+
+        <activity android:name=".listview.ListWithOnItemSelectedAction" android:label="ListWithOnItemSelectedAction">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>            
+        </activity>
+
+        <activity android:name=".listview.ListItemISVAndButton" android:label="ListItemISVAndButton">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".listview.ListOfTouchables" android:label="ListOfTouchables">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".listview.ListRecyclerProfiling" android:label="ListRecyclerProfiling">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".listview.ListHeterogeneous" android:label="ListHeterogeneous">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".listview.ListHorizontalFocusWithinItemWins" android:label="ListHorizontalFocusWithinItemWins">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>            
+        </activity>
+       
+	    <activity android:name=".listview.ListManagedCursor" android:label="ListManagedCursor">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+       
+	    <activity android:name=".listview.ListWithEmptyView" android:label="ListWithEmptyView">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+        
+        <activity android:name=".gridview.GridInHorizontal" android:label="GridInHorizontal">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+        
+        <activity android:name=".gridview.GridPadding" android:label="GridPadding">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".gridview.GridInVertical" android:label="GridInVertical">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".gridview.GridScrollListener" android:label="GridScrollListener">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+         <activity android:name=".gridview.GridThrasher" android:label="GridThrasher">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".gridview.GridSimple" android:label="GridSimple">
+           <intent-filter>
+               <action android:name="android.intent.action.MAIN" />
+               <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+           </intent-filter>
+       </activity>
+
+        <activity android:name=".gridview.GridDelete" android:label="GridDelete">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+         <activity android:name=".gridview.GridSetSelection" android:label="GridSetSelection">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".gridview.GridSetSelectionMany" android:label="GridSetSelectionMany">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".gridview.GridSetSelectionStackFromBottom" android:label="GridSetSelectionStackFromBottom">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".gridview.GridSetSelectionStackFromBottomMany" android:label="GridSetSelectionStackFromBottomMany">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".gridview.GridStackFromBottom" android:label="GridStackFromBottom">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".gridview.GridStackFromBottomMany" android:label="GridStackFromBottomMany">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".gridview.GridVerticalSpacing" android:label="GridVerticalSpacing">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+        
+        <activity android:name=".gridview.GridVerticalSpacingStackFromBottom" android:label="GridVerticalSpacingStackFromBottom">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+        
+        <activity android:name=".gridview.GridSingleColumn" android:label="GridSingleColumn">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+        
+        <activity android:name=".menus.ListContextMenu" android:label="ListContextMenu">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".view.ViewGroupChildren" android:label="ViewGroup Children">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".view.RemoteViewsActivity" android:label="RemoteViewsActicity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".drawable.BitmapDrawable" android:label="BitmapDrawable">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".drawable.DrawableBgMinSize" android:label="DrawableBgMinSize">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".drawable.MutateDrawable" android:label="MutateDrawable">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".activity.TranslucentFancyActivity" android:label="TranslucentFancyActivity">
+           <intent-filter>
+               <action android:name="android.intent.action.MAIN" />
+               <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+           </intent-filter>
+       </activity>
+
+        <activity android:name=".view.Longpress" android:label="Longpress">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".expandablelistview.ExpandableListWithHeaders" android:label="ExpandableListWithHeaders">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".listview.ListWithDisappearingItemBug" android:label="ListWithDisappearingItemBug">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".menus.MenuWith1Item" android:label="MenuWith1Item">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".menus.MenuLayoutPortrait" android:label="MenuLayoutPortrait"
+                android:screenOrientation="portrait">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".menus.MenuLayoutLandscape" android:label="MenuLayoutLandscape"
+                android:screenOrientation="landscape">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".expandablelistview.InflatedExpandableListView" android:label="ExpandableListView Inflated">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".expandablelistview.ExpandableListSimple" android:label="ExpandableListSimple">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".settings.RingtonePickerActivityLauncher" android:label="RingtonePickerActivityLauncher">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".settings.BrightnessLimit" android:label="BrightnessLimit">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+        
+        <activity android:name="android.widget.AutoCompleteTextViewSimple" 
+                  android:label="AutoCompleteTextViewSimple">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+    </application>
+
+</manifest>
diff --git a/tests/FrameworkTest/README b/tests/FrameworkTest/README
new file mode 100644
index 0000000..d6d0042
--- /dev/null
+++ b/tests/FrameworkTest/README
@@ -0,0 +1,8 @@
+FrameworkTestApplication should hold snippets of functionality that are
+helpful for testing the UI framework code, but not appropriate for
+sample code.  For instance, a layout contrived to exercise an edge case
+of scrolling behavior.
+
+InstrumentationTestCases should be added under tests and added to the
+list of tests in FrameworkInstrumentationTestRunner.
+
diff --git a/tests/FrameworkTest/res/drawable/big_drawable_background.9.png b/tests/FrameworkTest/res/drawable/big_drawable_background.9.png
new file mode 100644
index 0000000..aded635
--- /dev/null
+++ b/tests/FrameworkTest/res/drawable/big_drawable_background.9.png
Binary files differ
diff --git a/tests/FrameworkTest/res/drawable/bitmap_drawable.xml b/tests/FrameworkTest/res/drawable/bitmap_drawable.xml
new file mode 100644
index 0000000..35673ec
--- /dev/null
+++ b/tests/FrameworkTest/res/drawable/bitmap_drawable.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/sym_now_playing_pause_1"
+    android:gravity="top|right" />
diff --git a/tests/FrameworkTest/res/drawable/black_square.png b/tests/FrameworkTest/res/drawable/black_square.png
new file mode 100644
index 0000000..1bfe0a2
--- /dev/null
+++ b/tests/FrameworkTest/res/drawable/black_square.png
Binary files differ
diff --git a/tests/FrameworkTest/res/drawable/black_square_stretchable.9.png b/tests/FrameworkTest/res/drawable/black_square_stretchable.9.png
new file mode 100644
index 0000000..1fcbeb1
--- /dev/null
+++ b/tests/FrameworkTest/res/drawable/black_square_stretchable.9.png
Binary files differ
diff --git a/tests/FrameworkTest/res/drawable/box.xml b/tests/FrameworkTest/res/drawable/box.xml
new file mode 100644
index 0000000..6849bd34
--- /dev/null
+++ b/tests/FrameworkTest/res/drawable/box.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/drawable/box.xml
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="#00000000"/>
+    <stroke android:width="1dp" color="#ff000000"/>
+    <padding android:left="1dp" android:top="1dp"
+        android:right="1dp" android:bottom="1dp" />
+</shape>
diff --git a/tests/FrameworkTest/res/drawable/drawable_background.9.png b/tests/FrameworkTest/res/drawable/drawable_background.9.png
new file mode 100644
index 0000000..1337ba9
--- /dev/null
+++ b/tests/FrameworkTest/res/drawable/drawable_background.9.png
Binary files differ
diff --git a/tests/FrameworkTest/res/drawable/sym_now_playing_pause_1.png b/tests/FrameworkTest/res/drawable/sym_now_playing_pause_1.png
new file mode 100644
index 0000000..2f19d08
--- /dev/null
+++ b/tests/FrameworkTest/res/drawable/sym_now_playing_pause_1.png
Binary files differ
diff --git a/tests/FrameworkTest/res/drawable/sym_now_playing_skip_backward_1.png b/tests/FrameworkTest/res/drawable/sym_now_playing_skip_backward_1.png
new file mode 100644
index 0000000..f945a81
--- /dev/null
+++ b/tests/FrameworkTest/res/drawable/sym_now_playing_skip_backward_1.png
Binary files differ
diff --git a/tests/FrameworkTest/res/drawable/sym_now_playing_skip_forward_1.png b/tests/FrameworkTest/res/drawable/sym_now_playing_skip_forward_1.png
new file mode 100644
index 0000000..da9361a
--- /dev/null
+++ b/tests/FrameworkTest/res/drawable/sym_now_playing_skip_forward_1.png
Binary files differ
diff --git a/tests/FrameworkTest/res/layout/add_column_in_table.xml b/tests/FrameworkTest/res/layout/add_column_in_table.xml
new file mode 100644
index 0000000..62c27f3
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/add_column_in_table.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <TableLayout android:id="@+id/table"
+        android:layout_width="fill_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1.0">
+
+        <TableRow>
+            <TextView
+              android:text="@string/table_layout_a"
+                android:padding="3dip" />
+            <TextView
+                android:text="@string/table_layout_b"
+                android:padding="3dip" />
+            <TextView
+                android:text="@string/table_layout_c"
+                android:padding="3dip" />
+        </TableRow>
+
+    </TableLayout>
+
+    <Button android:id="@+id/add_row_button"
+        android:text="@string/add_row_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/autocompletetextview_simple.xml b/tests/FrameworkTest/res/layout/autocompletetextview_simple.xml
new file mode 100644
index 0000000..d408a86
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/autocompletetextview_simple.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/samples/SampleCode/res/layout/baseline_1.xml
+**
+** Copyright 2008, 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/layout"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <AutoCompleteTextView
+        android:id="@+id/autocompletetextview1"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:inputType="text|textAutoComplete"
+        android:completionThreshold="1" />
+        />
+
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/baseline_0width_and_weight.xml b/tests/FrameworkTest/res/layout/baseline_0width_and_weight.xml
new file mode 100644
index 0000000..83f3fcb
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/baseline_0width_and_weight.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+*
+**
+** Copyright 2008, 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:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+    <LinearLayout android:id="@+id/layout"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:visibility="gone">
+        <com.android.frameworktest.layout.linear.ExceptionTextView
+             android:id="@+id/routeToField"
+             android:textSize="16sp"
+             android:layout_width="0dip"
+             android:layout_weight="1"
+             android:layout_height="wrap_content"
+             android:lines="2"
+             android:autoText="false"
+             android:capitalize="none"
+             android:maxLines="1" />
+         <Button
+             android:layout_height="wrap_content"
+             android:layout_width="wrap_content"
+             android:layout_gravity="fill_vertical"
+             android:text="@string/side_button_label" />
+    </LinearLayout>
+    <Button android:id="@+id/show"
+         android:layout_height="wrap_content"
+         android:layout_width="wrap_content"
+         android:text="@string/show" />
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/baseline_buttons.xml b/tests/FrameworkTest/res/layout/baseline_buttons.xml
new file mode 100644
index 0000000..ae942017
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/baseline_buttons.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+*
+**
+** Copyright 2008, 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/layout"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal">
+
+    <TextView android:id="@+id/currenttime"
+    	android:text="@string/time"
+        android:textSize="12sp"
+        android:textStyle="bold"
+        android:layout_gravity="bottom"
+        android:layout_weight="1"
+        android:layout_width="0dip"
+        android:layout_height="wrap_content" />
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        android:gravity="center">
+
+        <ImageButton android:id="@+id/prev"
+            android:src="@drawable/sym_now_playing_skip_backward_1"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+
+        <ImageButton android:id="@+id/pause"
+            android:src="@drawable/sym_now_playing_pause_1"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+
+        <ImageButton android:id="@+id/next"
+            android:src="@drawable/sym_now_playing_skip_forward_1"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+
+    </LinearLayout>
+
+    <TextView android:id="@+id/totaltime"
+        android:textSize="12sp"
+        android:textStyle="bold"
+        android:gravity="right"
+        android:text="@string/time"
+        android:layout_gravity="bottom"
+        android:layout_weight="1"
+        android:layout_width="0dip"
+        android:layout_height="wrap_content" />
+
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/baseline_center_gravity.xml b/tests/FrameworkTest/res/layout/baseline_center_gravity.xml
new file mode 100644
index 0000000..9793ab4
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/baseline_center_gravity.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+*
+**
+** Copyright 2008, 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:orientation="horizontal"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content">
+    <Button android:id="@+id/button1"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:layout_gravity="center"
+        android:text="@string/side_button_label" />
+    <Button android:id="@+id/button2"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:layout_gravity="center"
+        android:text="@string/side_button_label" />
+    <Button android:id="@+id/button3"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:layout_gravity="center"
+        android:text="@string/side_button_label" />
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/brightness_limit.xml b/tests/FrameworkTest/res/layout/brightness_limit.xml
new file mode 100644
index 0000000..46e5767
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/brightness_limit.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2008, 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.
+*/
+-->
+
+<!-- Tries to set brightness to 0. See corresponding Java code. -->
+
+
+<Button xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/go"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:text="@string/go"/>
+
diff --git a/tests/FrameworkTest/res/layout/descendant_focusability.xml b/tests/FrameworkTest/res/layout/descendant_focusability.xml
new file mode 100644
index 0000000..6a30d50d
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/descendant_focusability.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2007, 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:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+        >
+
+    <LinearLayout
+        android:id="@+id/beforeDescendants"
+        android:orientation="vertical"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:descendantFocusability="beforeDescendants"
+            >
+        <Button
+          android:layout_width="fill_parent"
+          android:layout_height="wrap_content"
+                />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/afterDescendants"
+        android:orientation="vertical"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:descendantFocusability="afterDescendants"
+            >
+        <Button
+          android:layout_width="fill_parent"
+          android:layout_height="wrap_content"
+                />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/blocksDescendants"
+        android:orientation="vertical"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:descendantFocusability="blocksDescendants"
+            >
+        <Button
+          android:layout_width="fill_parent"
+          android:layout_height="wrap_content"
+                />
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/disabled.xml b/tests/FrameworkTest/res/layout/disabled.xml
new file mode 100644
index 0000000..ed7ff06
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/disabled.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<!-- Demonstrates changing view visibility. See corresponding Java code. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/clickableParent"
+    android:orientation="horizontal"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <Button android:id="@+id/disabledButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/disabled_button"/>
+
+    <Button android:id="@+id/disabledButtonA"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/disabled_button"/>
+        
+    <Button android:id="@+id/disabledButtonB"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/disabled_button"/>
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/drawable_background_minimum_size.xml b/tests/FrameworkTest/res/layout/drawable_background_minimum_size.xml
new file mode 100644
index 0000000..ea0cbfa
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/drawable_background_minimum_size.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+    
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+        
+        <Button
+            android:id="@+id/change_backgrounds"
+            android:text="@string/change_backgrounds"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+
+        <!-- Different views and layouts that should initially be small but still contain
+             some content (hence the minimal text inside each of the layouts).  Each of these
+             will each be tested to make sure they expand to at least the minimum size
+             recommended by different backgrounds -->
+             
+        <TextView
+            android:id="@+id/text_view"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/minimal_text" />
+                
+        <LinearLayout
+            android:id="@+id/linear_layout"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content">
+            
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/minimal_text" />
+                
+        </LinearLayout>
+    
+        <RelativeLayout
+            android:id="@+id/relative_layout"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content">
+            
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/minimal_text" />
+                
+        </RelativeLayout>
+    
+        <FrameLayout
+            android:id="@+id/frame_layout"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content">
+            
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/minimal_text" />
+                
+        </FrameLayout>
+    
+        <AbsoluteLayout
+            android:id="@+id/absolute_layout"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content">
+            
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/minimal_text" />
+                
+        </AbsoluteLayout>
+    
+    </LinearLayout>
+
+</ScrollView>
diff --git a/tests/FrameworkTest/res/layout/fill_in_wrap.xml b/tests/FrameworkTest/res/layout/fill_in_wrap.xml
new file mode 100644
index 0000000..b61fd30
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/fill_in_wrap.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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="fill_parent"
+    android:layout_height="?android:attr/listPreferredItemHeight"
+    android:orientation="horizontal"
+    android:baselineAligned="false"
+    android:gravity="center_vertical">
+
+    <Button
+        android:layout_width="100dip"
+        android:layout_height="wrap_content"
+        android:gravity="left|center_vertical"
+    />
+
+    <LinearLayout android:id="@+id/layout"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:paddingLeft="0dip"
+        android:paddingRight="0dip"
+        android:paddingTop="2dip"
+        android:paddingBottom="2dip"    
+        android:orientation="horizontal"
+        android:baselineAligned="false"
+        android:addStatesFromChildren="true"
+        android:background="@android:drawable/edit_text"
+        android:gravity="center_vertical">
+
+        <EditText android:id="@+id/data"
+            android:layout_width="0dip"
+            android:layout_weight="1"
+            android:layout_height="fill_parent"
+            android:layout_marginLeft="8dip"
+            android:paddingBottom="4dip"
+            android:layout_gravity="center_vertical"
+            android:background="@null"
+        />
+
+        <ImageButton
+            style="@android:style/Widget.Button.Inset"
+            android:src="@android:drawable/ic_delete"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginRight="2dip"
+            android:gravity="center"
+        />
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/focus_after_removal.xml b/tests/FrameworkTest/res/layout/focus_after_removal.xml
new file mode 100644
index 0000000..7cf6cbe
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/focus_after_removal.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/samples/SampleCode/res/layout/baseline_1.xml
+**
+** Copyright 2007, 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:orientation="horizontal"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content">
+
+    <LinearLayout android:id="@+id/leftLayout"
+        android:orientation="vertical"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content">
+
+        <Button android:id="@+id/topLeftButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginRight="3dip"
+            android:text="@string/left_top" />
+        <Button android:id="@+id/bottomLeftButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginRight="3dip"
+            android:text="@string/left_bottom" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content">
+
+        <Button android:id="@+id/topRightButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginRight="3dip"
+            android:text="@string/right_top" />
+        <Button android:id="@+id/bottomRightButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginRight="3dip"
+            android:text="@string/right_bottom" />
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/focus_listener.xml b/tests/FrameworkTest/res/layout/focus_listener.xml
new file mode 100644
index 0000000..a838205
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/focus_listener.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/samples/SampleCode/res/layout/baseline_1.xml
+**
+** Copyright 2007, 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:orientation="horizontal"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content">
+
+    <Button android:id="@+id/left"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginRight="3dip"
+        android:text="@string/left_top" />
+
+    <Button android:id="@+id/right"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginRight="3dip"
+        android:text="@string/left_bottom" />
+
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/framelayout_gravity.xml b/tests/FrameworkTest/res/layout/framelayout_gravity.xml
new file mode 100644
index 0000000..ce48825
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/framelayout_gravity.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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"
+    android:id="@+id/parent"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <Button android:id="@+id/left"
+        android:layout_gravity="left"
+        android:text="@string/view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <Button android:id="@+id/right"
+        android:layout_gravity="right"
+        android:text="@string/view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <Button android:id="@+id/center_horizontal"
+        android:layout_gravity="center_horizontal"
+        android:text="@string/view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <Button android:id="@+id/left_center_vertical"
+        android:layout_gravity="center_vertical|left"
+        android:text="@string/view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <Button android:id="@+id/right_center_vertical"
+        android:layout_gravity="center_vertical|right"
+        android:text="@string/view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <Button android:id="@+id/center"
+        android:layout_gravity="center"
+        android:text="@string/view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <Button android:id="@+id/left_bottom"
+        android:layout_gravity="bottom|left"
+        android:text="@string/view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <Button android:id="@+id/right_bottom"
+        android:layout_gravity="bottom|right"
+        android:text="@string/view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <Button android:id="@+id/center_horizontal_bottom"
+        android:layout_gravity="bottom|center_horizontal"
+        android:text="@string/view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+</FrameLayout>
diff --git a/tests/FrameworkTest/res/layout/framelayout_margin.xml b/tests/FrameworkTest/res/layout/framelayout_margin.xml
new file mode 100644
index 0000000..1e14899
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/framelayout_margin.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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"
+    android:id="@+id/parent"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <Button android:id="@+id/left"
+        android:layout_gravity="left"
+        android:layout_marginLeft="12dip"
+        android:text="@string/view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <Button android:id="@+id/right"
+        android:layout_gravity="right"
+        android:layout_marginRight="12dip"
+        android:text="@string/view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <Button android:id="@+id/top"
+        android:layout_gravity="top|center_horizontal"
+        android:layout_marginTop="12dip"
+        android:text="@string/view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <Button android:id="@+id/bottom"
+        android:layout_gravity="bottom|center_horizontal"
+        android:layout_marginBottom="12dip"
+        android:text="@string/view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+</FrameLayout>
diff --git a/tests/FrameworkTest/res/layout/grid_in_horizontal.xml b/tests/FrameworkTest/res/layout/grid_in_horizontal.xml
new file mode 100644
index 0000000..835dce3
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/grid_in_horizontal.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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:orientation="horizontal"
+	android:layout_width="fill_parent" 
+    android:layout_height="fill_parent">
+	
+	<GridView android:id="@+id/grid"
+	    android:layout_width="0dip" 
+	    android:layout_height="fill_parent"
+	    android:layout_weight="1"
+	    android:padding="10dip"
+	    android:verticalSpacing="10dp"    
+	    android:horizontalSpacing="10dp"
+	    android:numColumns="auto_fit"
+	    android:columnWidth="60dp"
+	    android:stretchMode="columnWidth" />
+	    
+    <ImageButton
+        android:src="@drawable/sym_now_playing_pause_1"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+    	
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/grid_in_vertical.xml b/tests/FrameworkTest/res/layout/grid_in_vertical.xml
new file mode 100644
index 0000000..731bc54
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/grid_in_vertical.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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:orientation="vertical"
+	android:layout_width="fill_parent" 
+    android:layout_height="fill_parent">
+	
+	<GridView android:id="@+id/grid"
+	    android:layout_width="wrap_content" 
+	    android:layout_height="wrap_content"
+	    android:numColumns="auto_fit" />
+	    
+    <ImageButton
+        android:src="@drawable/sym_now_playing_pause_1"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+   
+	<ImageButton
+        android:src="@drawable/sym_now_playing_pause_1"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+        
+	<ImageButton
+        android:src="@drawable/sym_now_playing_pause_1"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+         	
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/grid_padding.xml b/tests/FrameworkTest/res/layout/grid_padding.xml
new file mode 100644
index 0000000..bd666e1
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/grid_padding.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<GridView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/grid"
+	android:layout_width="wrap_content"
+	android:layout_height="wrap_content"
+	android:padding="10dip"
+	android:verticalSpacing="10dp"
+	android:horizontalSpacing="10dp"
+	android:numColumns="auto_fit"
+	android:columnWidth="50dp" />
diff --git a/tests/FrameworkTest/res/layout/grid_scroll_listener.xml b/tests/FrameworkTest/res/layout/grid_scroll_listener.xml
new file mode 100644
index 0000000..c02aed9
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/grid_scroll_listener.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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:orientation="vertical"
+	android:layout_width="fill_parent" 
+    android:layout_height="fill_parent">
+	
+	<GridView android:id="@+id/grid"
+	    android:layout_width="fill_parent" 
+	    android:layout_height="0dip"
+	    android:layout_weight="1"
+	    android:padding="10dip"
+	    android:verticalSpacing="10dp"    
+	    android:horizontalSpacing="10dp"
+	    android:numColumns="auto_fit"
+	    android:columnWidth="60dp"
+	    android:stretchMode="columnWidth"
+	    android:gravity="center"/>
+	    
+    <TextView android:id="@+id/text"
+    	android:layout_width="fill_parent" 
+    	android:layout_height="wrap_content"
+    	android:gravity="center_horizontal"/>
+    	
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/grid_thrasher.xml b/tests/FrameworkTest/res/layout/grid_thrasher.xml
new file mode 100644
index 0000000..1a260df
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/grid_thrasher.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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:orientation="vertical"
+	android:layout_width="fill_parent" 
+    android:layout_height="fill_parent">
+	
+	<GridView android:id="@+id/grid"
+	    android:layout_width="fill_parent" 
+		android:layout_height="fill_parent"
+	    android:padding="10dip"
+	    android:verticalSpacing="10dp"    
+	    android:horizontalSpacing="10dp"
+	    android:numColumns="auto_fit"
+	    android:columnWidth="60dp"
+	    android:stretchMode="columnWidth"
+	    android:gravity="center"/>
+	    
+    <TextView android:id="@+id/text"
+    	android:layout_width="fill_parent" 
+    	android:layout_height="wrap_content"
+    	android:gravity="center_horizontal"/>
+    	
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/include_button.xml b/tests/FrameworkTest/res/layout/include_button.xml
new file mode 100644
index 0000000..5857fa3
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/include_button.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<Button xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/included_button"
+    android:text="@string/include_button"        
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content" />
diff --git a/tests/FrameworkTest/res/layout/include_button_with_size.xml b/tests/FrameworkTest/res/layout/include_button_with_size.xml
new file mode 100644
index 0000000..0cd8eaa
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/include_button_with_size.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<Button xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/included_button"
+    android:text="@string/include_button"        
+    android:layout_width="23dip"
+    android:layout_height="23dip" />
diff --git a/tests/FrameworkTest/res/layout/include_tag.xml b/tests/FrameworkTest/res/layout/include_tag.xml
new file mode 100644
index 0000000..d1047f1
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/include_tag.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <TextView
+        android:text="@string/include_label"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <include
+        layout="@layout/include_button" />
+
+    <include
+        layout="@layout/include_button"
+        android:id="@+id/included_button_overriden"
+        android:layout_width="237dip"
+        android:layout_height="123dip" />
+
+    <include
+        layout="@layout/include_button"
+        android:id="@+id/included_button_visibility"
+        android:visibility="invisible" />
+    
+    <include
+        layout="@layout/include_button_with_size"
+        android:id="@+id/included_button_with_size" />
+
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/inflated_expandablelistview.xml b/tests/FrameworkTest/res/layout/inflated_expandablelistview.xml
new file mode 100644
index 0000000..d01e7c5
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/inflated_expandablelistview.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<ExpandableListView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/elv"
+        android:layout_height="fill_parent"
+        android:layout_width="fill_parent" />
diff --git a/tests/FrameworkTest/res/layout/linear_layout_buttons.xml b/tests/FrameworkTest/res/layout/linear_layout_buttons.xml
new file mode 100644
index 0000000..f60692a
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/linear_layout_buttons.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/samples/SampleCode/res/layout/baseline_1.xml
+**
+** Copyright 2007, 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/layout"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <Button
+        android:id="@+id/button1"
+        android:layout_width="fill_parent"
+        android:layout_height="0sp"
+        android:layout_weight="1"
+        android:text="@string/keypad_one"/>
+
+    <Button
+        android:id="@+id/button2"
+        android:layout_width="fill_parent"
+        android:layout_height="0sp"
+        android:layout_weight="1"
+        android:text="@string/keypad_two"/>
+
+    <Button
+        android:id="@+id/button3"
+        android:layout_width="fill_parent"
+        android:layout_height="0sp"
+        android:layout_weight="1"
+        android:text="@string/keypad_three"/>
+
+
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/linear_layout_edittext_then_button.xml b/tests/FrameworkTest/res/layout/linear_layout_edittext_then_button.xml
new file mode 100644
index 0000000..21e7399
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/linear_layout_edittext_then_button.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/samples/SampleCode/res/layout/baseline_1.xml
+**
+** Copyright 2007, 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/layout"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <EditText
+        android:id="@+id/editText"
+        android:layout_width="fill_parent"
+        android:layout_height="0sp"
+        android:layout_weight="1"/>
+
+    <Button
+        android:id="@+id/button"
+        android:layout_width="fill_parent"
+        android:layout_height="0sp"
+        android:layout_weight="1"
+        android:text="@string/keypad_one"/>
+
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/linear_layout_grid.xml b/tests/FrameworkTest/res/layout/linear_layout_grid.xml
new file mode 100644
index 0000000..81f7b15
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/linear_layout_grid.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/samples/SampleCode/res/layout/baseline_1.xml
+**
+** Copyright 2007, 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/layout"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <LinearLayout android:id="@+id/column1"
+        android:layout_width="fill_parent"
+        android:layout_height="0sp"
+        android:layout_weight="1"
+        android:orientation="horizontal">
+
+        <Button
+            android:layout_width="0sp"
+            android:layout_height="fill_parent"
+            android:layout_weight="1"
+            android:text="@string/keypad_one"/>
+
+        <Button
+            android:layout_width="0sp"
+            android:layout_height="fill_parent"
+            android:layout_weight="1"
+            android:text="@string/keypad_two"/>
+
+        <Button
+            android:layout_width="0sp"
+            android:layout_height="fill_parent"
+            android:layout_weight="1"
+            android:text="@string/keypad_three"/>
+    </LinearLayout>
+
+    <LinearLayout android:id="@+id/column2"
+        android:layout_width="fill_parent"
+        android:layout_height="0sp"
+        android:layout_weight="1"
+        android:orientation="horizontal">
+
+        <Button
+            android:layout_width="0sp"
+            android:layout_height="fill_parent"
+            android:layout_weight="1"
+            android:text="@string/keypad_four"/>
+
+        <Button
+            android:layout_width="0sp"
+            android:layout_height="fill_parent"
+            android:layout_weight="1"
+            android:text="@string/keypad_five"/>
+
+        <Button
+            android:layout_width="0sp"
+            android:layout_height="fill_parent"
+            android:layout_weight="1"
+            android:text="@string/keypad_six"/>
+    </LinearLayout>
+
+    <LinearLayout android:id="@+id/column3"
+        android:layout_width="fill_parent"
+        android:layout_height="0sp"
+        android:layout_weight="1"
+        android:orientation="horizontal">
+
+        <Button
+            android:layout_width="0sp"
+            android:layout_height="fill_parent"
+            android:layout_weight="1"
+            android:text="@string/keypad_seven"/>
+
+        <Button
+            android:layout_width="0sp"
+            android:layout_height="fill_parent"
+            android:layout_weight="1"
+            android:text="@string/keypad_eight"/>
+
+        <Button
+            android:layout_width="0sp"
+            android:layout_height="fill_parent"
+            android:layout_weight="1"
+            android:text="@string/keypad_nine"/>
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/linear_layout_listview_height.xml b/tests/FrameworkTest/res/layout/linear_layout_listview_height.xml
new file mode 100644
index 0000000..10ef2ce
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/linear_layout_listview_height.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2008, 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/layout"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+    
+    <!-- Outer linear layout providing vertical layout -->
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content" >
+        
+        <!-- The control buttons -->
+        <LinearLayout
+            android:orientation="horizontal"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content" >
+            
+            <Button
+                android:id="@+id/button1"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/linear_listheight_fixed"/>
+        
+            <Button
+                android:id="@+id/button2"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/linear_listheight_fill"/>
+        
+            <Button
+                android:id="@+id/button3"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/linear_listheight_hide"/>
+        </LinearLayout>
+        
+        <!-- The list view -->
+        <ListView 
+            android:id="@+id/inner_list"
+            android:layout_width="200dip"
+            android:layout_height="fill_parent"
+            android:background="@android:drawable/spinner_dropdown_background"
+            android:divider="@android:drawable/divider_horizontal_bright" />
+ 
+    </LinearLayout>
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/linear_layout_spinner_then_button.xml b/tests/FrameworkTest/res/layout/linear_layout_spinner_then_button.xml
new file mode 100644
index 0000000..7ed245b
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/linear_layout_spinner_then_button.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2008, 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:orientation="horizontal"
+   android:layout_width="fill_parent"
+   android:layout_height="wrap_content">
+
+   <Spinner android:id="@+id/reminder_value"
+       android:layout_width="0dip"
+       android:layout_height="wrap_content"
+       android:layout_weight="0.7"
+       android:entries="@array/reminder_minutes_labels"/>
+
+   <Button android:id="@+id/reminder_remove"
+       android:layout_width="0dip"
+       android:layout_height="wrap_content"
+       android:layout_weight="0.3"
+       android:text="@string/show" />
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/linear_layout_textviews.xml b/tests/FrameworkTest/res/layout/linear_layout_textviews.xml
new file mode 100644
index 0000000..84a898c
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/linear_layout_textviews.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2008, 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/layout"
+    android:background="#FFFF0000"
+    android:orientation="horizontal"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content">
+
+    <EditText
+        android:id="@+id/editText1"
+        android:text="@string/text"
+        android:layout_width="0dip"
+        android:layout_height="wrap_content"
+        android:layout_weight="1.0" />
+
+    <EditText
+        android:id="@+id/editText2"
+        android:text="@string/text"
+        android:layout_width="0dip"
+        android:layout_height="wrap_content"
+        android:layout_weight="1.0" />
+
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/linear_layout_weight.xml b/tests/FrameworkTest/res/layout/linear_layout_weight.xml
new file mode 100644
index 0000000..bb138df
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/linear_layout_weight.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2008, 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/layout"
+    android:background="#FFFFFFFF"
+    android:orientation="horizontal"
+    android:layout_width="87dip"
+    android:layout_height="wrap_content">
+
+    <View
+        android:id="@+id/child1"
+        android:background="#FFFF0000"
+        android:layout_width="20dip"
+        android:layout_height="wrap_content"
+        android:layout_weight="1.0" />
+
+    <View
+        android:id="@+id/child2"
+        android:background="#FF00FF00"
+        android:layout_width="20dip"
+        android:layout_height="wrap_content"
+        android:layout_weight="1.0" />
+
+    <View
+        android:background="#FF0000FF"
+        android:id="@+id/child3"
+        android:layout_width="20dip"
+        android:layout_height="wrap_content"
+        android:layout_weight="1.0" />
+
+    <View
+        android:background="#FFFF00FF"
+        android:id="@+id/child4"
+        android:layout_width="20dip"
+        android:layout_height="wrap_content"
+        android:layout_weight="1.0" />
+
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/list_dividers.xml b/tests/FrameworkTest/res/layout/list_dividers.xml
new file mode 100644
index 0000000..b56511e
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/list_dividers.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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:orientation="horizontal"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <Button
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <ListView android:id="@android:id/list"
+        android:paddingRight="15dip"
+        android:layout_marginLeft="50dip"
+        android:layout_width="150dip"
+        android:layout_height="300dip" />
+
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/list_filter.xml b/tests/FrameworkTest/res/layout/list_filter.xml
new file mode 100644
index 0000000..cea518c
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/list_filter.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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:orientation="vertical"
+    android:layout_width="fill_parent" 
+    android:layout_height="fill_parent">
+    
+    <FrameLayout android:id="@+id/frame"
+        android:layout_width="fill_parent" 
+        android:layout_height="0dip"
+        android:layout_weight="1">
+
+        <ListView android:id="@android:id/list"
+            android:layout_width="fill_parent" 
+            android:layout_height="fill_parent"
+            android:drawSelectorOnTop="false" />
+            
+    </FrameLayout>
+    
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="fill_parent" 
+        android:layout_height="wrap_content">
+        
+        <Button android:id="@+id/hide"
+            android:layout_width="wrap_content" 
+            android:layout_height="wrap_content"
+            android:text="@string/hide" />
+         
+        <Button android:id="@+id/show"
+            android:layout_width="wrap_content" 
+            android:layout_height="wrap_content"
+            android:text="@string/show" /> 
+            
+    </LinearLayout>
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/list_in_horizontal.xml b/tests/FrameworkTest/res/layout/list_in_horizontal.xml
new file mode 100644
index 0000000..371cb84
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/list_in_horizontal.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <TableRow>
+
+        <ListView android:id="@+id/list" />
+
+        <ImageButton android:src="@drawable/sym_now_playing_pause_1" />
+
+    </TableRow>
+
+</TableLayout>
diff --git a/tests/FrameworkTest/res/layout/list_in_vertical.xml b/tests/FrameworkTest/res/layout/list_in_vertical.xml
new file mode 100644
index 0000000..0ea2475
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/list_in_vertical.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content">
+
+        <ListView android:id="@+id/list"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content" />
+
+        <ImageButton
+            android:src="@drawable/sym_now_playing_pause_1"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+
+        <ImageButton
+            android:src="@drawable/sym_now_playing_pause_1"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+
+        <ImageButton
+            android:src="@drawable/sym_now_playing_pause_1"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+         	
+    </LinearLayout>
+</ScrollView>
diff --git a/tests/FrameworkTest/res/layout/list_recycler_profiling.xml b/tests/FrameworkTest/res/layout/list_recycler_profiling.xml
new file mode 100644
index 0000000..9678eb7
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/list_recycler_profiling.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <ListView android:id="@+id/list"
+        android:layout_width="fill_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1.0" />
+
+    <ImageButton android:id="@+id/pause"
+        android:src="@drawable/sym_now_playing_pause_1"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/list_scroll_listener.xml b/tests/FrameworkTest/res/layout/list_scroll_listener.xml
new file mode 100644
index 0000000..001296a
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/list_scroll_listener.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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:orientation="vertical"
+	android:layout_width="fill_parent" 
+    android:layout_height="fill_parent">
+	
+	<ListView android:id="@android:id/list"
+	    android:layout_width="fill_parent" 
+	    android:layout_height="0dip"
+	    android:layout_weight="1"
+	    android:drawSelectorOnTop="false"/>
+	    
+    <TextView android:id="@+id/text"
+    	android:layout_width="fill_parent" 
+    	android:layout_height="wrap_content"
+    	android:gravity="center_horizontal"/>
+    	
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/list_take_focus_from_side.xml b/tests/FrameworkTest/res/layout/list_take_focus_from_side.xml
new file mode 100644
index 0000000..cf141cc
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/list_take_focus_from_side.xml
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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:orientation="horizontal"
+    android:layout_width="fill_parent" 
+    android:layout_height="fill_parent">
+    
+    <ListView android:id="@android:id/list"
+        android:layout_width="0dip" 
+        android:layout_weight="1"
+        android:layout_height="fill_parent"
+        android:drawSelectorOnTop="false"/>
+        
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="wrap_content" 
+        android:layout_height="fill_parent">
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/side_button_label" />  
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/side_button_label" />  
+         <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/side_button_label" />  
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/side_button_label" />  
+         <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/side_button_label" />  
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/side_button_label" />  
+         <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/side_button_label" />  
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/side_button_label" />  
+         <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/side_button_label" />  
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/side_button_label" />  
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/side_button_label" />  
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/side_button_label" />  
+         <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/side_button_label" />  
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/side_button_label" />  
+         <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/side_button_label" />  
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/side_button_label" />  
+         <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/side_button_label" />  
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/side_button_label" />  
+         <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/side_button_label" />  
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/side_button_label" />
+    </LinearLayout>
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/list_thrasher.xml b/tests/FrameworkTest/res/layout/list_thrasher.xml
new file mode 100644
index 0000000..001296a
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/list_thrasher.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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:orientation="vertical"
+	android:layout_width="fill_parent" 
+    android:layout_height="fill_parent">
+	
+	<ListView android:id="@android:id/list"
+	    android:layout_width="fill_parent" 
+	    android:layout_height="0dip"
+	    android:layout_weight="1"
+	    android:drawSelectorOnTop="false"/>
+	    
+    <TextView android:id="@+id/text"
+    	android:layout_width="fill_parent" 
+    	android:layout_height="wrap_content"
+    	android:gravity="center_horizontal"/>
+    	
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/list_with_button_above.xml b/tests/FrameworkTest/res/layout/list_with_button_above.xml
new file mode 100644
index 0000000..25db016
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/list_with_button_above.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Simple layout with a button and a list below, can be used to build more
+ sophisticated test cases by adding stuff to the list programatically.-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/layout"
+        android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+
+    <Button android:id="@+id/button"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/button_above_list_label"/>
+
+
+    <ListView android:id="@android:id/list"
+        android:layout_width="fill_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:paddingTop="2dip"
+        android:drawSelectorOnTop="false"/>
+
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/list_with_disappearing_item_bug_item.xml b/tests/FrameworkTest/res/layout/list_with_disappearing_item_bug_item.xml
new file mode 100644
index 0000000..0163d96
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/list_with_disappearing_item_bug_item.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2006 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.
+-->
+
+<!-- A layout is needed to reprod the bug. -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="?android:attr/listPreferredItemHeight">
+
+    <TextView 
+        android:id="@+id/text1"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:textAppearance="?android:attr/textAppearanceLarge"
+        android:gravity="center_vertical"
+        android:paddingLeft="27dip"
+    />
+
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/list_with_empty_view.xml b/tests/FrameworkTest/res/layout/list_with_empty_view.xml
new file mode 100644
index 0000000..00d81a7
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/list_with_empty_view.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent" >
+
+    <ListView android:id="@android:id/list"
+        android:drawSelectorOnTop="false"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"/>
+
+    <TextView android:id="@+id/empty"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:gravity="center"
+        android:textSize="36sp"
+        android:textColor="#999"
+        android:visibility="gone"
+        android:text="@string/empty_list" />
+
+</FrameLayout>    
diff --git a/tests/FrameworkTest/res/layout/longpress.xml b/tests/FrameworkTest/res/layout/longpress.xml
new file mode 100644
index 0000000..ef3672c
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/longpress.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2007, 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:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <View android:id="@+id/simple_view"
+        android:background="@drawable/blue"
+        android:layout_width="20dip"
+        android:layout_height="20dip"
+        android:focusable="true" />
+    
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/mail_message.xml b/tests/FrameworkTest/res/layout/mail_message.xml
new file mode 100644
index 0000000..ed52751
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/mail_message.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- A layout similar to a gmail message.  useful for setting up tests, like
+ a list with a list of messages.-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content">
+
+    <TextView android:id="@+id/subject"
+              android:layout_width="fill_parent"
+              android:layout_height="wrap_content"/>
+
+    <WebView android:id="@+id/body"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
+
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/merge_child.xml b/tests/FrameworkTest/res/layout/merge_child.xml
new file mode 100644
index 0000000..9972924
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/merge_child.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <TextView
+        android:text="@string/include_label"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <TextView
+        android:text="@string/include_label"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <TextView
+        android:text="@string/include_label"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+</merge>
diff --git a/tests/FrameworkTest/res/layout/merge_tag.xml b/tests/FrameworkTest/res/layout/merge_tag.xml
new file mode 100644
index 0000000..9eec493
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/merge_tag.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <TextView
+        android:text="@string/include_label"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <TextView
+        android:text="@string/include_label"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <TextView
+        android:text="@string/include_label"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <TextView
+        android:text="@string/include_label"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <include layout="@layout/merge_child" />
+
+</merge>
diff --git a/tests/FrameworkTest/res/layout/popup_window_visibility.xml b/tests/FrameworkTest/res/layout/popup_window_visibility.xml
new file mode 100644
index 0000000..21c94bb
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/popup_window_visibility.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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:orientation="vertical"
+    android:layout_width="fill_parent" 
+    android:layout_height="fill_parent">
+    
+    <FrameLayout android:id="@+id/frame"
+        android:layout_width="fill_parent" 
+        android:layout_height="0dip"
+        android:layout_weight="1">
+
+        <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="fill_parent" 
+            android:layout_height="fill_parent">
+                
+            <Spinner android:id="@+id/spinner"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content" />
+        
+            <AutoCompleteTextView android:id="@+id/auto"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
+                
+        </LinearLayout>
+        
+    </FrameLayout>
+    
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="fill_parent" 
+        android:layout_height="wrap_content">
+        
+        <Button android:id="@+id/hide"
+            android:layout_width="wrap_content" 
+            android:layout_height="wrap_content"
+            android:text="@string/hide" />
+         
+        <Button android:id="@+id/show"
+            android:layout_width="wrap_content" 
+            android:layout_height="wrap_content"
+            android:text="@string/show" /> 
+            
+    </LinearLayout>
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/pre_draw_listener.xml b/tests/FrameworkTest/res/layout/pre_draw_listener.xml
new file mode 100644
index 0000000..d348d9f
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/pre_draw_listener.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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:orientation="vertical"
+    android:layout_width="fill_parent" 
+    android:layout_height="fill_parent">
+    
+
+	<ScrollView 
+		android:orientation="vertical"
+        android:layout_width="fill_parent" 
+        android:layout_height="0dip"
+        android:layout_weight="1">
+        
+        <view class="com.android.frameworktest.view.PreDrawListener$MyLinearLayout" android:id="@+id/frame"
+            android:orientation="vertical"
+            android:layout_width="fill_parent" 
+            android:layout_height="fill_parent" />
+
+    </ScrollView>
+        
+    <Button android:id="@+id/go"
+        android:layout_width="wrap_content" 
+        android:layout_height="wrap_content"
+        android:text="@string/go" />
+         
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/remote_view_host.xml b/tests/FrameworkTest/res/layout/remote_view_host.xml
new file mode 100644
index 0000000..dc52181
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/remote_view_host.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2008, 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:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/remote_view_test_bad_1.xml b/tests/FrameworkTest/res/layout/remote_view_test_bad_1.xml
new file mode 100644
index 0000000..6a65976
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/remote_view_test_bad_1.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2008, 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/linear"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <EditText android:id="@+id/edit"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+           
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/remote_view_test_bad_2.xml b/tests/FrameworkTest/res/layout/remote_view_test_bad_2.xml
new file mode 100644
index 0000000..70613c3
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/remote_view_test_bad_2.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2008, 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/linear"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <WebView android:id="@+id/web"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+            
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/remote_view_test_good.xml b/tests/FrameworkTest/res/layout/remote_view_test_good.xml
new file mode 100644
index 0000000..54f4db9
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/remote_view_test_good.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2008, 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/linear"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <TextView android:id="@+id/text"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+        
+    <ImageView android:id="@+id/image"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+        
+    <FrameLayout android:id="@+id/frame"
+        android:layout_width="10dip"
+        android:layout_height="10dip" />
+        
+    <RelativeLayout android:id="@+id/relative"
+        android:layout_width="10dip"
+        android:layout_height="10dip" />
+   
+    <AbsoluteLayout android:id="@+id/absolute"
+        android:layout_width="10dip"
+        android:layout_height="10dip" />       
+        
+    <ProgressBar android:id="@+id/progress"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />      
+
+    <ImageButton android:id="@+id/image_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <Button android:id="@+id/button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/scroll_to_rect_with_internal_scroll.xml b/tests/FrameworkTest/res/layout/scroll_to_rect_with_internal_scroll.xml
new file mode 100644
index 0000000..d22122d
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/scroll_to_rect_with_internal_scroll.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/samples/SampleCode/res/layout/scroll_view_1.xml
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<!-- Demonstrates scrolling with a ScrollView. -->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/scrollView"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:scrollbars="none">
+
+    <LinearLayout
+        android:id="@+id/layout"
+        android:orientation="vertical"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content">
+
+
+        <Button android:id="@+id/scrollToBlob"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/scroll_top_button"/>
+
+        <TextView android:id="@+id/blob"
+            android:layout_width="fill_parent"
+            android:layout_height="80dip"
+            android:layout_marginTop="500dip"
+            android:layout_marginBottom="5dip"/>
+
+
+    </LinearLayout>
+</ScrollView>
diff --git a/tests/FrameworkTest/res/layout/scroll_to_rectangle.xml b/tests/FrameworkTest/res/layout/scroll_to_rectangle.xml
new file mode 100644
index 0000000..0839b1a
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/scroll_to_rectangle.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/samples/SampleCode/res/layout/scroll_view_1.xml
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<!-- Demonstrates scrolling with a ScrollView. -->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/scrollView"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:scrollbars="none">
+
+    <LinearLayout
+        android:id="@+id/layout"
+        android:orientation="vertical"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content">
+
+
+        <Button android:id="@+id/scrollToRectFromTop"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/scroll_top_button"/>
+
+        <Button android:id="@+id/scrollToRectFromTop2"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:paddingBottom="10dip"
+            android:text="@string/scroll_top_button2"/>
+
+        <TextView android:id="@+id/topBlob"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="5dip"
+            android:layout_marginBottom="5dip"/>
+
+        <TextView android:id="@+id/childToMakeVisible"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="5dip"
+            android:layout_marginBottom="5dip"
+            android:text="@string/scroll_to_me"/>
+
+        <TextView android:id="@+id/bottomBlob"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="5dip"
+            android:layout_marginBottom="5dip"/>
+
+        <Button android:id="@+id/scrollToRectFromBottom2"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:paddingTop="10dip"
+            android:text="@string/scroll_bottom_button2"/>
+
+        <Button android:id="@+id/scrollToRectFromBottom"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/scroll_bottom_button"/>
+
+
+    </LinearLayout>
+</ScrollView>
diff --git a/tests/FrameworkTest/res/layout/scrollview_linear_layout.xml b/tests/FrameworkTest/res/layout/scrollview_linear_layout.xml
new file mode 100644
index 0000000..536d2ed
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/scrollview_linear_layout.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/scrollView"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:scrollbars="none">
+
+    <LinearLayout
+        android:id="@+id/layout"
+        android:orientation="vertical"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content">
+
+    </LinearLayout>
+
+
+</ScrollView>
diff --git a/tests/FrameworkTest/res/layout/scrollview_with_webviews.xml b/tests/FrameworkTest/res/layout/scrollview_with_webviews.xml
new file mode 100644
index 0000000..79634752
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/scrollview_with_webviews.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/scrollView"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:scrollbars="none">
+
+    <LinearLayout
+        android:id="@+id/layout"
+        android:orientation="vertical"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content">
+
+
+        <WebView android:id="@+id/wb1"
+             android:layout_width="fill_parent"
+             android:layout_height="wrap_content"/>
+
+        <Button android:id="@+id/button"
+             android:layout_width="fill_parent"
+             android:layout_height="wrap_content"/>
+
+        <WebView android:id="@+id/wb2"
+             android:layout_width="fill_parent"
+             android:layout_height="wrap_content"/>
+
+    </LinearLayout>
+
+
+</ScrollView>
diff --git a/tests/FrameworkTest/res/layout/table_layout_cell_span.xml b/tests/FrameworkTest/res/layout/table_layout_cell_span.xml
new file mode 100644
index 0000000..26831e4
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/table_layout_cell_span.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content">
+
+    <TableRow>
+        <TextView android:id="@+id/a"
+            android:text="@string/table_layout_a"
+            android:background="#FFFF0000"
+            android:padding="3dip" />
+        <TextView android:id="@+id/b"
+            android:text="@string/table_layout_b"
+            android:background="#FF00FF00"
+            android:padding="3dip" />
+        <TextView android:id="@+id/c"
+            android:text="@string/table_layout_c"
+            android:background="#FF0000FF"
+            android:padding="3dip" />
+    </TableRow>
+
+    <TableRow>
+        <TextView  android:id="@+id/spanThenCell"
+            android:text="@string/table_layout_d"
+            android:layout_span="2"
+            android:gravity="center_horizontal"
+            android:background="#FF0000FF"
+            android:padding="3dip" />
+        <TextView
+            android:text="@string/table_layout_e"
+            android:background="#FF00FF00"
+            android:padding="3dip" />
+    </TableRow>
+
+    <TableRow>
+        <TextView
+            android:text="@string/table_layout_f"
+            android:background="#FFFF00FF"
+            android:padding="3dip" />
+        <TextView
+            android:text="@string/table_layout_g"
+            android:background="#FF00FF00"
+            android:padding="3dip" />
+        <TextView
+            android:text="@string/table_layout_h"
+            android:background="#FFFF0000"
+            android:padding="3dip" />
+    </TableRow>
+
+    <TableRow>
+        <TextView
+            android:text="@string/table_layout_a"
+            android:background="#FF00FF00"
+            android:padding="3dip" />
+        <TextView android:id="@+id/cellThenSpan"
+            android:text="@string/table_layout_b"
+            android:layout_span="2"
+            android:gravity="center_horizontal"
+            android:background="#FF0000FF"
+            android:padding="3dip" />
+    </TableRow>
+
+    <TableRow>
+        <TextView android:id="@+id/span"
+            android:text="@string/table_layout_g"
+            android:layout_span="3"
+            android:gravity="center_horizontal"
+            android:background="#FFC0C0C0"
+            android:padding="3dip" />
+    </TableRow>
+</TableLayout>
diff --git a/tests/FrameworkTest/res/layout/table_layout_fixed_width.xml b/tests/FrameworkTest/res/layout/table_layout_fixed_width.xml
new file mode 100644
index 0000000..91d9128
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/table_layout_fixed_width.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content">
+
+    <TableRow>
+        <View android:id="@+id/fixed_height"
+            android:layout_height="48dip"
+            android:background="#FF909090" />
+        <TextView android:id="@+id/fixed_width"
+            android:layout_width="150dip"
+            android:text="@string/table_layout_export"
+            android:background="#FFFF0000"
+            android:padding="3dip" />
+        <TextView
+            android:text="@string/table_layout_export_shortcut"
+            android:background="#FF00FFFF"
+            android:gravity="right"
+            android:padding="3dip" />
+    </TableRow>
+
+    <TableRow>
+        <View
+            android:layout_height="48dip"
+            android:background="#FF909090" />
+        <TextView android:id="@+id/non_fixed_width"
+            android:text="@string/table_layout_export"
+            android:background="#FFFF0000"
+            android:padding="3dip" />
+        <TextView
+            android:text="@string/table_layout_export_shortcut"
+            android:background="#FF00FFFF"
+            android:gravity="right"
+            android:padding="3dip" />
+    </TableRow>
+
+</TableLayout>
diff --git a/tests/FrameworkTest/res/layout/table_layout_horizontal_gravity.xml b/tests/FrameworkTest/res/layout/table_layout_horizontal_gravity.xml
new file mode 100644
index 0000000..dee81a5
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/table_layout_horizontal_gravity.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:stretchColumns="1">
+
+    <TableRow>
+        <TextView android:id="@+id/reference"
+            android:layout_column="1"
+            android:background="#FF0000FF"
+            android:text="@string/table_layout_open"
+            android:padding="3dip" />
+        <TextView
+            android:text="@string/table_layout_open_shortcut"
+            android:gravity="right"
+            android:padding="3dip" />
+    </TableRow>
+
+    <TableRow>
+        <!-- Horizontally centers the content of the cell -->
+        <TextView android:id="@+id/center"
+            android:layout_column="1"
+            android:text="@string/table_layout_save_as"
+            android:background="#FFFF0000"
+            android:layout_gravity="center_horizontal"
+            android:padding="3dip" />
+        <TextView
+            android:text="@string/table_layout_save_as_shortcut"
+            android:background="#FFFF00FF"
+            android:gravity="right"
+            android:padding="3dip" />
+    </TableRow>
+
+    <TableRow>
+        <View
+            android:layout_height="24dip"
+            android:background="#FF909090" />
+        <!-- Aligns the content of the cell to the bottom right -->
+        <TextView android:id="@+id/bottomRight"
+            android:text="@string/table_layout_export"
+            android:background="#FFFF0000"
+            android:layout_gravity="right|bottom"
+            android:padding="3dip" />
+        <TextView
+            android:text="@string/table_layout_export_shortcut"
+            android:background="#FF00FFFF"
+            android:gravity="right"
+            android:padding="3dip" />
+    </TableRow>
+
+
+    <TableRow>
+        <TextView android:id="@+id/left"
+            android:layout_column="1"
+            android:background="#FF0000FF"
+            android:text="@string/table_layout_open"
+            android:padding="3dip" />
+        <TextView
+            android:text="@string/table_layout_open_shortcut"
+            android:gravity="right"
+            android:padding="3dip" />
+    </TableRow>
+</TableLayout>
diff --git a/tests/FrameworkTest/res/layout/table_layout_vertical_gravity.xml b/tests/FrameworkTest/res/layout/table_layout_vertical_gravity.xml
new file mode 100644
index 0000000..6a8b784
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/table_layout_vertical_gravity.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content">
+
+    <TableRow>
+        <View android:id="@+id/reference1"
+            android:layout_height="96dip"
+            android:background="#FF909090" />
+        <TextView
+            android:background="#FF0000FF"
+            android:text="@string/table_layout_open"
+            android:padding="3dip" />
+        <TextView android:id="@+id/cell_top"
+            android:background="#FF00FF00"
+            android:layout_gravity="top"
+            android:text="@string/table_layout_open_shortcut"
+            android:padding="3dip" />
+    </TableRow>
+
+    <TableRow>
+        <View android:id="@+id/reference2"
+            android:layout_height="96dip"
+            android:background="#FF909090" />
+        <TextView
+            android:background="#FF0000FF"
+            android:text="@string/table_layout_open"
+            android:padding="3dip" />
+        <TextView android:id="@+id/cell_center"
+            android:background="#FF00FF00"
+            android:layout_gravity="center_vertical"
+            android:text="@string/table_layout_open_shortcut"
+            android:padding="3dip" />
+    </TableRow>
+
+    <TableRow>
+        <View android:id="@+id/reference3"
+            android:layout_height="96dip"
+            android:background="#FF909090" />
+        <TextView
+            android:background="#FF0000FF"
+            android:text="@string/table_layout_open"
+            android:padding="3dip" />
+        <TextView android:id="@+id/cell_bottom"
+            android:background="#FF00FF00"
+            android:layout_gravity="bottom"
+            android:text="@string/table_layout_open_shortcut"
+            android:padding="3dip" />
+    </TableRow>
+
+</TableLayout>
diff --git a/tests/FrameworkTest/res/layout/table_layout_weight.xml b/tests/FrameworkTest/res/layout/table_layout_weight.xml
new file mode 100644
index 0000000..432c04a
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/table_layout_weight.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2008, 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.
+*/
+-->
+
+<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content">
+
+    <TableRow android:id="@+id/row"
+        android:weightSum="0.9">
+        <View android:id="@+id/cell1"
+            android:layout_width="0dip"
+            android:layout_weight="0.3"
+            android:layout_height="190dip"
+            android:background="#FF0000FF" />
+        <View android:id="@+id/cell2"
+            android:layout_width="0dip"
+            android:layout_weight="0.3"
+            android:layout_height="190dip"
+            android:background="#FFFFFFFF" />
+        <View android:id="@+id/cell3"
+            android:layout_width="0dip"
+            android:layout_weight="0.3"
+            android:layout_height="190dip"
+            android:background="#FFFF0000" />
+    </TableRow>
+
+</TableLayout>
diff --git a/tests/FrameworkTest/res/layout/translucent_background.xml b/tests/FrameworkTest/res/layout/translucent_background.xml
new file mode 100644
index 0000000..6b6e1cf
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/translucent_background.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates an activity with a fancy translucent background.
+     See corresponding Java code com.android.sdk.app.TranslucentBackground.java. -->
+
+<!-- This screen consists of a single text field that displays some text. -->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/text"
+    android:layout_width="fill_parent" android:layout_height="fill_parent"
+    android:gravity="center_vertical|center_horizontal"
+    android:text="@string/translucent_background"/>
diff --git a/tests/FrameworkTest/res/layout/viewgroupchildren.xml b/tests/FrameworkTest/res/layout/viewgroupchildren.xml
new file mode 100644
index 0000000..a5bb7cb
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/viewgroupchildren.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<!-- Demonstrates adding/removing views from ViewGroup. See corresponding Java code. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/group"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/viewstub.xml b/tests/FrameworkTest/res/layout/viewstub.xml
new file mode 100644
index 0000000..9a6f376
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/viewstub.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2007, 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:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <Button android:id="@+id/vis"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/visibility_1_vis" />
+
+    <ViewStub android:id="@+id/viewStub"
+        android:layout="@layout/linear_layout_buttons"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <ViewStub android:id="@+id/viewStubWithId"
+        android:inflatedId="@+id/stub_inflated"
+        android:layout="@layout/linear_layout_buttons"
+        android:layout_width="47dip"
+        android:layout_height="127dip" />
+
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/visibility.xml b/tests/FrameworkTest/res/layout/visibility.xml
new file mode 100644
index 0000000..b4f9d8b
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/visibility.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<!-- Demonstrates changing view visibility. See corresponding Java code. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <LinearLayout
+      android:orientation="vertical"
+      android:background="@drawable/box"
+      android:layout_width="fill_parent"
+      android:layout_height="wrap_content">
+
+      <TextView android:id="@+id/refUp"
+          android:background="@drawable/red"
+          android:layout_width="fill_parent"
+          android:layout_height="wrap_content"
+          android:text="@string/visibility_1_view_1"/>
+
+      <TextView android:id="@+id/victim"
+          android:background="@drawable/green"
+          android:layout_width="fill_parent"
+          android:layout_height="wrap_content"
+          android:text="@string/visibility_1_view_2"/>
+
+      <TextView android:id="@+id/refDown"
+          android:background="@drawable/blue"
+          android:layout_width="fill_parent"
+          android:layout_height="wrap_content"
+          android:text="@string/visibility_1_view_3"/>
+
+    </LinearLayout>
+
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content">
+
+        <Button android:id="@+id/vis"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/visibility_1_vis"/>
+
+        <Button android:id="@+id/invis"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/visibility_1_invis"/>
+
+        <Button android:id="@+id/gone"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/visibility_1_gone"/>
+
+    </LinearLayout>
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/weight_sum.xml b/tests/FrameworkTest/res/layout/weight_sum.xml
new file mode 100644
index 0000000..249dc68
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/weight_sum.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2008, 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 android:id="@+id/container" xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:weightSum="1.0"
+    android:gravity="center_horizontal"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <Button android:id="@+id/child"
+        android:layout_width="0dip"
+        android:layout_weight="0.5"
+        android:layout_height="wrap_content"
+        android:text="@string/visibility_1_vis"/>
+
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/with_bitmap_background.xml b/tests/FrameworkTest/res/layout/with_bitmap_background.xml
new file mode 100644
index 0000000..b32d99e
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/with_bitmap_background.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2008, 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 android:id="@+id/container" xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:background="@drawable/bitmap_drawable">
+
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/layout/zero_sized.xml b/tests/FrameworkTest/res/layout/zero_sized.xml
new file mode 100644
index 0000000..c837bf9
--- /dev/null
+++ b/tests/FrameworkTest/res/layout/zero_sized.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<!-- Demonstrates changing view visibility. See corresponding Java code. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <View android:id="@+id/dimension"
+        android:background="#ffff0000"
+        android:layout_width="42dip"
+        android:layout_height="42dip" />
+
+    <View android:id="@+id/noWidth"
+          android:background="#ff00ff00"
+        android:layout_width="0dip"
+        android:layout_height="42dip" />
+
+    <View android:id="@+id/noHeight"
+          android:background="#ff0000ff"
+        android:layout_width="42dip"
+        android:layout_height="0dip" />
+
+    <View android:id="@+id/noDimension"
+        android:background="#ffffffff"
+        android:layout_width="0dip"
+        android:layout_height="0dip" />
+
+</LinearLayout>
diff --git a/tests/FrameworkTest/res/values/arrays.xml b/tests/FrameworkTest/res/values/arrays.xml
new file mode 100644
index 0000000..f76da85
--- /dev/null
+++ b/tests/FrameworkTest/res/values/arrays.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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-array name="reminder_minutes_labels">
+        <item>5 minutes</item>
+        <item>10 minutes</item>
+        <item>15 minutes</item>
+        <item>20 minutes</item>
+        <item>25 minutes</item>
+        <item>30 minutes</item>
+        <item>45 minutes</item>
+        <item>1 hour</item>
+        <item>2 hours</item>
+        <item>3 hours</item>
+        <item>12 hours</item>
+        <item>24 hours</item>
+        <item>2 days</item>
+        <item>1 week</item>
+    </string-array>
+</resources>
diff --git a/tests/FrameworkTest/res/values/attrs.xml b/tests/FrameworkTest/res/values/attrs.xml
new file mode 100644
index 0000000..bf59e74
--- /dev/null
+++ b/tests/FrameworkTest/res/values/attrs.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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>
+     <declare-styleable name="SelectableRowView">
+        <attr name="numRows" format="integer" />
+    </declare-styleable>
+</resources>
diff --git a/tests/FrameworkTest/res/values/colors.xml b/tests/FrameworkTest/res/values/colors.xml
new file mode 100644
index 0000000..f881660
--- /dev/null
+++ b/tests/FrameworkTest/res/values/colors.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/samples/SampleCode/res/values/colors.xml
+**
+** Copyright 2007, 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>
+    <drawable name="red">#ffff0000</drawable>
+    <drawable name="blue">#ff0000ff</drawable>
+    <drawable name="green">#ff00ff00</drawable>
+    <drawable name="yellow">#ffffff00</drawable>
+</resources>
diff --git a/tests/FrameworkTest/res/values/strings.xml b/tests/FrameworkTest/res/values/strings.xml
new file mode 100644
index 0000000..05b57e0
--- /dev/null
+++ b/tests/FrameworkTest/res/values/strings.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">FrameworkTestApplication</string>
+
+    <!-- FocusAfterRemoval -->
+    <string name="left_top">parent GONE</string>
+    <string name="left_bottom">parent INVISIBLE</string>
+    <string name="right_top">me GONE</string>
+    <string name="right_bottom">me INVISIBLE</string>
+
+    <!-- Strings for the 12 key dialer -->
+    <string name="keypad_one">1</string>
+    <string name="keypad_two">"2\nabc"</string>
+    <string name="keypad_three">"3\ndef"</string>
+    <string name="keypad_four">"4\nghi"</string>
+    <string name="keypad_five">"5\njkl"</string>
+    <string name="keypad_six">"6\nmno"</string>
+    <string name="keypad_seven">"7\npqrs"</string>
+    <string name="keypad_eight">"8\ntuv"</string>
+    <string name="keypad_nine">"9\nwxyz"</string>
+    <string name="keypad_zero">0</string>
+    <string name="keypad_star">*</string>
+    <string name="keypad_pound">"#"</string>
+    
+
+    <!-- HorizontalGravity -->
+    <string name="table_layout_open">Open\u2026</string>
+    <string name="table_layout_open_shortcut">Ctrl-O</string>
+    <string name="table_layout_save_as">Save As\u2026</string>
+    <string name="table_layout_save_as_shortcut">Ctrl-Shift-S</string>
+    <string name="table_layout_export">Export\u2026</string>
+    <string name="table_layout_export_shortcut">Ctrl-E</string>
+
+    <!-- CellSpan -->
+    <string name="table_layout_a">A</string>
+    <string name="table_layout_b">BB</string>
+    <string name="table_layout_c">CCCC</string>
+    <string name="table_layout_d">D</string>
+    <string name="table_layout_e">E</string>
+    <string name="table_layout_f">F</string>
+    <string name="table_layout_g">G</string>
+    <string name="table_layout_h">H</string>
+    
+    <!-- scroll_to_rectangle -->
+    <string name="scroll_top_button">Click to make "hi!" on screen</string>
+    <string name="scroll_top_button2">Click to make blob on screen</string>
+    <string name="scroll_to_me">hi!</string>
+    <string name="scroll_bottom_button2">Click to make blob on screen</string>
+    <string name="scroll_bottom_button">Click to make "hi!" on screen</string>
+
+    <!-- Visibility -->
+    <string name="visibility_1_view_1">View A</string>
+    <string name="visibility_1_view_2">View B</string>
+    <string name="visibility_1_view_3">View C</string>
+    <string name="visibility_1_vis">Visible</string>
+    <string name="visibility_1_invis">Invisible</string>
+    <string name="visibility_1_gone">Gone</string>
+
+    <string name="submit">submit</string>
+    <string name="cancel">cancel</string>
+    <string name="enter_title">enter title</string>
+    <string name="enter_url">enter url</string>
+
+    <!-- List with button above -->
+    <string name="button_above_list_label">Button above list</string>
+    
+    <!-- List take focus from side -->
+    <string name="side_button_label">X</string>
+    
+    <!-- Linear Layout show/hide & sizing -->
+    <string name="linear_listheight_fixed">Fixed Size</string>
+    <string name="linear_listheight_fill">Fill Screen</string>
+    <string name="linear_listheight_hide">Hide</string>
+
+    <!-- Baseline -->
+    <string name="show">Show</string>
+    <string name="time">00:00:00</string>
+    
+    <!-- Drawable -->
+    <string name="minimal_text">a</string>
+    <string name="change_backgrounds">Change backgrounds</string>
+
+    <!-- List with empty view -->
+    <string name="empty_list">Empty list</string>
+    <string name="menu_add">Add</string>
+    <string name="menu_remove">Remove</string>
+
+    <!-- Misc. -->
+    <string name="add_row_button">Add Row</string>
+    <string name="disabled_button">Disabled</string>
+    <string name="translucent_background">Example of how you can make an
+            activity have a translucent background, compositing over
+            whatever is behind it.</string>
+    <string name="text">Lorem ipsum datum carat casus belli honorare</string>
+    
+	<string name="hide">Hide</string>
+    <string name="go">Go</string>
+
+    <string name="include_label">Included views below:</string>
+    <string name="include_button">I was included!</string>
+
+    <string name="view">View</string>
+</resources>
diff --git a/tests/FrameworkTest/res/values/styles.xml b/tests/FrameworkTest/res/values/styles.xml
new file mode 100644
index 0000000..7a90197
--- /dev/null
+++ b/tests/FrameworkTest/res/values/styles.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<resources>
+    <style name="Theme" parent="android:Theme">
+        <item name="android:windowAnimationStyle">@style/Animation</item>
+    </style>
+
+    <style name="Animation">
+        <item name="android:activityOpenEnterAnimation">@null</item>
+        <item name="android:activityOpenExitAnimation">@null</item>
+        <item name="android:activityCloseEnterAnimation">@null</item>
+        <item name="android:activityCloseExitAnimation">@null</item>
+        <item name="android:taskOpenEnterAnimation">@null</item>
+        <item name="android:taskOpenExitAnimation">@null</item>
+        <item name="android:taskCloseEnterAnimation">@null</item>
+        <item name="android:taskCloseExitAnimation">@null</item>
+        <item name="android:taskToFrontEnterAnimation">@null</item>
+        <item name="android:taskToFrontExitAnimation">@null</item>
+        <item name="android:taskToBackEnterAnimation">@null</item>
+        <item name="android:taskToBackExitAnimation">@null</item>
+    </style>
+</resources>
diff --git a/tests/FrameworkTest/src/android/widget/AutoCompleteTextViewSimple.java b/tests/FrameworkTest/src/android/widget/AutoCompleteTextViewSimple.java
new file mode 100644
index 0000000..af16cf8
--- /dev/null
+++ b/tests/FrameworkTest/src/android/widget/AutoCompleteTextViewSimple.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2008 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.widget;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.AdapterView.OnItemSelectedListener;
+
+public class AutoCompleteTextViewSimple extends Activity 
+        implements OnItemClickListener, OnItemSelectedListener {
+
+    private final String LOG_TAG = "AutoCompleteTextViewSimple";
+    
+    private AutoCompleteTextView mTextView;
+    
+    /** These are cleared by resetItemListeners(), and set by the callback listeners */
+    public boolean mItemClickCalled;
+    public int mItemClickPosition;
+    public boolean mItemSelectedCalled;
+    public int mItemSelectedPosition;
+    public boolean mNothingSelectedCalled;
+
+    @Override
+    protected void onCreate(Bundle icicle)
+    {
+        // Be sure to call the super class.
+        super.onCreate(icicle);
+
+        // setup layout & views
+        setContentView(R.layout.autocompletetextview_simple);
+        mTextView = (AutoCompleteTextView) findViewById(R.id.autocompletetextview1);
+        
+        // configure callbacks used for monitoring
+        mTextView.setOnItemClickListener(this);
+        mTextView.setOnItemSelectedListener(this);
+        resetItemListeners();
+        
+        setStringAdapter(5, "a");
+    }
+
+    /**
+     * @return The AutoCompleteTextView used in this test activity.
+     */
+    public AutoCompleteTextView getTextView() {
+        return mTextView;
+    }
+
+    /**
+     * Set the autocomplete data to an adapter containing 0..n strings with a consistent prefix.
+     */
+    public void setStringAdapter(int numSuggestions, String prefix) {
+        // generate the string array
+        String[] strings = new String[numSuggestions];
+        for (int i = 0; i < numSuggestions; ++i) {
+            strings[i] = prefix + String.valueOf(i);
+        }
+        
+        // install it with an adapter
+        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
+                android.R.layout.simple_dropdown_item_1line, strings);
+        mTextView.setAdapter(adapter);
+    }
+    
+    /**
+     * For monitoring OnItemClickListener & OnItemSelectedListener
+     * 
+     * An alternative here would be to provide a set of pass-through callbacks
+     */
+    public void resetItemListeners() {
+        mItemClickCalled = false;
+        mItemClickPosition = -1;
+        mItemSelectedCalled = false;
+        mItemSelectedPosition = -1;
+        mNothingSelectedCalled = false;
+    }
+    
+    /**
+     * Implements OnItemClickListener
+     */
+    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+        Log.d(LOG_TAG, "onItemClick() position " + position);
+        mItemClickCalled = true;
+        mItemClickPosition = position;
+    }
+
+    /** 
+     * Implements OnItemSelectedListener
+     */
+    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+        Log.d(LOG_TAG, "onItemSelected() position " + position);
+        mItemSelectedCalled = true;
+        mItemSelectedPosition = position;
+    }
+
+    /** 
+     * Implements OnItemSelectedListener
+     */
+    public void onNothingSelected(AdapterView<?> parent) {
+        Log.d(LOG_TAG, "onNothingSelected()");
+        mNothingSelectedCalled = true;
+    }
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/FrameworkTestApplication.java b/tests/FrameworkTest/src/com/android/frameworktest/FrameworkTestApplication.java
new file mode 100644
index 0000000..e76f387
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/FrameworkTestApplication.java
@@ -0,0 +1,19 @@
+package com.android.frameworktest;
+
+import android.app.LauncherActivity;
+import android.content.Intent;
+
+/**
+ * Holds little snippets of functionality used as code under test for
+ * instrumentation tests of framework code.
+ */
+public class FrameworkTestApplication extends LauncherActivity {
+
+    protected Intent getTargetIntent() {
+        // TODO: partition into categories by label like the sample code app
+        Intent targetIntent = new Intent(Intent.ACTION_MAIN, null);
+        targetIntent.addCategory(Intent.CATEGORY_FRAMEWORK_INSTRUMENTATION_TEST);
+        targetIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        return targetIntent;
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/activity/TranslucentFancyActivity.java b/tests/FrameworkTest/src/com/android/frameworktest/activity/TranslucentFancyActivity.java
new file mode 100644
index 0000000..9492f91
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/activity/TranslucentFancyActivity.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.activity;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.WindowManager;
+
+
+/**
+ * <h3>Fancy Translucent Activity</h3>
+ * 
+ * <p>This demonstrates the how to write an activity that is translucent,
+ * allowing windows underneath to show through, with a fancy
+ * compositing effect.</p>
+ * 
+ * <h4>Demo</h4>
+ * App/Activity/Translucent Fancy
+ * 
+ * <h4>Source files</h4>
+ * <table class="LinkTable">
+ *         <tr>
+ *             <td >src/com/android/samples/app/TranslucentFancyActivity.java</td>
+ *             <td >The Translucent Fancy Screen implementation</td>
+ *         </tr>
+ *         <tr>
+ *             <td >/res/any/layout/translucent_background.xml</td>
+ *             <td >Defines contents of the screen</td>
+ *         </tr>
+ * </table> 
+ */
+public class TranslucentFancyActivity extends Activity
+{
+    /**
+     * Initialization of the Activity after it is first created.  Must at least
+     * call {@link android.app.Activity#setContentView setContentView()} to
+     * describe what is to be displayed in the screen.
+     */
+    @Override
+	protected void onCreate(Bundle icicle)
+    {
+        // Be sure to call the super class.
+        super.onCreate(icicle);
+
+        // Have the system blur any windows behind this one.
+        getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
+                WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
+        
+        // See assets/res/any/layout/translucent_background.xml for this
+        // view layout definition, which is being set here as
+        // the content of our screen.
+        setContentView(R.layout.translucent_background);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/drawable/BitmapDrawable.java b/tests/FrameworkTest/src/com/android/frameworktest/drawable/BitmapDrawable.java
new file mode 100644
index 0000000..e88ebf9
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/drawable/BitmapDrawable.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.drawable;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.AbsoluteLayout;
+import android.widget.Button;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+public class BitmapDrawable extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        setContentView(R.layout.with_bitmap_background);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/drawable/DrawableBgMinSize.java b/tests/FrameworkTest/src/com/android/frameworktest/drawable/DrawableBgMinSize.java
new file mode 100644
index 0000000..a382995
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/drawable/DrawableBgMinSize.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.drawable;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.AbsoluteLayout;
+import android.widget.Button;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+/**
+ * Views should obey their background {@link Drawable}'s minimum size
+ * requirements ({@link Drawable#getMinimumHeight()} and
+ * {@link Drawable#getMinimumWidth()}) when possible.
+ * <p>
+ * This Activity exercises a few Views with background {@link Drawable}s. 
+ */
+public class DrawableBgMinSize extends Activity implements OnClickListener {
+    private boolean mUsingBigBg = false;
+    private Drawable mBackgroundDrawable;
+    private Drawable mBigBackgroundDrawable;
+    private Button mChangeBackgroundsButton;
+    
+    private TextView mTextView;
+    private LinearLayout mLinearLayout;
+    private RelativeLayout mRelativeLayout;
+    private FrameLayout mFrameLayout;
+    private AbsoluteLayout mAbsoluteLayout;
+    
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        
+        setContentView(R.layout.drawable_background_minimum_size);
+        
+        mBackgroundDrawable = getResources().getDrawable(R.drawable.drawable_background);
+        mBigBackgroundDrawable = getResources().getDrawable(R.drawable.big_drawable_background);
+ 
+        mChangeBackgroundsButton = (Button) findViewById(R.id.change_backgrounds);
+        mChangeBackgroundsButton.setOnClickListener(this);
+        
+        mTextView = (TextView) findViewById(R.id.text_view);
+        mLinearLayout = (LinearLayout) findViewById(R.id.linear_layout);
+        mRelativeLayout = (RelativeLayout) findViewById(R.id.relative_layout);
+        mFrameLayout = (FrameLayout) findViewById(R.id.frame_layout);
+        mAbsoluteLayout = (AbsoluteLayout) findViewById(R.id.absolute_layout);
+
+        changeBackgrounds(mBackgroundDrawable);
+    }
+
+    private void changeBackgrounds(Drawable newBg) {
+        mTextView.setBackgroundDrawable(newBg);
+        mLinearLayout.setBackgroundDrawable(newBg);
+        mRelativeLayout.setBackgroundDrawable(newBg);
+        mFrameLayout.setBackgroundDrawable(newBg);
+        mAbsoluteLayout.setBackgroundDrawable(newBg);
+    }
+    
+    public void onClick(View v) {
+        if (mUsingBigBg) {
+            changeBackgrounds(mBackgroundDrawable);
+        } else {
+            changeBackgrounds(mBigBackgroundDrawable);
+        }
+        
+        mUsingBigBg = !mUsingBigBg;
+    }
+    
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/drawable/MutateDrawable.java b/tests/FrameworkTest/src/com/android/frameworktest/drawable/MutateDrawable.java
new file mode 100644
index 0000000..2fcaea3
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/drawable/MutateDrawable.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.frameworktest.drawable;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.LinearLayout;
+import android.widget.Button;
+import com.android.frameworktest.R;
+
+public class MutateDrawable extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        LinearLayout layout = new LinearLayout(this);
+
+        Button ok = new Button(this);
+        ok.setId(R.id.a);
+        ok.setBackgroundDrawable(getResources().getDrawable(
+                R.drawable.sym_now_playing_skip_forward_1));
+
+        Button cancel = new Button(this);
+        cancel.setId(R.id.b);
+        cancel.setBackgroundDrawable(getResources().getDrawable(
+                R.drawable.sym_now_playing_skip_forward_1));
+
+        layout.addView(ok);
+        layout.addView(cancel);
+
+        ok.getBackground().mutate().setAlpha(127);
+
+        setContentView(layout);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/expandablelistview/ExpandableListSimple.java b/tests/FrameworkTest/src/com/android/frameworktest/expandablelistview/ExpandableListSimple.java
new file mode 100644
index 0000000..cee1d4d
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/expandablelistview/ExpandableListSimple.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.expandablelistview;
+
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MenuItem.OnMenuItemClickListener;
+import android.widget.BaseExpandableListAdapter;
+
+import com.android.frameworktest.util.ExpandableListScenario;
+
+public class ExpandableListSimple extends ExpandableListScenario {
+    private static final int[] NUM_CHILDREN = {4, 3, 2, 1, 0};
+
+    @Override
+    protected void init(ExpandableParams params) {
+        params.setNumChildren(NUM_CHILDREN)
+                .setItemScreenSizeFactor(0.14);
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+
+        menu.add("Add item").setOnMenuItemClickListener(new OnMenuItemClickListener() {
+            public boolean onMenuItemClick(MenuItem item) {
+                mGroups.add(0, new MyGroup(2));
+                ((BaseExpandableListAdapter) mAdapter).notifyDataSetChanged();
+                return true;
+            }
+        });
+        
+        return true;
+    }
+    
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/expandablelistview/ExpandableListWithHeaders.java b/tests/FrameworkTest/src/com/android/frameworktest/expandablelistview/ExpandableListWithHeaders.java
new file mode 100644
index 0000000..0155f09
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/expandablelistview/ExpandableListWithHeaders.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.expandablelistview;
+
+import com.android.frameworktest.util.ExpandableListScenario;
+
+import android.os.Bundle;
+import android.widget.Button;
+import android.widget.ExpandableListView;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+
+public class ExpandableListWithHeaders extends ExpandableListScenario {
+    private static final int[] sNumChildren = {1, 4, 3, 2, 6};
+    private static final int sNumOfHeadersAndFooters = 12;
+    
+    @Override
+    protected void init(ExpandableParams params) {
+        params.setStackFromBottom(false)
+                .setStartingSelectionPosition(-1)
+                .setNumChildren(sNumChildren)
+                .setItemScreenSizeFactor(0.14)
+                .setConnectAdapter(false);
+    }
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        final ExpandableListView expandableListView = getExpandableListView();
+        expandableListView.setItemsCanFocus(true);
+
+        for (int i = 0; i < sNumOfHeadersAndFooters; i++) {
+            Button header = new Button(this);
+            header.setText("Header View");
+            expandableListView.addHeaderView(header);
+        }
+
+        for (int i = 0; i < sNumOfHeadersAndFooters; i++) {
+            Button footer = new Button(this);
+            footer.setText("Footer View");
+            expandableListView.addFooterView(footer);
+        }
+        
+        // Set adapter here AFTER we set header and footer views
+        setAdapter(expandableListView);
+    }
+    
+    /**
+     * @return The number of headers (and the same number of footers)
+     */
+    public int getNumOfHeadersAndFooters() {
+        return sNumOfHeadersAndFooters;
+    }
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/expandablelistview/InflatedExpandableListView.java b/tests/FrameworkTest/src/com/android/frameworktest/expandablelistview/InflatedExpandableListView.java
new file mode 100644
index 0000000..f1089a1
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/expandablelistview/InflatedExpandableListView.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.expandablelistview;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.BaseExpandableListAdapter;
+import android.widget.ExpandableListView;
+import android.widget.TextView;
+
+public class InflatedExpandableListView extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        
+        setContentView(R.layout.inflated_expandablelistview);
+        
+        ExpandableListView elv = (ExpandableListView) findViewById(R.id.elv);
+        elv.setAdapter(new MyExpandableListAdapter());
+    }
+
+    public class MyExpandableListAdapter extends BaseExpandableListAdapter {
+        // Sample data set.  children[i] contains the children (String[]) for groups[i].
+        private String[] groups = { "People Names", "Dog Names", "Cat Names", "Fish Names" };
+        private String[][] children = {
+                { "Arnold", "Barry", "Chuck", "David" },
+                { "Ace", "Bandit", "Cha-Cha", "Deuce" },
+                { "Fluffy", "Snuggles" },
+                { "Goldy", "Bubbles" }
+        };
+        
+        public Object getChild(int groupPosition, int childPosition) {
+            return children[groupPosition][childPosition];
+        }
+
+        public long getChildId(int groupPosition, int childPosition) {
+            return childPosition;
+        }
+
+        public int getChildrenCount(int groupPosition) {
+            return children[groupPosition].length;
+        }
+
+        public TextView getGenericView() {
+            // Layout parameters for the ExpandableListView
+            AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
+                    ViewGroup.LayoutParams.FILL_PARENT, 64);
+
+            TextView textView = new TextView(InflatedExpandableListView.this);
+            textView.setLayoutParams(lp);
+            // Center the text vertically
+            textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
+            // Set the text starting position
+            textView.setPadding(36, 0, 0, 0);
+            return textView;
+        }
+        
+        public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
+                View convertView, ViewGroup parent) {
+            TextView textView = getGenericView();
+            textView.setText(getChild(groupPosition, childPosition).toString());
+            return textView;
+        }
+
+        public Object getGroup(int groupPosition) {
+            return groups[groupPosition];
+        }
+
+        public int getGroupCount() {
+            return groups.length;
+        }
+
+        public long getGroupId(int groupPosition) {
+            return groupPosition;
+        }
+
+        public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
+                ViewGroup parent) {
+            TextView textView = getGenericView();
+            textView.setText(getGroup(groupPosition).toString());
+            return textView;
+        }
+
+        public boolean isChildSelectable(int groupPosition, int childPosition) {
+            return true;
+        }
+
+        public boolean hasStableIds() {
+            return true;
+        }
+
+    }
+    
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/focus/AdjacentVerticalRectLists.java b/tests/FrameworkTest/src/com/android/frameworktest/focus/AdjacentVerticalRectLists.java
new file mode 100644
index 0000000..c4e2705
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/focus/AdjacentVerticalRectLists.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.focus;
+
+import com.android.frameworktest.util.InternalSelectionView;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.LinearLayout;
+import android.view.ViewGroup;
+
+/**
+ * {@link android.view.FocusFinder#findNextFocus(android.view.ViewGroup, android.view.View, int)}
+ * and
+ * {@link android.view.View#requestFocus(int, android.graphics.Rect)}
+ * work together to give a newly focused item a hint about the most interesting
+ * rectangle of the previously focused view.  The view taking focus can use this
+ * to set an internal selection more appropriate using this rect.
+ *
+ * This Activity excercises that behavior using three adjacent {@link com.android.frameworktest.util.InternalSelectionView}
+ * that report interesting rects when giving up focus, and use interesting rects
+ * when taking focus to best select the internal row to show as selected.
+ */
+public class AdjacentVerticalRectLists extends Activity {
+
+    private LinearLayout mLayout;
+    private InternalSelectionView mLeftColumn;
+    private InternalSelectionView mMiddleColumn;
+    private InternalSelectionView mRightColumn;
+
+
+    public LinearLayout getLayout() {
+        return mLayout;
+    }
+
+    public InternalSelectionView getLeftColumn() {
+        return mLeftColumn;
+    }
+
+    public InternalSelectionView getMiddleColumn() {
+        return mMiddleColumn;
+    }
+
+    public InternalSelectionView getRightColumn() {
+        return mRightColumn;
+    }
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        mLayout = new LinearLayout(this);
+        mLayout.setOrientation(LinearLayout.HORIZONTAL);
+        mLayout.setLayoutParams(new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT,
+                ViewGroup.LayoutParams.FILL_PARENT));
+
+        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0,
+                ViewGroup.LayoutParams.FILL_PARENT, 1);
+
+        mLeftColumn = new InternalSelectionView(this, 5, "left column");
+        mLeftColumn.setLayoutParams(params);
+        mLeftColumn.setPadding(10, 10, 10, 10);
+        mLayout.addView(mLeftColumn);
+
+        mMiddleColumn = new InternalSelectionView(this, 5, "middle column");
+        mMiddleColumn.setLayoutParams(params);
+        mMiddleColumn.setPadding(10, 10, 10, 10);
+        mLayout.addView(mMiddleColumn);
+
+        mRightColumn = new InternalSelectionView(this, 5, "right column");
+        mRightColumn.setLayoutParams(params);
+        mRightColumn.setPadding(10, 10, 10, 10);
+        mLayout.addView(mRightColumn);
+
+        setContentView(mLayout);
+    }
+
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/focus/DescendantFocusability.java b/tests/FrameworkTest/src/com/android/frameworktest/focus/DescendantFocusability.java
new file mode 100644
index 0000000..f0c1980
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/focus/DescendantFocusability.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.focus;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+public class DescendantFocusability extends Activity {
+
+    public ViewGroup beforeDescendants;
+    public Button beforeDescendantsChild;
+
+    public ViewGroup afterDescendants;
+    public Button afterDescendantsChild;
+
+    public ViewGroup blocksDescendants;
+    public Button blocksDescendantsChild;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.descendant_focusability);
+
+        beforeDescendants = (ViewGroup) findViewById(R.id.beforeDescendants);
+        beforeDescendantsChild = (Button) beforeDescendants.getChildAt(0);
+
+        afterDescendants = (ViewGroup) findViewById(R.id.afterDescendants);
+        afterDescendantsChild = (Button) afterDescendants.getChildAt(0);
+
+        blocksDescendants = (ViewGroup) findViewById(R.id.blocksDescendants);
+        blocksDescendantsChild = (Button) blocksDescendants.getChildAt(0);
+    }
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/focus/FocusAfterRemoval.java b/tests/FrameworkTest/src/com/android/frameworktest/focus/FocusAfterRemoval.java
new file mode 100644
index 0000000..6c5f1c4
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/focus/FocusAfterRemoval.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.focus;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.LinearLayout;
+import android.widget.Button;
+import android.view.View;
+
+/**
+ * Exercises cases where elements of the UI are removed (and
+ * focus should go somewhere).
+ */
+public class FocusAfterRemoval extends Activity {
+
+
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.focus_after_removal);
+
+        final LinearLayout left = (LinearLayout) findViewById(R.id.leftLayout);
+
+        // top left makes parent layout GONE
+        Button topLeftButton = (Button) findViewById(R.id.topLeftButton);
+        topLeftButton.setOnClickListener(new View.OnClickListener() {
+
+            public void onClick(View v) {
+                left.setVisibility(View.GONE);
+            }
+        });
+
+        // bottom left makes parent layout INVISIBLE
+        // top left makes parent layout GONE
+        Button bottomLeftButton = (Button) findViewById(R.id.bottomLeftButton);
+        bottomLeftButton.setOnClickListener(new View.OnClickListener() {
+
+            public void onClick(View v) {
+                left.setVisibility(View.INVISIBLE);
+            }
+        });
+
+        // top right button makes top right button GONE
+        final Button topRightButton = (Button) findViewById(R.id.topRightButton);
+        topRightButton.setOnClickListener(new View.OnClickListener() {
+
+            public void onClick(View v) {
+                topRightButton.setVisibility(View.GONE);
+            }
+        });
+
+        // bottom right button makes bottom right button INVISIBLE
+        final Button bottomRightButton = (Button) findViewById(R.id.bottomRightButton);
+        bottomRightButton.setOnClickListener(new View.OnClickListener() {
+
+            public void onClick(View v) {
+                bottomRightButton.setVisibility(View.INVISIBLE);
+            }
+        });
+
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/focus/GoneParentFocusedChild.java b/tests/FrameworkTest/src/com/android/frameworktest/focus/GoneParentFocusedChild.java
new file mode 100644
index 0000000..91bd7b4
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/focus/GoneParentFocusedChild.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.focus;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.LinearLayout;
+
+/**
+ * An activity that helps test the scenario where a parent is
+ * GONE and one of its children has focus; the activity should get
+ * the key event.  see bug 945150. 
+ */
+public class GoneParentFocusedChild extends Activity {
+    private LinearLayout mGoneGroup;
+    private Button mButton;
+
+    private boolean mUnhandledKeyEvent = false;
+    private LinearLayout mLayout;
+
+    public boolean isUnhandledKeyEvent() {
+        return mUnhandledKeyEvent;
+    }
+
+    public LinearLayout getLayout() {
+        return mLayout;
+    }
+
+    public LinearLayout getGoneGroup() {
+        return mGoneGroup;
+    }
+
+    public Button getButton() {
+        return mButton;
+    }
+
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        mLayout = new LinearLayout(this);
+        mLayout.setOrientation(LinearLayout.HORIZONTAL);
+        mLayout.setLayoutParams(new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT,
+                ViewGroup.LayoutParams.FILL_PARENT));
+
+
+        mGoneGroup = new LinearLayout(this);
+        mGoneGroup.setOrientation(LinearLayout.HORIZONTAL);
+        mGoneGroup.setLayoutParams(new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT,
+                ViewGroup.LayoutParams.FILL_PARENT));
+
+        mButton = new Button(this);
+        mButton.setLayoutParams(new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.WRAP_CONTENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT));
+
+
+        mGoneGroup.addView(mButton);
+        setContentView(mLayout);
+
+        mGoneGroup.setVisibility(View.GONE);
+        mButton.requestFocus();
+    }
+
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        mUnhandledKeyEvent = true;
+        return true;
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/focus/HorizontalFocusSearch.java b/tests/FrameworkTest/src/com/android/frameworktest/focus/HorizontalFocusSearch.java
new file mode 100644
index 0000000..01a9821
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/focus/HorizontalFocusSearch.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.focus;
+
+import android.app.Activity;
+import android.widget.LinearLayout;
+import android.widget.Button;
+import android.widget.TextView;
+import android.os.Bundle;
+import android.view.ViewGroup;
+import android.content.Context;
+
+public class HorizontalFocusSearch extends Activity {
+
+    private LinearLayout mLayout;
+
+    private Button mLeftTall;
+    private Button mMidShort1Top;
+    private Button mMidShort2Bottom;
+    private Button mRightTall;
+
+
+    public LinearLayout getLayout() {
+        return mLayout;
+    }
+
+    public Button getLeftTall() {
+        return mLeftTall;
+    }
+
+    public Button getMidShort1Top() {
+        return mMidShort1Top;
+    }
+
+    public Button getMidShort2Bottom() {
+        return mMidShort2Bottom;
+    }
+
+    public Button getRightTall() {
+        return mRightTall;
+    }
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        mLayout = new LinearLayout(this);
+        mLayout.setOrientation(LinearLayout.HORIZONTAL);
+        mLayout.setLayoutParams(new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT,
+                ViewGroup.LayoutParams.FILL_PARENT));
+
+        mLeftTall = makeTall("left tall");
+        mLayout.addView(mLeftTall);
+
+        mMidShort1Top = addShort(mLayout, "mid(1) top", false);
+        mMidShort2Bottom = addShort(mLayout, "mid(2) bottom", true);
+
+        mRightTall = makeTall("right tall");
+        mLayout.addView(mRightTall);
+
+        setContentView(mLayout);
+    }
+
+    // just to get toString non-sucky
+    private static class MyButton extends Button {
+
+        public MyButton(Context context) {
+            super(context);
+        }
+
+
+        @Override
+        public String toString() {
+            return getText().toString();
+        }
+    }
+
+    private Button makeTall(String label) {
+        Button button = new MyButton(this);
+        button.setText(label);
+        button.setLayoutParams(new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.WRAP_CONTENT,
+                ViewGroup.LayoutParams.FILL_PARENT));
+        return button;
+    }
+
+    private Button addShort(LinearLayout root, String label, boolean atBottom) {
+        Button button = new MyButton(this);
+        button.setText(label);
+        button.setLayoutParams(new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.WRAP_CONTENT,
+                0, // height
+                490));
+
+        TextView filler = new TextView(this);
+        filler.setText("filler");
+        filler.setLayoutParams(new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.WRAP_CONTENT,
+                0, // height
+                510));
+
+        LinearLayout ll = new LinearLayout(this);
+        ll.setOrientation(LinearLayout.VERTICAL);
+        ll.setLayoutParams(new LinearLayout.LayoutParams(
+            ViewGroup.LayoutParams.WRAP_CONTENT,
+            ViewGroup.LayoutParams.FILL_PARENT));
+
+        if (atBottom) {
+            ll.addView(filler);
+            ll.addView(button);
+            root.addView(ll);
+        } else {
+            ll.addView(button);
+            ll.addView(filler);
+            root.addView(ll);
+        }
+        return button;
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/focus/LinearLayoutGrid.java b/tests/FrameworkTest/src/com/android/frameworktest/focus/LinearLayoutGrid.java
new file mode 100644
index 0000000..9aec0d5
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/focus/LinearLayoutGrid.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.focus;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import com.android.frameworktest.R;
+
+public class LinearLayoutGrid extends Activity {
+
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.linear_layout_grid);
+    }
+
+    public ViewGroup getRootView() {
+        return (ViewGroup) findViewById(R.id.layout);
+    }
+
+    public Button getButtonAt(int column, int row) {
+        if (row < 0 || row > 2) {
+            throw new IllegalArgumentException("row out of range");
+        }
+        if (column < 0 || column > 2) {
+            throw new IllegalArgumentException("column out of range");
+        }
+        return (Button) getColumn(column).getChildAt(row);
+    }
+
+
+
+    private LinearLayout getColumn(int column) {
+        switch (column) {
+            case 0:
+                return (LinearLayout) findViewById(R.id.column1);
+            case 1:
+                return (LinearLayout) findViewById(R.id.column2);
+            case 2:
+                return (LinearLayout) findViewById(R.id.column3);
+            default:
+                throw new IllegalArgumentException("column out of range");
+        }
+    }
+
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/focus/ListOfButtons.java b/tests/FrameworkTest/src/com/android/frameworktest/focus/ListOfButtons.java
new file mode 100644
index 0000000..0abcebb
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/focus/ListOfButtons.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.focus;
+
+import com.android.frameworktest.R;
+
+import android.app.ListActivity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+
+/**
+ * A layout with a ListView containing buttons.
+ */
+public class ListOfButtons extends ListActivity {
+
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        setContentView(R.layout.list_with_button_above);
+        getListView().setItemsCanFocus(true);
+        setListAdapter(new MyAdapter(this, mLabels));
+    }
+
+    String[] mLabels = {
+            "Alabama", "Alaska", "Arizona", "apple sauce!",
+            "California", "Colorado", "Connecticut", "Delaware"
+    };
+
+
+    public String[] getLabels() {
+        return mLabels;
+    }
+
+    public static class MyAdapter extends ArrayAdapter<String> {
+
+
+        public MyAdapter(Context context, String[] labels) {
+            super(context, 0, labels);
+        }
+
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            String label = getItem(position);
+
+            Button button = new Button(parent.getContext());
+            button.setText(label);
+            return button;
+        }
+
+        @Override
+        public boolean areAllItemsEnabled() {
+            return false;
+        }
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/focus/ListOfEditTexts.java b/tests/FrameworkTest/src/com/android/frameworktest/focus/ListOfEditTexts.java
new file mode 100644
index 0000000..f59e2b7
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/focus/ListOfEditTexts.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.focus;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.*;
+import com.google.android.collect.Lists;
+
+import java.util.List;
+
+public class ListOfEditTexts extends Activity {
+
+    private int mLinesPerEditText = 12;
+
+    private ListView mListView;
+    private LinearLayout mLinearLayout;
+
+    public ListView getListView() {
+        return mListView;
+    }
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        // create linear layout
+        mLinearLayout = new LinearLayout(this);
+        mLinearLayout.setOrientation(LinearLayout.VERTICAL);
+        mLinearLayout.setLayoutParams(new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT,
+                ViewGroup.LayoutParams.FILL_PARENT));
+
+        // add a button above
+        Button buttonAbove = new Button(this);
+        buttonAbove.setLayoutParams(
+                new LinearLayout.LayoutParams(
+                        ViewGroup.LayoutParams.FILL_PARENT,
+                        ViewGroup.LayoutParams.WRAP_CONTENT));
+        buttonAbove.setText("button above list");
+        mLinearLayout.addView(buttonAbove);
+
+        // add a list view to it
+        mListView = new ListView(this);
+        mListView.setLayoutParams(new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT,
+                ViewGroup.LayoutParams.FILL_PARENT));
+        mListView.setDrawSelectorOnTop(false);
+        mListView.setItemsCanFocus(true);
+        mListView.setLayoutParams((new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT,
+                0,
+                1f)));
+
+        List<String> bodies = Lists.newArrayList(
+                getBody("zero hello, my name is android"),
+                getBody("one i'm a paranoid android"),
+                getBody("two i robot.  huh huh."),
+                getBody("three not the g-phone!"));
+
+        mListView.setAdapter(new MyAdapter(this, bodies));
+        mLinearLayout.addView(mListView);
+
+        // add button below
+        Button buttonBelow = new Button(this);
+        buttonBelow.setLayoutParams(
+                new LinearLayout.LayoutParams(
+                        ViewGroup.LayoutParams.FILL_PARENT,
+                        ViewGroup.LayoutParams.WRAP_CONTENT));
+        buttonBelow.setText("button below list");
+        mLinearLayout.addView(buttonBelow);
+        
+        setContentView(mLinearLayout);
+    }
+
+    String getBody(String line) {
+        StringBuilder sb = new StringBuilder((line.length() + 5) * mLinesPerEditText);
+        for (int i = 0; i < mLinesPerEditText; i++) {
+            sb.append(i + 1).append(' ').append(line);
+            if (i < mLinesPerEditText - 1) {
+                sb.append('\n'); // all but last line
+            }
+        }
+        return sb.toString();
+    }
+
+
+    private static class MyAdapter extends ArrayAdapter<String> {
+
+        public MyAdapter(Context context, List<String> bodies) {
+            super(context, 0, bodies);
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            String body = getItem(position);
+
+            if (convertView != null) {
+                ((EditText) convertView).setText(body);
+                return convertView;                
+            }
+
+            EditText editText = new EditText(getContext());
+            editText.setText(body);
+            return editText;
+        }
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/focus/ListOfInternalSelectionViews.java b/tests/FrameworkTest/src/com/android/frameworktest/focus/ListOfInternalSelectionViews.java
new file mode 100644
index 0000000..4bbca74
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/focus/ListOfInternalSelectionViews.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.focus;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ListView;
+import com.android.frameworktest.util.InternalSelectionView;
+
+/**
+ * A list of {@link InternalSelectionView}s paramatarized by the number of items,
+ * how many rows in each item, and how tall each item is.
+ */
+public class ListOfInternalSelectionViews extends Activity {
+
+    private ListView mListView;
+
+
+    // keys for initializing via Intent params
+    public static final String BUNDLE_PARAM_NUM_ITEMS = "com.google.test.numItems";
+    public static final String BUNDLE_PARAM_NUM_ROWS_PER_ITEM = "com.google.test.numRowsPerItem";
+    public static final String BUNDLE_PARAM_ITEM_SCREEN_HEIGHT_FACTOR = "com.google.test.itemScreenHeightFactor";
+
+    private int mScreenHeight;
+
+    private int mNumItems = 5;
+    private int mNumRowsPerItem = 4;
+    private double mItemScreenSizeFactor = 5 / 4;
+
+    public ListView getListView() {
+        return mListView;
+    }
+
+    /**
+     * Each item is screen height * this factor tall.
+     */
+    public double getItemScreenSizeFactor() {
+        return mItemScreenSizeFactor;
+    }
+
+    /**
+     * @return The number of rows per item.
+     */
+    public int getNumRowsPerItem() {
+        return mNumRowsPerItem;
+    }
+
+    /**
+     * @return The number of items in the list.
+     */
+    public int getNumItems() {
+        return mNumItems;
+    }
+
+    /**
+     * @param position The position
+     * @return The label (closest thing to a value) for the item at position
+     */
+    public String getLabelForPosition(int position) {
+        return "position " + position;
+    }
+
+    /**
+     * Get the currently selected view.
+     */
+    public InternalSelectionView getSelectedView() {
+        return (InternalSelectionView) getListView().getSelectedView();
+    }
+
+    /**
+     * Get the screen height.
+     */
+    public int getScreenHeight() {
+        return mScreenHeight;
+    }
+
+    /**
+     * Initialize a bundle suitable for sending as the params of the intent that
+     * launches this activity.
+     * @param numItems The number of items in the list.
+     * @param numRowsPerItem The number of rows per item.
+     * @param itemScreenHeightFactor see {@link #getScreenHeight()}
+     * @return the intialized bundle.
+     */
+    public static Bundle getBundleFor(int numItems, int numRowsPerItem, double itemScreenHeightFactor) {
+        Bundle bundle = new Bundle();
+        bundle.putInt(BUNDLE_PARAM_NUM_ITEMS, numItems);
+        bundle.putInt(BUNDLE_PARAM_NUM_ROWS_PER_ITEM, numRowsPerItem);
+        bundle.putDouble(BUNDLE_PARAM_ITEM_SCREEN_HEIGHT_FACTOR, itemScreenHeightFactor);
+        return bundle;
+    }
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        mScreenHeight = getWindowManager().getDefaultDisplay().getHeight();
+
+        Bundle extras = getIntent().getExtras();
+        if (extras != null) {
+            initFromBundle(extras);
+        }
+
+        mListView = new ListView(this);
+        mListView.setLayoutParams(new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT,
+                ViewGroup.LayoutParams.FILL_PARENT));
+        mListView.setDrawSelectorOnTop(false);
+        mListView.setAdapter(new MyAdapter());
+        mListView.setItemsCanFocus(true);
+        setContentView(mListView);
+    }
+
+    private void initFromBundle(Bundle icicle) {
+
+        int numItems = icicle.getInt(BUNDLE_PARAM_NUM_ITEMS, -1);
+        if (numItems != -1) {
+            mNumItems = numItems;
+        }
+        int numRowsPerItem = icicle.getInt(BUNDLE_PARAM_NUM_ROWS_PER_ITEM, -1);
+        if (numRowsPerItem != -1) {
+            mNumRowsPerItem = numRowsPerItem;
+        }
+        double screenHeightFactor = icicle.getDouble(BUNDLE_PARAM_ITEM_SCREEN_HEIGHT_FACTOR, -1.0);
+        if (screenHeightFactor > 0) {
+            mItemScreenSizeFactor = screenHeightFactor;
+        }
+    }
+
+    private class MyAdapter extends BaseAdapter {
+
+        public int getCount() {
+            return mNumItems;
+        }
+
+        public Object getItem(int position) {
+            return getLabelForPosition(position);
+        }
+
+        public long getItemId(int position) {
+            return position;
+        }
+
+        public View getView(int position, View convertView, ViewGroup parent) {
+            InternalSelectionView item =
+                    new InternalSelectionView(
+                            parent.getContext(),
+                            mNumRowsPerItem,
+                            getLabelForPosition(position));
+            item.setDesiredHeight((int) (mScreenHeight * mItemScreenSizeFactor));
+            return item;
+        }
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/focus/ListWithFooterViewAndNewLabels.java b/tests/FrameworkTest/src/com/android/frameworktest/focus/ListWithFooterViewAndNewLabels.java
new file mode 100644
index 0000000..730f9aa
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/focus/ListWithFooterViewAndNewLabels.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.focus;
+
+import android.app.ListActivity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.BaseAdapter;
+import android.widget.Button;
+import android.widget.TextView;
+
+import com.google.android.collect.Lists;
+import com.android.frameworktest.R;
+
+import java.util.List;
+
+public class ListWithFooterViewAndNewLabels extends ListActivity {
+
+    private MyAdapter mMyAdapter;
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        setContentView(R.layout.list_with_button_above);
+
+        Button footerButton = new Button(this);
+        footerButton.setText("hi");
+        footerButton.setLayoutParams(
+                new AbsListView.LayoutParams(
+                        ViewGroup.LayoutParams.WRAP_CONTENT,
+                        ViewGroup.LayoutParams.WRAP_CONTENT));
+        getListView().addFooterView(footerButton);
+
+        mMyAdapter = new MyAdapter(this);
+        setListAdapter(mMyAdapter);
+
+        // not in list
+        Button topButton = (Button) findViewById(R.id.button);
+        topButton.setText("click to add new item");
+        topButton.setOnClickListener(new View.OnClickListener() {
+
+            public void onClick(View v) {
+                mMyAdapter.addLabel("yo");
+            }
+        });
+
+        mMyAdapter.addLabel("first");
+    }
+
+    /**
+     * An adapter that can take new string labels.
+     */
+    static class MyAdapter extends BaseAdapter {
+
+        private final Context mContext;
+        private List<String> mLabels = Lists.newArrayList();
+
+        public MyAdapter(Context context) {
+            mContext = context;
+        }
+
+        public int getCount() {
+            return mLabels.size();
+        }
+
+        public Object getItem(int position) {
+            return mLabels.get(position);
+        }
+
+        public long getItemId(int position) {
+            return position;
+        }
+
+        public View getView(int position, View convertView, ViewGroup parent) {
+            String label = mLabels.get(position);
+
+            LayoutInflater inflater = (LayoutInflater)
+                    mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+            TextView tv = (TextView) inflater.inflate(
+                    android.R.layout.simple_list_item_1,
+                    null);
+            tv.setText(label);
+            return tv;
+        }
+
+        public void addLabel(String s) {
+            mLabels.add(s + mLabels.size());
+            notifyDataSetChanged();
+        }
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/focus/ListWithMailMessages.java b/tests/FrameworkTest/src/com/android/frameworktest/focus/ListWithMailMessages.java
new file mode 100644
index 0000000..27c642a
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/focus/ListWithMailMessages.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.focus;
+
+import com.android.frameworktest.R;
+import com.google.android.collect.Lists;
+
+import android.app.ListActivity;
+import android.os.Bundle;
+import android.widget.ArrayAdapter;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.LayoutInflater;
+import android.webkit.WebView;
+
+import java.util.List;
+
+public class ListWithMailMessages extends ListActivity {
+
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.list_with_button_above);
+
+        List<MailMessage> messages = Lists.newArrayList();
+        messages.add(new MailMessage("hello!", "<p>this is a test "
+                + "message, with a bunch of text and stuff.</p>", true));
+
+//        String android = "android";
+        String android = "<a href=\"www.android.com\">android</a>";
+
+        String sentance = "all work and no play makes "
+        + android + " a dull... robot!";
+        StringBuffer longBody = new StringBuffer().append("<ol>\n");
+        for (int i = 0; i < 12; i++) {
+            longBody.append("<li>").append(sentance).append("</li>");
+        }
+        longBody.append("</ol>");
+
+        messages.add(new MailMessage("hello2!", longBody.toString(), true));
+        messages.add(new MailMessage("phone number?", "<p>hey man, what's ur "
+                + "contact info? i need to mail you this photo of my two"
+                + " cats, they've gotten soooo fat!</p>", true));
+
+        setListAdapter(new MyAdapter(this, R.layout.mail_message, messages));
+        getListView().setItemsCanFocus(true);
+    }
+
+
+    /**
+     * POJO mail message.
+     */
+    static class MailMessage {
+        private String mSubject;
+        private String mBody;
+        private boolean mFocusable;
+
+
+        public MailMessage(String subject, String body) {
+            this(subject, body, false);
+        }
+
+
+        public MailMessage(String subject, String body, boolean focusable) {
+            mSubject = subject;
+            mBody = body;
+            mFocusable = focusable;
+        }
+
+        public String getSubject() {
+            return mSubject;
+        }
+
+        public void setSubject(String subject) {
+            this.mSubject = subject;
+        }
+
+        public String getBody() {
+            return mBody;
+        }
+
+        public void setBody(String body) {
+            this.mBody = body;
+        }
+
+
+        public boolean isFocusable() {
+            return mFocusable;
+        }
+
+        public void setFocusable(boolean focusable) {
+            mFocusable = focusable;
+        }
+    }
+
+
+    public static class MyAdapter extends ArrayAdapter<MailMessage> {
+
+        public MyAdapter(Context context, int resource,
+                List<MailMessage> objects) {
+            super(context, resource, objects);
+        }
+
+        final String mimeType = "text/html";
+        final String encoding = "utf-8";
+
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            MailMessage message = getItem(position);
+
+            LayoutInflater inflater = (LayoutInflater)
+                    getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+            LinearLayout messageUi = (LinearLayout) inflater
+                    .inflate(R.layout.mail_message, null);
+
+            TextView subject = (TextView) messageUi.findViewById(R.id.subject);
+            subject.setText(message.getSubject());
+
+            WebView body = (WebView) messageUi.findViewById(R.id.body);
+            body.loadData(message.getBody(), mimeType, encoding);
+//            body.setText(message.getBody());
+            body.setFocusable(message.isFocusable());
+
+            return messageUi;
+        }
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/focus/RequestFocus.java b/tests/FrameworkTest/src/com/android/frameworktest/focus/RequestFocus.java
new file mode 100644
index 0000000..803815b
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/focus/RequestFocus.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.focus;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.widget.LinearLayout;
+import android.widget.Button;
+import android.view.View;
+
+/**
+ * Exercises cases where elements of the UI are requestFocus()ed.
+ */
+public class RequestFocus extends Activity {
+    protected final Handler mHandler = new Handler();
+
+    @Override protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.focus_after_removal);
+
+        // bottom right button starts with the focus.
+        final Button bottomRightButton = (Button) findViewById(R.id.bottomRightButton);
+        bottomRightButton.requestFocus();
+        bottomRightButton.setText("I should have focus");
+    }
+
+    public Handler getHandler() {
+        return mHandler;
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/focus/VerticalFocusSearch.java b/tests/FrameworkTest/src/com/android/frameworktest/focus/VerticalFocusSearch.java
new file mode 100644
index 0000000..d1b83a3
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/focus/VerticalFocusSearch.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.focus;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.LinearLayout;
+import android.widget.Button;
+import android.widget.TextView;
+import android.view.Gravity;
+import android.view.ViewGroup;
+import android.content.Context;
+
+/**
+ * Holds a few buttons of various sizes and horizontal placements in a
+ * vertical layout to excercise some core focus searching.
+ */
+public class VerticalFocusSearch extends Activity {
+
+    private LinearLayout mLayout;
+
+    private Button mTopWide;
+    private Button mMidSkinny1Left;
+    private Button mBottomWide;
+
+    private Button mMidSkinny2Right;
+
+
+    public LinearLayout getLayout() {
+        return mLayout;
+    }
+
+    public Button getTopWide() {
+        return mTopWide;
+    }
+
+    public Button getMidSkinny1Left() {
+        return mMidSkinny1Left;
+    }
+
+    public Button getMidSkinny2Right() {
+        return mMidSkinny2Right;
+    }
+
+    public Button getBottomWide() {
+        return mBottomWide;
+    }
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        mLayout = new LinearLayout(this);
+        mLayout.setOrientation(LinearLayout.VERTICAL);
+        mLayout.setHorizontalGravity(Gravity.LEFT);
+        mLayout.setLayoutParams(new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT,
+                ViewGroup.LayoutParams.FILL_PARENT));
+
+        mTopWide = makeWide("top wide");
+        mLayout.addView(mTopWide);
+
+        mMidSkinny1Left = addSkinny(mLayout, "mid skinny 1(L)", false);
+
+        mMidSkinny2Right = addSkinny(mLayout, "mid skinny 2(R)", true);
+
+        mBottomWide = makeWide("bottom wide");
+        mLayout.addView(mBottomWide);
+
+        setContentView(mLayout);
+    }
+
+    // just to get toString non-sucky
+    private static class MyButton extends Button {
+
+        public MyButton(Context context) {
+            super(context);
+        }
+
+
+        @Override
+        public String toString() {
+            return getText().toString();
+        }
+    }
+
+    private Button makeWide(String label) {
+        Button button = new MyButton(this);
+        button.setText(label);
+        button.setLayoutParams(new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT));
+        return button;
+    }
+
+    /**
+     * Add a skinny button that takes up just less than half of the screen
+     * horizontally.
+     * @param root The layout to add the button to.
+     * @param label The label of the button.
+     * @param atRight Which side to put the button on.
+     * @return The newly created button.
+     */
+    private Button addSkinny(LinearLayout root, String label, boolean atRight) {
+        Button button = new MyButton(this);
+        button.setText(label);
+        button.setLayoutParams(new LinearLayout.LayoutParams(
+                0, // width
+                ViewGroup.LayoutParams.WRAP_CONTENT,
+                480));
+
+        TextView filler = new TextView(this);
+        filler.setText("filler");
+        filler.setLayoutParams(new LinearLayout.LayoutParams(
+                0, // width
+                ViewGroup.LayoutParams.WRAP_CONTENT,
+                520));
+
+        LinearLayout ll = new LinearLayout(this);
+        ll.setOrientation(LinearLayout.HORIZONTAL);
+        ll.setLayoutParams(new LinearLayout.LayoutParams(
+            ViewGroup.LayoutParams.FILL_PARENT,
+            ViewGroup.LayoutParams.WRAP_CONTENT));
+
+        if (atRight) {
+            ll.addView(filler);
+            ll.addView(button);
+            root.addView(ll);
+        } else {
+            ll.addView(button);
+            ll.addView(filler);
+            root.addView(ll);
+        }
+        return button;
+    }
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridDelete.java b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridDelete.java
new file mode 100644
index 0000000..4c0d23b
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridDelete.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.GridView;
+import android.widget.ListAdapter;
+
+import com.android.frameworktest.util.GridScenario;
+
+import java.util.ArrayList;
+
+/**
+ * A grid with vertical spacing between rows
+ */
+public class GridDelete extends GridScenario {
+    @Override
+    protected void init(Params params) {
+        params.setStartingSelectionPosition(-1)
+                .setMustFillScreen(false)
+                .setNumItems(1001)
+                .setNumColumns(4)
+                .setItemScreenSizeFactor(0.20)
+                .setVerticalSpacing(20);
+    }
+    
+    
+    
+    @Override
+    protected ListAdapter createAdapter() {
+        return new DeleteAdapter(getInitialNumItems());
+    }
+
+    
+    
+    
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        if (keyCode == KeyEvent.KEYCODE_DEL) {
+            GridView g = getGridView();
+            ((DeleteAdapter)g.getAdapter()).deletePosition(g.getSelectedItemPosition());
+            return true;
+        } else {
+            return super.onKeyDown(keyCode, event);
+        }
+    }
+
+
+
+
+    private class DeleteAdapter extends BaseAdapter {
+        
+        private ArrayList<Integer> mData;
+        
+        public DeleteAdapter(int initialNumItems) {
+            super();
+            mData = new ArrayList<Integer>(initialNumItems);
+            
+            int i;
+            for (i=0; i<initialNumItems; ++i) {
+                mData.add(new Integer(10000 + i));
+            }
+            
+        }
+
+        public void deletePosition(int selectedItemPosition) {
+            if (selectedItemPosition >=0 && selectedItemPosition < mData.size()) {
+                mData.remove(selectedItemPosition);
+                notifyDataSetChanged();
+            }
+            
+        }
+
+        public int getCount() {
+            return mData.size();
+        }
+
+        public Object getItem(int position) {
+            return mData.get(position);
+        }
+
+        public long getItemId(int position) {
+            return mData.get(position);
+        }
+
+        public View getView(int position, View convertView, ViewGroup parent) {
+            int desiredHeight = getDesiredItemHeight();
+            return createView(mData.get(position), parent, desiredHeight);
+        }
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridInHorizontal.java b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridInHorizontal.java
new file mode 100644
index 0000000..c10a53b
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridInHorizontal.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.widget.ArrayAdapter;
+import android.widget.GridView;
+import android.widget.TextView;
+
+import com.android.frameworktest.R;
+
+/**
+ * Exercises a grid in a horizontal linear layout
+ */
+public class GridInHorizontal extends Activity {
+    Handler mHandler = new Handler();
+    TextView mText;
+    GridView mGridView;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        
+        setContentView(R.layout.grid_in_horizontal);
+
+        String values[] = new String[1000];
+        int i=0;
+        for(i=0; i<1000; i++) {
+            values[i] = ((Integer)i).toString();
+        }
+        
+        mText = (TextView) findViewById(R.id.text);
+        mGridView = (GridView) findViewById(R.id.grid);
+        mGridView.setAdapter(new ArrayAdapter<String>(this,
+                android.R.layout.simple_list_item_1, values));
+
+    }
+    
+    public GridView getGridView() {
+        return mGridView;
+    }
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridInVertical.java b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridInVertical.java
new file mode 100644
index 0000000..acde73e
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridInVertical.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.widget.ArrayAdapter;
+import android.widget.GridView;
+import android.widget.TextView;
+
+import com.android.frameworktest.R;
+
+/**
+ * Exercises a grid in a vertical linear layout
+ */
+public class GridInVertical extends Activity {
+    Handler mHandler = new Handler();
+    TextView mText;
+    GridView mGridView;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        
+        setContentView(R.layout.grid_in_vertical);
+
+        String values[] = new String[1000];
+        int i=0;
+        for(i=0; i<1000; i++) {
+            values[i] = ((Integer)i).toString();
+        }
+        
+        mText = (TextView) findViewById(R.id.text);
+        mGridView = (GridView) findViewById(R.id.grid);
+        mGridView.setAdapter(new ArrayAdapter<String>(this,
+                android.R.layout.simple_list_item_1, values));
+
+    }
+    
+    public GridView getGridView() {
+        return mGridView;
+    }
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridPadding.java b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridPadding.java
new file mode 100644
index 0000000..41909ac2
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridPadding.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.ArrayAdapter;
+import android.widget.GridView;
+
+import com.android.frameworktest.R;
+
+/**
+ * Exercises a grid with padding
+ */
+public class GridPadding extends Activity {
+    private GridView mGridView;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        setContentView(R.layout.grid_padding);
+
+        String values[] = new String[1000];
+        for(int i = 0; i < 1000; i++) {
+            values[i] = String.valueOf(i);
+        }
+
+        mGridView = (GridView) findViewById(R.id.grid);
+        mGridView.setAdapter(new ArrayAdapter<String>(this,
+                android.R.layout.simple_list_item_1, values));
+    }
+
+    public GridView getGridView() {
+        return mGridView;
+    }
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridScrollListener.java b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridScrollListener.java
new file mode 100644
index 0000000..4655230
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridScrollListener.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.widget.AbsListView;
+import android.widget.ArrayAdapter;
+import android.widget.GridView;
+import android.widget.TextView;
+
+import com.android.frameworktest.R;
+
+/**
+ * Exercises change notification in a list
+ */
+public class GridScrollListener extends Activity implements AbsListView.OnScrollListener {
+    Handler mHandler = new Handler();
+    TextView mText;
+    GridView mGridView;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        
+        setContentView(R.layout.grid_scroll_listener);
+
+        String values[] = new String[1000];
+        int i=0;
+        for(i=0; i<1000; i++) {
+            values[i] = ((Integer)i).toString();
+        }
+        
+        mText = (TextView) findViewById(R.id.text);
+        mGridView = (GridView) findViewById(R.id.grid);
+        mGridView.setAdapter(new ArrayAdapter<String>(this,
+                android.R.layout.simple_list_item_1, values));
+
+        mGridView.setOnScrollListener(this);
+    }
+    
+    public GridView getGridView() {
+        return mGridView;
+    }
+
+    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
+        int lastItem = firstVisibleItem + visibleItemCount - 1;
+        mText.setText("Showing " + firstVisibleItem + "-" + lastItem + "/" + totalItemCount);
+    }
+
+    public void onScrollStateChanged(AbsListView view, int scrollState) {        
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridSetSelection.java b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridSetSelection.java
new file mode 100644
index 0000000..38f629d
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridSetSelection.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import com.android.frameworktest.util.GridScenario;
+
+/**
+ * Basic stacking from top scenario, nothing fancy. Items do not
+ * fill the screen.
+ */
+public class GridSetSelection extends GridScenario {
+    @Override
+    protected void init(Params params) {
+        params.setStackFromBottom(false)
+                .setStartingSelectionPosition(-1)
+                .setMustFillScreen(false)
+                .setNumItems(15)
+                .setNumColumns(4)
+                .setItemScreenSizeFactor(0.12);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridSetSelectionMany.java b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridSetSelectionMany.java
new file mode 100644
index 0000000..34aeb75
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridSetSelectionMany.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import com.android.frameworktest.util.GridScenario;
+
+/**
+ * Basic stacking from top scenario, nothing fancy. Items do
+ * fill the screen.
+ */
+public class GridSetSelectionMany extends GridScenario {
+    @Override
+    protected void init(Params params) {
+        params.setStackFromBottom(false)
+                .setStartingSelectionPosition(-1)
+                .setMustFillScreen(false)
+                .setNumItems(150)
+                .setNumColumns(4)
+                .setItemScreenSizeFactor(0.12);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridSetSelectionStackFromBottom.java b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridSetSelectionStackFromBottom.java
new file mode 100644
index 0000000..6a2445f
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridSetSelectionStackFromBottom.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import com.android.frameworktest.util.GridScenario;
+
+/**
+ * Basic stacking from bottom scenario, nothing fancy. Items do not
+ * fill the screen.
+ */
+public class GridSetSelectionStackFromBottom extends GridScenario {
+    @Override
+    protected void init(Params params) {
+        params.setStackFromBottom(true)
+                .setStartingSelectionPosition(-1)
+                .setMustFillScreen(false)
+                .setNumItems(15)
+                .setNumColumns(4)
+                .setItemScreenSizeFactor(0.12);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridSetSelectionStackFromBottomMany.java b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridSetSelectionStackFromBottomMany.java
new file mode 100644
index 0000000..838c431
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridSetSelectionStackFromBottomMany.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import com.android.frameworktest.util.GridScenario;
+
+/**
+ * Basic stacking from bottom scenario, nothing fancy. Items do
+ * fill the screen.
+ */
+public class GridSetSelectionStackFromBottomMany extends GridScenario {
+    @Override
+    protected void init(Params params) {
+        params.setStackFromBottom(true)
+                .setStartingSelectionPosition(-1)
+                .setMustFillScreen(false)
+                .setNumItems(150)
+                .setNumColumns(4)
+                .setItemScreenSizeFactor(0.12);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridSimple.java b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridSimple.java
new file mode 100644
index 0000000..f7f68f5
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridSimple.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.gridview;
+
+import android.graphics.drawable.PaintDrawable;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import com.android.frameworktest.util.GridScenario;
+
+public class GridSimple extends GridScenario {
+    @Override
+    protected void init(Params params) {
+        params.setStackFromBottom(false)
+                .setStartingSelectionPosition(-1)
+                .setNumItems(1000)
+                .setNumColumns(3)
+                .setItemScreenSizeFactor(0.14);
+    }
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        getGridView().setSelector(new PaintDrawable(0xFFFF0000));
+        getGridView().setPadding(0, 0, 0, 0);
+        getGridView().setFadingEdgeLength(64);
+        getGridView().setVerticalFadingEdgeEnabled(true);
+        getGridView().setBackgroundColor(0xFFC0C0C0);
+    }
+
+    @Override
+    protected View createView(int position, ViewGroup parent, int desiredHeight) {
+        View view = super.createView(position, parent, desiredHeight);
+        view.setBackgroundColor(0xFF000000);
+        ((TextView) view).setTextSize(16.0f);
+        return view;
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridSingleColumn.java b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridSingleColumn.java
new file mode 100644
index 0000000..a909bd8
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridSingleColumn.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import com.android.frameworktest.util.GridScenario;
+import android.widget.GridView;
+
+/**
+ * A grid with vertical spacing between rows
+ */
+public class GridSingleColumn extends GridScenario {
+    @Override
+    protected void init(Params params) {
+        params.setStartingSelectionPosition(-1)
+                .setMustFillScreen(false)
+                .setNumItems(101)
+                .setNumColumns(1)
+                .setColumnWidth(60)
+                .setItemScreenSizeFactor(0.20)
+                .setVerticalSpacing(20)
+                .setStretchMode(GridView.STRETCH_SPACING);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridStackFromBottom.java b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridStackFromBottom.java
new file mode 100644
index 0000000..304110e
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridStackFromBottom.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import com.android.frameworktest.util.GridScenario;
+
+/**
+ * Basic bottom stacking from bottom scenario, nothing fancy. Items do not
+ * fill the screen
+ */
+public class GridStackFromBottom extends GridScenario {
+    @Override
+    protected void init(Params params) {
+        params.setStackFromBottom(true)
+                .setStartingSelectionPosition(-1)
+                .setMustFillScreen(false)
+                .setNumItems(15)
+                .setNumColumns(4)
+                .setItemScreenSizeFactor(0.12);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridStackFromBottomMany.java b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridStackFromBottomMany.java
new file mode 100644
index 0000000..94d801e
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridStackFromBottomMany.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import com.android.frameworktest.util.GridScenario;
+
+/**
+ * Basic bottom stacking from bottom scenario, nothing fancy. The grid items do not fit on the
+ * screen (to exercise scrolling.)
+ */
+public class GridStackFromBottomMany extends GridScenario {
+    @Override
+    protected void init(Params params) {
+        params.setStackFromBottom(true)
+                .setStartingSelectionPosition(-1)
+                .setMustFillScreen(false)
+                .setNumItems(54)
+                .setNumColumns(4)
+                .setItemScreenSizeFactor(0.12);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridThrasher.java b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridThrasher.java
new file mode 100644
index 0000000..d628f2d
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridThrasher.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.LayoutInflater;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.GridView;
+import android.widget.TextView;
+
+import java.util.Random;
+
+/**
+ * Exercises change notification in a list
+ */
+public class GridThrasher extends Activity implements AdapterView.OnItemSelectedListener
+{
+    Handler mHandler = new Handler();
+    ThrashListAdapter mAdapter;
+    Random mRandomizer = new Random();
+    TextView mText;
+    
+    Runnable mThrash = new Runnable() {
+        public void run() {
+            mAdapter.bumpVersion();
+            mHandler.postDelayed(mThrash, 500);
+        }
+    };
+
+    private class ThrashListAdapter extends BaseAdapter {
+        private LayoutInflater mInflater;
+        
+        /**
+         * Our data, part 1.
+         */
+        private String[] mTitles = new String[100];
+        
+        /**
+         * Our data, part 2.
+         */
+        private int[] mVersion = new int[100];
+
+        public ThrashListAdapter(Context context) {
+            mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+            mTitles = new String[100];
+            mVersion = new int[100];
+            
+            int i;
+            for (i=0; i<100; i++) {
+                mTitles[i] = "[" + i + "]";
+                mVersion[i] = 0;
+            }
+        }
+
+        public int getCount() {
+            return mTitles.length;
+        }
+
+        public Object getItem(int position) {
+            return position;
+        }
+
+        public long getItemId(int position) {
+            return position;
+        }
+
+        public View getView(int position, View convertView, ViewGroup parent) {
+            TextView view;
+
+            if (convertView == null) {
+                view = (TextView) mInflater.inflate(android.R.layout.simple_list_item_1, null);
+            } else {
+                view = (TextView) convertView;
+            }
+            view.setText(mTitles[position] + " " + mVersion[position]);
+            return view;
+        }
+
+        
+        public void bumpVersion() {
+            int position = mRandomizer.nextInt(getCount());
+            mVersion[position]++;
+            notifyDataSetChanged();
+        }
+             
+
+    }
+    
+    @Override
+    public void onCreate(Bundle icicle) 
+    {
+        super.onCreate(icicle);
+        
+        setContentView(R.layout.grid_thrasher);
+        
+        mText = (TextView) findViewById(R.id.text);
+        mAdapter = new ThrashListAdapter(this);
+        GridView g = (GridView) findViewById(R.id.grid);
+        g.setAdapter(mAdapter);
+        
+        mHandler.postDelayed(mThrash, 5000);
+        
+        g.setOnItemSelectedListener(this);
+    }
+
+    public void onItemSelected(AdapterView parent, View v, int position, long id) {
+        mText.setText("Position " + position);
+    }
+
+    public void onNothingSelected(AdapterView parent) {
+        mText.setText("Nothing");
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridVerticalSpacing.java b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridVerticalSpacing.java
new file mode 100644
index 0000000..3f6b8d6
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridVerticalSpacing.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import com.android.frameworktest.util.GridScenario;
+
+/**
+ * A grid with vertical spacing between rows
+ */
+public class GridVerticalSpacing extends GridScenario {
+    @Override
+    protected void init(Params params) {
+        params.setStartingSelectionPosition(-1)
+                .setMustFillScreen(false)
+                .setNumItems(101)
+                .setNumColumns(4)
+                .setItemScreenSizeFactor(0.20)
+                .setVerticalSpacing(20);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridVerticalSpacingStackFromBottom.java b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridVerticalSpacingStackFromBottom.java
new file mode 100644
index 0000000..1a39ffb
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/gridview/GridVerticalSpacingStackFromBottom.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import com.android.frameworktest.util.GridScenario;
+
+/**
+ * A grid with vertical spacing between rows that stacks from the bottom
+ */
+public class GridVerticalSpacingStackFromBottom extends GridScenario {
+    @Override
+    protected void init(Params params) {
+        params.setStackFromBottom(true)
+                .setStartingSelectionPosition(-1)
+                .setMustFillScreen(false)
+                .setNumItems(101)
+                .setNumColumns(4)
+                .setItemScreenSizeFactor(0.20)
+                .setVerticalSpacing(20);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/layout/frame/FrameLayoutGravity.java b/tests/FrameworkTest/src/com/android/frameworktest/layout/frame/FrameLayoutGravity.java
new file mode 100644
index 0000000..1383dae
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/layout/frame/FrameLayoutGravity.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.frame;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+
+public class FrameLayoutGravity extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.framelayout_gravity);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/layout/frame/FrameLayoutMargin.java b/tests/FrameworkTest/src/com/android/frameworktest/layout/frame/FrameLayoutMargin.java
new file mode 100644
index 0000000..0434726
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/layout/frame/FrameLayoutMargin.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.frame;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+
+public class FrameLayoutMargin extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.framelayout_margin);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/BaselineAlignmentCenterGravity.java b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/BaselineAlignmentCenterGravity.java
new file mode 100644
index 0000000..5087c62
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/BaselineAlignmentCenterGravity.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.linear;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+
+public class BaselineAlignmentCenterGravity extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.baseline_center_gravity);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/BaselineAlignmentZeroWidthAndWeight.java b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/BaselineAlignmentZeroWidthAndWeight.java
new file mode 100644
index 0000000..3c1d7fd
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/BaselineAlignmentZeroWidthAndWeight.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.linear;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+
+public class BaselineAlignmentZeroWidthAndWeight extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.baseline_0width_and_weight);
+
+        findViewById(R.id.show).setOnClickListener(new View.OnClickListener() {
+            public void onClick(View v) {
+                findViewById(R.id.layout).setVisibility(View.VISIBLE);
+            }
+        });
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/BaselineButtons.java b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/BaselineButtons.java
new file mode 100644
index 0000000..9bb9bff
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/BaselineButtons.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.linear;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+
+public class BaselineButtons extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.baseline_buttons);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/ExceptionTextView.java b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/ExceptionTextView.java
new file mode 100644
index 0000000..54f6b98
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/ExceptionTextView.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.linear;
+
+import junit.framework.Assert;
+
+import android.widget.EditText;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.text.BoringLayout;
+
+
+/**
+ * A special EditText that sets {@link #isFailed()} to true as its internal makeNewLayout() method is called
+ * with a width lower than 0. This is used to fail the unit test in
+ * BaselineAlignmentZeroWidthAndWeightTest.
+ */
+public class ExceptionTextView extends EditText {
+
+    private boolean mFailed = false;
+
+    public ExceptionTextView(Context context) {
+        super(context);
+    }
+
+    public ExceptionTextView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public ExceptionTextView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    public boolean isFailed() {
+        return mFailed;
+    }
+
+    @Override
+    protected void makeNewLayout(int w, int hintWidth,
+                                 BoringLayout.Metrics boring,
+                                 BoringLayout.Metrics hintMetrics,
+                                 int ellipsizedWidth, boolean bringIntoView) {
+        if (w < 0) {
+            mFailed = true;
+            w = 100;
+        }
+
+        super.makeNewLayout(w, hintWidth, boring, hintMetrics, ellipsizedWidth,
+                            bringIntoView);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/FillInWrap.java b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/FillInWrap.java
new file mode 100644
index 0000000..a95cf17
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/FillInWrap.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.layout.linear;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+
+public class FillInWrap extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.fill_in_wrap);
+        ((TextView) findViewById(R.id.data)).setText("1\n2\n3\n4\n5");
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/HorizontalOrientationVerticalAlignment.java b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/HorizontalOrientationVerticalAlignment.java
new file mode 100644
index 0000000..1308b8b
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/HorizontalOrientationVerticalAlignment.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.layout.linear;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+
+public class HorizontalOrientationVerticalAlignment extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.linear_layout_spinner_then_button);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/LLEditTextThenButton.java b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/LLEditTextThenButton.java
new file mode 100644
index 0000000..db868cb
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/LLEditTextThenButton.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.linear;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+
+public class LLEditTextThenButton extends Activity {
+    private EditText mEditText;
+    private Button mButton;
+
+    private LinearLayout mLayout;
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        setContentView(R.layout.linear_layout_edittext_then_button);
+
+        mLayout = (LinearLayout) findViewById(R.id.layout);
+        mEditText = (EditText) findViewById(R.id.editText);
+        mButton = (Button) findViewById(R.id.button);
+    }
+
+    public LinearLayout getLayout() {
+        return mLayout;
+    }
+
+    public EditText getEditText() {
+        return mEditText;
+    }
+
+    public Button getButton() {
+        return mButton;
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/LLOfButtons1.java b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/LLOfButtons1.java
new file mode 100644
index 0000000..33189e5
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/LLOfButtons1.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.linear;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import com.android.frameworktest.R;
+
+/**
+ * One of two simple vertical linear layouts of buttons used to test out
+ * the transistion between touch and focus mode.
+ */
+public class LLOfButtons1 extends Activity {
+
+    private boolean mButtonPressed = false;
+    private Button mFirstButton;
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.linear_layout_buttons);
+        mFirstButton = (Button) findViewById(R.id.button1);
+
+        mFirstButton.setOnClickListener(new View.OnClickListener() {
+            public void onClick(View v) {
+                mButtonPressed = true;
+            }
+        });
+
+    }
+
+    public LinearLayout getLayout() {
+        return (LinearLayout) findViewById(R.id.layout);
+    }
+
+    public Button getFirstButton() {
+        return mFirstButton;
+    }
+
+    public boolean buttonClickListenerFired() {
+        return mButtonPressed;
+    }
+
+    public boolean isInTouchMode() {
+        return mFirstButton.isInTouchMode();
+    }
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/LLOfButtons2.java b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/LLOfButtons2.java
new file mode 100644
index 0000000..1e0c97a
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/LLOfButtons2.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.linear;
+
+/**
+ * One of two simple vertical linear layouts of buttons used to test out
+ * the transistion between touch and focus mode.
+ */
+public class LLOfButtons2  extends LLOfButtons1 {
+
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/LLOfTwoFocusableInTouchMode.java b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/LLOfTwoFocusableInTouchMode.java
new file mode 100644
index 0000000..201c8f9
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/LLOfTwoFocusableInTouchMode.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.linear;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+
+public class LLOfTwoFocusableInTouchMode extends Activity {
+
+    private View mButton1;
+    private View mButton2;
+    private View mButton3;
+
+    private boolean mB1Fired = false;
+    private boolean mB2Fired = false;
+    private boolean mB3Fired = false;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.linear_layout_buttons);
+
+        mButton1 = findViewById(R.id.button1);
+        mButton2 = findViewById(R.id.button2);
+        mButton3 = findViewById(R.id.button3);
+
+        mButton1.setFocusableInTouchMode(true);
+        mButton2.setFocusableInTouchMode(true);
+        mButton3.setFocusableInTouchMode(true);
+
+        mButton1.setOnClickListener(new View.OnClickListener() {
+            public void onClick(View v) {
+                mB1Fired = true;
+            }
+        });
+
+        mButton2.setOnClickListener(new View.OnClickListener() {
+            public void onClick(View v) {
+                mB2Fired = true;
+            }
+        });
+
+        mButton3.setOnClickListener(new View.OnClickListener() {
+            public void onClick(View v) {
+                mB3Fired = true;
+            }
+        });
+    }
+
+    public View getButton1() {
+        return mButton1;
+    }
+
+    public View getButton2() {
+        return mButton2;
+    }
+
+    public View getButton3() {
+        return mButton3;
+    }
+
+    public boolean isB1Fired() {
+        return mB1Fired;
+    }
+
+    public boolean isB2Fired() {
+        return mB2Fired;
+    }
+
+    public boolean isB3Fired() {
+        return mB3Fired;
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/LinearLayoutEditTexts.java b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/LinearLayoutEditTexts.java
new file mode 100644
index 0000000..4877a63
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/LinearLayoutEditTexts.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.layout.linear;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class LinearLayoutEditTexts extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.linear_layout_textviews);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/Weight.java b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/Weight.java
new file mode 100644
index 0000000..0535f00
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/Weight.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.layout.linear;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class Weight extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.linear_layout_weight);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/WeightSum.java b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/WeightSum.java
new file mode 100644
index 0000000..8b9a497
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/layout/linear/WeightSum.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.layout.linear;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+
+public class WeightSum extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.weight_sum);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/layout/table/AddColumn.java b/tests/FrameworkTest/src/com/android/frameworktest/layout/table/AddColumn.java
new file mode 100644
index 0000000..c490e0f
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/layout/table/AddColumn.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.table;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TableLayout;
+import android.widget.TableRow;
+import android.widget.TextView;
+
+/**
+ * This test adds an extra row with an extra column in the table.
+ */
+public class AddColumn extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.add_column_in_table);
+
+        final Button addRowButton = (Button) findViewById(R.id.add_row_button);
+        addRowButton.setOnClickListener(new View.OnClickListener() {
+            public void onClick(View v) {
+                final TableLayout table = (TableLayout) findViewById(R.id.table);
+                final TableRow newRow = new TableRow(AddColumn.this);
+                for (int i = 0; i < 4; i++) {
+                    final TextView view = new TextView(AddColumn.this);
+                    view.setText("Column " + (i + 1));
+                    view.setPadding(3, 3, 3, 3);
+                    newRow.addView(view, new TableRow.LayoutParams());
+                }
+                table.addView(newRow, new TableLayout.LayoutParams());
+                newRow.requestLayout();
+            }
+        });
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/layout/table/CellSpan.java b/tests/FrameworkTest/src/com/android/frameworktest/layout/table/CellSpan.java
new file mode 100644
index 0000000..243efc7
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/layout/table/CellSpan.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.table;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * Exercise table layout with cells spanning.
+ */
+public class CellSpan extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.table_layout_cell_span);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/layout/table/FixedWidth.java b/tests/FrameworkTest/src/com/android/frameworktest/layout/table/FixedWidth.java
new file mode 100644
index 0000000..2e2defc
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/layout/table/FixedWidth.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.table;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * Exercise table layout with cells having a fixed width and height.
+ */
+public class FixedWidth extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.table_layout_fixed_width);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/layout/table/HorizontalGravity.java b/tests/FrameworkTest/src/com/android/frameworktest/layout/table/HorizontalGravity.java
new file mode 100644
index 0000000..fdafa12
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/layout/table/HorizontalGravity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.table;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * Exercise table layout with cells using a horizontal gravity.
+ */
+public class HorizontalGravity extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.table_layout_horizontal_gravity);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/layout/table/VerticalGravity.java b/tests/FrameworkTest/src/com/android/frameworktest/layout/table/VerticalGravity.java
new file mode 100644
index 0000000..1f161d9
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/layout/table/VerticalGravity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.table;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * Exercise table layout with cells using a vertical gravity.
+ */
+public class VerticalGravity extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.table_layout_vertical_gravity);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/layout/table/Weight.java b/tests/FrameworkTest/src/com/android/frameworktest/layout/table/Weight.java
new file mode 100644
index 0000000..4c3835f
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/layout/table/Weight.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.layout.table;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * Exercise table layout with cells having a weight.
+ */
+public class Weight extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.table_layout_weight);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/AdjacentListsWithAdjacentISVsInside.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/AdjacentListsWithAdjacentISVsInside.java
new file mode 100644
index 0000000..5c38ef0
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/AdjacentListsWithAdjacentISVsInside.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.listview;
+
+import com.android.frameworktest.util.InternalSelectionView;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+
+/**
+ * Most bodacious scenario yet!
+ */
+public class AdjacentListsWithAdjacentISVsInside extends Activity {
+
+    private ListView mLeftListView;
+    private ListView mRightListView;
+
+    public ListView getLeftListView() {
+        return mLeftListView;
+    }
+
+    public ListView getRightListView() {
+        return mRightListView;
+    }
+
+    public InternalSelectionView getLeftIsv() {
+        return (InternalSelectionView)
+                ((ViewGroup) mLeftListView.getChildAt(0)).getChildAt(0);
+    }
+
+    public InternalSelectionView getLeftMiddleIsv() {
+        return (InternalSelectionView)
+                ((ViewGroup) mLeftListView.getChildAt(0)).getChildAt(1);
+    }
+
+    public InternalSelectionView getRightMiddleIsv() {
+        return (InternalSelectionView)
+                ((ViewGroup) mRightListView.getChildAt(0)).getChildAt(0);
+    }
+
+    public InternalSelectionView getRightIsv() {
+        return (InternalSelectionView)
+                ((ViewGroup) mRightListView.getChildAt(0)).getChildAt(1);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        final int desiredHeight = (int) (0.8 * getWindowManager().getDefaultDisplay().getHeight());
+
+        mLeftListView = new ListView(this);
+        mLeftListView.setAdapter(new AdjacentISVAdapter(desiredHeight));
+        mLeftListView.setItemsCanFocus(true);
+
+
+        mRightListView = new ListView(this);
+        mRightListView.setAdapter(new AdjacentISVAdapter(desiredHeight));
+        mRightListView.setItemsCanFocus(true);
+
+
+
+        setContentView(combineAdjacent(mLeftListView, mRightListView));
+    }
+
+    private static View combineAdjacent(View... views) {
+        if (views.length < 2) {
+            throw new IllegalArgumentException("you should pass at least 2 views in");
+        }
+
+        final LinearLayout ll = new LinearLayout(views[0].getContext());
+        ll.setOrientation(LinearLayout.HORIZONTAL);
+        final LinearLayout.LayoutParams lp =
+                new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1.0f);
+
+        for (View view : views) {
+            ll.addView(view, lp);
+        }
+        return ll;
+    }
+
+    static class AdjacentISVAdapter extends BaseAdapter {
+
+        private final int mItemHeight;
+
+        AdjacentISVAdapter(int itemHeight) {
+            mItemHeight = itemHeight;
+        }
+
+        public int getCount() {
+            return 1;
+        }
+
+        public Object getItem(int position) {
+            return position;
+        }
+
+        public long getItemId(int position) {
+            return position;
+        }
+
+        public View getView(int position, View convertView, ViewGroup parent) {
+            final InternalSelectionView isvLeft = new InternalSelectionView(
+                    parent.getContext(), 5, "isv left");
+            isvLeft.setDesiredHeight(mItemHeight);
+            final InternalSelectionView isvRight = new InternalSelectionView(
+                    parent.getContext(), 5, "isv right");
+            isvRight.setDesiredHeight(mItemHeight);
+            return combineAdjacent(isvLeft, isvRight);
+        }
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListBottomGravity.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListBottomGravity.java
new file mode 100644
index 0000000..e729d52
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListBottomGravity.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.view.Gravity;
+
+import com.android.frameworktest.util.ListScenario;
+
+/**
+ * Basic bottom gravity scenario, nothing fancy. Items do not
+ * fill the screen
+ */
+public class ListBottomGravity extends ListScenario {
+
+    @Override
+    protected void init(Params params) {
+        params.setStackFromBottom(true)
+                .setStartingSelectionPosition(-1)
+                .setMustFillScreen(false)
+                .setNumItems(2)
+                .setItemScreenSizeFactor(0.22);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListBottomGravityMany.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListBottomGravityMany.java
new file mode 100644
index 0000000..1225b9a
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListBottomGravityMany.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.view.Gravity;
+
+import com.android.frameworktest.util.ListScenario;
+
+/**
+ * Basic bottom gravity scenario, nothing fancy. There are
+ * more items than fit on the screen
+ */
+public class ListBottomGravityMany extends ListScenario {
+
+    @Override
+    protected void init(Params params) {
+        params.setStackFromBottom(true)
+                .setStartingSelectionPosition(-1)
+                .setNumItems(10)
+                .setItemScreenSizeFactor(0.22);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListButtonsDiagonalAcrossItems.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListButtonsDiagonalAcrossItems.java
new file mode 100644
index 0000000..bda2cd1
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListButtonsDiagonalAcrossItems.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.listview;
+
+import com.android.frameworktest.util.ListItemFactory;
+import static com.android.frameworktest.util.ListItemFactory.Slot;
+import com.android.frameworktest.util.ListScenario;
+
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+public class ListButtonsDiagonalAcrossItems extends ListScenario {
+
+    @Override
+    protected void init(Params params) {
+        params.setItemsFocusable(true)
+                .setNumItems(3)
+                .setItemScreenSizeFactor(0.2)
+                .setMustFillScreen(false);
+    }
+
+    public Button getLeftButton() {
+        return (Button) ((ViewGroup) getListView().getChildAt(0)).getChildAt(0);
+    }
+
+    public Button getCenterButton() {
+        return (Button) ((ViewGroup) getListView().getChildAt(1)).getChildAt(1);
+    }
+
+    public Button getRightButton() {
+        return (Button) ((ViewGroup) getListView().getChildAt(2)).getChildAt(2);
+    }
+
+    @Override
+    protected View createView(int position, ViewGroup parent,
+            int desiredHeight) {
+        final Slot slot = position == 0 ? Slot.Left :
+                (position == 1 ? Slot.Middle : Slot.Right);
+        return ListItemFactory.horizontalButtonSlots(
+                parent.getContext(), desiredHeight, slot);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListDividers.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListDividers.java
new file mode 100644
index 0000000..62045d8
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListDividers.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+import com.android.frameworktest.R;
+
+/**
+ * Exercises a list width dividers and padding.
+ */
+public class ListDividers extends Activity {
+    private ListView mListView;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        setContentView(R.layout.list_dividers);
+
+        String values[] = new String[1000];
+        for (int i = 0; i < 1000; i++) {
+            values[i] = ((Integer) i).toString();
+        }
+
+        mListView = (ListView) findViewById(android.R.id.list);
+        mListView.setAdapter(new ArrayAdapter<String>(this,
+                android.R.layout.simple_list_item_1, values));
+
+    }
+
+    public ListView getListView() {
+        return mListView;
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListEndingWithMultipleSeparators.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListEndingWithMultipleSeparators.java
new file mode 100644
index 0000000..4ab1eef6
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListEndingWithMultipleSeparators.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import com.android.frameworktest.util.ListScenario;
+
+public class ListEndingWithMultipleSeparators extends ListScenario {
+
+    protected void init(Params params) {
+        params.setItemsFocusable(false)
+                .setNumItems(5)
+                .setItemScreenSizeFactor(0.22)
+                .setPositionUnselectable(3)
+                .setPositionUnselectable(4);
+    }
+
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListFilter.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListFilter.java
new file mode 100644
index 0000000..b164d86
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListFilter.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.app.ListActivity;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+
+import com.android.frameworktest.R;
+
+
+/**
+ * Tests hiding and showing the list filter by hiding and showing an ancestor of the 
+ * ListView
+ */
+public class ListFilter extends ListActivity implements OnClickListener {
+
+    private View mFrame;
+    private Button mHide;
+    private Button mShow;
+    
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.list_filter);
+        setListAdapter(new ArrayAdapter<String>(this,
+                android.R.layout.simple_list_item_1, mStrings));
+        getListView().setTextFilterEnabled(true);
+        mFrame = findViewById(R.id.frame);
+        
+        mHide = (Button) findViewById(R.id.hide);
+        mHide.setOnClickListener(this);
+        
+        mShow = (Button) findViewById(R.id.show);
+        mShow.setOnClickListener(this);
+    }
+    
+
+    public void onClick(View v) {
+        mFrame.setVisibility(v == mHide ? View.INVISIBLE : View.VISIBLE);
+    }
+
+    private String[] mStrings = {
+            "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
+            "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale",
+            "Aisy Cendre", "Allgauer Emmentaler", "Alverca", "Ambert", "American Cheese",
+            "Ami du Chambertin", "Anejo Enchilado", "Anneau du Vic-Bilh", "Anthoriro", "Appenzell",
+            "Aragon", "Ardi Gasna", "Ardrahan", "Armenian String", "Aromes au Gene de Marc",
+            "Asadero", "Asiago", "Aubisque Pyrenees", "Autun", "Avaxtskyr", "Baby Swiss",
+            "Babybel", "Baguette Laonnaise", "Bakers", "Baladi", "Balaton", "Bandal", "Banon",
+            "Barry's Bay Cheddar", "Basing", "Basket Cheese", "Bath Cheese", "Bavarian Bergkase",
+            "Baylough", "Beaufort", "Beauvoorde", "Beenleigh Blue", "Beer Cheese", "Bel Paese",
+            "Bergader", "Bergere Bleue", "Berkswell", "Beyaz Peynir", "Bierkase", "Bishop Kennedy",
+            "Blarney", "Bleu d'Auvergne", "Bleu de Gex", "Bleu de Laqueuille",
+            "Bleu de Septmoncel", "Bleu Des Causses", "Blue", "Blue Castello", "Blue Rathgore",
+            "Blue Vein (Australian)", "Blue Vein Cheeses", "Bocconcini", "Bocconcini (Australian)",
+            "Boeren Leidenkaas", "Bonchester", "Bosworth", "Bougon", "Boule Du Roves",
+            "Boulette d'Avesnes", "Boursault", "Boursin", "Bouyssou", "Bra", "Braudostur",
+            "Breakfast Cheese", "Brebis du Lavort", "Brebis du Lochois", "Brebis du Puyfaucon",
+            "Bresse Bleu", "Brick", "Brie", "Brie de Meaux", "Brie de Melun", "Brillat-Savarin",
+            "Brin", "Brin d' Amour", "Brin d'Amour", "Brinza (Burduf Brinza)",
+            "Briquette de Brebis", "Briquette du Forez", "Broccio", "Broccio Demi-Affine",
+            "Brousse du Rove", "Bruder Basil", "Brusselae Kaas (Fromage de Bruxelles)", "Bryndza",
+            "Buchette d'Anjou", "Buffalo", "Burgos", "Butte", "Butterkase", "Button (Innes)",
+            "Buxton Blue", "Cabecou", "Caboc", "Cabrales", "Cachaille", "Caciocavallo", "Caciotta",
+            "Caerphilly", "Cairnsmore", "Calenzana", "Cambazola", "Camembert de Normandie",
+            "Canadian Cheddar", "Canestrato", "Cantal", "Caprice des Dieux", "Capricorn Goat",
+            "Capriole Banon", "Carre de l'Est", "Casciotta di Urbino", "Cashel Blue", "Castellano",
+            "Castelleno", "Castelmagno", "Castelo Branco", "Castigliano", "Cathelain",
+            "Celtic Promise", "Cendre d'Olivet", "Cerney", "Chabichou", "Chabichou du Poitou",
+            "Chabis de Gatine", "Chaource", "Charolais", "Chaumes", "Cheddar",
+            "Cheddar Clothbound", "Cheshire", "Chevres", "Chevrotin des Aravis", "Chontaleno",
+            "Civray", "Coeur de Camembert au Calvados", "Coeur de Chevre", "Colby", "Cold Pack",
+            "Comte", "Coolea", "Cooleney", "Coquetdale", "Corleggy", "Cornish Pepper",
+            "Cotherstone", "Cotija", "Cottage Cheese", "Cottage Cheese (Australian)",
+            "Cougar Gold", "Coulommiers", "Coverdale", "Crayeux de Roncq", "Cream Cheese",
+            "Cream Havarti", "Crema Agria", "Crema Mexicana", "Creme Fraiche", "Crescenza",
+            "Croghan", "Crottin de Chavignol", "Crottin du Chavignol", "Crowdie", "Crowley",
+            "Cuajada", "Curd", "Cure Nantais", "Curworthy", "Cwmtawe Pecorino",
+            "Cypress Grove Chevre", "Danablu (Danish Blue)", "Danbo", "Danish Fontina",
+            "Daralagjazsky", "Dauphin", "Delice des Fiouves", "Denhany Dorset Drum", "Derby",
+            "Dessertnyj Belyj", "Devon Blue", "Devon Garland", "Dolcelatte", "Doolin",
+            "Doppelrhamstufel", "Dorset Blue Vinney", "Double Gloucester", "Double Worcester",
+            "Dreux a la Feuille", "Dry Jack", "Duddleswell", "Dunbarra", "Dunlop", "Dunsyre Blue",
+            "Duroblando", "Durrus", "Dutch Mimolette (Commissiekaas)", "Edam", "Edelpilz",
+            "Emental Grand Cru", "Emlett", "Emmental", "Epoisses de Bourgogne", "Esbareich",
+            "Esrom", "Etorki", "Evansdale Farmhouse Brie", "Evora De L'Alentejo", "Exmoor Blue",
+            "Explorateur", "Feta", "Feta (Australian)", "Figue", "Filetta", "Fin-de-Siecle",
+            "Finlandia Swiss", "Finn", "Fiore Sardo", "Fleur du Maquis", "Flor de Guia",
+            "Flower Marie", "Folded", "Folded cheese with mint", "Fondant de Brebis",
+            "Fontainebleau", "Fontal", "Fontina Val d'Aosta", "Formaggio di capra", "Fougerus",
+            "Four Herb Gouda", "Fourme d' Ambert", "Fourme de Haute Loire", "Fourme de Montbrison",
+            "Fresh Jack", "Fresh Mozzarella", "Fresh Ricotta", "Fresh Truffles", "Fribourgeois",
+            "Friesekaas", "Friesian", "Friesla", "Frinault", "Fromage a Raclette", "Fromage Corse",
+            "Fromage de Montagne de Savoie", "Fromage Frais", "Fruit Cream Cheese",
+            "Frying Cheese", "Fynbo", "Gabriel", "Galette du Paludier", "Galette Lyonnaise",
+            "Galloway Goat's Milk Gems", "Gammelost", "Gaperon a l'Ail", "Garrotxa", "Gastanberra",
+            "Geitost", "Gippsland Blue", "Gjetost", "Gloucester", "Golden Cross", "Gorgonzola",
+            "Gornyaltajski", "Gospel Green", "Gouda", "Goutu", "Gowrie", "Grabetto", "Graddost",
+            "Grafton Village Cheddar", "Grana", "Grana Padano", "Grand Vatel",
+            "Grataron d' Areches", "Gratte-Paille", "Graviera", "Greuilh", "Greve",
+            "Gris de Lille", "Gruyere", "Gubbeen", "Guerbigny", "Halloumi",
+            "Halloumy (Australian)", "Haloumi-Style Cheese", "Harbourne Blue", "Havarti",
+            "Heidi Gruyere", "Hereford Hop", "Herrgardsost", "Herriot Farmhouse", "Herve",
+            "Hipi Iti", "Hubbardston Blue Cow", "Hushallsost", "Iberico", "Idaho Goatster",
+            "Idiazabal", "Il Boschetto al Tartufo", "Ile d'Yeu", "Isle of Mull", "Jarlsberg",
+            "Jermi Tortes", "Jibneh Arabieh", "Jindi Brie", "Jubilee Blue", "Juustoleipa",
+            "Kadchgall", "Kaseri", "Kashta", "Kefalotyri", "Kenafa", "Kernhem", "Kervella Affine",
+            "Kikorangi", "King Island Cape Wickham Brie", "King River Gold", "Klosterkaese",
+            "Knockalara", "Kugelkase", "L'Aveyronnais", "L'Ecir de l'Aubrac", "La Taupiniere",
+            "La Vache Qui Rit", "Laguiole", "Lairobell", "Lajta", "Lanark Blue", "Lancashire",
+            "Langres", "Lappi", "Laruns", "Lavistown", "Le Brin", "Le Fium Orbo", "Le Lacandou",
+            "Le Roule", "Leafield", "Lebbene", "Leerdammer", "Leicester", "Leyden", "Limburger",
+            "Lincolnshire Poacher", "Lingot Saint Bousquet d'Orb", "Liptauer", "Little Rydings",
+            "Livarot", "Llanboidy", "Llanglofan Farmhouse", "Loch Arthur Farmhouse",
+            "Loddiswell Avondale", "Longhorn", "Lou Palou", "Lou Pevre", "Lyonnais", "Maasdam",
+            "Macconais", "Mahoe Aged Gouda", "Mahon", "Malvern", "Mamirolle", "Manchego",
+            "Manouri", "Manur", "Marble Cheddar", "Marbled Cheeses", "Maredsous", "Margotin",
+            "Maribo", "Maroilles", "Mascares", "Mascarpone", "Mascarpone (Australian)",
+            "Mascarpone Torta", "Matocq", "Maytag Blue", "Meira", "Menallack Farmhouse",
+            "Menonita", "Meredith Blue", "Mesost", "Metton (Cancoillotte)", "Meyer Vintage Gouda",
+            "Mihalic Peynir", "Milleens", "Mimolette", "Mine-Gabhar", "Mini Baby Bells", "Mixte",
+            "Molbo", "Monastery Cheeses", "Mondseer", "Mont D'or Lyonnais", "Montasio",
+            "Monterey Jack", "Monterey Jack Dry", "Morbier", "Morbier Cru de Montagne",
+            "Mothais a la Feuille", "Mozzarella", "Mozzarella (Australian)",
+            "Mozzarella di Bufala", "Mozzarella Fresh, in water", "Mozzarella Rolls", "Munster",
+            "Murol", "Mycella", "Myzithra", "Naboulsi", "Nantais", "Neufchatel",
+            "Neufchatel (Australian)", "Niolo", "Nokkelost", "Northumberland", "Oaxaca",
+            "Olde York", "Olivet au Foin", "Olivet Bleu", "Olivet Cendre",
+            "Orkney Extra Mature Cheddar", "Orla", "Oschtjepka", "Ossau Fermier", "Ossau-Iraty",
+            "Oszczypek", "Oxford Blue", "P'tit Berrichon", "Palet de Babligny", "Paneer", "Panela",
+            "Pannerone", "Pant ys Gawn", "Parmesan (Parmigiano)", "Parmigiano Reggiano",
+            "Pas de l'Escalette", "Passendale", "Pasteurized Processed", "Pate de Fromage",
+            "Patefine Fort", "Pave d'Affinois", "Pave d'Auge", "Pave de Chirac", "Pave du Berry",
+            "Pecorino", "Pecorino in Walnut Leaves", "Pecorino Romano", "Peekskill Pyramid",
+            "Pelardon des Cevennes", "Pelardon des Corbieres", "Penamellera", "Penbryn",
+            "Pencarreg", "Perail de Brebis", "Petit Morin", "Petit Pardou", "Petit-Suisse",
+            "Picodon de Chevre", "Picos de Europa", "Piora", "Pithtviers au Foin",
+            "Plateau de Herve", "Plymouth Cheese", "Podhalanski", "Poivre d'Ane", "Polkolbin",
+            "Pont l'Eveque", "Port Nicholson", "Port-Salut", "Postel", "Pouligny-Saint-Pierre",
+            "Pourly", "Prastost", "Pressato", "Prince-Jean", "Processed Cheddar", "Provolone",
+            "Provolone (Australian)", "Pyengana Cheddar", "Pyramide", "Quark",
+            "Quark (Australian)", "Quartirolo Lombardo", "Quatre-Vents", "Quercy Petit",
+            "Queso Blanco", "Queso Blanco con Frutas --Pina y Mango", "Queso de Murcia",
+            "Queso del Montsec", "Queso del Tietar", "Queso Fresco", "Queso Fresco (Adobera)",
+            "Queso Iberico", "Queso Jalapeno", "Queso Majorero", "Queso Media Luna",
+            "Queso Para Frier", "Queso Quesadilla", "Rabacal", "Raclette", "Ragusano", "Raschera",
+            "Reblochon", "Red Leicester", "Regal de la Dombes", "Reggianito", "Remedou",
+            "Requeson", "Richelieu", "Ricotta", "Ricotta (Australian)", "Ricotta Salata", "Ridder",
+            "Rigotte", "Rocamadour", "Rollot", "Romano", "Romans Part Dieu", "Roncal", "Roquefort",
+            "Roule", "Rouleau De Beaulieu", "Royalp Tilsit", "Rubens", "Rustinu", "Saaland Pfarr",
+            "Saanenkaese", "Saga", "Sage Derby", "Sainte Maure", "Saint-Marcellin",
+            "Saint-Nectaire", "Saint-Paulin", "Salers", "Samso", "San Simon", "Sancerre",
+            "Sap Sago", "Sardo", "Sardo Egyptian", "Sbrinz", "Scamorza", "Schabzieger", "Schloss",
+            "Selles sur Cher", "Selva", "Serat", "Seriously Strong Cheddar", "Serra da Estrela",
+            "Sharpam", "Shelburne Cheddar", "Shropshire Blue", "Siraz", "Sirene", "Smoked Gouda",
+            "Somerset Brie", "Sonoma Jack", "Sottocenare al Tartufo", "Soumaintrain",
+            "Sourire Lozerien", "Spenwood", "Sraffordshire Organic", "St. Agur Blue Cheese",
+            "Stilton", "Stinking Bishop", "String", "Sussex Slipcote", "Sveciaost", "Swaledale",
+            "Sweet Style Swiss", "Swiss", "Syrian (Armenian String)", "Tala", "Taleggio", "Tamie",
+            "Tasmania Highland Chevre Log", "Taupiniere", "Teifi", "Telemea", "Testouri",
+            "Tete de Moine", "Tetilla", "Texas Goat Cheese", "Tibet", "Tillamook Cheddar",
+            "Tilsit", "Timboon Brie", "Toma", "Tomme Brulee", "Tomme d'Abondance",
+            "Tomme de Chevre", "Tomme de Romans", "Tomme de Savoie", "Tomme des Chouans", "Tommes",
+            "Torta del Casar", "Toscanello", "Touree de L'Aubier", "Tourmalet",
+            "Trappe (Veritable)", "Trois Cornes De Vendee", "Tronchon", "Trou du Cru", "Truffe",
+            "Tupi", "Turunmaa", "Tymsboro", "Tyn Grug", "Tyning", "Ubriaco", "Ulloa",
+            "Vacherin-Fribourgeois", "Valencay", "Vasterbottenost", "Venaco", "Vendomois",
+            "Vieux Corse", "Vignotte", "Vulscombe", "Waimata Farmhouse Blue",
+            "Washed Rind Cheese (Australian)", "Waterloo", "Weichkaese", "Wellington",
+            "Wensleydale", "White Stilton", "Whitestone Farmhouse", "Wigmore", "Woodside Cabecou",
+            "Xanadu", "Xynotyro", "Yarg Cornish", "Yarra Valley Pyramid", "Yorkshire Blue",
+            "Zamorano", "Zanetti Grana Padano", "Zanetti Parmigiano Reggiano"};
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListGetSelectedView.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListGetSelectedView.java
new file mode 100644
index 0000000..28fa21a
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListGetSelectedView.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import com.android.frameworktest.util.ListScenario;
+
+/**
+ * Basic top gravity scenario. This test is made to check that getSelectedView() will return
+ * null in touch mode.
+ */
+public class ListGetSelectedView extends ListScenario {
+    @Override
+    protected void init(Params params) {
+        params.setMustFillScreen(false).setNumItems(2).setItemScreenSizeFactor(0.22);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListHeterogeneous.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListHeterogeneous.java
new file mode 100644
index 0000000..93abd78
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListHeterogeneous.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.frameworktest.util.ListItemFactory;
+import com.android.frameworktest.util.ListScenario;
+
+/**
+ * List that has different view types
+ */
+public class ListHeterogeneous extends ListScenario {
+
+    @Override
+    protected void init(Params params) {
+        params.setNumItems(50)
+                .setItemScreenSizeFactor(1.0 / 8)
+                .setItemsFocusable(true)
+                .setHeaderViewCount(3)
+                .setFooterViewCount(2);
+    }
+
+    @Override
+    protected View createView(int position, ViewGroup parent, int desiredHeight) {
+        switch (position % 3) {
+        case 0:
+            return ListItemFactory.text(
+                    position, parent.getContext(), getValueAtPosition(position), desiredHeight);
+        case 1:
+            return ListItemFactory.button(
+                    position, parent.getContext(), getValueAtPosition(position), desiredHeight);
+        case 2:
+            return ListItemFactory.doubleText(
+                    position, parent.getContext(), getValueAtPosition(position), desiredHeight);
+        }
+        
+        return null;
+    }
+
+    @Override
+    public View convertView(int position, View convertView, ViewGroup parent) {
+        switch (position % 3) {
+        case 0:
+            return ListItemFactory.convertText(convertView, getValueAtPosition(position), position);
+        case 1:
+            return ListItemFactory.convertButton(convertView, getValueAtPosition(position),
+                    position);
+        case 2:
+            return ListItemFactory.convertDoubleText(convertView, getValueAtPosition(position),
+                    position);
+        }
+
+        return null;
+    }
+    
+    @Override
+    public int getItemViewType(int position) {
+        return position % 3;
+    }
+
+    @Override
+    public int getViewTypeCount() {
+        return 3;
+    }
+    
+    
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListHorizontalFocusWithinItemWins.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListHorizontalFocusWithinItemWins.java
new file mode 100644
index 0000000..c5e1e97
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListHorizontalFocusWithinItemWins.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.listview;
+
+import com.android.frameworktest.util.ListItemFactory;
+import static com.android.frameworktest.util.ListItemFactory.Slot;
+import com.android.frameworktest.util.ListScenario;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+public class ListHorizontalFocusWithinItemWins extends ListScenario {
+
+    @Override
+    protected void init(Params params) {
+        params.setItemsFocusable(true)
+                .setNumItems(2)
+                .setItemScreenSizeFactor(0.2)
+                .setMustFillScreen(false);
+    }
+
+    public Button getTopLeftButton() {
+        return (Button) ((ViewGroup) getListView().getChildAt(0)).getChildAt(0);
+    }
+
+    public Button getTopRightButton() {
+        return (Button) ((ViewGroup) getListView().getChildAt(0)).getChildAt(2);
+    }
+
+    public Button getBottomMiddleButton() {
+        return (Button) ((ViewGroup) getListView().getChildAt(1)).getChildAt(1);
+    }
+
+    @Override
+    protected View createView(int position, ViewGroup parent,
+            int desiredHeight) {
+        final Context context = parent.getContext();
+        if (position == 0) {
+            return ListItemFactory.horizontalButtonSlots(
+                    context, desiredHeight, Slot.Left, Slot.Right);
+        } else if (position == 1) {
+            return ListItemFactory.horizontalButtonSlots(
+                    context, desiredHeight, Slot.Middle);
+        } else {
+            throw new IllegalArgumentException("expecting position 0 or 1");
+        }
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListInHorizontal.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListInHorizontal.java
new file mode 100644
index 0000000..2128746
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListInHorizontal.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.widget.ArrayAdapter;
+import android.widget.GridView;
+import android.widget.TextView;
+import android.widget.ListView;
+
+import com.android.frameworktest.R;
+
+/**
+ * Exercises a list in a horizontal linear layout
+ */
+public class ListInHorizontal extends Activity {
+    private ListView mListView;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        setContentView(R.layout.list_in_horizontal);
+
+        String values[] = new String[1000];
+        for (int i = 0; i < 1000; i++) {
+            values[i] = ((Integer) i).toString();
+        }
+
+        mListView = (ListView) findViewById(R.id.list);
+        mListView.setAdapter(new ArrayAdapter<String>(this,
+                android.R.layout.simple_list_item_1, values));
+
+    }
+
+    public ListView getListView() {
+        return mListView;
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListInVertical.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListInVertical.java
new file mode 100644
index 0000000..f4c93c8
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListInVertical.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.widget.ArrayAdapter;
+import android.widget.GridView;
+import android.widget.TextView;
+import android.widget.ListView;
+
+import com.android.frameworktest.R;
+
+/**
+ * Exercises a list in a vertical linear layout
+ */
+public class ListInVertical extends Activity {
+    private ListView mListView;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        setContentView(R.layout.list_in_vertical);
+
+        String values[] = new String[1000];
+        for (int i = 0; i < 1000; i++) {
+            values[i] = ((Integer) i).toString();
+        }
+
+        mListView = (ListView) findViewById(R.id.list);
+        mListView.setAdapter(new ArrayAdapter<String>(this,
+                android.R.layout.simple_list_item_1, values));
+
+    }
+
+    public ListView getListView() {
+        return mListView;
+    }
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListInterleaveFocusables.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListInterleaveFocusables.java
new file mode 100644
index 0000000..e45297e
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListInterleaveFocusables.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.view.View;
+ import android.view.ViewGroup;
+ import com.google.android.collect.Sets;
+ import com.android.frameworktest.util.ListScenario;
+ import com.android.frameworktest.util.ListItemFactory;
+
+ import java.util.Set;
+
+/**
+ * List that interleaves focusable items.
+ */
+public class ListInterleaveFocusables extends ListScenario {
+
+    private Set<Integer> mFocusablePositions = Sets.newHashSet(1, 3, 6);
+
+    @Override
+    protected void init(Params params) {
+        params.setNumItems(7)
+                .setItemScreenSizeFactor(1.0 / 8)
+                .setItemsFocusable(true)
+                .setMustFillScreen(false);
+    }
+
+    @Override
+    protected View createView(int position, ViewGroup parent, int desiredHeight) {
+        if (mFocusablePositions.contains(position)) {
+            return ListItemFactory.button(
+                    position, parent.getContext(), getValueAtPosition(position), desiredHeight);
+        } else {
+            return super.createView(position, parent, desiredHeight);
+        }
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        return mFocusablePositions.contains(position) ? 0 : 1;
+    }
+
+    @Override
+    public int getViewTypeCount() {
+        return 2;
+    }
+    
+    
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListItemFocusableAboveUnfocusable.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListItemFocusableAboveUnfocusable.java
new file mode 100644
index 0000000..e14da5b
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListItemFocusableAboveUnfocusable.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+import com.android.frameworktest.util.ListItemFactory;
+import com.android.frameworktest.util.ListScenario;
+
+/**
+ * A list where the items may befocusable, but the second item isn't actually focusabe.
+ */
+public class ListItemFocusableAboveUnfocusable extends ListScenario {
+
+
+    protected void init(Params params) {
+        params.setNumItems(2)
+                .setItemsFocusable(true)
+                .setItemScreenSizeFactor(0.2)
+                .setMustFillScreen(false);
+    }
+
+    @Override
+    protected View createView(int position, ViewGroup parent, int desiredHeight) {
+        if (position == 0) {
+            return ListItemFactory.button(
+                    position, parent.getContext(), getValueAtPosition(position), desiredHeight);
+        } else {
+            return super.createView(position, parent, desiredHeight);
+        }
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListItemFocusablesClose.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListItemFocusablesClose.java
new file mode 100644
index 0000000..e20f633
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListItemFocusablesClose.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import com.android.frameworktest.util.ListScenario;
+import com.android.frameworktest.util.ListItemFactory;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * Each list item has two focusables that are close enough together that
+ * it shouldn't require panning to move focus.
+ */
+public class ListItemFocusablesClose extends ListScenario {
+
+
+    /**
+     * Get the child of a list item.
+     * @param listIndex The index of the currently visible items
+     * @param index The index of the child.
+     */
+    public View getChildOfItem(int listIndex, int index) {
+        return ((ViewGroup) getListView().getChildAt(listIndex)).getChildAt(index);
+
+    }
+        
+    @Override
+    protected void init(Params params) {
+        params.setItemsFocusable(true)
+                .setNumItems(2)
+                .setItemScreenSizeFactor(0.55);
+    }
+
+
+    @Override
+    protected View createView(int position, ViewGroup parent, int desiredHeight) {
+        return ListItemFactory.twoButtonsSeparatedByFiller(
+                position, parent.getContext(), desiredHeight);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListItemFocusablesFarApart.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListItemFocusablesFarApart.java
new file mode 100644
index 0000000..e974478
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListItemFocusablesFarApart.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.view.View;
+import android.view.ViewGroup;
+import com.android.frameworktest.util.ListItemFactory;
+import com.android.frameworktest.util.ListScenario;
+
+/**
+ * A list where each item is tall with buttons that are farther apart than the screen
+ * size.  We don't want to jump over content off screen to the next button, we need to
+ * pan across the intermediate part.
+ */
+public class ListItemFocusablesFarApart extends ListScenario  {
+
+
+    @Override
+    protected void init(Params params) {
+        params.setItemsFocusable(true)
+                .setNumItems(2)
+                .setItemScreenSizeFactor(2);
+    }
+
+    @Override
+    protected View createView(int position, ViewGroup parent, int desiredHeight) {
+        return ListItemFactory.twoButtonsSeparatedByFiller(
+                position, parent.getContext(), desiredHeight);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListItemISVAndButton.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListItemISVAndButton.java
new file mode 100644
index 0000000..d6c11b7
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListItemISVAndButton.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import com.android.frameworktest.util.InternalSelectionView;
+import com.android.frameworktest.util.ListScenario;
+
+/**
+ * Each item is an internal selection view, a button, and some filler
+ */
+public class ListItemISVAndButton extends ListScenario {
+
+
+    @Override
+    protected void init(Params params) {
+        params.setItemScreenSizeFactor(2.0)
+                .setNumItems(3)
+                .setItemsFocusable(true);
+    }
+
+    @Override
+    protected View createView(int position, ViewGroup parent, int desiredHeight) {
+        Context context = parent.getContext();
+
+        final LinearLayout ll = new LinearLayout(context);
+        ll.setOrientation(LinearLayout.VERTICAL);
+
+        final InternalSelectionView isv = new InternalSelectionView(context, 8, "ISV postion " + position);
+        isv.setLayoutParams(new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT,
+                desiredHeight - 240));
+        ll.addView(isv);
+
+        final LinearLayout.LayoutParams buttonLp =
+                new LinearLayout.LayoutParams(
+                        ViewGroup.LayoutParams.FILL_PARENT,
+                        40);
+        final Button topButton = new Button(context);
+        topButton.setLayoutParams(
+                buttonLp);
+        topButton.setText("button " + position + ")");
+        ll.addView(topButton);
+
+        final TextView filler = new TextView(context);
+        filler.setLayoutParams(new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT,
+                200));
+        filler.setText("filler");
+        ll.addView(filler);
+
+
+        return ll;
+    }
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListItemsExpandOnSelection.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListItemsExpandOnSelection.java
new file mode 100644
index 0000000..a137116
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListItemsExpandOnSelection.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.TextView;
+
+import com.android.frameworktest.util.ListScenario;
+
+/**
+ * A list where each item expands by 1.5 when selected.
+ */
+public class ListItemsExpandOnSelection extends ListScenario {
+
+
+    @Override
+    protected void init(Params params) {
+        params.setNumItems(10)
+                .setItemScreenSizeFactor(1.0/5);
+    }
+
+
+    @Override
+    protected View createView(int position, ViewGroup parent, int desiredHeight) {
+        TextView result = new ExpandWhenSelectedView(parent.getContext(), desiredHeight);
+        result.setHeight(desiredHeight);
+        result.setFocusable(mItemsFocusable);
+        result.setText(getValueAtPosition(position));
+        final AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT);
+        result.setLayoutParams(lp);
+        return result;
+    }
+
+    
+    @Override
+    public View convertView(int position, View convertView, ViewGroup parent) {
+        ((ExpandWhenSelectedView)convertView).setText(getValueAtPosition(position));
+        return convertView;
+    }
+
+
+    static private class ExpandWhenSelectedView extends TextView {
+
+        private final int mDesiredHeight;
+
+        public ExpandWhenSelectedView(Context context, int desiredHeight) {
+            super(context);
+            mDesiredHeight = desiredHeight;
+        }
+
+        @Override
+        public void setSelected(boolean selected) {
+            super.setSelected(selected);
+            if (selected) {
+                setHeight((int) (mDesiredHeight * 1.5));
+            } else {
+                setHeight(mDesiredHeight);
+            }
+        }
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListLastItemPartiallyVisible.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListLastItemPartiallyVisible.java
new file mode 100644
index 0000000..23b76a9
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListLastItemPartiallyVisible.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import com.android.frameworktest.util.ListScenario;
+
+/**
+ * A list where the very last item is partially visible, but still requires scrolling
+ * to bring it into view.
+ */
+public class ListLastItemPartiallyVisible extends ListScenario {
+
+    protected void init(Params params) {
+        params.setNumItems(5)
+                .setItemScreenSizeFactor(0.22);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListManagedCursor.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListManagedCursor.java
new file mode 100644
index 0000000..0cc242f
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListManagedCursor.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.listview;
+
+import android.app.ListActivity;
+import android.content.Intent;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.provider.Contacts.People;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListAdapter;
+import android.widget.SimpleCursorAdapter;
+import android.widget.AdapterView.OnItemClickListener;
+
+
+public class ListManagedCursor extends ListActivity implements OnItemClickListener {
+    
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // Get a cursor with all people
+        Cursor c = getContentResolver().query(Settings.System.CONTENT_URI, null, null, null, null);
+        startManagingCursor(c);
+
+        ListAdapter adapter = new SimpleCursorAdapter(this, 
+                // Use a template that displays a text view
+                android.R.layout.simple_list_item_1, 
+                // Give the cursor to the list adatper
+                c, 
+                // Map the NAME column in the people database to...
+                new String[] {People.NAME} ,
+                // The "text1" view defined in the XML template
+                new int[] {android.R.id.text1}); 
+        setListAdapter(adapter);
+        getListView().setOnItemClickListener(this);
+    }
+    
+    public void onItemClick(AdapterView parent, View view, int position, long id) {
+        Intent dummyIntent = new Intent(this, ListSimple.class);
+        startActivity(dummyIntent);
+    }
+}
+             
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListOfItemsShorterThanScreen.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListOfItemsShorterThanScreen.java
new file mode 100644
index 0000000..475ab31
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListOfItemsShorterThanScreen.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import com.android.frameworktest.util.ListScenario;
+
+public class ListOfItemsShorterThanScreen extends ListScenario {
+
+    protected void init(Params params) {
+        params.setNumItems(5)
+            .setItemScreenSizeFactor(1.1 / 4)
+            .setItemsFocusable(false);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListOfItemsTallerThanScreen.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListOfItemsTallerThanScreen.java
new file mode 100644
index 0000000..0d70abf
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListOfItemsTallerThanScreen.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import com.android.frameworktest.util.ListScenario;
+
+public class ListOfItemsTallerThanScreen extends ListScenario {
+
+
+    protected void init(Params params) {
+        params.setNumItems(3)
+            .setItemScreenSizeFactor(4.0 / 3)
+            .setItemsFocusable(false);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListOfShortShortTallShortShort.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListOfShortShortTallShortShort.java
new file mode 100644
index 0000000..62c5aa7
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListOfShortShortTallShortShort.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import com.android.frameworktest.util.ListScenario;
+
+/**
+ * Exposes fading in and out multiple items.
+ */
+public class ListOfShortShortTallShortShort extends ListScenario {
+
+
+    protected void init(Params params) {
+        params.setNumItems(5)
+                .setItemScreenSizeFactor(0.1)
+                .setFadingEdgeScreenSizeFactor(0.22)
+                .setPositionScreenSizeFactorOverride(2, 1.1);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListOfShortTallShort.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListOfShortTallShort.java
new file mode 100644
index 0000000..e60dee7
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListOfShortTallShort.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import com.android.frameworktest.util.ListScenario;
+
+/**
+ * Two short items separated by one that is taller than the screen.
+ */
+public class ListOfShortTallShort extends ListScenario {
+
+
+    protected void init(Params params) {
+        params.setItemScreenSizeFactor(1.0 / 8)
+                .setNumItems(3)
+                .setPositionScreenSizeFactorOverride(1, 1.2);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListOfThinItems.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListOfThinItems.java
new file mode 100644
index 0000000..d613c9b
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListOfThinItems.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import com.android.frameworktest.util.ListScenario;
+
+public class ListOfThinItems extends ListScenario {
+
+    protected void init(Params params) {
+
+        final int numItemsOnScreen = getScreenHeight() / 18;
+
+        params.setNumItems(numItemsOnScreen + 5)
+            .setItemScreenSizeFactor(18.0 / getScreenHeight())
+            .setItemsFocusable(false);
+    }
+
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListOfTouchables.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListOfTouchables.java
new file mode 100644
index 0000000..0e09190
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListOfTouchables.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+import com.android.frameworktest.util.ListScenario;
+
+/**
+ * Each list item has two focusables that are close enough together that
+ * it shouldn't require panning to move focus.
+ */
+public class ListOfTouchables extends ListScenario {
+
+
+    @Override
+    protected void init(Params params) {
+        params.setItemsFocusable(true)
+                .setItemScreenSizeFactor(0.2)
+                .setNumItems(100);
+    }
+
+
+    @Override
+    protected View createView(int position, ViewGroup parent, int desiredHeight) {
+        Button b = new Button(this);
+        b.setText("Position " + position);
+        b.setId(position);
+        return b;
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListRecyclerProfiling.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListRecyclerProfiling.java
new file mode 100644
index 0000000..3df3b9a
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListRecyclerProfiling.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.ImageButton;
+import android.view.ViewDebug;
+import android.view.View;
+
+import com.android.frameworktest.R;
+
+public class ListRecyclerProfiling extends Activity {
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        setContentView(R.layout.list_recycler_profiling);
+
+        String values[] = new String[1000];
+        for (int i = 0; i < 1000; i++) {
+            values[i] = ((Integer) i).toString();
+        }
+
+        ListView listView = (ListView) findViewById(R.id.list);
+
+        ViewDebug.startRecyclerTracing("SimpleList", listView);
+
+        listView.setAdapter(new ArrayAdapter<String>(this,
+                android.R.layout.simple_list_item_1, values));
+
+        ImageButton stopProfiling = (ImageButton) findViewById(R.id.pause);
+        stopProfiling.setOnClickListener(new View.OnClickListener() {
+            public void onClick(View v) {
+                ViewDebug.stopRecyclerTracing();
+            }
+        });
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListScrollListener.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListScrollListener.java
new file mode 100644
index 0000000..f5e4faf
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListScrollListener.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.app.ListActivity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.View;
+import android.widget.AbsListView;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.TextView;
+
+import com.android.frameworktest.R;
+
+/**
+ * Exercises change notification in a list
+ */
+public class ListScrollListener extends ListActivity implements AbsListView.OnScrollListener {
+    Handler mHandler = new Handler();
+    TextView mText;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        setContentView(R.layout.list_scroll_listener);
+
+        String values[] = new String[1000];
+        int i=0;
+        for(i=0; i<1000; i++) {
+            values[i] = ((Integer)i).toString();
+        }
+        
+        mText = (TextView) findViewById(R.id.text);
+        setListAdapter(new ArrayAdapter<String>(this,
+                android.R.layout.simple_list_item_1, values));
+
+
+        getListView().setOnScrollListener(this);
+    }
+
+    public void onItemSelected(AdapterView parent, View v, int position, long id) {
+        mText.setText("Position " + position);
+    }
+
+    public void onNothingSelected(AdapterView parent) {
+        mText.setText("Nothing");
+    }
+
+    public void onScroll(AbsListView view, int firstCell, int cellCount, int itemCount) {
+        int last = firstCell + cellCount - 1;
+        mText.setText("Showing " + firstCell + "-" + last + "/" + itemCount);
+    }
+
+    public void onScrollStateChanged(AbsListView view, int scrollState) {        
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListSetSelection.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListSetSelection.java
new file mode 100644
index 0000000..87888ca
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListSetSelection.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import com.android.frameworktest.util.ListScenario;
+import android.view.KeyEvent;
+import android.view.View;
+import android.os.Bundle;
+import android.widget.LinearLayout;
+import android.widget.Button;
+
+/**
+ * List of 1,000 items used to test calls to setSelection() in touch mode.
+ * Pressing the S key will call setSelection(0) on the list.
+ */
+public class ListSetSelection extends ListScenario {
+    private Button mButton;
+
+    @Override
+    protected void init(Params params) {
+        params.setStackFromBottom(false)
+                .setStartingSelectionPosition(-1)
+                .setNumItems(1000)
+                .setItemScreenSizeFactor(0.22);
+    }
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        mButton = new Button(this);
+        mButton.setText("setSelection(0)");
+        mButton.setOnClickListener(new View.OnClickListener() {
+            public void onClick(View v) {
+                getListView().setSelection(0);
+            }
+        });
+
+        getListViewContainer().addView(mButton, new LinearLayout.LayoutParams(
+                LinearLayout.LayoutParams.FILL_PARENT,
+                LinearLayout.LayoutParams.WRAP_CONTENT
+        ));
+    }
+
+    public Button getButton() {
+        return mButton;
+    }
+
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        if (event.getKeyCode() == KeyEvent.KEYCODE_S) {
+            getListView().setSelection(0);
+            return true;
+        }
+
+        return super.dispatchKeyEvent(event);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListSimple.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListSimple.java
new file mode 100644
index 0000000..e7517d6
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListSimple.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import com.android.frameworktest.util.ListScenario;
+
+import android.view.View;
+import android.view.ViewGroup;
+import android.os.Bundle;
+import android.widget.TextView;
+
+public class ListSimple extends ListScenario {
+    @Override
+    protected void init(Params params) {
+        params.setStackFromBottom(false)
+                .setStartingSelectionPosition(-1)
+                .setNumItems(1000)
+                .setItemScreenSizeFactor(0.14);
+    }
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+    
+        getListView().setVerticalScrollBarEnabled(true);
+        getListView().setFadingEdgeLength(12);
+        getListView().setVerticalFadingEdgeEnabled(true);
+    }
+
+    @Override
+    protected View createView(int position, ViewGroup parent, int desiredHeight) {
+        View view = super.createView(position, parent, desiredHeight);
+        view.setBackgroundColor(0xFF191919);
+        ((TextView) view).setTextSize(16.0f);
+        return view;
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListTakeFocusFromSide.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListTakeFocusFromSide.java
new file mode 100644
index 0000000..e576ea2
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListTakeFocusFromSide.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import com.android.frameworktest.R;
+
+import android.app.ListActivity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.LayoutInflater;
+import android.widget.BaseAdapter;
+import android.widget.TextView;
+
+/**
+ * Exercises moving focus into the list from the side
+ */
+public class ListTakeFocusFromSide extends ListActivity {
+
+    
+    private class ThrashListAdapter extends BaseAdapter {
+        private LayoutInflater mInflater;
+
+        private String[] mTitles = new String[100];
+
+        public ThrashListAdapter(Context context) {
+            mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+            mTitles = new String[100];
+
+            int i;
+            for (i = 0; i < 100; i++) {
+                mTitles[i] = "[" + i + "]";
+            }
+        }
+
+        public int getCount() {
+            return mTitles.length;
+        }
+
+        public Object getItem(int position) {
+            return position;
+        }
+
+        public long getItemId(int position) {
+            return position;
+        }
+
+        public View getView(int position, View convertView, ViewGroup parent) {
+            TextView view;
+
+            if (convertView == null) {
+                view = (TextView) mInflater.inflate(android.R.layout.simple_list_item_1, null);
+            } else {
+                view = (TextView) convertView;
+            }
+            view.setText(mTitles[position]);
+            return view;
+        }
+
+    }
+  
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        setContentView(R.layout.list_take_focus_from_side);
+        setListAdapter(new ThrashListAdapter(this));
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListThrasher.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListThrasher.java
new file mode 100644
index 0000000..e0b18a2
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListThrasher.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import com.android.frameworktest.R;
+
+import android.app.ListActivity;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.LayoutInflater;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.TextView;
+
+import java.util.Random;
+
+/**
+ * Exercises change notification in a list
+ */
+public class ListThrasher extends ListActivity implements AdapterView.OnItemSelectedListener {
+    Handler mHandler = new Handler();
+    ThrashListAdapter mAdapter;
+    Random mRandomizer = new Random();
+    TextView mText;
+
+    Runnable mThrash = new Runnable() {
+        public void run() {
+            mAdapter.bumpVersion();
+            mHandler.postDelayed(mThrash, 500);
+        }
+    };
+
+    private class ThrashListAdapter extends BaseAdapter {
+        private LayoutInflater mInflater;
+
+        /**
+         * Our data, part 1.
+         */
+        private String[] mTitles = new String[100];
+
+        /**
+         * Our data, part 2.
+         */
+        private int[] mVersion = new int[100];
+
+        public ThrashListAdapter(Context context) {
+            mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+            mTitles = new String[100];
+            mVersion = new int[100];
+
+            int i;
+            for (i = 0; i < 100; i++) {
+                mTitles[i] = "[" + i + "]";
+                mVersion[i] = 0;
+            }
+        }
+
+        public int getCount() {
+            return mTitles.length;
+        }
+
+        public Object getItem(int position) {
+            return position;
+        }
+
+        public long getItemId(int position) {
+            return position;
+        }
+
+        public View getView(int position, View convertView, ViewGroup parent) {
+            TextView view;
+
+            if (convertView == null) {
+                view = (TextView) mInflater.inflate(android.R.layout.simple_list_item_1, null);
+            } else {
+                view = (TextView) convertView;
+            }
+            view.setText(mTitles[position] + " " + mVersion[position]);
+            return view;
+        }
+
+
+        public void bumpVersion() {
+            int position = mRandomizer.nextInt(getCount());
+            mVersion[position]++;
+            notifyDataSetChanged();
+        }
+
+
+    }
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        setContentView(R.layout.list_thrasher);
+
+        mText = (TextView) findViewById(R.id.text);
+        mAdapter = new ThrashListAdapter(this);
+        setListAdapter(mAdapter);
+
+        mHandler.postDelayed(mThrash, 5000);
+
+        getListView().setOnItemSelectedListener(this);
+    }
+
+    public void onItemSelected(AdapterView parent, View v, int position, long id) {
+        mText.setText("Position " + position);
+    }
+
+    public void onNothingSelected(AdapterView parent) {
+        mText.setText("Nothing");
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListTopGravity.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListTopGravity.java
new file mode 100644
index 0000000..6eb65a9
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListTopGravity.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.view.Gravity;
+
+import com.android.frameworktest.util.ListScenario;
+
+/**
+ * Basic top gravity scenario, nothing fancy. Items do not
+ * fill the screen
+ */
+public class ListTopGravity extends ListScenario {
+
+    @Override
+    protected void init(Params params) {
+        params.setStackFromBottom(false)
+                .setStartingSelectionPosition(-1)
+                .setMustFillScreen(false)
+                .setNumItems(2)
+                .setItemScreenSizeFactor(0.22);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListTopGravityMany.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListTopGravityMany.java
new file mode 100644
index 0000000..8cff8ca
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListTopGravityMany.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import com.android.frameworktest.util.ListScenario;
+
+/**
+ * Basic top gravity scenario, nothing fancy. There are
+ * more items than fit on the screen
+ */
+public class ListTopGravityMany extends ListScenario {
+    
+    @Override
+    protected void init(Params params) {
+        params.setStackFromBottom(false)
+                .setStartingSelectionPosition(-1)
+                .setNumItems(10)
+                .setItemScreenSizeFactor(0.22);
+    }    
+    
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListViewHeight.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListViewHeight.java
new file mode 100644
index 0000000..17222d9
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListViewHeight.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+import com.android.frameworktest.R;
+
+public class ListViewHeight extends Activity {
+
+    private View mButton1;
+    private View mButton2;
+    private View mButton3;
+    
+    private View mOuterLayout;
+    private ListView mInnerList;
+
+    ArrayAdapter<String> mAdapter;
+    private String[] mStrings = {
+            "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi" };
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.linear_layout_listview_height);
+
+        mButton1 = findViewById(R.id.button1);
+        mButton2 = findViewById(R.id.button2);
+        mButton3 = findViewById(R.id.button3);
+        
+        mOuterLayout = findViewById(R.id.layout);
+        mInnerList = (ListView)findViewById(R.id.inner_list);
+        
+        mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, 
+                                            mStrings);
+
+        // Clicking this button will show the list view and set it to a fixed height
+        // If you then hide the views, there is no problem.
+        mButton1.setOnClickListener(new View.OnClickListener() {
+            public void onClick(View v) {
+                // set listview to fixed height 
+                ViewGroup.MarginLayoutParams lp;
+                lp = (ViewGroup.MarginLayoutParams) mInnerList.getLayoutParams();
+                lp.height = 200;
+                mInnerList.setLayoutParams(lp);
+                // enable list adapter
+                mInnerList.setAdapter(mAdapter);
+                // and show it
+                mOuterLayout.setVisibility(View.VISIBLE);
+            }
+        });
+
+        // Clicking this button will show the list view and set it fill_parent height
+        // If you then hide the views, there is an NPE when calculating the ListView height.
+        mButton2.setOnClickListener(new View.OnClickListener() {
+            public void onClick(View v) {
+                // set listview to fill screen
+                ViewGroup.MarginLayoutParams lp;
+                lp = (ViewGroup.MarginLayoutParams) mInnerList.getLayoutParams();
+                lp.height = lp.FILL_PARENT;
+                mInnerList.setLayoutParams(lp);
+                // enable list adapter
+                mInnerList.setAdapter(mAdapter);
+                // and show it
+                mOuterLayout.setVisibility(View.VISIBLE);
+            }
+        });
+
+        // Clicking this button will remove the list adapter and hide the outer enclosing view.
+        // We have to climb all the way to the top because the bug (not checking visibility)
+        // only occurs at the very outer loop of ViewRoot.performTraversals and in the case of
+        // an Activity, this means you have to crawl all the way out to the root view.
+        // In the search manager, it's sufficient to simply show/hide the outer search manager
+        // view to trigger the same bug.
+        mButton3.setOnClickListener(new View.OnClickListener() {
+            public void onClick(View v) {
+                mInnerList.setAdapter(null);
+                // hide listview's owner
+                // as it turns out, the owner doesn't take us high enough
+                // because our activity includes a title bar, thus another layer
+                View parent = (View) mOuterLayout.getParent();      // FrameLayout (app container)
+                View grandpa = (View) parent.getParent();           // LinearLayout (title+app)
+                View great = (View) grandpa.getParent();            // PhoneWindow.DecorView
+                great.setVisibility(View.GONE);
+            }
+        });
+    }
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithDisappearingItemBug.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithDisappearingItemBug.java
new file mode 100644
index 0000000..3a968af
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithDisappearingItemBug.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import com.android.frameworktest.R;
+
+import android.app.ListActivity;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.provider.Contacts.People;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
+import android.view.animation.AnimationSet;
+import android.view.animation.LayoutAnimationController;
+import android.view.animation.TranslateAnimation;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+import android.widget.SimpleCursorAdapter;
+import android.widget.Toast;
+
+/**
+ * See 1080989. You need some contacts for this adapter.
+ */
+public class ListWithDisappearingItemBug extends ListActivity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        Toast.makeText(this, "Make sure you rotate screen to see bug", Toast.LENGTH_LONG).show();
+        
+        // Get a cursor with all people
+        Cursor c = getContentResolver().query(People.CONTENT_URI, null, null, null, null);
+        startManagingCursor(c);
+
+        ListAdapter adapter = new SimpleCursorAdapter(this, 
+                // Use a template that displays a text view
+                R.layout.list_with_disappearing_item_bug_item, 
+                // Give the cursor to the list adatper
+                c, 
+                // Map the NAME column in the people database to...
+                new String[] {People.NAME} ,
+                // The "text1" view defined in the XML template
+                new int[] {R.id.text1}); 
+        setListAdapter(adapter);
+
+        AnimationSet set = new AnimationSet(true);
+
+        Animation animation = new AlphaAnimation(0.0f, 1.0f);
+        animation.setDuration(50);
+        set.addAnimation(animation);
+
+        animation = new TranslateAnimation(
+            Animation.RELATIVE_TO_SELF, 0.0f,Animation.RELATIVE_TO_SELF, 0.0f,
+            Animation.RELATIVE_TO_SELF, -1.0f,Animation.RELATIVE_TO_SELF, 0.0f
+        );
+        animation.setDuration(100);
+        set.addAnimation(animation);
+
+        LayoutAnimationController controller =
+                new LayoutAnimationController(set, 0.5f);
+        ListView listView = getListView();        
+        listView.setLayoutAnimation(controller);
+    }
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithEditTextHeader.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithEditTextHeader.java
new file mode 100644
index 0000000..b5cac2a
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithEditTextHeader.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.listview;
+
+import com.android.frameworktest.util.ListScenario;
+
+/**
+ * A list view with a single edit text in a header.
+ */
+public class ListWithEditTextHeader extends ListScenario {
+
+    @Override
+    protected void init(Params params) {
+        params.setHeaderViewCount(1)
+                .setHeaderFocusable(true)
+                .setItemsFocusable(true)
+                .setNumItems(6)
+                .setItemScreenSizeFactor(0.2);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithEmptyView.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithEmptyView.java
new file mode 100644
index 0000000..6f43551
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithEmptyView.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.listview;
+
+import com.android.frameworktest.R;
+
+import android.app.ListActivity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.ArrayAdapter;
+
+
+/**
+ * Tests using an empty view with a list */
+public class ListWithEmptyView extends ListActivity {
+    
+    private class CarefulAdapter<T> extends ArrayAdapter<T> {
+
+        public CarefulAdapter(Context context, int textViewResourceId) {
+            super(context, textViewResourceId);
+            // TODO Auto-generated constructor stub
+        }
+
+        @Override
+        public long getItemId(int position) {
+            if (position <  0 || position >= this.getCount()) {
+                throw new ArrayIndexOutOfBoundsException();
+            }
+            return super.getItemId(position);
+        }
+       
+        
+    }
+    
+    public static final int MENU_ADD = Menu.FIRST + 1;
+    public static final int MENU_REMOVE = Menu.FIRST + 2;
+    
+    private CarefulAdapter<String> mAdapter;
+    
+    private int mNextItem = 0;
+    
+    private View mEmptyView;
+    
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mAdapter = new CarefulAdapter<String>(this,
+                android.R.layout.simple_list_item_1);
+        setContentView(R.layout.list_with_empty_view);
+        setListAdapter(mAdapter);
+        
+        mEmptyView = findViewById(R.id.empty);
+        getListView().setEmptyView(mEmptyView);
+    }
+    
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        super.onCreateOptionsMenu(menu);
+        menu.add(0, MENU_ADD, 0, R.string.menu_add)
+                .setIcon(android.R.drawable.ic_menu_add);
+        menu.add(0, MENU_REMOVE, 0, R.string.menu_remove)
+                .setIcon(android.R.drawable.ic_menu_delete);
+        return true;
+    }
+    
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case MENU_ADD:
+                String str = "Item + " + mNextItem++;
+                mAdapter.add(str);
+                return true;
+            case MENU_REMOVE:
+                if (mAdapter.getCount() > 0) {
+                    mAdapter.remove(mAdapter.getItem(0));
+                }
+                return true;
+        }
+
+        return super.onOptionsItemSelected(item);
+    }
+
+    public View getEmptyView() {
+        return mEmptyView;
+    }
+   
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithFirstScreenUnSelectable.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithFirstScreenUnSelectable.java
new file mode 100644
index 0000000..4ad72fd
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithFirstScreenUnSelectable.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.frameworktest.listview;
+
+import com.android.frameworktest.util.ListScenario;
+
+/**
+ * The first item is unselectable, and takes up the whole screen.
+ */
+public class ListWithFirstScreenUnSelectable extends ListScenario {
+
+    @Override
+    protected void init(Params params) {
+        params.setItemScreenSizeFactor(1.2)
+                .setNumItems(2)
+                .setPositionsUnselectable(0);
+
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithHeaders.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithHeaders.java
new file mode 100644
index 0000000..d523094
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithHeaders.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import com.android.frameworktest.util.ListScenario;
+
+import android.os.Bundle;
+import android.widget.Button;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+
+public class ListWithHeaders extends ListScenario {
+    @Override
+    protected void init(Params params) {
+        params.setStackFromBottom(false)
+                .setStartingSelectionPosition(-1)
+                .setNumItems(24)
+                .setItemScreenSizeFactor(0.14);
+    }
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        final ListView listView = getListView();
+        listView.setItemsCanFocus(true);
+
+        for (int i = 0; i < 12; i++) {
+            Button header = new Button(this);
+            header.setText("Header View");
+            listView.addHeaderView(header);
+        }
+
+        for (int i = 0; i < 12; i++) {
+            Button footer = new Button(this);
+            footer.setText("Footer View");
+            listView.addFooterView(footer);
+        }
+
+        final ListAdapter adapter = listView.getAdapter();
+        listView.setAdapter(adapter);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithNoFadingEdge.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithNoFadingEdge.java
new file mode 100644
index 0000000..ecfc793
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithNoFadingEdge.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.listview;
+
+import com.android.frameworktest.util.ListScenario;
+
+public class ListWithNoFadingEdge extends ListScenario {
+
+    protected void init(Params params) {
+        params.setFadingEdgeScreenSizeFactor(0.0)
+                .setNumItems(10)
+                .setItemScreenSizeFactor(0.2);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithOffScreenNextSelectable.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithOffScreenNextSelectable.java
new file mode 100644
index 0000000..71525c0
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithOffScreenNextSelectable.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import com.android.frameworktest.util.ListScenario;
+
+/**
+ * Pressing down from position 0 requires looking past positions 1, 2 and 3 to
+ * an offscreen item to know that it is the next selectable.
+ */
+public class ListWithOffScreenNextSelectable extends ListScenario {
+
+
+    protected void init(Params params) {
+        params.setItemsFocusable(false)
+                .setNumItems(5)
+                .setItemScreenSizeFactor(0.25)
+                .setPositionUnselectable(1)
+                .setPositionUnselectable(2)
+                .setPositionUnselectable(3);
+    }
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithOnItemSelectedAction.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithOnItemSelectedAction.java
new file mode 100644
index 0000000..2683040
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithOnItemSelectedAction.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.widget.TextView;
+import com.android.frameworktest.util.ListScenario;
+
+/**
+ * The header text view echos the value of the selected item by using (indirectly)
+ * the {@link android.widget.AdapterView.OnItemSelectedListener}.
+ */
+public class ListWithOnItemSelectedAction extends ListScenario {
+    protected void init(Params params) {
+        params.setNumItems(8)
+                .setItemScreenSizeFactor(0.2)
+                .includeHeaderAboveList(true);
+
+    }
+
+    @Override
+    protected void positionSelected(int positon) {
+        if (positon != getListView().getSelectedItemPosition()) {
+            throw new IllegalStateException("something is fishy... the selected postion does not " +
+                    "match what the list reports.");
+        }
+        setHeaderValue(
+                ((TextView) getListView().getSelectedView()).getText().toString());
+
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithScreenOfNoSelectables.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithScreenOfNoSelectables.java
new file mode 100644
index 0000000..a2f3dc2
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithScreenOfNoSelectables.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.listview;
+
+import com.android.frameworktest.util.ListScenario;
+
+public class ListWithScreenOfNoSelectables extends ListScenario {
+
+    protected void init(Params params) {
+        params.setNumItems(10)
+                .setItemScreenSizeFactor(0.2)
+                .setPositionsUnselectable(1, 2, 3, 4, 5, 6, 7, 8, 9);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithSeparators.java b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithSeparators.java
new file mode 100644
index 0000000..71ce4e7
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/listview/ListWithSeparators.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import com.android.frameworktest.util.ListScenario;
+
+/**
+ * Basic separator scenario, nothing fancy.
+ */
+public class ListWithSeparators extends ListScenario {
+
+    protected void init(Params params) {
+        params.setItemsFocusable(false)
+                .setNumItems(5)
+                .setItemScreenSizeFactor(0.22)
+                .setPositionUnselectable(0)
+                .setPositionUnselectable(2);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/menus/ListContextMenu.java b/tests/FrameworkTest/src/com/android/frameworktest/menus/ListContextMenu.java
new file mode 100644
index 0000000..13c7552
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/menus/ListContextMenu.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.menus;
+
+import com.android.frameworktest.R;
+
+import android.app.ListActivity;
+import android.content.Context;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.ContextMenu;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.SubMenu;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.LayoutInflater;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.TextView;
+
+/**
+ * Exercises context menus in lists
+ */
+public class ListContextMenu extends ListActivity implements View.OnCreateContextMenuListener
+{
+    static final String TAG = "ListContextMenu";
+    
+    ThrashListAdapter mAdapter; 
+    
+    private class ThrashListAdapter extends BaseAdapter {
+        private LayoutInflater mInflater;
+        
+        private String[] mTitles = new String[100];
+
+        public ThrashListAdapter(Context context) {
+            mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+            mTitles = new String[100];
+            
+            int i;
+            for (i=0; i<100; i++) {
+                mTitles[i] = "[" + i + "]";
+            }
+        }
+
+        public int getCount() {
+            return mTitles.length;
+        }
+
+        public Object getItem(int position) {
+            return position;
+        }
+
+        public long getItemId(int position) {
+            return position;
+        }
+
+        public View getView(int position, View convertView, ViewGroup parent) {
+            TextView view;
+
+            if (convertView == null) {
+                view = (TextView) mInflater.inflate(android.R.layout.simple_list_item_1, null);
+            } else {
+                view = (TextView) convertView;
+            }
+            view.setText("List item " + mTitles[position]);
+            return view;
+        }
+
+    }
+    
+    @Override
+    public void onCreate(Bundle icicle) 
+    {
+        super.onCreate(icicle);
+        
+        mAdapter = new ThrashListAdapter(this);
+        getListView().setOnCreateContextMenuListener(this);
+        setListAdapter(mAdapter);
+    }
+    
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        MenuItem item = menu.add(0, 0, 0, "Really long menu item name");
+        item.setTitleCondensed("Long name");
+        item.setIcon(R.drawable.black_square);
+        
+        SubMenu sm = menu.addSubMenu(0, 0, 0, "The 2nd item, a sub menu").setIcon(R.drawable.black_square_stretchable);
+        item = sm.getItem();
+        item.setTitleCondensed("Sub menu");
+        sm.add(1, 0, 0, "Subitem 1");
+        sm.add(1, 0, 0, "Subitem 2");
+        sm.add(1, 0, 0, "Subitem 3");
+        sm.setGroupCheckable(1, true, true);
+        menu.add(0, 0, 0, "Item 3");
+        menu.add(0, 0, 0, "Item 4");
+        menu.add(0, 0, 0, "Item 5");
+        menu.add(0, 0, 0, "Item 6");
+        menu.add(0, 0, 0, "Item 7");
+        menu.add(0, 0, 0, "Item 8");
+        menu.add(0, 0, 0, "Item 9");
+        sm = menu.addSubMenu(0, 0, 0, "Item 10 SM");
+        sm.add(0, 0, 0, "Subitem 1");
+        sm.add(0, 0, 0, "Subitem 2");
+        sm.add(0, 0, 0, "Subitem 3");
+        sm.add(0, 0, 0, "Subitem 4");
+        sm.add(0, 0, 0, "Subitem 5");
+        sm.add(0, 0, 0, "Subitem 6");
+        sm.add(0, 0, 0, "Subitem 7");
+        sm.add(0, 0, 0, "Subitem 8");
+        
+        return true;
+    }
+
+    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
+        
+        AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo;
+        
+        String text = ((TextView) info.targetView).getText().toString();
+        if (text.contains("[0]")) {
+            menu.setHeaderTitle("This is a test of the title and the icon").setHeaderIcon(
+                    android.R.drawable.sym_def_app_icon);
+        } else if (text.contains("[1]")) {
+            menu.setHeaderTitle("This is a test of just the title");
+        } else {
+            TextView textView = new TextView(this);
+            textView.setText("This is a test of a custom View");
+            menu.setHeaderView(textView);
+        }
+        
+        menu.add(0, 0, 0, "Test 1");
+        SubMenu sm = menu.addSubMenu(0, 0, 0, "Test 1.5 SM");
+        sm.add(0, 0, 0, "CM Subitem 1");
+        sm.add(0, 0, 0, "CM Subitem 2");
+        sm.add(0, 0, 0, "CM Subitem 3");
+        menu.add(0, 0, 0, "Test 2");
+        menu.add(0, 0, 0, "Test 3");
+        menu.add(0, 0, 0, "Test 4");
+        menu.add(0, 0, 0, "Test 5");
+        menu.add(0, 0, 0, "Test 6");
+        menu.add(0, 0, 0, "Test 7");
+        menu.add(0, 0, 0, "Test 8");
+        menu.add(0, 0, 0, "Test 9");
+        menu.add(0, 0, 0, "Test 10");
+        menu.add(0, 0, 0, "Test 11");
+        menu.add(0, 0, 0, "Test 12");
+        menu.add(0, 0, 0, "Test 13");
+        menu.add(0, 0, 0, "Test 14");
+        menu.add(0, 0, 0, "Test 15");
+        menu.add(0, 0, 0, "Test 16");
+        menu.add(0, 0, 0, "Test 17");
+        menu.add(0, 0, 0, "Test 18");
+        menu.add(0, 0, 0, "Test 19");
+        menu.add(0, 0, 0, "Test 20");
+        menu.add(0, 0, 0, "Test 21");
+        menu.add(0, 0, 0, "Test 22");
+        menu.add(0, 0, 0, "Test 23");
+        menu.add(0, 0, 0, "Test 24");
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        Log.i(TAG, "Options item " + item.toString() + " selected.");
+        
+        return super.onOptionsItemSelected(item);
+    }
+
+    @Override
+    public void onOptionsMenuClosed(Menu menu) {
+        Log.i(TAG, "Options menu closed");
+    }
+
+    @Override
+    public boolean onContextItemSelected(MenuItem item) {
+        Log.i(TAG, "Context item " + item.toString() + " selected.");
+        
+        return super.onContextItemSelected(item);
+    }
+
+    @Override
+    public void onContextMenuClosed(Menu menu) {
+        Log.i(TAG, "Context menu closed");
+    }
+    
+    
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/menus/MenuLayout.java b/tests/FrameworkTest/src/com/android/frameworktest/menus/MenuLayout.java
new file mode 100644
index 0000000..6ed6433
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/menus/MenuLayout.java
@@ -0,0 +1,65 @@
+/**
+ * Copyright (C) 2008 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.frameworktest.menus;
+
+import com.android.frameworktest.menus.MenuScenario.Params;
+
+import android.os.Bundle;
+import android.view.Menu;
+import android.widget.Button;
+
+public class MenuLayout extends MenuScenario {
+    private static final String LONG_TITLE = "Really really really really really really really really really really long title";
+    private static final String SHORT_TITLE = "Item";
+
+    private Button mButton;
+    
+    @Override
+    protected void onInitParams(Params params) {
+        super.onInitParams(params);
+        params
+            .setNumItems(2)
+            .setItemTitle(0, LONG_TITLE)
+            .setItemTitle(1, LONG_TITLE);
+    }
+
+    @Override
+    public boolean onPrepareOptionsMenu(Menu menu) {
+
+        /*
+         * This activity is meant to try a bunch of different menu layouts. So,
+         * we recreate the menu every time it is prepared.
+         */ 
+        menu.clear();
+        onCreateOptionsMenu(menu);
+        
+        return true;
+    }
+
+    public Button getButton() {
+        return mButton;
+    }
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        mButton  = new Button(this);
+        setContentView(mButton);
+    }
+    
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/menus/MenuLayoutLandscape.java b/tests/FrameworkTest/src/com/android/frameworktest/menus/MenuLayoutLandscape.java
new file mode 100644
index 0000000..8a98610
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/menus/MenuLayoutLandscape.java
@@ -0,0 +1,24 @@
+/**
+ * Copyright (C) 2008 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.frameworktest.menus;
+
+/**
+ * An activity (inherits from MenuLayout) that shows in landscape.
+ */
+public class MenuLayoutLandscape extends MenuLayout {
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/menus/MenuLayoutPortrait.java b/tests/FrameworkTest/src/com/android/frameworktest/menus/MenuLayoutPortrait.java
new file mode 100644
index 0000000..71e7e49
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/menus/MenuLayoutPortrait.java
@@ -0,0 +1,24 @@
+/**
+ * Copyright (C) 2008 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.frameworktest.menus;
+
+/**
+ * An activity (inherits from MenuLayout) that shows in portrait.
+ */
+public class MenuLayoutPortrait extends MenuLayout {
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/menus/MenuScenario.java b/tests/FrameworkTest/src/com/android/frameworktest/menus/MenuScenario.java
new file mode 100644
index 0000000..4df9b1b
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/menus/MenuScenario.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.menus;
+
+import com.android.frameworktest.util.ListScenario;
+import com.android.internal.view.menu.MenuBuilder;
+import com.android.internal.view.menu.MenuBuilder.MenuAdapter;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.SparseArray;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+
+/**
+ * Utility base class for creating various Menu scenarios. Configurable by the
+ * number of menu items. Used @link {@link ListScenario} as a reference.
+ */
+public class MenuScenario extends Activity implements MenuItem.OnMenuItemClickListener {
+    private Params mParams = new Params();
+    private Menu mMenu;
+    private MenuItem[] mItems;
+    private boolean[] mWasItemClicked;
+    private MenuAdapter[] mMenuAdapters = new MenuAdapter[MenuBuilder.NUM_TYPES];
+    
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        dispatchInitParams();
+    }
+
+    private void dispatchInitParams() {
+        onInitParams(mParams);
+        onParamsChanged();
+    }
+    
+    public void setParams(Params params) {
+        mParams = params;
+        onParamsChanged();
+    }
+    
+    public void onParamsChanged() {
+        mItems = new MenuItem[mParams.numItems];
+        mWasItemClicked = new boolean[mParams.numItems];
+    }
+    
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        // Safe to hold on to
+        mMenu = menu;
+        
+        if (!mParams.shouldShowMenu) return false;
+        
+        MenuItem item;
+        for (int i = 0; i < mParams.numItems; i++) {
+            if ((item = onAddMenuItem(menu, i)) == null) {
+                // Add a default item for this position if the subclasses
+                // haven't
+                CharSequence givenTitle = mParams.itemTitles.get(i);
+                item = menu.add(0, 0, 0, (givenTitle != null) ? givenTitle : ("Item " + i));
+            }
+    
+            if (item != null) {
+                mItems[i] = item;
+                
+                if (mParams.listenForClicks) {
+                    item.setOnMenuItemClickListener(this);
+                }
+            }
+                
+        }
+        
+        return true;
+    }
+
+    @Override
+    public boolean onPrepareOptionsMenu(Menu menu) {
+        // Safe to hold on to
+        mMenu = menu;
+
+        return mParams.shouldShowMenu;
+    }
+
+    /**
+     * Override this to add an item to the menu.
+     * 
+     * @param itemPosition The position of the item to add (only for your
+     *            reference).
+     * @return The item that was added to the menu, or null if nothing was
+     *         added.
+     */
+    protected MenuItem onAddMenuItem(Menu menu, int itemPosition) {
+        return null;
+    }
+    
+    /**
+     * Override this to set the parameters for the scenario. Call through to super first.
+     * 
+     * @param params
+     */
+    protected void onInitParams(Params params) {
+    }
+    
+    public Menu getMenu() {
+        return mMenu;
+    }
+    
+    public boolean onMenuItemClick(MenuItem item) {
+        final int position = findItemPosition(item);
+        if (position < 0) return false;
+        
+        mWasItemClicked[position] = true;
+        
+        return true;
+    }
+
+    public boolean wasItemClicked(int position) {
+        return mWasItemClicked[position];
+    }
+
+    /**
+     * Finds the position for a given Item.
+     * 
+     * @param item The item to find.
+     * @return The position, or -1 if not found.
+     */
+    public int findItemPosition(MenuItem item) {
+        // Could create reverse mapping, but optimizations aren't important (yet :P)
+        for (int i = 0; i < mParams.numItems; i++) {
+            if (mItems[i] == item) return i;
+        }
+        
+        return -1;
+    }
+    
+    /**
+     * @see MenuBuilder#getMenuAdapter(int)
+     */
+    public MenuAdapter getMenuAdapter(int menuType) {
+        if (mMenuAdapters[menuType] == null) {
+            mMenuAdapters[menuType] = ((MenuBuilder) mMenu).getMenuAdapter(menuType);
+        }
+        
+        return mMenuAdapters[menuType];
+    }
+
+    /**
+     * Gets a menu view. Call this after you're sure it has been shown,
+     * otherwise it may not have the proper layout_* attributes set.
+     * 
+     * @param menuType The type of menu.
+     * @return The MenuView for that type.
+     */
+    public View getMenuView(int menuType) {
+        return ((MenuBuilder) mMenu).getMenuView(menuType, null);
+    }
+    
+    /**
+     * Gets the menu item view for a given position.
+     * 
+     * @param menuType The type of menu.
+     * @param position The position of the item.
+     * @return The menu item view for the given item in the given menu type.
+     */
+    public View getItemView(int menuType, int position) {
+        return getMenuAdapter(menuType).getView(position, null, null);
+    }
+    
+    public static class Params {
+        // Using as data structure, so no m prefix
+        private boolean shouldShowMenu = true;
+        private int numItems = 10;
+        private boolean listenForClicks = true;
+        private SparseArray<CharSequence> itemTitles = new SparseArray<CharSequence>();
+
+        public Params setShouldShowMenu(boolean shouldShowMenu) {
+            this.shouldShowMenu = shouldShowMenu;
+            return this;
+        }
+        
+        public Params setNumItems(int numItems) {
+            this.numItems = numItems;
+            return this;
+        }
+        
+        public Params setListenForClicks(boolean listenForClicks) {
+            this.listenForClicks = listenForClicks;
+            return this;
+        }
+        
+        public Params setItemTitle(int itemPos, CharSequence title) {
+            itemTitles.put(itemPos, title);
+            return this;
+        }
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/menus/MenuWith1Item.java b/tests/FrameworkTest/src/com/android/frameworktest/menus/MenuWith1Item.java
new file mode 100644
index 0000000..d7468f5
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/menus/MenuWith1Item.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.menus;
+
+import android.os.Bundle;
+import android.widget.Button;
+
+public class MenuWith1Item extends MenuScenario {
+
+    private Button mButton;
+
+    @Override
+    protected void onInitParams(Params params) {
+        super.onInitParams(params);
+        
+        params.setNumItems(1);
+    }
+
+    public Button getButton() {
+        return mButton;
+    }
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        mButton  = new Button(this);
+        setContentView(mButton);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/performance/InvalidateCycle.java b/tests/FrameworkTest/src/com/android/frameworktest/performance/InvalidateCycle.java
new file mode 100644
index 0000000..8663f06
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/performance/InvalidateCycle.java
@@ -0,0 +1,49 @@
+package com.android.frameworktest.performance;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Debug;
+import android.os.Handler;
+import android.view.View;
+import android.view.ViewGroup;
+import android.content.Context;
+import android.graphics.Canvas;
+
+public class InvalidateCycle extends Activity {
+    private boolean mStartProfiling;
+    private InvalidateCycle.AutoInvalidateView mView;
+
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        mView = new AutoInvalidateView(this);
+        mView.setLayoutParams(new ViewGroup.LayoutParams(16, 16));
+        setContentView(mView);
+
+        new Handler().postDelayed(new Runnable() {
+            public void run() {
+                mStartProfiling = true;
+                android.util.Log.d("Performance", "Profiling started");
+                Debug.startMethodTracing("invalidateCycle");
+                mView.invalidate();
+            }
+        }, 15000);
+    }
+
+    private class AutoInvalidateView extends View {
+        private boolean mFirstDraw;
+
+        public AutoInvalidateView(Context context) {
+            super(context);
+        }
+
+        protected void onDraw(Canvas canvas) {
+            if (mStartProfiling && !mFirstDraw) {
+                Debug.stopMethodTracing();
+                android.util.Log.d("Performance", "Profiling ended");
+                mFirstDraw = true;
+            }
+            canvas.drawColor(0xFFFF0000);            
+        }
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/scroll/ButtonAboveTallInternalSelectionView.java b/tests/FrameworkTest/src/com/android/frameworktest/scroll/ButtonAboveTallInternalSelectionView.java
new file mode 100644
index 0000000..986b800
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/scroll/ButtonAboveTallInternalSelectionView.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.scroll;
+
+import com.android.frameworktest.util.InternalSelectionView;
+import com.android.frameworktest.util.ScrollViewScenario;
+
+import android.widget.Button;
+
+/**
+ * A button above a tall internal selection view, wrapped in a scroll view.
+ */
+public class ButtonAboveTallInternalSelectionView extends ScrollViewScenario {
+
+    private final int mNumRowsInIsv = 5;
+
+
+    public Button getButtonAbove() {
+        return getContentChildAt(0);
+    }
+
+    public InternalSelectionView getIsv() {
+        return getContentChildAt(1);
+    }
+
+
+    protected void init(Params params) {
+        params.addButton("howdy", 0.1f)
+                .addInternalSelectionView(mNumRowsInIsv, 1.1f)
+                .addButton("below", 0.1f);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/scroll/ButtonsWithTallTextViewInBetween.java b/tests/FrameworkTest/src/com/android/frameworktest/scroll/ButtonsWithTallTextViewInBetween.java
new file mode 100644
index 0000000..ed098aa
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/scroll/ButtonsWithTallTextViewInBetween.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.scroll;
+
+import com.android.frameworktest.util.ScrollViewScenario;
+
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+/**
+ * Two buttons sandwiching a tall text view (good for testing panning across
+ * before getting to next button).
+ */
+public class ButtonsWithTallTextViewInBetween extends ScrollViewScenario {
+
+    public Button getTopButton() {
+        return getContentChildAt(0);
+    }
+
+    public TextView getMiddleFiller() {
+        return getContentChildAt(1);
+    }
+
+    public Button getBottomButton() {
+        LinearLayout ll = getContentChildAt(2);
+        return (Button) ll.getChildAt(0);
+    }
+
+    protected void init(Params params) {
+        
+        params.addButton("top button", 0.2f)
+                .addTextView("middle filler", 1.51f)
+                .addVerticalLLOfButtons("bottom", 1, 0.2f);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/scroll/RequestRectangleVisible.java b/tests/FrameworkTest/src/com/android/frameworktest/scroll/RequestRectangleVisible.java
new file mode 100644
index 0000000..affd3c7
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/scroll/RequestRectangleVisible.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.scroll;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.graphics.Rect;
+import android.view.View;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+/**
+ * A screen with some scenarios that exercise {@link ScrollView}'s implementation
+ * of {@link android.view.ViewGroup#requestChildRectangleOnScreen}:
+ * <li>Scrolling to something off screen (from top and from bottom)
+ * <li>Scrolling to bring something that is larger than the screen on screen
+ *  (from top and from bottom).
+ */
+public class RequestRectangleVisible extends Activity {
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        setContentView(R.layout.scroll_to_rectangle);
+
+        final Rect rect = new Rect();
+        final View childToMakeVisible = findViewById(R.id.childToMakeVisible);
+
+        final TextView topBlob = (TextView) findViewById(R.id.topBlob);
+        final TextView bottomBlob = (TextView) findViewById(R.id.bottomBlob);
+
+        // estimate to get blobs larger than screen
+        int screenHeight = getWindowManager().getDefaultDisplay().getHeight();
+        int numLinesForScreen = screenHeight / 18;
+
+        for (int i = 0; i < numLinesForScreen; i++) {
+            topBlob.append(i + " another line in the blob\n");
+            bottomBlob.append(i + " another line in the blob\n");
+        }
+
+        findViewById(R.id.scrollToRectFromTop).setOnClickListener(new View.OnClickListener() {
+
+            public void onClick(View v) {
+                rect.set(0, 0, childToMakeVisible.getLeft(), childToMakeVisible.getHeight());
+                childToMakeVisible.requestRectangleOnScreen(rect, true);
+            }
+        });
+
+        findViewById(R.id.scrollToRectFromTop2).setOnClickListener(new View.OnClickListener() {
+
+            public void onClick(View v) {
+                rect.set(0, 0, topBlob.getWidth(), topBlob.getHeight());
+                topBlob.requestRectangleOnScreen(rect, true);
+            }
+        });
+
+        findViewById(R.id.scrollToRectFromBottom).setOnClickListener(new View.OnClickListener() {
+
+            public void onClick(View v) {
+                rect.set(0, 0, childToMakeVisible.getLeft(), childToMakeVisible.getHeight());
+                childToMakeVisible.requestRectangleOnScreen(rect, true);
+            }
+        });
+
+        findViewById(R.id.scrollToRectFromBottom2).setOnClickListener(new View.OnClickListener() {
+
+            public void onClick(View v) {
+                rect.set(0, 0, bottomBlob.getWidth(), bottomBlob.getHeight());
+                bottomBlob.requestRectangleOnScreen(rect, true);
+            }
+        });
+        
+    }
+
+
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/scroll/RequestRectangleVisibleWithInternalScroll.java b/tests/FrameworkTest/src/com/android/frameworktest/scroll/RequestRectangleVisibleWithInternalScroll.java
new file mode 100644
index 0000000..0a8dc30
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/scroll/RequestRectangleVisibleWithInternalScroll.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.scroll;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.Button;
+import android.view.View;
+import android.graphics.Rect;
+
+public class RequestRectangleVisibleWithInternalScroll extends Activity {
+
+    private int scrollYofBlob = 52;
+
+    private TextView mTextBlob;
+    private Button mScrollToBlob;
+
+
+    public int getScrollYofBlob() {
+        return scrollYofBlob;
+    }
+
+
+    public TextView getTextBlob() {
+        return mTextBlob;
+    }
+
+
+    public Button getScrollToBlob() {
+        return mScrollToBlob;
+    }
+
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        setContentView(R.layout.scroll_to_rect_with_internal_scroll);
+
+        mTextBlob = (TextView) findViewById(R.id.blob);
+        mTextBlob.scrollBy(0, scrollYofBlob);
+
+
+        mScrollToBlob = (Button) findViewById(R.id.scrollToBlob);
+        mScrollToBlob.setOnClickListener(new View.OnClickListener() {
+
+            public void onClick(View v) {
+
+                // the rect we want to make visible is offset to match
+                // the internal scroll
+                Rect rect = new Rect();
+                rect.set(0, 0, 0, mTextBlob.getHeight());
+                rect.offset(0, mTextBlob.getScrollY());
+                mTextBlob.requestRectangleOnScreen(rect);
+            }
+        });
+    }
+
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/scroll/ScrollViewButtonsAndLabels.java b/tests/FrameworkTest/src/com/android/frameworktest/scroll/ScrollViewButtonsAndLabels.java
new file mode 100644
index 0000000..4763ab1
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/scroll/ScrollViewButtonsAndLabels.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.scroll;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+import android.widget.TextView;
+import android.widget.Button;
+
+
+/**
+ * Basic scroll view example
+ */
+public class ScrollViewButtonsAndLabels extends Activity {
+
+    private ScrollView mScrollView;
+    private LinearLayout mLinearLayout;
+
+    private int mNumGroups = 10;
+
+
+    public ScrollView getScrollView() {
+        return mScrollView;
+    }
+
+    public LinearLayout getLinearLayout() {
+        return mLinearLayout;
+    }
+
+    public int getNumButtons() {
+        return mNumGroups;
+    }
+
+    public Button getButton(int groupNum) {
+        if (groupNum > mNumGroups) {
+            throw new IllegalArgumentException("groupNum > " + mNumGroups);
+        }
+        return (Button) mLinearLayout.getChildAt(2*groupNum);
+    }
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.scrollview_linear_layout);
+
+
+        // estimated ratio to get enough buttons so a couple are off screen
+        int screenHeight = getWindowManager().getDefaultDisplay().getHeight();
+        mNumGroups = screenHeight / 30;
+
+        mScrollView = (ScrollView) findViewById(R.id.scrollView);
+        mLinearLayout = (LinearLayout) findViewById(R.id.layout);
+
+        LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(
+                LinearLayout.LayoutParams.FILL_PARENT,
+                LinearLayout.LayoutParams.WRAP_CONTENT
+        );
+
+        for (int i = 0; i < mNumGroups; i++) {
+            // want button to be first and last
+            if (i > 0) {
+                TextView textView = new TextView(this);
+                textView.setText("Text View " + i);
+                mLinearLayout.addView(textView, p);
+            }
+
+            Button button = new Button(this);
+            button.setText("Button " + (i + 1));
+            mLinearLayout.addView(button, p);
+        }
+    }
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/scroll/ShortButtons.java b/tests/FrameworkTest/src/com/android/frameworktest/scroll/ShortButtons.java
new file mode 100644
index 0000000..b903382
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/scroll/ShortButtons.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.scroll;
+
+import com.android.frameworktest.util.ScrollViewScenario;
+
+import android.widget.Button;
+import android.widget.LinearLayout;
+
+/**
+ * A series of short buttons, some of which are embedded within another
+ * layout.
+ */
+public class ShortButtons extends ScrollViewScenario {
+
+    private final int mNumButtons = 10;
+    protected final float mButtonHeightFactor = 0.2f;
+
+    public int getNumButtons() {
+        return mNumButtons;
+    }
+
+    public Button getButtonAt(int index) {
+        if (index < 3) {
+            return getContentChildAt(index);
+        } else {
+            LinearLayout ll = getContentChildAt(3);
+            return (Button) ll.getChildAt(index - 3);
+        }
+    }
+
+    @Override
+    protected void init(Params params) {
+        final int numButtonsInSubLayout = getNumButtons() - 3;
+        params.addButtons(3, "top-level", mButtonHeightFactor)
+                .addVerticalLLOfButtons("embedded",
+                        numButtonsInSubLayout,
+                        numButtonsInSubLayout * mButtonHeightFactor);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/scroll/TallTextAboveButton.java b/tests/FrameworkTest/src/com/android/frameworktest/scroll/TallTextAboveButton.java
new file mode 100644
index 0000000..8b2e4f9
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/scroll/TallTextAboveButton.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.scroll;
+
+import com.android.frameworktest.util.ScrollViewScenario;
+
+/**
+ * An (unfocusable) text view that takes up more than the height
+ * of the screen followed by a button.
+ */
+public class TallTextAboveButton extends ScrollViewScenario {
+
+    protected void init(Params params) {
+        params.addTextView("top tall", 1.1f)
+                .addButton("button", 0.2f);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/settings/BrightnessLimit.java b/tests/FrameworkTest/src/com/android/frameworktest/settings/BrightnessLimit.java
new file mode 100644
index 0000000..b812181
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/settings/BrightnessLimit.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.settings;
+
+import android.os.IHardwareService;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.provider.Settings;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+import com.android.frameworktest.R;
+
+/**
+ * Tries to set the brightness to 0. Should be silently thwarted by the framework.
+ */
+public class BrightnessLimit extends Activity implements OnClickListener {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        
+        setContentView(R.layout.brightness_limit);
+        
+        Button b = (Button) findViewById(R.id.go);
+        b.setOnClickListener(this);
+    }
+
+    public void onClick(View v) {
+        IHardwareService hardware = IHardwareService.Stub.asInterface(
+                ServiceManager.getService("hardware"));
+        if (hardware != null) {
+            try {
+                hardware.setScreenBacklight(0);
+            } catch (RemoteException darn) {
+                
+            }
+        }
+        Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, 0);
+    }
+}
+
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/settings/RingtonePickerActivityLauncher.java b/tests/FrameworkTest/src/com/android/frameworktest/settings/RingtonePickerActivityLauncher.java
new file mode 100644
index 0000000..19113da
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/settings/RingtonePickerActivityLauncher.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.settings;
+
+import com.android.internal.app.RingtonePickerActivity;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.Bundle;
+
+/**
+ * Activity that will launch the RingtonePickerActivity as a subactivity, and
+ * waits for its result.
+ */
+public class RingtonePickerActivityLauncher extends Activity {
+
+    private static final String TAG = "RingtonePickerActivityLauncher";
+    
+    public boolean resultReceived = false;
+    
+    public int resultCode;
+    public Intent result;
+
+    public Uri pickedUri;
+    
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        
+        setContentView(android.R.layout.simple_list_item_1);
+    }
+
+    /**
+     * Launches the {@link RingtonePickerActivity} and blocks until it returns.
+     * 
+     * @param showDefault {@link RingtonePickerActivity#EXTRA_SHOW_DEFAULT}
+     * @param existingUri {@link RingtonePickerActivity#EXTRA_EXISTING_URI}
+     * @param filterColumns {@link RingtonePickerActivity#EXTRA_RINGTONE_COLUMNS}
+     */
+    public void launchRingtonePickerActivity(boolean showDefault, Uri existingUri,
+            int types) {
+        Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
+        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, showDefault);
+        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, existingUri);
+        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, types);
+        startActivityForResult(intent, 0);
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+       
+        resultReceived = true;
+
+        this.resultCode = resultCode;
+        this.result = data;
+        
+        if (data != null) {
+            this.pickedUri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
+        }
+    }
+    
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/util/ExpandableListScenario.java b/tests/FrameworkTest/src/com/android/frameworktest/util/ExpandableListScenario.java
new file mode 100644
index 0000000..f72cbe8
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/util/ExpandableListScenario.java
@@ -0,0 +1,387 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.BaseExpandableListAdapter;
+import android.widget.ExpandableListAdapter;
+import android.widget.ExpandableListView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+/**
+ * Utility base class for creating various Expandable List scenarios.
+ * <p>
+ * WARNING: A lot of the features are mixed between ListView's expected position
+ * (flat list position) and an ExpandableListView's expected position.  You must add/change
+ * features as you need them.
+ * 
+ * @see ListScenario
+ */
+public abstract class ExpandableListScenario extends ListScenario {
+    protected ExpandableListAdapter mAdapter; 
+    protected List<MyGroup> mGroups;
+    
+    @Override
+    protected ListView createListView() {
+        return new ExpandableListView(this);
+    }
+
+    @Override
+    protected Params createParams() {
+        return new ExpandableParams();
+    }
+
+    @Override
+    protected void setAdapter(ListView listView) {
+        ((ExpandableListView) listView).setAdapter(mAdapter = createAdapter());
+    }
+    
+    protected ExpandableListAdapter createAdapter() {
+        return new MyAdapter();
+    }
+    
+    @Override
+    protected void readAndValidateParams(Params params) {
+        ExpandableParams expandableParams = (ExpandableParams) params;
+        
+        int[] numChildren = expandableParams.mNumChildren;
+        
+        mGroups = new ArrayList<MyGroup>(numChildren.length);
+        for (int i = 0; i < numChildren.length; i++) {
+            mGroups.add(new MyGroup(numChildren[i]));
+        }
+        
+        expandableParams.superSetNumItems();
+        
+        super.readAndValidateParams(params);
+    }
+
+    /**
+     * Get the ExpandableListView widget.
+     * @return The main widget.
+     */
+    public ExpandableListView getExpandableListView() {
+        return (ExpandableListView) super.getListView();
+    }
+
+    public static class ExpandableParams extends Params {
+        private int[] mNumChildren;
+        
+        /**
+         * Sets the number of children per group.
+         *  
+         * @param numChildrenPerGroup The number of children per group.
+         */
+        public ExpandableParams setNumChildren(int[] numChildren) {
+            mNumChildren = numChildren;
+            return this;
+        }
+
+        /**
+         * Sets the number of items on the superclass based on the number of
+         * groups and children per group.
+         */
+        private ExpandableParams superSetNumItems() {
+            int numItems = 0;
+            
+            if (mNumChildren != null) {
+                for (int i = mNumChildren.length - 1; i >= 0; i--) {
+                    numItems += mNumChildren[i];
+                }
+            }
+            
+            super.setNumItems(numItems);
+            
+            return this;
+        }
+        
+        @Override
+        public Params setNumItems(int numItems) {
+            throw new IllegalStateException("Use setNumGroups and setNumChildren instead.");
+        }
+
+        @Override
+        public ExpandableParams setFadingEdgeScreenSizeFactor(double fadingEdgeScreenSizeFactor) {
+            return (ExpandableParams) super.setFadingEdgeScreenSizeFactor(fadingEdgeScreenSizeFactor);
+        }
+
+        @Override
+        public ExpandableParams setItemScreenSizeFactor(double itemScreenSizeFactor) {
+            return (ExpandableParams) super.setItemScreenSizeFactor(itemScreenSizeFactor);
+        }
+
+        @Override
+        public ExpandableParams setItemsFocusable(boolean itemsFocusable) {
+            return (ExpandableParams) super.setItemsFocusable(itemsFocusable);
+        }
+
+        @Override
+        public ExpandableParams setMustFillScreen(boolean fillScreen) {
+            return (ExpandableParams) super.setMustFillScreen(fillScreen);
+        }
+
+        @Override
+        public ExpandableParams setPositionScreenSizeFactorOverride(int position, double itemScreenSizeFactor) {
+            return (ExpandableParams) super.setPositionScreenSizeFactorOverride(position, itemScreenSizeFactor);
+        }
+
+        @Override
+        public ExpandableParams setPositionUnselectable(int position) {
+            return (ExpandableParams) super.setPositionUnselectable(position);
+        }
+
+        @Override
+        public ExpandableParams setStackFromBottom(boolean stackFromBottom) {
+            return (ExpandableParams) super.setStackFromBottom(stackFromBottom);
+        }
+
+        @Override
+        public ExpandableParams setStartingSelectionPosition(int startingSelectionPosition) {
+            return (ExpandableParams) super.setStartingSelectionPosition(startingSelectionPosition);
+        }
+
+        @Override
+        public ExpandableParams setConnectAdapter(boolean connectAdapter) {
+            return (ExpandableParams) super.setConnectAdapter(connectAdapter);
+        }
+    }
+
+    /**
+     * Gets a string for the value of some item.
+     * @param packedPosition The position of the item.
+     * @return The string.
+     */
+    public final String getValueAtPosition(long packedPosition) {
+        final int type = ExpandableListView.getPackedPositionType(packedPosition);
+        
+        if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
+            return mGroups.get(ExpandableListView.getPackedPositionGroup(packedPosition))
+                    .children.get(ExpandableListView.getPackedPositionChild(packedPosition))
+                    .name;
+        } else if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
+            return mGroups.get(ExpandableListView.getPackedPositionGroup(packedPosition))
+                    .name;
+        } else {
+            throw new IllegalStateException("packedPosition is not a valid position.");
+        }
+    }
+
+    /**
+     * Whether a particular position is out of bounds.
+     * 
+     * @param packedPosition The packed position.
+     * @return Whether it's out of bounds.
+     */
+    private boolean isOutOfBounds(long packedPosition) {
+        final int type = ExpandableListView.getPackedPositionType(packedPosition);
+        
+        if (type == ExpandableListView.PACKED_POSITION_TYPE_NULL) {
+            throw new IllegalStateException("packedPosition is not a valid position.");
+        }
+
+        final int group = ExpandableListView.getPackedPositionGroup(packedPosition); 
+        if (group >= mGroups.size() || group < 0) {
+            return true;
+        }
+        
+        if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
+            final int child = ExpandableListView.getPackedPositionChild(packedPosition); 
+            if (child >= mGroups.get(group).children.size() || child < 0) {
+                return true;
+            }
+        }
+        
+        return false;
+    }
+    
+    /**
+     * Gets a view for the packed position, possibly reusing the convertView.
+     * 
+     * @param packedPosition The position to get a view for.
+     * @param convertView Optional view to convert.
+     * @param parent The future parent.
+     * @return A view.
+     */
+    private View getView(long packedPosition, View convertView, ViewGroup parent) {
+        if (isOutOfBounds(packedPosition)) {
+            throw new IllegalStateException("position out of range for adapter!");
+        }
+        
+        final ExpandableListView elv = getExpandableListView();
+        final int flPos = elv.getFlatListPosition(packedPosition); 
+        
+        if (convertView != null) {
+            ((TextView) convertView).setText(getValueAtPosition(packedPosition));
+            convertView.setId(flPos);
+            return convertView;
+        }
+
+        int desiredHeight = getHeightForPosition(flPos);
+        return createView(packedPosition, flPos, parent, desiredHeight);
+    }
+    
+    /**
+     * Create a view for a group or child position.
+     * 
+     * @param packedPosition The packed position (has type, group pos, and optionally child pos).
+     * @param flPos The flat list position (the position that the ListView goes by).
+     * @param parent The parent view.
+     * @param desiredHeight The desired height.
+     * @return A view.
+     */
+    protected View createView(long packedPosition, int flPos, ViewGroup parent, int desiredHeight) {
+        TextView result = new TextView(parent.getContext());
+        result.setHeight(desiredHeight);
+        result.setText(getValueAtPosition(packedPosition));
+        final ViewGroup.LayoutParams lp = new AbsListView.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT);
+        result.setLayoutParams(lp);
+        result.setGravity(Gravity.CENTER_VERTICAL);
+        result.setPadding(36, 0, 0, 0);
+        result.setId(flPos);
+        return result;
+    }
+    
+    /**
+     * Returns a group index containing either the number of children or at
+     * least one child.
+     * 
+     * @param numChildren The group must have this amount, or -1 if using
+     *            atLeastOneChild.
+     * @param atLeastOneChild The group must have at least one child, or false
+     *            if using numChildren.
+     * @return A group index with the requirements.
+     */
+    public int findGroupWithNumChildren(int numChildren, boolean atLeastOneChild) {
+        final ExpandableListAdapter adapter = mAdapter;
+        
+        for (int i = adapter.getGroupCount() - 1; i >= 0; i--) {
+            final int curNumChildren = adapter.getChildrenCount(i);
+            
+            if (numChildren == curNumChildren || atLeastOneChild && curNumChildren > 0) {
+                return i;
+            }
+        }
+        
+        return -1;
+    }
+    
+    public List<MyGroup> getGroups() {
+        return mGroups;
+    }
+    
+    public ExpandableListAdapter getAdapter() {
+        return mAdapter;
+    }
+
+    /**
+     * Simple expandable list adapter.
+     */
+    protected class MyAdapter extends BaseExpandableListAdapter {
+        public Object getChild(int groupPosition, int childPosition) {
+            return getValueAtPosition(ExpandableListView.getPackedPositionForChild(groupPosition,
+                    childPosition));
+        }
+
+        public long getChildId(int groupPosition, int childPosition) {
+            return mGroups.get(groupPosition).children.get(childPosition).id;
+        }
+
+        public int getChildrenCount(int groupPosition) {
+            return mGroups.get(groupPosition).children.size();
+        }
+
+        public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
+                View convertView, ViewGroup parent) {
+            return getView(ExpandableListView.getPackedPositionForChild(groupPosition,
+                    childPosition), convertView, parent);
+        }
+
+        public Object getGroup(int groupPosition) {
+            return getValueAtPosition(ExpandableListView.getPackedPositionForGroup(groupPosition));
+        }
+
+        public int getGroupCount() {
+            return mGroups.size();
+        }
+
+        public long getGroupId(int groupPosition) {
+            return mGroups.get(groupPosition).id;
+        }
+
+        public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
+                ViewGroup parent) {
+            return getView(ExpandableListView.getPackedPositionForGroup(groupPosition),
+                    convertView, parent);
+        }
+
+        public boolean isChildSelectable(int groupPosition, int childPosition) {
+            return true;
+        }
+
+        public boolean hasStableIds() {
+            return true;
+        }
+        
+    }
+
+    public static class MyGroup {
+        private static long mNextId = 1000;
+        
+        String name;
+        long id = mNextId++;
+        List<MyChild> children;
+        
+        public MyGroup(int numChildren) {
+            name = "Group " + id;
+            children = new ArrayList<MyChild>(numChildren);
+            for (int i = 0; i < numChildren; i++) {
+                children.add(new MyChild());
+            }
+        }
+    }
+    
+    public static class MyChild {
+        private static long mNextId = 2000;
+        
+        String name;
+        long id = mNextId++;
+        
+        public MyChild() {
+            name = "Child " + id;
+        }
+    }
+    
+    @Override
+    protected final void init(Params params) {
+        init((ExpandableParams) params);
+    }
+
+    /**
+     * @see ListScenario#init
+     */
+    protected abstract void init(ExpandableParams params);
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/util/GridScenario.java b/tests/FrameworkTest/src/com/android/frameworktest/util/GridScenario.java
new file mode 100644
index 0000000..746cf23
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/util/GridScenario.java
@@ -0,0 +1,370 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.util;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.widget.AbsListView;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.GridView;
+import android.widget.ListAdapter;
+import android.widget.TextView;
+
+import com.google.android.collect.Maps;
+
+import java.util.Map;
+
+/**
+ * Utility base class for creating various GridView scenarios.  Configurable by the number
+ * of items, how tall each item should be (in relation to the screen height), and
+ * what item should start with selection.
+ */
+public abstract class GridScenario extends Activity {
+
+    private GridView mGridView;
+
+    private int mNumItems;
+
+    private int mStartingSelectionPosition;
+    private double mItemScreenSizeFactor;
+    private Map<Integer, Double> mOverrideItemScreenSizeFactors = Maps.newHashMap();
+
+    private int mScreenHeight;
+
+    private boolean mStackFromBottom;
+
+    private int mColumnWidth;
+    
+    private int mNumColumns;
+    
+    private int mStretchMode;
+
+    private int mVerticalSpacing;
+
+    public GridView getGridView() {
+        return mGridView;
+    }
+
+    protected int getScreenHeight() {
+        return mScreenHeight;
+    }
+    
+    /**
+     * @return The initial number of items in the grid as specified by the scenario.
+     * This number may change over time.
+     */
+    protected int getInitialNumItems() {
+        return mNumItems;
+    }
+    
+    /**
+     * @return The desired height of 1 item, ignoring overrides
+     */
+    public int getDesiredItemHeight() {
+        return (int) (mScreenHeight * mItemScreenSizeFactor);
+    }
+
+    /**
+     * Better way to pass in optional params than a honkin' paramater list :)
+     */
+    public static class Params {
+        private int mNumItems = 4;
+        private int mStartingSelectionPosition = -1;
+        private double mItemScreenSizeFactor = 1 / 5;
+
+        private Map<Integer, Double> mOverrideItemScreenSizeFactors = Maps.newHashMap();
+
+        private boolean mStackFromBottom = false;
+        private boolean mMustFillScreen = true;
+
+        private int mColumnWidth = 0;
+        private int mNumColumns = GridView.AUTO_FIT;
+        private int mStretchMode = GridView.STRETCH_COLUMN_WIDTH;
+        private int mVerticalSpacing = 0;
+
+        /**
+         * Set the number of items in the grid.
+         */
+        public Params setNumItems(int numItems) {
+            mNumItems = numItems;
+            return this;
+        }
+
+        /**
+         * Set the position that starts selected.
+         *
+         * @param startingSelectionPosition The selected position within the adapter's data set.
+         * Pass -1 if you do not want to force a selection.
+         * @return
+         */
+        public Params setStartingSelectionPosition(int startingSelectionPosition) {
+            mStartingSelectionPosition = startingSelectionPosition;
+            return this;
+        }
+
+        /**
+         * Set the factor that determines how tall each item is in relation to the
+         * screen height.
+         */
+        public Params setItemScreenSizeFactor(double itemScreenSizeFactor) {
+            mItemScreenSizeFactor = itemScreenSizeFactor;
+            return this;
+        }
+
+        /**
+         * Override the item screen size factor for a particular item.  Useful for
+         * creating grids with non-uniform item height.
+         * @param position The position in the grid.
+         * @param itemScreenSizeFactor The screen size factor to use for the height.
+         */
+        public Params setPositionScreenSizeFactorOverride(
+                int position, double itemScreenSizeFactor) {
+            mOverrideItemScreenSizeFactors.put(position, itemScreenSizeFactor);
+            return this;
+        }
+
+        /**
+         * Sets the stacking direction
+         * @param stackFromBottom
+         * @return
+         */
+        public Params setStackFromBottom(boolean stackFromBottom) {
+            mStackFromBottom = stackFromBottom;
+            return this;
+        }
+
+        /**
+         * Sets whether the sum of the height of the grid items must be at least the
+         * height of the grid view.
+         */
+        public Params setMustFillScreen(boolean fillScreen) {
+            mMustFillScreen = fillScreen;
+            return this;
+        }
+
+        /**
+         * Sets the individual width of each column.
+         *
+         * @param requestedWidth the width in pixels of the column
+         */
+        public Params setColumnWidth(int requestedWidth) {
+            mColumnWidth = requestedWidth;
+            return this;
+        }
+
+        /**
+         * Sets the number of columns in the grid.
+         */
+        public Params setNumColumns(int numColumns) {
+            mNumColumns = numColumns;
+            return this;
+        }
+        
+        /**
+         * Sets the stretch mode.
+         */
+        public Params setStretchMode(int stretchMode) {
+            mStretchMode = stretchMode;
+            return this;
+        }
+        
+        /**
+         * Sets the spacing between rows in the grid
+         */
+        public Params setVerticalSpacing(int verticalSpacing) {
+            mVerticalSpacing  = verticalSpacing;
+            return this;
+        }
+    }
+
+    /**
+     * How each scenario customizes its behavior.
+     * @param params
+     */
+    protected abstract void init(Params params);
+    
+    /**
+     * Override this to provide an different adapter for your scenario
+     * @return The adapter that this scenario will use
+     */
+    protected ListAdapter createAdapter() {
+        return new MyAdapter();
+    }
+
+    /**
+     * Override this if you want to know when something has been selected (perhaps
+     * more importantly, that {@link android.widget.AdapterView.OnItemSelectedListener} has
+     * been triggered).
+     */
+    @SuppressWarnings({ "UnusedDeclaration" })
+    protected void positionSelected(int positon) {
+
+    }
+
+    /**
+     * Override this if you want to know that nothing is selected.
+     */
+    protected void nothingSelected() {
+
+    }
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        // turn off title bar
+        requestWindowFeature(Window.FEATURE_NO_TITLE);
+
+        mScreenHeight = getWindowManager().getDefaultDisplay().getHeight();
+
+        final Params params = new Params();
+        init(params);
+
+        readAndValidateParams(params);
+
+        mGridView = new GridView(this);
+        mGridView.setLayoutParams(new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT,
+                ViewGroup.LayoutParams.FILL_PARENT));
+        mGridView.setDrawSelectorOnTop(false);
+        if (mNumColumns >= GridView.AUTO_FIT) {
+            mGridView.setNumColumns(mNumColumns);
+        }
+        if (mColumnWidth > 0) {
+            mGridView.setColumnWidth(mColumnWidth);
+        }
+        if (mVerticalSpacing > 0) {
+            mGridView.setVerticalSpacing(mVerticalSpacing);
+        }
+        mGridView.setStretchMode(mStretchMode);
+        mGridView.setAdapter(createAdapter());
+        if (mStartingSelectionPosition >= 0) {
+            mGridView.setSelection(mStartingSelectionPosition);
+        }
+        mGridView.setPadding(10, 10, 10, 10);
+        mGridView.setStackFromBottom(mStackFromBottom);
+
+        mGridView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+            public void onItemSelected(AdapterView parent, View v, int position, long id) {
+                positionSelected(position);
+            }
+
+            public void onNothingSelected(AdapterView parent) {
+                nothingSelected();
+            }
+        });
+
+        setContentView(mGridView);
+    }
+    
+    
+
+    /**
+     * Read in and validate all of the params passed in by the scenario.
+     * @param params
+     */
+    private void readAndValidateParams(Params params) {
+        if (params.mMustFillScreen ) {
+            double totalFactor = 0.0;
+            for (int i = 0; i < params.mNumItems; i++) {
+                if (params.mOverrideItemScreenSizeFactors.containsKey(i)) {
+                    totalFactor += params.mOverrideItemScreenSizeFactors.get(i);
+                } else {
+                    totalFactor += params.mItemScreenSizeFactor;
+                }
+            }
+            if (totalFactor < 1.0) {
+                throw new IllegalArgumentException("grid items must combine to be at least " +
+                        "the height of the screen.  this is not the case with " + params.mNumItems
+                        + " items and " + params.mItemScreenSizeFactor + " screen factor and " +
+                        "screen height of " + mScreenHeight);
+            }
+        }
+
+        mNumItems = params.mNumItems;
+        mStartingSelectionPosition = params.mStartingSelectionPosition;
+        mItemScreenSizeFactor = params.mItemScreenSizeFactor;
+
+        mOverrideItemScreenSizeFactors.putAll(params.mOverrideItemScreenSizeFactors);
+
+        mStackFromBottom = params.mStackFromBottom;
+        mColumnWidth = params.mColumnWidth;
+        mNumColumns = params.mNumColumns;
+        mStretchMode = params.mStretchMode;
+        mVerticalSpacing = params.mVerticalSpacing;
+    }
+
+    public final String getValueAtPosition(int position) {
+        return "postion " + position;
+    }
+
+    /**
+     * Create a view for a grid item.  Override this to create a custom view beyond
+     * the simple focusable / unfocusable text view.
+     * @param position The position.
+     * @param parent The parent
+     * @param desiredHeight The height the view should be to respect the desired item
+     *   to screen height ratio.
+     * @return a view for the grid.
+     */
+    protected View createView(int position, ViewGroup parent, int desiredHeight) {
+        TextView result = new TextView(parent.getContext());
+        result.setHeight(desiredHeight);
+        result.setText(getValueAtPosition(position));
+        final ViewGroup.LayoutParams lp = new AbsListView.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT);
+        result.setLayoutParams(lp);
+        result.setId(position);
+        result.setBackgroundColor(0x55ffffff);
+        return result;
+    }
+
+
+
+    private class MyAdapter extends BaseAdapter {
+        public int getCount() {
+            return mNumItems;
+        }
+
+        public Object getItem(int position) {
+            return getValueAtPosition(position);
+        }
+
+        public long getItemId(int position) {
+            return position;
+        }
+
+        public View getView(int position, View convertView, ViewGroup parent) {
+            if (convertView != null) {
+                ((TextView) convertView).setText(getValueAtPosition(position));
+                convertView.setId(position);
+                return convertView;
+            }
+
+            int desiredHeight = getDesiredItemHeight();
+            if (mOverrideItemScreenSizeFactors.containsKey(position)) {
+                desiredHeight = (int) (mScreenHeight * mOverrideItemScreenSizeFactors.get(position));
+            }
+            return createView(position, parent, desiredHeight);
+        }
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/util/InternalSelectionView.java b/tests/FrameworkTest/src/com/android/frameworktest/util/InternalSelectionView.java
new file mode 100644
index 0000000..e500b94
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/util/InternalSelectionView.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.util;
+
+import com.android.frameworktest.R;
+
+import android.view.View;
+import android.view.KeyEvent;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Paint;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.Color;
+import android.util.AttributeSet;
+
+
+
+/**
+ * A view that has a known number of selectable rows, and maintains a notion of which
+ * row is selected. The rows take up the
+ * entire width of the view.  The height of the view is divided evenly among
+ * the rows.
+ *
+ * Notice what this view does to be a good citizen w.r.t its internal selection:
+ * 1) calls {@link View#requestRectangleOnScreen} each time the selection changes due to
+ *    internal navigation.
+ * 2) implements {@link View#getFocusedRect} by filling in the rectangle of the currently
+ *    selected row
+ * 3) overrides {@link View#onFocusChanged} and sets selection appropriately according to
+ *    the previously focused rectangle.
+ */
+public class InternalSelectionView extends View {
+
+    private Paint mPainter = new Paint();
+    private Paint mTextPaint = new Paint();
+    private Rect mTempRect = new Rect();
+
+    private int mNumRows = 5;
+    private int mSelectedRow = 0;
+    private final int mEstimatedPixelHeight = 10;
+
+    private Integer mDesiredHeight = null;
+    private String mLabel = null;
+
+    public InternalSelectionView(Context context, int numRows, String label) {
+        super(context);
+        mNumRows = numRows;
+        mLabel = label;
+        init();
+    }
+
+    public InternalSelectionView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        TypedArray a =
+                context.obtainStyledAttributes(
+                        attrs, R.styleable.SelectableRowView);
+        mNumRows = a.getInt(R.styleable.SelectableRowView_numRows, 5);
+        init();
+    }
+
+    private void init() {
+        setFocusable(true);
+        mTextPaint.setAntiAlias(true);
+        mTextPaint.setTextSize(10);
+        mTextPaint.setColor(Color.WHITE);
+    }
+
+    public int getNumRows() {
+        return mNumRows;
+    }
+
+    public int getSelectedRow() {
+        return mSelectedRow;
+    }
+
+    public void setDesiredHeight(int desiredHeight) {
+        mDesiredHeight = desiredHeight;
+    }
+
+    public String getLabel() {
+        return mLabel;
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        setMeasuredDimension(
+            measureWidth(widthMeasureSpec),
+            measureHeight(heightMeasureSpec));
+    }
+
+    private int measureWidth(int measureSpec) {
+        int specMode = MeasureSpec.getMode(measureSpec);
+        int specSize = MeasureSpec.getSize(measureSpec);
+
+        int desiredWidth = 300 + mPaddingLeft + mPaddingRight;
+        if (specMode == MeasureSpec.EXACTLY) {
+            // We were told how big to be
+            return specSize;
+        } else if (specMode == MeasureSpec.AT_MOST) {
+            return desiredWidth < specSize ? desiredWidth : specSize;
+        } else {
+            return desiredWidth;
+        }
+    }
+
+    private int measureHeight(int measureSpec) {
+        int specMode = MeasureSpec.getMode(measureSpec);
+        int specSize = MeasureSpec.getSize(measureSpec);
+
+        int desiredHeight = mDesiredHeight != null ?
+                mDesiredHeight :
+                mNumRows * mEstimatedPixelHeight + mPaddingTop + mPaddingBottom;
+        if (specMode == MeasureSpec.EXACTLY) {
+            // We were told how big to be
+            return specSize;
+        } else if (specMode == MeasureSpec.AT_MOST) {
+            return desiredHeight < specSize ? desiredHeight : specSize;
+        } else {
+            return desiredHeight;
+        }
+    }
+
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+
+        int rowHeight = getRowHeight();
+
+        int rectTop = mPaddingTop;
+        int rectLeft = mPaddingLeft;
+        int rectRight = getWidth() - mPaddingRight;
+        for (int i = 0; i < mNumRows; i++) {
+
+            mPainter.setColor(Color.BLACK);
+            mPainter.setAlpha(0x20);
+
+            // draw background rect
+            mTempRect.set(rectLeft, rectTop, rectRight, rectTop + rowHeight);
+            canvas.drawRect(mTempRect, mPainter);
+
+            // draw forground rect
+            if (i == mSelectedRow && hasFocus()) {
+                mPainter.setColor(Color.RED);
+                mPainter.setAlpha(0xF0);
+                mTextPaint.setAlpha(0xFF);
+            } else {
+                mPainter.setColor(Color.BLACK);
+                mPainter.setAlpha(0x40);
+                mTextPaint.setAlpha(0xF0);
+            }
+            mTempRect.set(rectLeft + 2, rectTop + 2,
+                    rectRight - 2, rectTop + rowHeight - 2);
+            canvas.drawRect(mTempRect, mPainter);
+
+            // draw text to help when visually inspecting
+            canvas.drawText(
+                    Integer.toString(i),
+                    rectLeft + 2,
+                    rectTop + 2 - (int) mTextPaint.ascent(),
+                    mTextPaint);
+
+            rectTop += rowHeight;
+        }
+    }
+
+    private int getRowHeight() {
+        return (getHeight() - mPaddingTop - mPaddingBottom) / mNumRows;
+    }
+
+    public void getRectForRow(Rect rect, int row) {
+        final int rowHeight = getRowHeight();
+        final int top = mPaddingTop + row * rowHeight;
+        rect.set(mPaddingLeft,
+                top,
+                getWidth() - mPaddingRight,
+                top + rowHeight);
+    }
+
+
+    void ensureRectVisible() {
+        getRectForRow(mTempRect, mSelectedRow);
+        requestRectangleOnScreen(mTempRect);
+    }
+
+
+    /* (non-Javadoc)
+    * @see android.view.KeyEvent.Callback#onKeyDown(int, android.view.KeyEvent)
+    */
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        switch(event.getKeyCode()) {
+            case KeyEvent.KEYCODE_DPAD_UP:
+                if (mSelectedRow > 0) {
+                    mSelectedRow--;
+                    invalidate();
+                    ensureRectVisible();
+                    return true;
+                }
+                break;
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+                if (mSelectedRow < (mNumRows - 1)) {
+                    mSelectedRow++;
+                    invalidate();
+                    ensureRectVisible();
+                    return true;
+                }
+                break;
+        }
+        return false;
+    }
+
+
+    @Override
+    public void getFocusedRect(Rect r) {
+        getRectForRow(r, mSelectedRow);
+    }
+
+    @Override
+    protected void onFocusChanged(boolean focused, int direction,
+            Rect previouslyFocusedRect) {
+        super.onFocusChanged(focused, direction, previouslyFocusedRect);
+
+        if (focused) {
+            switch (direction) {
+                case View.FOCUS_DOWN:
+                    mSelectedRow = 0;
+                    break;
+                case View.FOCUS_UP:
+                    mSelectedRow = mNumRows - 1;
+                    break;
+                case View.FOCUS_LEFT:  // fall through
+                case View.FOCUS_RIGHT:
+                    // set the row that is closest to the rect
+                    if (previouslyFocusedRect != null) {
+                        int y = previouslyFocusedRect.top
+                                + (previouslyFocusedRect.height() / 2);
+                        int yPerRow = getHeight() / mNumRows;
+                        mSelectedRow = y / yPerRow;
+                    } else {
+                        mSelectedRow = 0;
+                    }
+                    break;
+                default:
+                    // can't gleam any useful information about what internal
+                    // selection should be...
+                    return;
+            }
+            invalidate();
+        }
+    }
+
+    @Override
+    public String toString() {
+        if (mLabel != null) {
+            return mLabel;
+        }
+        return super.toString();
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/util/KeyUtils.java b/tests/FrameworkTest/src/com/android/frameworktest/util/KeyUtils.java
new file mode 100644
index 0000000..06feab4
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/util/KeyUtils.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.util;
+
+import android.app.Instrumentation;
+import android.os.SystemClock;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.InstrumentationTestCase;
+import android.view.Gravity;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+
+/**
+ * Reusable methods for generating key events.
+ * <p>
+ * Definitions:
+ * <li> Tap refers to pushing and releasing a button (down and up event).
+ * <li> Chord refers to pushing a modifier key, tapping a regular key, and
+ * releasing the modifier key.
+ */
+public class KeyUtils {
+    /**
+     * Simulates tapping the menu key.
+     * 
+     * @param test The test case that is being run.
+     */
+    public static void tapMenuKey(ActivityInstrumentationTestCase test) {
+        final Instrumentation inst = test.getInstrumentation();
+
+        inst.sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MENU));
+        inst.sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MENU));
+    }
+
+    /**
+     * Simulates chording the menu key.
+     * 
+     * @param test The test case that is being run.
+     * @param shortcutKey The shortcut key to tap while chording the menu key.
+     */
+    public static void chordMenuKey(ActivityInstrumentationTestCase test, char shortcutKey) {
+        final Instrumentation inst = test.getInstrumentation();
+
+        final KeyEvent pushMenuKey = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MENU);
+        final KeyCharacterMap keyCharMap = KeyCharacterMap.load(pushMenuKey.getDeviceId());
+        final KeyEvent shortcutKeyEvent = keyCharMap.getEvents(new char[] { shortcutKey })[0];
+        final int shortcutKeyCode = shortcutKeyEvent.getKeyCode();
+        
+        inst.sendKeySync(pushMenuKey);
+        inst.sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, shortcutKeyCode));
+        inst.sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, shortcutKeyCode));
+        inst.sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MENU));
+    }
+
+    /**
+     * Simulates a long click via the keyboard.
+     * 
+     * @param test The test case that is being run. 
+     */
+    public static void longClick(ActivityInstrumentationTestCase test) {
+        final Instrumentation inst = test.getInstrumentation();
+
+        inst.sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER));
+        try {
+            Thread.sleep((long)(ViewConfiguration.getLongPressTimeout() * 1.5f));
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        inst.sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER));
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/util/ListItemFactory.java b/tests/FrameworkTest/src/com/android/frameworktest/util/ListItemFactory.java
new file mode 100644
index 0000000..4327a8a
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/util/ListItemFactory.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.util;
+
+import android.content.Context;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+/**
+ * Reusable methods for creating more complex list items.
+ */
+public class ListItemFactory {
+
+    /**
+     * Create a view with a button at the top and bottom, with filler in between.
+     * The filler is sized to take up any space left over within desiredHeight.
+     *
+     * @param position      The position within the list.
+     * @param context       The context.
+     * @param desiredHeight The desired height of the entire view.
+     * @return The created view.
+     */
+    public static View twoButtonsSeparatedByFiller(int position, Context context, int desiredHeight) {
+        if (desiredHeight < 90) {
+            throw new IllegalArgumentException("need at least 90 pixels of height " +
+                    "to create the two buttons and leave 10 pixels for the filler");
+        }
+
+        final LinearLayout ll = new LinearLayout(context);
+        ll.setOrientation(LinearLayout.VERTICAL);
+
+        final LinearLayout.LayoutParams buttonLp =
+                new LinearLayout.LayoutParams(
+                        ViewGroup.LayoutParams.FILL_PARENT,
+                        50);
+
+        final Button topButton = new Button(context);
+        topButton.setLayoutParams(
+                buttonLp);
+        topButton.setText("top (position " + position + ")");
+        ll.addView(topButton);
+
+        final TextView middleFiller = new TextView(context);
+        middleFiller.setLayoutParams(new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT,
+                desiredHeight - 100));
+        middleFiller.setText("filler");
+        ll.addView(middleFiller);
+
+        final Button bottomButton = new Button(context);
+        bottomButton.setLayoutParams(buttonLp);
+        bottomButton.setText("bottom (position " + position + ")");
+        ll.addView(bottomButton);
+        ll.setTag("twoButtons");
+        return ll;
+    }
+
+    public enum Slot {
+        Left,
+        Middle,
+        Right
+    }
+
+    /**
+     * Create a horizontal linear layout divided into thirds (with some margins
+     * separating the thirds), filled with buttons into some slots.
+     * @param context The context.
+     * @param desiredHeight The height of the LL.
+     * @param slots Which slots to fill with buttons.
+     * @return The linear layout.
+     */
+    public static View horizontalButtonSlots(Context context, int desiredHeight, Slot... slots) {
+
+        final LinearLayout ll = new LinearLayout(context);
+        ll.setOrientation(LinearLayout.HORIZONTAL);
+
+        final LinearLayout.LayoutParams lp
+                = new LinearLayout.LayoutParams(0, desiredHeight);
+        lp.setMargins(10, 0, 10, 0);
+        lp.weight = 0.33f;
+
+        boolean left = false;
+        boolean middle = false;
+        boolean right = false;
+        for (Slot slot : slots) {
+            switch (slot) {
+                case Left:
+                    left = true;
+                    break;
+                case Middle:
+                    middle = true;
+                    break;
+                case Right:
+                    right = true;
+                    break;
+            }
+        }
+
+        if (left) {
+            final Button button = new Button(context);
+            button.setText("left");
+            ll.addView(button, lp);
+        } else {
+           ll.addView(new View(context), lp);
+        }
+
+        if (middle) {
+            final Button button = new Button(context);
+            button.setText("center");
+            ll.addView(button, lp);
+        } else {
+           ll.addView(new View(context), lp);
+        }
+
+        if (right) {
+            final Button button = new Button(context);
+            button.setText("right");
+            ll.addView(button, lp);
+        } else {
+           ll.addView(new View(context), lp);
+        }
+
+        return ll;
+    }
+
+
+    /**
+     * Create a button ready to be a list item.
+     *
+     * @param position      The position within the list.
+     * @param context       The context.
+     * @param text          The text of the button
+     * @param desiredHeight The desired height of the button
+     * @return The created view.
+     */
+    public static View button(int position, Context context, String text, int desiredHeight) {
+        TextView result = new Button(context);
+        result.setHeight(desiredHeight);
+        result.setText(text);
+        final ViewGroup.LayoutParams lp = new AbsListView.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT);
+        result.setLayoutParams(lp);
+        result.setId(position);
+        result.setTag("button");
+        return result;
+    }
+    
+    /**
+     * Convert an existing button view to display the data at a new position.
+     * 
+     * @param convertView Non-null Button created by {@link #button}
+     * @param text The text of the button
+     * @param position The position withion the list
+     * @return The converted view
+     */
+    public static View convertButton(View convertView, String text, int position) {
+        if (((String) convertView.getTag()).equals("button")) {
+            ((Button) convertView).setText(text);
+            convertView.setId(position);
+            return convertView;
+        } else {
+            return null;
+        }
+    }
+    
+    /**
+     * Create a text view ready to be a list item.
+     *
+     * @param position      The position within the list.
+     * @param context       The context.
+     * @param text          The text to display
+     * @param desiredHeight The desired height of the text view
+     * @return The created view.
+     */
+    public static View text(int position, Context context, String text, int desiredHeight) {
+        TextView result = new TextView(context);
+        result.setHeight(desiredHeight);
+        result.setText(text);
+        final ViewGroup.LayoutParams lp = new AbsListView.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT);
+        result.setLayoutParams(lp);
+        result.setId(position);
+        result.setTag("text");
+        return result;
+    }
+    
+    /**
+     * Convert an existing text view to display the data at a new position.
+     * 
+     * @param convertView Non-null TextView created by {@link #text}
+     * @param text The text to display
+     * @param position The position withion the list
+     * @return The converted view
+     */
+    public static View convertText(View convertView, String text, int position) {
+        if(convertView.getTag() != null && ((String) convertView.getTag()).equals("text")) {
+            ((TextView) convertView).setText(text);
+            convertView.setId(position);
+            return convertView;
+
+        } else {
+            return null;
+        }
+    }
+    
+    /**
+     * Create a text view ready to be a list item.
+     *
+     * @param position      The position within the list.
+     * @param context       The context.
+     * @param text          The text of the button
+     * @param desiredHeight The desired height of the button
+     * @return The created view.
+     */
+    public static View doubleText(int position, Context context, String text, int desiredHeight) {
+        final LinearLayout ll = new LinearLayout(context);
+        ll.setOrientation(LinearLayout.HORIZONTAL);
+
+        final AbsListView.LayoutParams lp =
+                new AbsListView.LayoutParams(
+                        ViewGroup.LayoutParams.FILL_PARENT,
+                        desiredHeight);
+        ll.setLayoutParams(lp);
+        ll.setId(position);
+        
+        TextView t1 = new TextView(context);
+        t1.setHeight(desiredHeight);
+        t1.setText(text);
+        t1.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
+        final ViewGroup.LayoutParams lp1 = new LinearLayout.LayoutParams(
+                0,
+                ViewGroup.LayoutParams.WRAP_CONTENT, 1.0f);
+        ll.addView(t1, lp1);
+        
+        TextView t2 = new TextView(context);
+        t2.setHeight(desiredHeight);
+        t2.setText(text);
+        t2.setGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL);
+        final ViewGroup.LayoutParams lp2 = new LinearLayout.LayoutParams(
+                0,
+                ViewGroup.LayoutParams.WRAP_CONTENT,
+                1.0f);
+
+        ll.addView(t2, lp2);
+        ll.setTag("double");
+        return ll;
+    }
+
+    
+    /**
+     * Convert an existing button view to display the data at a new position.
+     * 
+     * @param convertView Non-null view created by {@link #doubleText}
+     * @param text The text of the button
+     * @param position The position withion the list
+     * @return The converted view
+     */
+    public static View convertDoubleText(View convertView, String text, int position) {
+        if (((String) convertView.getTag()).equals("double")) {
+            TextView t1 = (TextView) ((LinearLayout) convertView).getChildAt(0);
+            TextView t2 = (TextView) ((LinearLayout) convertView).getChildAt(1);
+            t1.setText(text);
+            t2.setText(text);
+            convertView.setId(position);
+            return convertView;
+        } else {
+            return null;
+        }
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/util/ListScenario.java b/tests/FrameworkTest/src/com/android/frameworktest/util/ListScenario.java
new file mode 100644
index 0000000..5889658
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/util/ListScenario.java
@@ -0,0 +1,662 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.util;
+
+import android.app.Activity;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.TextView;
+import com.google.android.collect.Maps;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Utility base class for creating various List scenarios.  Configurable by the number
+ * of items, how tall each item should be (in relation to the screen height), and
+ * what item should start with selection.
+ */
+public abstract class ListScenario extends Activity {
+
+    private ListView mListView;
+    private TextView mHeaderTextView;
+
+    private int mNumItems;
+    protected boolean mItemsFocusable;
+
+    private int mStartingSelectionPosition;
+    private double mItemScreenSizeFactor;
+    private Map<Integer, Double> mOverrideItemScreenSizeFactors = Maps.newHashMap();
+
+    private int mScreenHeight;
+
+    // whether to include a text view above the list
+    private boolean mIncludeHeader;
+
+    // separators
+    private Set<Integer> mUnselectableItems = new HashSet<Integer>();
+    
+    private boolean mStackFromBottom;
+
+    private int mClickedPosition = -1;
+    
+    private int mLongClickedPosition = -1;
+    
+    private int mConvertMisses = 0;
+    
+    private int mHeaderViewCount;
+    private boolean mHeadersFocusable;
+    
+    private int mFooterViewCount;
+    private LinearLayout mLinearLayout;
+
+    public ListView getListView() {
+        return mListView;
+    }
+
+    protected int getScreenHeight() {
+        return mScreenHeight;
+    }
+
+    /**
+     * Return whether the item at position is selectable (i.e is a separator).
+     * (external users can access this info using the adapter)
+     */
+    private boolean isItemAtPositionSelectable(int position) {
+        return !mUnselectableItems.contains(position);
+    }
+
+    /**
+     * Better way to pass in optional params than a honkin' paramater list :)
+     */
+    public static class Params {
+        private int mNumItems = 4;
+        private boolean mItemsFocusable = false;
+        private int mStartingSelectionPosition = 0;
+        private double mItemScreenSizeFactor = 1 / 5;
+        private Double mFadingEdgeScreenSizeFactor = null;
+
+        private Map<Integer, Double> mOverrideItemScreenSizeFactors = Maps.newHashMap();
+
+        // separators
+        private List<Integer> mUnselectableItems = new ArrayList<Integer>(8);
+        // whether to include a text view above the list
+        private boolean mIncludeHeader = false;
+        private boolean mStackFromBottom = false;
+        public boolean mMustFillScreen = true;
+        private int mHeaderViewCount;
+        private boolean mHeaderFocusable = false;
+        private int mFooterViewCount;
+
+        private boolean mConnectAdapter = true;
+
+        /**
+         * Set the number of items in the list.
+         */
+        public Params setNumItems(int numItems) {
+            mNumItems = numItems;
+            return this;
+        }
+
+        /**
+         * Set whether the items are focusable.
+         */
+        public Params setItemsFocusable(boolean itemsFocusable) {
+            mItemsFocusable = itemsFocusable;
+            return this;
+        }
+
+        /**
+         * Set the position that starts selected.
+         *
+         * @param startingSelectionPosition The selected position within the adapter's data set.
+         * Pass -1 if you do not want to force a selection.
+         * @return
+         */
+        public Params setStartingSelectionPosition(int startingSelectionPosition) {
+            mStartingSelectionPosition = startingSelectionPosition;
+            return this;
+        }
+
+        /**
+         * Set the factor that determines how tall each item is in relation to the
+         * screen height.
+         */
+        public Params setItemScreenSizeFactor(double itemScreenSizeFactor) {
+            mItemScreenSizeFactor = itemScreenSizeFactor;
+            return this;
+        }
+
+        /**
+         * Override the item screen size factor for a particular item.  Useful for
+         * creating lists with non-uniform item height.
+         * @param position The position in the list.
+         * @param itemScreenSizeFactor The screen size factor to use for the height.
+         */
+        public Params setPositionScreenSizeFactorOverride(
+                int position, double itemScreenSizeFactor) {
+            mOverrideItemScreenSizeFactors.put(position, itemScreenSizeFactor);
+            return this;
+        }
+
+        /**
+         * Set a position as unselectable (a.k.a a separator)
+         * @param position
+         * @return
+         */
+        public Params setPositionUnselectable(int position) {
+            mUnselectableItems.add(position);
+            return this;
+        }
+
+        /**
+         * Set positions as unselectable (a.k.a a separator)
+         */
+        public Params setPositionsUnselectable(int ...positions) {
+            for (int pos : positions) {
+                setPositionUnselectable(pos);
+            }
+            return this;
+        }
+
+        /**
+         * Include a header text view above the list.
+         * @param includeHeader
+         * @return
+         */
+        public Params includeHeaderAboveList(boolean includeHeader) {
+            mIncludeHeader = includeHeader;
+            return this;
+        }
+        
+        /**
+         * Sets the stacking direction
+         * @param stackFromBottom
+         * @return
+         */
+        public Params setStackFromBottom(boolean stackFromBottom) {
+            mStackFromBottom = stackFromBottom;
+            return this;
+        }
+        
+        /**
+         * Sets whether the sum of the height of the list items must be at least the
+         * height of the list view.
+         */
+        public Params setMustFillScreen(boolean fillScreen) {
+            mMustFillScreen = fillScreen;
+            return this;
+        }
+
+        /**
+         * Set the factor for the fading edge length.
+         */
+        public Params setFadingEdgeScreenSizeFactor(double fadingEdgeScreenSizeFactor) {
+            mFadingEdgeScreenSizeFactor = fadingEdgeScreenSizeFactor;
+            return this;
+        }
+        
+        /**
+         * Set the number of header views to appear within the list
+         */
+        public Params setHeaderViewCount(int headerViewCount) {
+            mHeaderViewCount = headerViewCount;
+            return this;
+        }
+
+        /**
+         * Set whether the headers should be focusable.
+         * @param headerFocusable Whether the headers should be focusable (i.e
+         *   created as edit texts rather than text views).
+         */
+        public Params setHeaderFocusable(boolean headerFocusable) {
+            mHeaderFocusable = headerFocusable;
+            return this;
+        }
+
+        /**
+         * Set the number of footer views to appear within the list
+         */
+        public Params setFooterViewCount(int footerViewCount) {
+            mFooterViewCount = footerViewCount;
+            return this;
+        }
+        
+        /**
+         * Sets whether the {@link ListScenario} will automatically set the
+         * adapter on the list view. If this is false, the client MUST set it
+         * manually (this is useful when adding headers to the list view, which
+         * must be done before the adapter is set).
+         */
+        public Params setConnectAdapter(boolean connectAdapter) {
+            mConnectAdapter = connectAdapter;
+            return this;
+        }
+    }
+
+    /**
+     * How each scenario customizes its behavior.
+     * @param params
+     */
+    protected abstract void init(Params params);
+
+    /**
+     * Override this if you want to know when something has been selected (perhaps
+     * more importantly, that {@link android.widget.AdapterView.OnItemSelectedListener} has
+     * been triggered).
+     */
+    protected void positionSelected(int positon) {
+    }
+
+    /**
+     * Override this if you want to know that nothing is selected.
+     */
+    protected void nothingSelected() {
+    }
+    
+    /**
+     * Override this if you want to know when something has been clicked (perhaps
+     * more importantly, that {@link android.widget.AdapterView.OnItemClickListener} has
+     * been triggered).
+     */
+    protected void positionClicked(int position) {
+        setClickedPosition(position);
+    }
+    
+    /**
+     * Override this if you want to know when something has been long clicked (perhaps
+     * more importantly, that {@link android.widget.AdapterView.OnItemLongClickListener} has
+     * been triggered).
+     */
+    protected void positionLongClicked(int position) {
+        setLongClickedPosition(position);
+    }
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        // for test stability, turn off title bar
+        requestWindowFeature(Window.FEATURE_NO_TITLE);
+        
+
+        mScreenHeight = getWindowManager().getDefaultDisplay().getHeight();
+
+        final Params params = createParams();
+        init(params);
+
+        readAndValidateParams(params);
+
+
+        mListView = createListView();
+        mListView.setLayoutParams(new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT,
+                ViewGroup.LayoutParams.FILL_PARENT));
+        mListView.setDrawSelectorOnTop(false);
+
+        for (int i=0; i<mHeaderViewCount; i++) {
+            TextView header = mHeadersFocusable ?
+                    new EditText(this) :
+                    new TextView(this);
+            header.setText("Header: " + i);
+            mListView.addHeaderView(header);
+        }
+        
+        for (int i=0; i<mFooterViewCount; i++) {
+            TextView header = new TextView(this);
+            header.setText("Footer: " + i);
+            mListView.addFooterView(header);
+        }
+
+        if (params.mConnectAdapter) {
+            setAdapter(mListView);
+        }
+        
+        mListView.setItemsCanFocus(mItemsFocusable);
+        if (mStartingSelectionPosition >= 0) {
+            mListView.setSelection(mStartingSelectionPosition);
+        }
+        mListView.setPadding(0, 0, 0, 0);
+        mListView.setStackFromBottom(mStackFromBottom);
+        mListView.setDivider(null);
+
+        mListView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+            public void onItemSelected(AdapterView parent, View v, int position, long id) {
+                positionSelected(position);
+            }
+
+            public void onNothingSelected(AdapterView parent) {
+                nothingSelected();
+            }
+        });
+
+        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+            public void onItemClick(AdapterView parent, View v, int position, long id) {
+                positionClicked(position);
+            }
+        });
+        
+        // set the fading edge length porportionally to the screen
+        // height for test stability
+        if (params.mFadingEdgeScreenSizeFactor != null) {
+            mListView.setFadingEdgeLength((int) (params.mFadingEdgeScreenSizeFactor * mScreenHeight));            
+        } else {
+            mListView.setFadingEdgeLength((int) ((64.0 / 480) * mScreenHeight));
+        }
+
+        if (mIncludeHeader) {
+            mLinearLayout = new LinearLayout(this);
+
+            mHeaderTextView = new TextView(this);
+            mHeaderTextView.setText("hi");
+            mHeaderTextView.setLayoutParams(new LinearLayout.LayoutParams(
+                    ViewGroup.LayoutParams.FILL_PARENT,
+                    ViewGroup.LayoutParams.WRAP_CONTENT));
+            mLinearLayout.addView(mHeaderTextView);
+
+            mLinearLayout.setOrientation(LinearLayout.VERTICAL);
+            mLinearLayout.setLayoutParams(new ViewGroup.LayoutParams(
+                    ViewGroup.LayoutParams.FILL_PARENT,
+                    ViewGroup.LayoutParams.FILL_PARENT));
+            mListView.setLayoutParams((new LinearLayout.LayoutParams(
+                    ViewGroup.LayoutParams.FILL_PARENT,
+                    0,
+                    1f)));
+
+            mLinearLayout.addView(mListView);
+            setContentView(mLinearLayout);
+        } else {
+            mLinearLayout = new LinearLayout(this);
+            mLinearLayout.setOrientation(LinearLayout.VERTICAL);
+            mLinearLayout.setLayoutParams(new ViewGroup.LayoutParams(
+                    ViewGroup.LayoutParams.FILL_PARENT,
+                    ViewGroup.LayoutParams.FILL_PARENT));
+            mListView.setLayoutParams((new LinearLayout.LayoutParams(
+                    ViewGroup.LayoutParams.FILL_PARENT,
+                    0,
+                    1f)));
+            mLinearLayout.addView(mListView);
+            setContentView(mLinearLayout);
+        }
+    }
+
+    /**
+     * Returns the LinearLayout containing the ListView in this scenario.
+     *
+     * @return The LinearLayout in which the ListView is held.
+     */
+    protected LinearLayout getListViewContainer() {
+        return mLinearLayout;
+    }
+
+    /**
+     * Attaches a long press listener. You can find out which views were clicked by calling
+     * {@link #getLongClickedPosition()}.
+     */
+    public void enableLongPress() {
+        mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
+            public boolean onItemLongClick(AdapterView parent, View v, int position, long id) {
+                positionLongClicked(position);
+                return true;
+            }
+        });
+    }
+    
+    /**
+     * @return The newly created ListView widget.
+     */
+    protected ListView createListView() {
+        return new ListView(this);
+    }
+
+    /**
+     * @return The newly created Params object.
+     */
+    protected Params createParams() {
+        return new Params();
+    }
+    
+    /**
+     * Sets an adapter on a ListView.
+     * 
+     * @param listView The ListView to set the adapter on.
+     */
+    protected void setAdapter(ListView listView) {
+        listView.setAdapter(new MyAdapter());
+    }
+    
+    /**
+     * Read in and validate all of the params passed in by the scenario.
+     * @param params
+     */
+    protected void readAndValidateParams(Params params) {
+        if (params.mMustFillScreen ) {
+            double totalFactor = 0.0;
+            for (int i = 0; i < params.mNumItems; i++) {
+                if (params.mOverrideItemScreenSizeFactors.containsKey(i)) {
+                    totalFactor += params.mOverrideItemScreenSizeFactors.get(i);
+                } else {
+                    totalFactor += params.mItemScreenSizeFactor;
+                }
+            }
+            if (totalFactor < 1.0) {
+                throw new IllegalArgumentException("list items must combine to be at least " +
+                        "the height of the screen.  this is not the case with " + params.mNumItems
+                        + " items and " + params.mItemScreenSizeFactor + " screen factor and " +
+                        "screen height of " + mScreenHeight);
+            }
+        }
+
+        mNumItems = params.mNumItems;
+        mItemsFocusable = params.mItemsFocusable;
+        mStartingSelectionPosition = params.mStartingSelectionPosition;
+        mItemScreenSizeFactor = params.mItemScreenSizeFactor;
+
+        mOverrideItemScreenSizeFactors.putAll(params.mOverrideItemScreenSizeFactors);
+
+        mUnselectableItems.addAll(params.mUnselectableItems);
+        mIncludeHeader = params.mIncludeHeader;
+        mStackFromBottom = params.mStackFromBottom;
+        mHeaderViewCount = params.mHeaderViewCount;
+        mHeadersFocusable = params.mHeaderFocusable;
+        mFooterViewCount = params.mFooterViewCount;
+    }
+
+    public final String getValueAtPosition(int position) {
+        return isItemAtPositionSelectable(position)
+                ?
+                "position " + position:
+                "------- " + position;
+    }
+
+    /**
+     * @return The height that will be set for a particular position.
+     */
+    public int getHeightForPosition(int position) {
+        int desiredHeight = (int) (mScreenHeight * mItemScreenSizeFactor);
+        if (mOverrideItemScreenSizeFactors.containsKey(position)) {
+            desiredHeight = (int) (mScreenHeight * mOverrideItemScreenSizeFactors.get(position));
+        }
+        return desiredHeight;
+    }
+
+
+    /**
+     * @return The contents of the header above the list.
+     * @throws IllegalArgumentException if there is no header.
+     */
+    public final String getHeaderValue() {
+        if (!mIncludeHeader) {
+            throw new IllegalArgumentException("no header above list");
+        }
+        return mHeaderTextView.getText().toString();
+    }
+
+    /**
+     * @param value What to put in the header text view
+     * @throws IllegalArgumentException if there is no header.
+     */
+    protected final void setHeaderValue(String value) {
+        if (!mIncludeHeader) {
+            throw new IllegalArgumentException("no header above list");
+        }
+        mHeaderTextView.setText(value);        
+    }
+
+    /**
+     * Create a view for a list item.  Override this to create a custom view beyond
+     * the simple focusable / unfocusable text view.
+     * @param position The position.
+     * @param parent The parent
+     * @param desiredHeight The height the view should be to respect the desired item
+     *   to screen height ratio.
+     * @return a view for the list.
+     */
+    protected View createView(int position, ViewGroup parent, int desiredHeight) {
+        return ListItemFactory.text(position, parent.getContext(), getValueAtPosition(position),
+                desiredHeight);
+    }
+
+    /**
+     * Convert a non-null view. 
+     */
+    public View convertView(int position, View convertView, ViewGroup parent) {
+        return ListItemFactory.convertText(convertView, getValueAtPosition(position), position);
+    }
+    
+    public void setClickedPosition(int clickedPosition) {
+        mClickedPosition = clickedPosition;
+    }
+
+    public int getClickedPosition() {
+        return mClickedPosition;
+    }
+
+    public void setLongClickedPosition(int longClickedPosition) {
+        mLongClickedPosition = longClickedPosition;
+    }
+
+    public int getLongClickedPosition() {
+        return mLongClickedPosition;
+    }
+
+    /**
+     * Have a child of the list view call {@link View#requestRectangleOnScreen(android.graphics.Rect)}.
+     * @param childIndex The index into the viewgroup children (i.e the children that are
+     *   currently visible).
+     * @param rect The rectangle, in the child's coordinates.
+     */
+    public void requestRectangleOnScreen(int childIndex, final Rect rect) {
+        final View child = getListView().getChildAt(childIndex);
+
+        child.post(new Runnable() {
+            public void run() {
+                child.requestRectangleOnScreen(rect);
+            }
+        });
+    }
+    
+    /**
+     * Return an item type for the specified position in the adapter. Override if your
+     * adapter creates more than one type.
+     */
+    public int getItemViewType(int position) {
+        return 0;
+    }
+
+    /**
+     * Return an the number of types created by the adapter. Override if your
+     * adapter creates more than one type.
+     */
+    public int getViewTypeCount() {
+        return 1;
+    }
+    
+    /**
+     * @return The number of times convertView failed
+     */
+    public int getConvertMisses() {
+        return mConvertMisses;
+    }
+
+    private class MyAdapter extends BaseAdapter {
+
+        public int getCount() {
+            return mNumItems;
+        }
+
+        public Object getItem(int position) {
+            return getValueAtPosition(position);
+        }
+
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public boolean areAllItemsEnabled() {
+            return mUnselectableItems.isEmpty();
+        }
+
+        @Override
+        public boolean isEnabled(int position) {
+            return isItemAtPositionSelectable(position);
+        }
+
+        public View getView(int position, View convertView, ViewGroup parent) {
+            View result = null;
+            if (position >= mNumItems || position < 0) {
+                throw new IllegalStateException("position out of range for adapter!");
+            }
+
+            if (convertView != null) {
+                result = convertView(position, convertView, parent);
+                if (result == null) {
+                    mConvertMisses++;
+                }
+            }
+
+            if (result == null) {
+                int desiredHeight = getHeightForPosition(position);
+                result = createView(position, parent, desiredHeight);
+            }
+            return result;
+        }
+        
+        @Override
+        public int getItemViewType(int position) {
+            return ListScenario.this.getItemViewType(position);
+        }
+
+        @Override
+        public int getViewTypeCount() {
+            return ListScenario.this.getViewTypeCount();
+        }
+
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/util/ListUtil.java b/tests/FrameworkTest/src/com/android/frameworktest/util/ListUtil.java
new file mode 100644
index 0000000..1a05fac
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/util/ListUtil.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.util;
+
+import android.app.Instrumentation;
+import android.view.KeyEvent;
+import android.widget.ListView;
+
+
+/**
+ * Various useful stuff for instrumentation testing listview.
+ */
+public class ListUtil {
+
+
+    private final ListView mListView;
+    private final Instrumentation mInstrumentation;
+
+    /**
+     * @param listView The listview to act on
+     * @param instrumentation The instrumentation to use.
+     */
+    public ListUtil(ListView listView, Instrumentation instrumentation) {
+        mListView = listView;
+        mInstrumentation = instrumentation;
+    }
+
+    /**
+     * Set the selected position of the list view.
+     * @param pos The desired position.
+     */
+    public final void setSelectedPosition(final int pos) {
+        mListView.post(new Runnable() {
+            public void run() {
+                mListView.setSelection(pos);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+    }
+
+    /**
+     * Get the top of the list.
+     */
+    public final int getListTop() {
+        return mListView.getListPaddingTop();
+    }
+
+    /**
+     * Get the bottom of the list.
+     */
+    public final int getListBottom() {
+        return mListView.getHeight() - mListView.getListPaddingBottom();
+    }
+
+    /**
+     * Arrow (up or down as appropriate) to the desired position in the list.
+     * @param desiredPos The desired position
+     * @throws IllegalStateException if the position can't be reached within 20 presses.
+     */
+    public final void arrowScrollToSelectedPosition(int desiredPos) {
+        if (desiredPos > mListView.getSelectedItemPosition()) {
+            arrowDownToSelectedPosition(desiredPos);
+        } else {
+            arrowUpToSelectedPosition(desiredPos);
+        }
+    }
+
+    private void arrowDownToSelectedPosition(int position) {
+        int maxDowns = 20;
+        while(mListView.getSelectedItemPosition() < position && --maxDowns > 0) {
+            mInstrumentation.sendCharacterSync(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+        if (position != mListView.getSelectedItemPosition()) {
+            throw new IllegalStateException("couldn't get to item after 20 downs");
+        }
+
+    }
+
+    private void arrowUpToSelectedPosition(int position) {
+        int maxUps = 20;
+        while(mListView.getSelectedItemPosition() > position && --maxUps > 0) {
+            mInstrumentation.sendCharacterSync(KeyEvent.KEYCODE_DPAD_UP);
+        }
+        if (position != mListView.getSelectedItemPosition()) {
+            throw new IllegalStateException("couldn't get to item after 20 ups");
+        }
+    }
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/util/ScrollViewScenario.java b/tests/FrameworkTest/src/com/android/frameworktest/util/ScrollViewScenario.java
new file mode 100644
index 0000000..aa17194
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/util/ScrollViewScenario.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.util;
+
+import com.google.android.collect.Lists;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+import java.util.List;
+
+/**
+ * Utility base class for creating scroll view scenarios, allowing you to add
+ * a series of different kinds of views arranged vertically, taking up a
+ * specified amount of the screen height.
+ */
+public abstract class ScrollViewScenario extends Activity {
+
+    /**
+     * Holds content of scroll view
+     */
+    private LinearLayout mLinearLayout;
+
+    /**
+     * The actual scroll view
+     */
+    private ScrollView mScrollView;
+
+
+    /**
+     * What we need of each view that the user wants: the view, and the ratio
+     * to the screen height for its desired height.
+     */
+    private interface ViewFactory {
+        View create(final Context context);
+
+        float getHeightRatio();
+    }
+
+    /**
+     * Partially implement ViewFactory given a height ratio.
+     */
+    private static abstract class ViewFactoryBase implements ViewFactory {
+
+        private float mHeightRatio;
+
+        @SuppressWarnings({"UnusedDeclaration"})
+        private ViewFactoryBase() {throw new UnsupportedOperationException("don't call this!");}
+
+        protected ViewFactoryBase(float heightRatio) {
+            mHeightRatio = heightRatio;
+        }
+
+        public float getHeightRatio() {
+            return mHeightRatio;
+        }
+    }
+
+    /**
+     * Builder for selecting the views to be vertically arranged in the scroll
+     * view.
+     */
+    @SuppressWarnings({"JavaDoc"})
+    public static class Params {
+
+        List<ViewFactory> mViewFactories = Lists.newArrayList();
+
+        /**
+         * Add a text view.
+         * @param text The text of the text view.
+         * @param heightRatio The view's height will be this * the screen height.
+         */
+        public Params addTextView(final String text, float heightRatio) {
+            mViewFactories.add(new ViewFactoryBase(heightRatio) {
+                public View create(final Context context) {
+                    final TextView tv = new TextView(context);
+                    tv.setText(text);
+                    return tv;
+                }
+            });
+            return this;
+        }
+
+        /**
+         * Add multiple text views.
+         * @param numViews the number of views to add.
+         * @param textPrefix The text to prepend to each text view.
+         * @param heightRatio The view's height will be this * the screen height.
+         */
+        public Params addTextViews(int numViews, String textPrefix, float heightRatio) {
+            for (int i = 0; i < numViews; i++) {
+                addTextView(textPrefix + i, heightRatio);
+            }
+            return this;
+        }
+
+        /**
+         * Add a button.
+         * @param text The text of the button.
+         * @param heightRatio The view's height will be this * the screen height.
+         */
+        public Params addButton(final String text, float heightRatio) {
+            mViewFactories.add(new ViewFactoryBase(heightRatio) {
+                public View create(final Context context) {
+                    final Button button = new Button(context);
+                    button.setText(text);
+                    return button;
+                }
+            });
+            return this;
+        }
+
+        /**
+         * Add multiple buttons.
+         * @param numButtons the number of views to add.
+         * @param textPrefix The text to prepend to each button.
+         * @param heightRatio The view's height will be this * the screen height.
+         */
+        public Params addButtons(int numButtons, String textPrefix, float heightRatio) {
+            for (int i = 0; i < numButtons; i++) {
+                addButton(textPrefix + i, heightRatio);
+            }
+            return this;
+        }
+
+        /**
+         * Add an {@link InternalSelectionView}.
+         * @param numRows The number of rows in the internal selection view.
+         * @param heightRatio The view's height will be this * the screen height.
+         */
+        public Params addInternalSelectionView(final int numRows, float heightRatio) {
+            mViewFactories.add(new ViewFactoryBase(heightRatio) {
+                public View create(final Context context) {
+                    return new InternalSelectionView(context, numRows, "isv");
+                }
+            });
+            return this;
+        }
+
+        /**
+         * Add a sublayout of buttons as a single child of the scroll view.
+         * @param numButtons The number of buttons in the sub layout
+         * @param heightRatio The layout's height will be this * the screen height.
+         */
+        public Params addVerticalLLOfButtons(final String prefix, final int numButtons, float heightRatio) {
+            mViewFactories.add(new ViewFactoryBase(heightRatio) {
+
+                public View create(Context context) {
+                    final LinearLayout ll = new LinearLayout(context);
+                    ll.setOrientation(LinearLayout.VERTICAL);
+
+                    // fill width, equally weighted on height
+                    final LinearLayout.LayoutParams lp =
+                            new LinearLayout.LayoutParams(
+                                    ViewGroup.LayoutParams.FILL_PARENT, 0, 1f);
+                    for (int i = 0; i < numButtons; i++) {
+                        final Button button = new Button(context);
+                        button.setText(prefix + i);
+                        ll.addView(button, lp);
+                    }
+
+                    return ll;
+                }
+            });
+            return this;
+        }
+    }
+
+    /**
+     * Override this and initialized the views in the scroll view.
+     * @param params Used to configure the contents of the scroll view.
+     */
+    protected abstract void init(Params params);
+
+    public LinearLayout getLinearLayout() {
+        return mLinearLayout;
+    }
+
+    public ScrollView getScrollView() {
+        return mScrollView;
+    }
+
+    /**
+     * Get the child contained within the vertical linear layout of the
+     * scroll view.
+     * @param index The index within the linear layout.
+     * @return the child within the vertical linear layout of the scroll view
+     *   at the specified index.
+     */
+    @SuppressWarnings({"unchecked"})
+    public <T extends View> T getContentChildAt(int index) {
+        return (T) mLinearLayout.getChildAt(index);
+    }
+
+    /**
+     * Hook for changing how scroll view's are created.
+     */
+    @SuppressWarnings({"JavaDoc"})
+    protected ScrollView createScrollView() {
+        return new ScrollView(this);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // for test stability, turn off title bar
+        requestWindowFeature(Window.FEATURE_NO_TITLE);
+        int screenHeight = getWindowManager().getDefaultDisplay().getHeight()
+                - 25;
+        mLinearLayout = new LinearLayout(this);
+        mLinearLayout.setOrientation(LinearLayout.VERTICAL);
+
+        // initialize params
+        final Params params = new Params();
+        init(params);
+
+        // create views specified by params
+        for (ViewFactory viewFactory : params.mViewFactories) {
+            final LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
+                    ViewGroup.LayoutParams.FILL_PARENT,
+                    (int) (viewFactory.getHeightRatio() * screenHeight));
+            mLinearLayout.addView(viewFactory.create(this), lp);
+        }
+
+        mScrollView = createScrollView();
+        mScrollView.addView(mLinearLayout, new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT,
+                ViewGroup.LayoutParams.FILL_PARENT));
+
+        // no animation to speed up tests
+        mScrollView.setSmoothScrollingEnabled(false);
+
+        setContentView(mScrollView);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/util/TouchModeFlexibleAsserts.java b/tests/FrameworkTest/src/com/android/frameworktest/util/TouchModeFlexibleAsserts.java
new file mode 100644
index 0000000..66adb17
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/util/TouchModeFlexibleAsserts.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.util;
+
+import junit.framework.Assert;
+
+import android.test.InstrumentationTestCase;
+import android.test.TouchUtils;
+import android.view.View;
+
+/**
+ * When entering touch mode via touch, the tests can be flaky.  These asserts
+ * are more flexible (allowing up to MAX_ATTEMPTS touches to enter touch mode via touch or
+ * tap) until we can find a way to solve the flakiness.
+ */
+public class TouchModeFlexibleAsserts {
+
+    private static int MAX_ATTEMPTS = 2;
+
+    private static int MAX_DELAY_MILLIS = 2000;
+
+    public static void assertInTouchModeAfterClick(InstrumentationTestCase test, View viewToTouch) {
+        int numAttemptsAtTouchMode = 0;
+        while (numAttemptsAtTouchMode < MAX_ATTEMPTS &&
+                !viewToTouch.isInTouchMode()) {
+            TouchUtils.clickView(test, viewToTouch);
+            numAttemptsAtTouchMode++;
+        }
+        Assert.assertTrue("even after " + MAX_ATTEMPTS + " clicks, did not enter "
+                + "touch mode", viewToTouch.isInTouchMode());
+        //Assert.assertEquals("number of touches to enter touch mode", 1, numAttemptsAtTouchMode);
+    }
+
+    public static void assertInTouchModeAfterTap(InstrumentationTestCase test, View viewToTouch) {
+        int numAttemptsAtTouchMode = 0;
+        while (numAttemptsAtTouchMode < MAX_ATTEMPTS &&
+                !viewToTouch.isInTouchMode()) {
+            TouchUtils.tapView(test, viewToTouch);
+            numAttemptsAtTouchMode++;
+        }
+        Assert.assertTrue("even after " + MAX_ATTEMPTS + " taps, did not enter "
+                + "touch mode", viewToTouch.isInTouchMode());
+        //Assert.assertEquals("number of touches to enter touch mode", 1, numAttemptsAtTouchMode);
+    }
+
+    public static void assertNotInTouchModeAfterKey(InstrumentationTestCase test, int keyCode, View checkForTouchMode) {
+        test.sendKeys(keyCode);
+        int amountLeft = MAX_DELAY_MILLIS;
+
+        while (checkForTouchMode.isInTouchMode() && amountLeft > 0) {
+            amountLeft -= 200;
+            try {
+                Thread.sleep(200);
+            } catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        Assert.assertFalse("even after waiting " + MAX_DELAY_MILLIS + " millis after " 
+                + "pressing key event, still in touch mode", checkForTouchMode.isInTouchMode());
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/view/BigCache.java b/tests/FrameworkTest/src/com/android/frameworktest/view/BigCache.java
new file mode 100644
index 0000000..6f5eb00
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/view/BigCache.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.view;
+
+import com.android.frameworktest.R;
+
+import android.os.Bundle;
+import android.app.Activity;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+import android.view.ViewGroup;
+import android.view.View;
+import android.view.Display;
+import android.view.ViewConfiguration;
+
+/**
+ * This activity contains two Views, one as big as the screen, one much larger. The large one
+ * should not be able to activate its drawing cache.
+ */
+public class BigCache extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        final LinearLayout testBed = new LinearLayout(this);
+        testBed.setOrientation(LinearLayout.VERTICAL);
+        testBed.setLayoutParams(new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+
+        final int cacheSize = ViewConfiguration.getMaximumDrawingCacheSize();
+        final Display display = getWindowManager().getDefaultDisplay();
+        final int screenWidth = display.getWidth();
+        final int screenHeight = display.getHeight();
+
+        final View tiny = new View(this);
+        tiny.setId(R.id.a);
+        tiny.setBackgroundColor(0xFFFF0000);
+        tiny.setLayoutParams(new LinearLayout.LayoutParams(screenWidth, screenHeight));
+
+        final View large = new View(this);
+        large.setId(R.id.b);
+        large.setBackgroundColor(0xFF00FF00);
+        // Compute the height of the view assuming a cache size based on ARGB8888
+        final int height = 2 * (cacheSize / 2) / screenWidth;
+        large.setLayoutParams(new LinearLayout.LayoutParams(screenWidth, height));
+
+        final ScrollView scroller = new ScrollView(this);
+        scroller.setLayoutParams(new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
+
+        testBed.addView(tiny);
+        testBed.addView(large);
+        scroller.addView(testBed);
+
+        setContentView(scroller);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/view/Disabled.java b/tests/FrameworkTest/src/com/android/frameworktest/view/Disabled.java
new file mode 100644
index 0000000..1f1f4f4
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/view/Disabled.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.view;
+
+import com.android.frameworktest.R;
+
+import android.os.Bundle;
+import android.widget.Button;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.app.Activity;
+
+/**
+ * Exercise View's disabled state.
+ */
+public class Disabled extends Activity implements OnClickListener {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.disabled);
+
+        // Find our buttons
+        Button disabledButton = (Button) findViewById(R.id.disabledButton);
+        disabledButton.setEnabled(false);
+        
+        // Find our buttons
+        Button disabledButtonA = (Button) findViewById(R.id.disabledButtonA);
+        disabledButtonA.setOnClickListener(this);
+    }
+
+    public void onClick(View v) {
+        Button disabledButtonB = (Button) findViewById(R.id.disabledButtonB);
+        disabledButtonB.setEnabled(!disabledButtonB.isEnabled());
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/view/GlobalFocusChange.java b/tests/FrameworkTest/src/com/android/frameworktest/view/GlobalFocusChange.java
new file mode 100644
index 0000000..1cbf05a
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/view/GlobalFocusChange.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.view;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.ViewTreeObserver;
+import android.view.View;
+
+public class GlobalFocusChange extends Activity implements ViewTreeObserver.OnGlobalFocusChangeListener {
+    public View mOldFocus;
+    public View mNewFocus;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.focus_listener);
+        findViewById(R.id.left).getViewTreeObserver().addOnGlobalFocusChangeListener(this);
+    }
+
+    public void reset() {
+        mOldFocus = mNewFocus = null;
+    }
+
+    public void onGlobalFocusChanged(View oldFocus, View newFocus) {
+        mOldFocus = oldFocus;
+        mNewFocus = newFocus;
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/view/Include.java b/tests/FrameworkTest/src/com/android/frameworktest/view/Include.java
new file mode 100644
index 0000000..fc36e37
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/view/Include.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.view;
+
+import com.android.frameworktest.R;
+
+import android.os.Bundle;
+import android.app.Activity;
+
+/**
+ * Exercise <include /> tag in XML files.
+ */
+public class Include extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.include_tag);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/view/Longpress.java b/tests/FrameworkTest/src/com/android/frameworktest/view/Longpress.java
new file mode 100644
index 0000000..f3483fc
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/view/Longpress.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2006 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.frameworktest.view;
+
+import com.android.frameworktest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class Longpress extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.longpress);
+    }
+}
+
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/view/Merge.java b/tests/FrameworkTest/src/com/android/frameworktest/view/Merge.java
new file mode 100644
index 0000000..9596e91
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/view/Merge.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.view;
+
+import com.android.frameworktest.R;
+
+import android.os.Bundle;
+import android.app.Activity;
+import android.widget.LinearLayout;
+import android.view.ViewGroup;
+import android.view.LayoutInflater;
+
+/**
+ * Exercise <merge /> tag in XML files.
+ */
+public class Merge extends Activity {
+    private LinearLayout mLayout;
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        mLayout = new LinearLayout(this);
+        mLayout.setOrientation(LinearLayout.VERTICAL);
+        LayoutInflater.from(this).inflate(R.layout.merge_tag, mLayout);
+
+        setContentView(mLayout);
+    }
+
+    public ViewGroup getLayout() {
+        return mLayout;
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/view/PopupWindowVisibility.java b/tests/FrameworkTest/src/com/android/frameworktest/view/PopupWindowVisibility.java
new file mode 100644
index 0000000..f4d477d4
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/view/PopupWindowVisibility.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.view;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.AutoCompleteTextView;
+import android.widget.Button;
+import android.widget.Spinner;
+
+import com.android.frameworktest.R;
+
+/**
+ * Tests views with popupWindows becoming invisible
+ */
+public class PopupWindowVisibility extends Activity implements OnClickListener {
+    
+    private View mFrame;
+    private Button mHide;
+    private Button mShow;
+    
+
+    
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.popup_window_visibility);
+
+        mFrame = findViewById(R.id.frame);
+        
+        mHide = (Button) findViewById(R.id.hide);
+        mHide.setOnClickListener(this);
+        
+        mShow = (Button) findViewById(R.id.show);
+        mShow.setOnClickListener(this);
+        
+        Spinner spinner = (Spinner) findViewById(R.id.spinner);
+        ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String>(this,
+                android.R.layout.simple_spinner_item, mStrings);
+        spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        spinner.setAdapter(spinnerAdapter);
+        
+        ArrayAdapter<String> autoAdapter = new ArrayAdapter<String>(this,
+                android.R.layout.simple_dropdown_item_1line, COUNTRIES);
+        AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.auto);
+        textView.setAdapter(autoAdapter);
+    }
+
+
+    public void onClick(View v) {
+        mFrame.setVisibility(v == mHide ? View.INVISIBLE : View.VISIBLE);
+    }
+    private static final String[] mStrings = {
+        "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"
+        };
+    
+    static final String[] COUNTRIES = new String[] {
+        "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
+        "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina",
+        "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan",
+        "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium",
+        "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia",
+        "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil", "British Indian Ocean Territory",
+        "British Virgin Islands", "Brunei", "Bulgaria", "Burkina Faso", "Burundi",
+        "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
+        "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
+        "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
+        "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+        "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
+        "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
+        "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
+        "Former Yugoslav Republic of Macedonia", "France", "French Guiana", "French Polynesia",
+        "French Southern Territories", "Gabon", "Georgia", "Germany", "Ghana", "Gibraltar",
+        "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea", "Guinea-Bissau",
+        "Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong", "Hungary",
+        "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica",
+        "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos",
+        "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
+        "Macau", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands",
+        "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova",
+        "Monaco", "Mongolia", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia",
+        "Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand",
+        "Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "North Korea", "Northern Marianas",
+        "Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru",
+        "Philippines", "Pitcairn Islands", "Poland", "Portugal", "Puerto Rico", "Qatar",
+        "Reunion", "Romania", "Russia", "Rwanda", "Sqo Tome and Principe", "Saint Helena",
+        "Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon",
+        "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Saudi Arabia", "Senegal",
+        "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands",
+        "Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "South Korea",
+        "Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden",
+        "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "The Bahamas",
+        "The Gambia", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey",
+        "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Virgin Islands", "Uganda",
+        "Ukraine", "United Arab Emirates", "United Kingdom",
+        "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan",
+        "Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Wallis and Futuna", "Western Sahara",
+        "Yemen", "Yugoslavia", "Zambia", "Zimbabwe"
+        };
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/view/PreDrawListener.java b/tests/FrameworkTest/src/com/android/frameworktest/view/PreDrawListener.java
new file mode 100644
index 0000000..cb456b2
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/view/PreDrawListener.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.view;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewTreeObserver;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.LinearLayout;
+
+import com.android.frameworktest.R;
+
+
+/**
+ * Tests views with popupWindows becoming invisible
+ */
+public class PreDrawListener extends Activity implements OnClickListener {
+    
+    private MyLinearLayout mFrame;
+
+
+    static public class MyLinearLayout extends LinearLayout implements
+            ViewTreeObserver.OnPreDrawListener {
+
+        public boolean mCancelNextDraw;
+        
+        public MyLinearLayout(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+
+        public MyLinearLayout(Context context) {
+            super(context);
+        }
+
+        @Override
+        protected void onAttachedToWindow() {
+            super.onAttachedToWindow();
+            getViewTreeObserver().addOnPreDrawListener(this);
+        }
+        
+        public boolean onPreDraw() {
+            if (mCancelNextDraw) {
+                Button b = new Button(this.getContext());
+                b.setText("Hello");
+                addView(b, new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
+                        LayoutParams.WRAP_CONTENT));
+                mCancelNextDraw = false;
+                return false;
+            }
+            return true;
+        }
+        
+    }
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.pre_draw_listener);
+
+        mFrame = (MyLinearLayout) findViewById(R.id.frame);
+
+        Button mGoButton = (Button) findViewById(R.id.go);
+        mGoButton.setOnClickListener(this);
+    }
+
+
+    public void onClick(View v) {
+        mFrame.mCancelNextDraw = true;
+        mFrame.invalidate();
+    }
+
+
+
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/view/RemoteViewsActivity.java b/tests/FrameworkTest/src/com/android/frameworktest/view/RemoteViewsActivity.java
new file mode 100644
index 0000000..146c0ab
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/view/RemoteViewsActivity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.view;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.frameworktest.R;
+
+/**
+ * Exercise RemoteViews -- especially filtering
+ */
+public class RemoteViewsActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.remote_view_host);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/view/RunQueue.java b/tests/FrameworkTest/src/com/android/frameworktest/view/RunQueue.java
new file mode 100644
index 0000000..c8c3c28
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/view/RunQueue.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.view;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+import android.view.View;
+import android.view.ViewTreeObserver;
+import com.android.frameworktest.R;
+
+/**
+ * Tests views using post*() and getViewTreeObserver() before onAttachedToWindow().
+ */
+public class RunQueue extends Activity implements ViewTreeObserver.OnGlobalLayoutListener {
+    public boolean runnableRan = false;
+    public boolean runnableCancelled = true;
+    public boolean globalLayout = false;
+    public ViewTreeObserver viewTreeObserver;
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        TextView textView = new TextView(this);
+        textView.setText("RunQueue");
+        textView.setId(R.id.simple_view);
+
+        setContentView(textView);
+        final View view = findViewById(R.id.simple_view);
+
+        view.post(new Runnable() {
+            public void run() {
+                runnableRan = true;
+            }
+        });
+
+        final Runnable runnable = new Runnable() {
+            public void run() {
+                runnableCancelled = false;
+            }
+        };
+        view.post(runnable);
+        view.post(runnable);
+        view.post(runnable);
+        view.post(runnable);
+        view.removeCallbacks(runnable);
+
+        viewTreeObserver = view.getViewTreeObserver();
+        viewTreeObserver.addOnGlobalLayoutListener(this);
+    }
+
+    public void onGlobalLayout() {
+        globalLayout = true;
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/view/StubbedView.java b/tests/FrameworkTest/src/com/android/frameworktest/view/StubbedView.java
new file mode 100644
index 0000000..2b0db9d
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/view/StubbedView.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.view;
+
+import com.android.frameworktest.R;
+
+import android.os.Bundle;
+import android.app.Activity;
+import android.view.View;
+
+/**
+ * Exercise <ViewStub /> tag in XML files.
+ */
+public class StubbedView extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.viewstub);
+
+        findViewById(R.id.vis).setOnClickListener(new View.OnClickListener() {
+            public void onClick(View v) {
+                final View view = findViewById(R.id.viewStub);
+                if (view != null) {
+                    view.setVisibility(View.VISIBLE);
+                }
+            }
+        });
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/view/ViewGroupChildren.java b/tests/FrameworkTest/src/com/android/frameworktest/view/ViewGroupChildren.java
new file mode 100644
index 0000000..163e03c
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/view/ViewGroupChildren.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.view;
+
+import com.android.frameworktest.R;
+
+import android.os.Bundle;
+import android.widget.Button;
+import android.view.View;
+import android.app.Activity;
+
+/**
+ * Exercise ViewGroup's ability to add and remove children.
+ */
+public class ViewGroupChildren extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.viewgroupchildren);
+    }
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/view/Visibility.java b/tests/FrameworkTest/src/com/android/frameworktest/view/Visibility.java
new file mode 100644
index 0000000..e068620
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/view/Visibility.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.view;
+
+import com.android.frameworktest.R;
+
+import android.os.Bundle;
+import android.widget.Button;
+import android.view.View;
+import android.app.Activity;
+
+/**
+ * Exercise View's ability to change their visibility: GONE, INVISIBLE and
+ * VISIBLE. 
+ */
+public class Visibility extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.visibility);
+
+        // Find the view whose visibility will change
+        mVictim = findViewById(R.id.victim);
+
+        // Find our buttons
+        Button visibleButton = (Button) findViewById(R.id.vis);
+        Button invisibleButton = (Button) findViewById(R.id.invis);
+        Button goneButton = (Button) findViewById(R.id.gone);
+
+        // Wire each button to a click listener
+        visibleButton.setOnClickListener(mVisibleListener);
+        invisibleButton.setOnClickListener(mInvisibleListener);
+        goneButton.setOnClickListener(mGoneListener);
+    }
+
+
+    View.OnClickListener mVisibleListener = new View.OnClickListener() {
+        public void onClick(View v) {
+            mVictim.setVisibility(View.VISIBLE);
+        }
+    };
+
+    View.OnClickListener mInvisibleListener = new View.OnClickListener() {
+        public void onClick(View v) {
+            mVictim.setVisibility(View.INVISIBLE);
+        }
+    };
+
+    View.OnClickListener mGoneListener = new View.OnClickListener() {
+        public void onClick(View v) {
+            mVictim.setVisibility(View.GONE);
+        }
+    };
+
+    private View mVictim;
+}
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/view/ZeroSized.java b/tests/FrameworkTest/src/com/android/frameworktest/view/ZeroSized.java
new file mode 100644
index 0000000..e858fc0
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/view/ZeroSized.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.view;
+
+import com.android.frameworktest.R;
+
+import android.os.Bundle;
+import android.app.Activity;
+
+/**
+ * This activity contains Views with various widths and heights. The goal is to exercise the
+ * drawing cache when width is null, height is null or both.
+ */
+public class ZeroSized extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.zero_sized);
+    }
+}
diff --git a/tests/FrameworkTest/tests/Android.mk b/tests/FrameworkTest/tests/Android.mk
new file mode 100644
index 0000000..5c54684
--- /dev/null
+++ b/tests/FrameworkTest/tests/Android.mk
@@ -0,0 +1,17 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+
+# Include all test java files.
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_PACKAGE_NAME := FrameworkTestTests
+
+LOCAL_INSTRUMENTATION_FOR := FrameworkTest
+
+include $(BUILD_PACKAGE)
+
diff --git a/tests/FrameworkTest/tests/AndroidManifest.xml b/tests/FrameworkTest/tests/AndroidManifest.xml
new file mode 100644
index 0000000..65aaebb
--- /dev/null
+++ b/tests/FrameworkTest/tests/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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 name must be unique so suffix with "tests" so package loader doesn't ignore us -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.frameworktest.tests">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <!--
+    This declares that this app uses the instrumentation test runner targeting
+    the package of com.android.frameworktest.  To run the tests use the command:
+    "adb shell am instrument -w com.android.frameworktest.tests/android.test.InstrumentationTestRunner"
+    -->
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+                     android:targetPackage="com.android.frameworktest"
+                     android:label="framework tests"/>
+
+</manifest>
diff --git a/tests/FrameworkTest/tests/src/android/content/AbstractTableMergerTest.java b/tests/FrameworkTest/tests/src/android/content/AbstractTableMergerTest.java
new file mode 100644
index 0000000..aa3d186
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/android/content/AbstractTableMergerTest.java
@@ -0,0 +1,578 @@
+package android.content;
+
+import com.google.android.collect.Lists;
+import com.google.android.collect.Sets;
+
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.net.Uri;
+import android.test.AndroidTestCase;
+import android.text.TextUtils;
+
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.SortedSet;
+
+/** Unit test for {@link android.content.AbstractTableMerger}. */
+public class AbstractTableMergerTest extends AndroidTestCase {
+    MockSyncableContentProvider mRealProvider;
+    MockSyncableContentProvider mTempProvider;
+    MockTableMerger mMerger;
+    MockSyncContext mSyncContext;
+
+    static final String TABLE_NAME = "items";
+    static final String DELETED_TABLE_NAME = "deleted_items";
+    static final Uri CONTENT_URI = Uri.parse("content://testdata");
+    static final Uri TABLE_URI = Uri.withAppendedPath(CONTENT_URI, TABLE_NAME);
+    static final Uri DELETED_TABLE_URI = Uri.withAppendedPath(CONTENT_URI, DELETED_TABLE_NAME);
+
+    private final String ACCOUNT = "account@goo.com";
+
+    private final ArrayList<Expectation> mExpectations = Lists.newArrayList();
+
+    static class Expectation {
+        enum Type {
+            UPDATE,
+            INSERT,
+            DELETE,
+            RESOLVE
+        }
+
+        Type mType;
+        ContentValues mValues;
+        Long mLocalRowId;
+
+        Expectation(Type type, Long localRowId, ContentValues values) {
+            mType = type;
+            mValues = values;
+            mLocalRowId = localRowId;
+            if (type == Type.DELETE) {
+                assertNull(values);
+            } else {
+                assertFalse(values.containsKey("_id"));
+            }
+        }
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mSyncContext = new MockSyncContext();
+        mRealProvider = new MockSyncableContentProvider();
+        mTempProvider = mRealProvider.getTemporaryInstance();
+        mMerger = new MockTableMerger(mRealProvider.getDatabase(),
+                TABLE_NAME, TABLE_URI, DELETED_TABLE_NAME, DELETED_TABLE_URI);
+        mExpectations.clear();
+    }
+
+    ContentValues newValues(String data, String syncId, String syncAccount,
+            String syncTime, String syncVersion, Long syncLocalId) {
+        ContentValues values = new ContentValues();
+        if (data != null) values.put("data", data);
+        if (syncTime != null) values.put("_sync_time", syncTime);
+        if (syncVersion != null) values.put("_sync_version", syncVersion);
+        if (syncId != null) values.put("_sync_id", syncId);
+        if (syncAccount != null) values.put("_sync_account", syncAccount);
+        values.put("_sync_local_id", syncLocalId);
+        values.put("_sync_dirty", 0);
+        return values;
+    }
+
+    ContentValues newDeletedValues(String syncId, String syncAccount, String syncVersion,
+            Long syncLocalId) {
+        ContentValues values = new ContentValues();
+        if (syncVersion != null) values.put("_sync_version", syncVersion);
+        if (syncId != null) values.put("_sync_id", syncId);
+        if (syncAccount != null) values.put("_sync_account", syncAccount);
+        if (syncLocalId != null) values.put("_sync_local_id", syncLocalId);
+        return values;
+    }
+
+    ContentValues newModifyData(String data) {
+        ContentValues values = new ContentValues();
+        values.put("data", data);
+        values.put("_sync_dirty", 1);
+        return values;
+    }
+
+    // Want to test adding, changing, deleting entries to a provider that has extra entries
+    // before and after the entries being changed.
+    public void testInsert() {
+        // add rows to the real provider
+        // add new row to the temp provider
+        final ContentValues row1 = newValues("d1", "si1", ACCOUNT, "st1", "sv1", null);
+        mTempProvider.insert(TABLE_URI, row1);
+
+        // add expected callbacks to merger
+        mExpectations.add(new Expectation(Expectation.Type.INSERT, null /* syncLocalId */, row1));
+
+        // run merger
+        SyncResult syncResult = new SyncResult();
+        mMerger.mergeServerDiffs(mSyncContext, ACCOUNT, mTempProvider, syncResult);
+
+        // check that all expectations were met
+        assertEquals("not all expectations were met", 0, mExpectations.size());
+    }
+
+    public void testUpdateWithLocalId() {
+        // add rows to the real provider
+        // add new row to the temp provider that matches an unsynced row in the real provider
+        final ContentValues row1 = newValues("d1", "si1", ACCOUNT, "st1", "sv1", 11L);
+        mTempProvider.insert(TABLE_URI, row1);
+
+        // add expected callbacks to merger
+        mExpectations.add(new Expectation(Expectation.Type.UPDATE, 11L, row1));
+
+        // run merger
+        SyncResult syncResult = new SyncResult();
+        mMerger.mergeServerDiffs(mSyncContext, ACCOUNT, mTempProvider, syncResult);
+
+        // check that all expectations were met
+        assertEquals("not all expectations were met", 0, mExpectations.size());
+    }
+
+    public void testUpdateWithoutLocalId() {
+        // add rows to the real provider
+        Uri i1 = mRealProvider.insert(TABLE_URI,
+                newValues("d1", "si1", ACCOUNT, "st1", "sv1", null));
+
+        // add new row to the temp provider that matches an unsynced row in the real provider
+        final ContentValues row1 = newValues("d2", "si1", ACCOUNT, "st2", "sv2", null);
+        mTempProvider.insert(TABLE_URI, row1);
+
+        // add expected callbacks to merger
+        mExpectations.add(new Expectation(Expectation.Type.UPDATE, ContentUris.parseId(i1), row1));
+
+        // run merger
+        SyncResult syncResult = new SyncResult();
+        mMerger.mergeServerDiffs(mSyncContext, ACCOUNT, mTempProvider, syncResult);
+
+        // check that all expectations were met
+        assertEquals("not all expectations were met", 0, mExpectations.size());
+    }
+
+    public void testResolve() {
+        // add rows to the real provider
+        Uri i1 = mRealProvider.insert(TABLE_URI,
+                newValues("d1", "si1", ACCOUNT, "st1", "sv1", null));
+        mRealProvider.update(TABLE_URI, newModifyData("d2"), null, null);
+
+        // add row to the temp provider that matches a dirty, synced row in the real provider
+        final ContentValues row1 = newValues("d3", "si1", ACCOUNT, "st2", "sv2", null);
+        mTempProvider.insert(TABLE_URI, row1);
+
+        // add expected callbacks to merger
+        mExpectations.add(new Expectation(Expectation.Type.RESOLVE, ContentUris.parseId(i1), row1));
+
+        // run merger
+        SyncResult syncResult = new SyncResult();
+        mMerger.mergeServerDiffs(mSyncContext, ACCOUNT, mTempProvider, syncResult);
+
+        // check that all expectations were met
+        assertEquals("not all expectations were met", 0, mExpectations.size());
+    }
+
+    public void testResolveWithLocalId() {
+        // add rows to the real provider
+        Uri i1 = mRealProvider.insert(TABLE_URI,
+                newValues("d1", "si1", ACCOUNT, "st1", "sv1", null));
+        mRealProvider.update(TABLE_URI, newModifyData("d2"), null, null);
+
+        // add row to the temp provider that matches a dirty, synced row in the real provider
+        ContentValues row1 = newValues("d2", "si1", ACCOUNT, "st2", "sv2", ContentUris.parseId(i1));
+        mTempProvider.insert(TABLE_URI, row1);
+
+        // add expected callbacks to merger
+        mExpectations.add(new Expectation(Expectation.Type.UPDATE, ContentUris.parseId(i1), row1));
+
+        // run merger
+        SyncResult syncResult = new SyncResult();
+        mMerger.mergeServerDiffs(mSyncContext, ACCOUNT, mTempProvider, syncResult);
+
+        // check that all expectations were met
+        assertEquals("not all expectations were met", 0, mExpectations.size());
+    }
+
+    public void testDeleteRowAfterDelete() {
+        // add rows to the real provider
+        Uri i1 = mRealProvider.insert(TABLE_URI,
+                newValues("d1", "si1", ACCOUNT, "st1", "sv1", null));
+
+        // add a deleted record to the temp provider
+        ContentValues row1 = newDeletedValues(null, null, null, ContentUris.parseId(i1));
+        mTempProvider.insert(DELETED_TABLE_URI, row1);
+
+        // add expected callbacks to merger
+        mExpectations.add(new Expectation(Expectation.Type.DELETE, ContentUris.parseId(i1), null));
+
+        // run merger
+        SyncResult syncResult = new SyncResult();
+        mMerger.mergeServerDiffs(mSyncContext, ACCOUNT, mTempProvider, syncResult);
+
+        // check that all expectations were met
+        assertEquals("not all expectations were met", 0, mExpectations.size());
+    }
+
+    public void testDeleteRowAfterInsert() {
+        // add rows to the real provider
+        Uri i1 = mRealProvider.insert(TABLE_URI, newModifyData("d1"));
+
+        // add a deleted record to the temp provider
+        ContentValues row1 = newDeletedValues(null, null, null, ContentUris.parseId(i1));
+        mTempProvider.insert(DELETED_TABLE_URI, row1);
+
+        // add expected callbacks to merger
+        mExpectations.add(new Expectation(Expectation.Type.DELETE, ContentUris.parseId(i1), null));
+
+        // run merger
+        SyncResult syncResult = new SyncResult();
+        mMerger.mergeServerDiffs(mSyncContext, ACCOUNT, mTempProvider, syncResult);
+
+        // check that all expectations were met
+        assertEquals("not all expectations were met", 0, mExpectations.size());
+    }
+
+    public void testDeleteRowAfterUpdate() {
+        // add rows to the real provider
+        Uri i1 = mRealProvider.insert(TABLE_URI,
+                newValues("d1", "si1", ACCOUNT, "st1", "sv1", null));
+
+        // add a deleted record to the temp provider
+        ContentValues row1 = newDeletedValues("si1", ACCOUNT, "sv1", ContentUris.parseId(i1));
+        mTempProvider.insert(DELETED_TABLE_URI, row1);
+
+        // add expected callbacks to merger
+        mExpectations.add(new Expectation(Expectation.Type.DELETE, ContentUris.parseId(i1), null));
+
+        // run merger
+        SyncResult syncResult = new SyncResult();
+        mMerger.mergeServerDiffs(mSyncContext, ACCOUNT, mTempProvider, syncResult);
+
+        // check that all expectations were met
+        assertEquals("not all expectations were met", 0, mExpectations.size());
+    }
+
+    public void testDeleteRowFromServer() {
+        // add rows to the real provider
+        Uri i1 = mRealProvider.insert(TABLE_URI,
+                newValues("d1", "si1", ACCOUNT, "st1", "sv1", null));
+
+        // add a deleted record to the temp provider
+        ContentValues row1 = newDeletedValues("si1", ACCOUNT, "sv1", null);
+        mTempProvider.insert(DELETED_TABLE_URI, row1);
+
+        // add expected callbacks to merger
+        mExpectations.add(new Expectation(Expectation.Type.DELETE, ContentUris.parseId(i1), null));
+
+        // run merger
+        SyncResult syncResult = new SyncResult();
+        mMerger.mergeServerDiffs(mSyncContext, ACCOUNT, mTempProvider, syncResult);
+
+        // check that all expectations were met
+        assertEquals("not all expectations were met", 0, mExpectations.size());
+    }
+
+    class MockTableMerger extends AbstractTableMerger {
+        public MockTableMerger(SQLiteDatabase database, String table, Uri tableURL,
+                String deletedTable, Uri deletedTableURL) {
+            super(database, table, tableURL, deletedTable, deletedTableURL);
+        }
+
+        public void insertRow(ContentProvider diffs, Cursor diffsCursor) {
+            Expectation expectation = mExpectations.remove(0);
+            checkExpectation(expectation,
+                    Expectation.Type.INSERT, null /* syncLocalId */, diffsCursor);
+        }
+
+        public void updateRow(long localPersonID, ContentProvider diffs, Cursor diffsCursor) {
+            Expectation expectation = mExpectations.remove(0);
+            checkExpectation(expectation, Expectation.Type.UPDATE, localPersonID, diffsCursor);
+        }
+
+        public void resolveRow(long localPersonID, String syncID, ContentProvider diffs,
+                Cursor diffsCursor) {
+            Expectation expectation = mExpectations.remove(0);
+            checkExpectation(expectation, Expectation.Type.RESOLVE, localPersonID, diffsCursor);
+        }
+
+        @Override
+        public void deleteRow(Cursor cursor) {
+            Expectation expectation = mExpectations.remove(0);
+            assertEquals(expectation.mType, Expectation.Type.DELETE);
+            assertNotNull(expectation.mLocalRowId);
+            final long localRowId = cursor.getLong(cursor.getColumnIndexOrThrow("_id"));
+            assertEquals((long)expectation.mLocalRowId, localRowId);
+            cursor.moveToNext();
+            mDb.delete(TABLE_NAME, "_id=" + localRowId, null);
+        }
+
+        protected void notifyChanges() {
+            throw new UnsupportedOperationException();
+        }
+
+        void checkExpectation(Expectation expectation,
+                Expectation.Type actualType, Long localRowId,
+                Cursor cursor) {
+            assertEquals(expectation.mType, actualType);
+            assertEquals(expectation.mLocalRowId, localRowId);
+
+            final SortedSet<String> actualKeys = Sets.newSortedSet(cursor.getColumnNames());
+            final SortedSet<String> expectedKeys = Sets.newSortedSet();
+            for (Map.Entry<String, Object> entry : expectation.mValues.valueSet()) {
+                expectedKeys.add(entry.getKey());
+            }
+            actualKeys.remove("_id");
+            actualKeys.remove("_sync_mark");
+            actualKeys.remove("_sync_local_id");
+            expectedKeys.remove("_sync_local_id");
+            expectedKeys.remove("_id");
+            assertEquals("column mismatch",
+                    TextUtils.join(",", expectedKeys), TextUtils.join(",", actualKeys));
+
+//            if (localRowId != null) {
+//                assertEquals((long) localRowId,
+//                        cursor.getLong(cursor.getColumnIndexOrThrow("_sync_local_id")));
+//            } else {
+//                assertTrue("unexpected _sync_local_id, "
+//                        + cursor.getLong(cursor.getColumnIndexOrThrow("_sync_local_id")),
+//                        cursor.isNull(cursor.getColumnIndexOrThrow("_sync_local_id")));
+//            }
+
+            for (String name : cursor.getColumnNames()) {
+                if ("_id".equals(name)) {
+                    continue;
+                }
+                if (cursor.isNull(cursor.getColumnIndexOrThrow(name))) {
+                    assertNull(expectation.mValues.getAsString(name));
+                } else {
+                    String actualValue =
+                            cursor.getString(cursor.getColumnIndexOrThrow(name));
+                    assertEquals("mismatch on column " + name,
+                            expectation.mValues.getAsString(name), actualValue);
+                }
+            }
+        }
+    }
+
+    class MockSyncableContentProvider extends SyncableContentProvider {
+        SQLiteDatabase mDb;
+        boolean mIsTemporary;
+        boolean mContainsDiffs;
+
+        private final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+
+        private static final int MATCHER_ITEMS = 0;
+        private static final int MATCHER_DELETED_ITEMS = 1;
+
+        public MockSyncableContentProvider() {
+            mIsTemporary = false;
+            setContainsDiffs(false);
+            sURIMatcher.addURI(CONTENT_URI.getAuthority(), "items", MATCHER_ITEMS);
+            sURIMatcher.addURI(CONTENT_URI.getAuthority(), "deleted_items", MATCHER_DELETED_ITEMS);
+
+            mDb = SQLiteDatabase.create(null);
+            mDb.execSQL("CREATE TABLE items ("
+                    + "_id INTEGER PRIMARY KEY AUTOINCREMENT, "
+                    + "data TEXT, "
+                    + "_sync_time TEXT, "
+                    + "_sync_version TEXT, "
+                    + "_sync_id TEXT, "
+                    + "_sync_local_id INTEGER, "
+                    + "_sync_dirty INTEGER NOT NULL DEFAULT 0, "
+                    + "_sync_account TEXT, "
+                    + "_sync_mark INTEGER)");
+
+            mDb.execSQL("CREATE TABLE deleted_items ("
+                    + "_id INTEGER PRIMARY KEY AUTOINCREMENT, "
+                    + "_sync_version TEXT, "
+                    + "_sync_id TEXT, "
+                    + "_sync_local_id INTEGER, "
+                    + "_sync_account TEXT, "
+                    + "_sync_mark INTEGER)");
+        }
+
+        public boolean onCreate() {
+            throw new UnsupportedOperationException();
+        }
+
+        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+                String sortOrder) {
+            int match = sURIMatcher.match(uri);
+            switch (match) {
+                case MATCHER_ITEMS:
+                    return mDb.query(TABLE_NAME, projection, selection, selectionArgs,
+                            null, null, sortOrder);
+                case MATCHER_DELETED_ITEMS:
+                    return mDb.query(DELETED_TABLE_NAME, projection, selection, selectionArgs,
+                            null, null, sortOrder);
+                default:
+                    throw new UnsupportedOperationException("Cannot query URL: " + uri);
+            }
+        }
+
+        public String getType(Uri uri) {
+            throw new UnsupportedOperationException();
+        }
+
+        public Uri insert(Uri uri, ContentValues values) {
+            int match = sURIMatcher.match(uri);
+            switch (match) {
+                case MATCHER_ITEMS: {
+                    long id = mDb.insert(TABLE_NAME, "_id", values);
+                    return CONTENT_URI.buildUpon().appendPath(String.valueOf(id)).build();
+                }
+                case MATCHER_DELETED_ITEMS: {
+                    long id = mDb.insert(DELETED_TABLE_NAME, "_id", values);
+                    return CONTENT_URI.buildUpon().appendPath(String.valueOf(id)).build();
+                }
+                default:
+                    throw new UnsupportedOperationException("Cannot query URL: " + uri);
+            }
+        }
+
+        public int delete(Uri uri, String selection, String[] selectionArgs) {
+            int match = sURIMatcher.match(uri);
+            switch (match) {
+                case MATCHER_ITEMS:
+                    return mDb.delete(TABLE_NAME, selection, selectionArgs);
+                case MATCHER_DELETED_ITEMS:
+                    return mDb.delete(DELETED_TABLE_NAME, selection, selectionArgs);
+                default:
+                    throw new UnsupportedOperationException("Cannot query URL: " + uri);
+            }
+        }
+
+        public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+            int match = sURIMatcher.match(uri);
+            switch (match) {
+                case MATCHER_ITEMS:
+                    return mDb.update(TABLE_NAME, values, selection, selectionArgs);
+                case MATCHER_DELETED_ITEMS:
+                    return mDb.update(DELETED_TABLE_NAME, values, selection, selectionArgs);
+                default:
+                    throw new UnsupportedOperationException("Cannot query URL: " + uri);
+            }
+        }
+
+        protected boolean isTemporary() {
+            return mIsTemporary;
+        }
+
+        public void close() {
+            throw new UnsupportedOperationException();
+        }
+
+        protected void bootstrapDatabase(SQLiteDatabase db) {
+            throw new UnsupportedOperationException();
+        }
+
+        protected boolean upgradeDatabase(SQLiteDatabase db, int oldVersion, int newVersion) {
+            throw new UnsupportedOperationException();
+        }
+
+        protected void onDatabaseOpened(SQLiteDatabase db) {
+            throw new UnsupportedOperationException();
+        }
+
+        public MockSyncableContentProvider getTemporaryInstance() {
+            MockSyncableContentProvider temp = new MockSyncableContentProvider();
+            temp.mIsTemporary = true;
+            temp.setContainsDiffs(true);
+            return temp;
+        }
+
+        public SQLiteDatabase getDatabase() {
+            return mDb;
+        }
+
+        public boolean getContainsDiffs() {
+            return mContainsDiffs;
+        }
+
+        public void setContainsDiffs(boolean containsDiffs) {
+            mContainsDiffs = containsDiffs;
+        }
+
+        protected Iterable<? extends AbstractTableMerger> getMergers() {
+            throw new UnsupportedOperationException();
+        }
+
+        public boolean changeRequiresLocalSync(Uri uri) {
+            throw new UnsupportedOperationException();
+        }
+
+        public void onSyncStart(SyncContext context, String account) {
+            throw new UnsupportedOperationException();
+        }
+
+        public void onSyncStop(SyncContext context, boolean success) {
+            throw new UnsupportedOperationException();
+        }
+
+        public String getSyncingAccount() {
+            throw new UnsupportedOperationException();
+        }
+
+        public void merge(SyncContext context, SyncableContentProvider diffs,
+                TempProviderSyncResult result, SyncResult syncResult) {
+            throw new UnsupportedOperationException();
+        }
+
+        public void onSyncCanceled() {
+            throw new UnsupportedOperationException();
+        }
+
+        public boolean isMergeCancelled() {
+            return false;
+        }
+
+        protected int updateInternal(Uri url, ContentValues values, String selection,
+                String[] selectionArgs) {
+            throw new UnsupportedOperationException();
+        }
+
+        protected int deleteInternal(Uri url, String selection, String[] selectionArgs) {
+            throw new UnsupportedOperationException();
+        }
+
+        protected Uri insertInternal(Uri url, ContentValues values) {
+            throw new UnsupportedOperationException();
+        }
+
+        protected Cursor queryInternal(Uri url, String[] projection, String selection,
+                String[] selectionArgs, String sortOrder) {
+            throw new UnsupportedOperationException();
+        }
+
+        protected void onAccountsChanged(String[] accountsArray) {
+            throw new UnsupportedOperationException();
+        }
+
+        protected void deleteRowsForRemovedAccounts(Map<String, Boolean> accounts, String table,
+                String accountColumnName) {
+            throw new UnsupportedOperationException();
+        }
+
+        public void wipeAccount(String account) {
+            throw new UnsupportedOperationException();
+        }
+
+        public byte[] readSyncDataBytes(String account) {
+            throw new UnsupportedOperationException();
+        }
+
+        public void writeSyncDataBytes(String account, byte[] data) {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    class MockSyncContext extends SyncContext {
+        public MockSyncContext() {
+            super(null);
+        }
+
+        @Override
+        public void setStatusText(String message) {
+        }
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/android/content/SearchRecentSuggestionsProviderTest.java b/tests/FrameworkTest/tests/src/android/content/SearchRecentSuggestionsProviderTest.java
new file mode 100644
index 0000000..a4c33f5
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/android/content/SearchRecentSuggestionsProviderTest.java
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2008 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.content;
+
+import android.app.SearchManager;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.SearchRecentSuggestions;
+import android.test.ProviderTestCase2;
+import android.test.suitebuilder.annotation.Suppress;
+
+/**
+ * Very simple provider that I can instantiate right here.
+ */
+class TestProvider extends SearchRecentSuggestionsProvider {
+    final static String AUTHORITY = "android.content.TestProvider";
+    final static int MODE = DATABASE_MODE_QUERIES + DATABASE_MODE_2LINES;
+    
+    public TestProvider() {
+        super();
+        setupSuggestions(AUTHORITY, MODE);
+    }
+}
+
+/**
+ * ProviderTestCase that performs unit tests of SearchRecentSuggestionsProvider.
+ * 
+ * You can run this test in isolation via the commands:
+ * 
+ * $ (cd tests/FrameworkTests/ && mm) && adb sync
+ * $ adb shell am instrument -w \
+ *     -e class android.content.SearchRecentSuggestionsProviderTest 
+ *     com.android.frameworktest.tests/android.test.InstrumentationTestRunner
+ */
+// Suppress these until bug http://b/issue?id=1416586 is fixed.
+@Suppress
+public class SearchRecentSuggestionsProviderTest extends ProviderTestCase2<TestProvider> {
+
+    // Elements prepared by setUp()
+    SearchRecentSuggestions mSearchHelper;
+    
+    public SearchRecentSuggestionsProviderTest() {
+        super(TestProvider.class, TestProvider.AUTHORITY);
+    }
+    
+    /**
+     * During setup, grab a helper for DB access 
+     */
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        
+        // Use the recent suggestions helper.  As long as we pass in our isolated context,
+        // it should correctly access the provider under test.
+        mSearchHelper = new SearchRecentSuggestions(getMockContext(), 
+                TestProvider.AUTHORITY, TestProvider.MODE);
+
+        // test for empty database at setup time
+        checkOpenCursorCount(0);
+    }
+    
+    /**
+     * Simple test to see if we can instantiate the whole mess.
+     */
+    public void testSetup() {
+        assertTrue(true);
+    }
+    
+    /**
+     * Simple test to see if we can write and read back a single query
+     */
+    public void testOneQuery() {
+        final String TEST_LINE1 = "test line 1";
+        final String TEST_LINE2 = "test line 2";
+        mSearchHelper.saveRecentQuery(TEST_LINE1, TEST_LINE2);
+        
+        // make sure that there are is exactly one entry returned by a non-filtering cursor
+        checkOpenCursorCount(1);
+        
+        // test non-filtering cursor for correct entry
+        checkResultCounts(null, 1, 1, TEST_LINE1, TEST_LINE2);
+        
+        // test filtering cursor for correct entry
+        checkResultCounts(TEST_LINE1, 1, 1, TEST_LINE1, TEST_LINE2);
+        checkResultCounts(TEST_LINE2, 1, 1, TEST_LINE1, TEST_LINE2);
+        
+        // test that a different filter returns zero results
+        checkResultCounts("bad filter", 0, 0, null, null);
+    }
+    
+    /** 
+     * Simple test to see if we can write and read back a diverse set of queries
+     */
+    public void testMixedQueries() {
+        // we'll make 10 queries named "query x" and 10 queries named "test x"
+        final String TEST_GROUP_1 = "query ";
+        final String TEST_GROUP_2 = "test ";
+        final String TEST_LINE2 = "line2 ";
+        final int GROUP_COUNT = 10;
+        
+        writeEntries(GROUP_COUNT, TEST_GROUP_1, TEST_LINE2);
+        writeEntries(GROUP_COUNT, TEST_GROUP_2, TEST_LINE2);
+        
+        // check counts
+        checkOpenCursorCount(2 * GROUP_COUNT);
+        
+        // check that each query returns the right result counts
+        checkResultCounts(TEST_GROUP_1, GROUP_COUNT, GROUP_COUNT, null, null);
+        checkResultCounts(TEST_GROUP_2, GROUP_COUNT, GROUP_COUNT, null, null);
+        checkResultCounts(TEST_LINE2, 2 * GROUP_COUNT, 2 * GROUP_COUNT, null, null);
+    }
+    
+    /**
+     * Test that the reordering code works properly.  The most recently injected queries
+     * should replace existing queries and be sorted to the top of the list.
+     */
+    public void testReordering() {
+        // first we'll make 10 queries named "group1 x"
+        final int GROUP_1_COUNT = 10;
+        final String GROUP_1_QUERY = "group1 ";
+        final String GROUP_1_LINE2 = "line2 ";
+        writeEntries(GROUP_1_COUNT, GROUP_1_QUERY, GROUP_1_LINE2);
+        
+        // check totals
+        checkOpenCursorCount(GROUP_1_COUNT);
+
+        // guarantee that group 1 has older timestamps
+        writeDelay();
+        
+        // next we'll add 10 entries named "group2 x"
+        final int GROUP_2_COUNT = 10;
+        final String GROUP_2_QUERY = "group2 ";
+        final String GROUP_2_LINE2 = "line2 ";
+        writeEntries(GROUP_2_COUNT, GROUP_2_QUERY, GROUP_2_LINE2);
+        
+        // check totals
+        checkOpenCursorCount(GROUP_1_COUNT + GROUP_2_COUNT);
+
+        // guarantee that group 2 has older timestamps
+        writeDelay();
+        
+        // now refresh 5 of the 10 from group 1
+        // change line2 so they can be more easily tracked
+        final int GROUP_3_COUNT = 5;
+        final String GROUP_3_QUERY = GROUP_1_QUERY;
+        final String GROUP_3_LINE2 = "refreshed ";
+        writeEntries(GROUP_3_COUNT, GROUP_3_QUERY, GROUP_3_LINE2);
+        
+        // confirm that the total didn't change (those were replacements, not adds)
+        checkOpenCursorCount(GROUP_1_COUNT + GROUP_2_COUNT);
+        
+        // confirm that the are now 5 in group 1, 10 in group 2, and 5 in group 3
+        int newGroup1Count = GROUP_1_COUNT - GROUP_3_COUNT;
+        checkResultCounts(GROUP_1_QUERY, newGroup1Count, newGroup1Count, null, GROUP_1_LINE2);
+        checkResultCounts(GROUP_2_QUERY, GROUP_2_COUNT, GROUP_2_COUNT, null, null);
+        checkResultCounts(GROUP_3_QUERY, GROUP_3_COUNT, GROUP_3_COUNT, null, GROUP_3_LINE2);
+        
+        // finally, spot check that the right groups are in the right places
+        // the ordering should be group 3 (newest), group 2, group 1 (oldest)
+        Cursor c = getQueryCursor(null);
+        int colQuery = c.getColumnIndexOrThrow(SearchManager.SUGGEST_COLUMN_QUERY);
+        int colDisplay1 = c.getColumnIndexOrThrow(SearchManager.SUGGEST_COLUMN_TEXT_1);
+        int colDisplay2 = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2);
+
+        // Spot check the first and last expected entries of group 3
+        c.moveToPosition(0);
+        assertTrue("group 3 did not properly reorder to head of list",
+                checkRow(c, colQuery, colDisplay1, colDisplay2, GROUP_3_QUERY, GROUP_3_LINE2));
+        c.move(GROUP_3_COUNT - 1);
+        assertTrue("group 3 did not properly reorder to head of list",
+                checkRow(c, colQuery, colDisplay1, colDisplay2, GROUP_3_QUERY, GROUP_3_LINE2));
+
+        // Spot check the first and last expected entries of group 2
+        c.move(1);
+        assertTrue("group 2 not in expected position after reordering",
+                checkRow(c, colQuery, colDisplay1, colDisplay2, GROUP_2_QUERY, GROUP_2_LINE2));
+        c.move(GROUP_2_COUNT - 1);
+        assertTrue("group 2 not in expected position after reordering",
+                checkRow(c, colQuery, colDisplay1, colDisplay2, GROUP_2_QUERY, GROUP_2_LINE2));
+
+        // Spot check the first and last expected entries of group 1
+        c.move(1);
+        assertTrue("group 1 not in expected position after reordering",
+                checkRow(c, colQuery, colDisplay1, colDisplay2, GROUP_1_QUERY, GROUP_1_LINE2));
+        c.move(newGroup1Count - 1);
+        assertTrue("group 1 not in expected position after reordering",
+                checkRow(c, colQuery, colDisplay1, colDisplay2, GROUP_1_QUERY, GROUP_1_LINE2));
+        
+        c.close();
+    }
+    
+    /**
+     * Test that the pruning code works properly,  The database should not go beyond 250 entries,
+     * and the oldest entries should always be discarded first. 
+     * 
+     * TODO:  This is a slow test, do we have annotation for that?
+     */
+    public void testPruning() {
+        // first we'll make 50 queries named "group1 x"
+        final int GROUP_1_COUNT = 50;
+        final String GROUP_1_QUERY = "group1 ";
+        final String GROUP_1_LINE2 = "line2 ";
+        writeEntries(GROUP_1_COUNT, GROUP_1_QUERY, GROUP_1_LINE2);
+        
+        // check totals
+        checkOpenCursorCount(GROUP_1_COUNT);
+
+        // guarantee that group 1 has older timestamps (and will be pruned first)
+        writeDelay();
+        
+        // next we'll add 200 entries named "group2 x"
+        final int GROUP_2_COUNT = 200;
+        final String GROUP_2_QUERY = "group2 ";
+        final String GROUP_2_LINE2 = "line2 ";
+        writeEntries(GROUP_2_COUNT, GROUP_2_QUERY, GROUP_2_LINE2);
+        
+        // check totals
+        checkOpenCursorCount(GROUP_1_COUNT + GROUP_2_COUNT);
+        
+        // Finally we'll add 10 more entries named "group3 x"
+        // These should push out 10 entries from group 1
+        final int GROUP_3_COUNT = 10;
+        final String GROUP_3_QUERY = "group3 ";
+        final String GROUP_3_LINE2 = "line2 ";
+        writeEntries(GROUP_3_COUNT, GROUP_3_QUERY, GROUP_3_LINE2);
+        
+        // total should still be 250
+        checkOpenCursorCount(GROUP_1_COUNT + GROUP_2_COUNT);
+
+        // there should be 40 group 1, 200 group 2, and 10 group 3
+        int group1NewCount = GROUP_1_COUNT-GROUP_3_COUNT;
+        checkResultCounts(GROUP_1_QUERY, group1NewCount, group1NewCount, null, null);
+        checkResultCounts(GROUP_2_QUERY, GROUP_2_COUNT, GROUP_2_COUNT, null, null);
+        checkResultCounts(GROUP_3_QUERY, GROUP_3_COUNT, GROUP_3_COUNT, null, null);
+    }
+    
+    /**
+     * Test that the clear history code works properly.
+     */
+    public void testClear() {
+        // first we'll make 10 queries named "group1 x"
+        final int GROUP_1_COUNT = 10;
+        final String GROUP_1_QUERY = "group1 ";
+        final String GROUP_1_LINE2 = "line2 ";
+        writeEntries(GROUP_1_COUNT, GROUP_1_QUERY, GROUP_1_LINE2);
+        
+        // next we'll add 10 entries named "group2 x"
+        final int GROUP_2_COUNT = 10;
+        final String GROUP_2_QUERY = "group2 ";
+        final String GROUP_2_LINE2 = "line2 ";
+        writeEntries(GROUP_2_COUNT, GROUP_2_QUERY, GROUP_2_LINE2);
+        
+        // check totals
+        checkOpenCursorCount(GROUP_1_COUNT + GROUP_2_COUNT);
+
+        // delete all
+        mSearchHelper.clearHistory();
+        
+        // check totals
+        checkOpenCursorCount(0);
+    }
+    
+    /**
+     * Write a sequence of queries into the database, with incrementing counters in the strings.
+     */
+    private void writeEntries(int groupCount, String line1Base, String line2Base) {
+        for (int i = 0; i < groupCount; i++) {
+            final String line1 = line1Base + i;
+            final String line2 = line2Base + i;
+            mSearchHelper.saveRecentQuery(line1, line2);
+        }
+    }
+    
+    /**
+     * A very slight delay to ensure that successive groups of queries in the DB cannot
+     * have the same timestamp.
+     */
+    private void writeDelay() {
+        try {
+            Thread.sleep(10);
+        } catch (InterruptedException e) {
+            fail("Interrupted sleep.");
+        }
+    }
+    
+    /**
+     * Access an "open" (no selection) suggestions cursor and confirm that it has the specified
+     * number of entries.
+     * 
+     * @param expectCount The expected number of entries returned by the cursor.
+     */
+    private void checkOpenCursorCount(int expectCount) {
+        Cursor c = getQueryCursor(null);
+        assertEquals(expectCount, c.getCount());
+        c.close();
+    }
+    
+    /**
+     * Set up a filter cursor and then scan it for specific results.
+     * 
+     * @param queryString The query string to apply.
+     * @param minRows The minimum number of matching rows that must be found.
+     * @param maxRows The maximum number of matching rows that must be found.
+     * @param matchDisplay1 If non-null, must match DISPLAY1 column if row counts as match
+     * @param matchDisplay2 If non-null, must match DISPLAY2 column if row counts as match
+     */
+    private void checkResultCounts(String queryString, int minRows, int maxRows,
+            String matchDisplay1, String matchDisplay2) {
+        
+        // get the cursor and apply sanity checks to result
+        Cursor c = getQueryCursor(queryString);
+        assertNotNull(c);
+        assertTrue("Insufficient rows in filtered cursor", c.getCount() >= minRows);
+        
+        // look for minimum set of columns (note, display2 is optional)
+        int colQuery = c.getColumnIndexOrThrow(SearchManager.SUGGEST_COLUMN_QUERY);
+        int colDisplay1 = c.getColumnIndexOrThrow(SearchManager.SUGGEST_COLUMN_TEXT_1);
+        int colDisplay2 = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2);
+
+        // now loop through rows and look for desired rows
+        int foundRows = 0;
+        c.moveToFirst();
+        while (!c.isAfterLast()) {
+            if (checkRow(c, colQuery, colDisplay1, colDisplay2, matchDisplay1, matchDisplay2)) {
+                foundRows++;
+            }            
+            c.moveToNext();
+        }
+
+        // now check the results
+        assertTrue(minRows <= foundRows);
+        assertTrue(foundRows <= maxRows);
+        
+        c.close();
+    }
+    
+    /**
+     * Check a single row for equality with target strings.
+     * 
+     * @param c The cursor, already moved to the row
+     * @param colQuery The column # containing the query.  The query must match display1.
+     * @param colDisp1 The column # containing display line 1.
+     * @param colDisp2 The column # containing display line 2, or -1 if no column
+     * @param matchDisplay1 If non-null, this must be the prefix of display1
+     * @param matchDisplay2 If non-null, this must be the prefix of display2
+     * @return Returns true if the row is a "match"
+     */
+    private boolean checkRow(Cursor c, int colQuery, int colDisp1, int colDisp2,
+            String matchDisplay1, String matchDisplay2) {
+        // Get the data from the row
+        String query = c.getString(colQuery);
+        String display1 = c.getString(colDisp1);
+        String display2 = (colDisp2 >= 0) ? c.getString(colDisp2) : null;
+        
+        assertEquals(query, display1);
+        boolean result = true;
+        if (matchDisplay1 != null) {
+            result = result && (display1 != null) && display1.startsWith(matchDisplay1);
+        }
+        if (matchDisplay2 != null) {
+            result = result && (display2 != null) && display2.startsWith(matchDisplay2);
+        }
+        
+        return result;
+    }
+
+    /**
+     * Generate a query cursor in a manner like the search dialog would.
+     * 
+     * @param queryString The search string, or, null for "all"
+     * @return Returns a cursor, or null if there was some problem.  Be sure to close the cursor
+     * when done with it.
+     */
+    private Cursor getQueryCursor(String queryString) {
+        ContentResolver cr = getMockContext().getContentResolver();
+
+        String uriStr = "content://" + TestProvider.AUTHORITY + 
+        '/' + SearchManager.SUGGEST_URI_PATH_QUERY;
+        Uri contentUri = Uri.parse(uriStr);
+
+        String[] selArgs = new String[] {queryString};
+
+        Cursor c = cr.query(contentUri, null, null, selArgs, null);
+
+        assertNotNull(c);
+        return c;
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewCallbacks.java b/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewCallbacks.java
new file mode 100644
index 0000000..93cb84a
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewCallbacks.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2008 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.widget;
+
+import android.app.Instrumentation;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.MediumTest;
+
+public class AutoCompleteTextViewCallbacks 
+        extends ActivityInstrumentationTestCase2<AutoCompleteTextViewSimple> {
+
+    public AutoCompleteTextViewCallbacks() {
+        super("com.android.frameworktest", AutoCompleteTextViewSimple.class);
+    }
+
+    /** Test that the initial popup of the suggestions does not select anything */
+    @MediumTest
+    public void testPopupNoSelection() {
+        AutoCompleteTextViewSimple theActivity = getActivity();
+        AutoCompleteTextView textView = theActivity.getTextView();
+        final Instrumentation instrumentation = getInstrumentation();
+        
+        // focus and type
+        textView.requestFocus();
+        instrumentation.waitForIdleSync();
+        sendKeys("A");
+        
+        // now check for selection callbacks.  Nothing should be clicked or selected.
+        assertFalse("onItemClick should not be called", theActivity.mItemClickCalled);
+        assertFalse("onItemSelected should not be called", theActivity.mItemSelectedCalled);
+        
+        // arguably, this should be "false", because we aren't deselecting - we shouldn't
+        // really be calling it.  But it's not the end of the world, and we might wind up
+        // breaking something if we change this.
+        assertTrue("onNothingSelected should be called", theActivity.mNothingSelectedCalled);
+    }
+
+    /** Test that arrow-down into the popup calls the onSelected callback */
+    @MediumTest
+    public void testPopupEnterSelection() {
+        AutoCompleteTextViewSimple theActivity = getActivity();
+        AutoCompleteTextView textView = theActivity.getTextView();
+        final Instrumentation instrumentation = getInstrumentation();
+        
+        // focus and type
+        textView.requestFocus();
+        instrumentation.waitForIdleSync();
+        sendKeys("A");
+        
+        // prepare to move down into the popup
+        theActivity.resetItemListeners();
+        sendKeys("DPAD_DOWN");
+        
+        // now check for selection callbacks.
+        assertFalse("onItemClick should not be called", theActivity.mItemClickCalled);
+        assertTrue("onItemSelected should be called", theActivity.mItemSelectedCalled);
+        assertEquals("onItemSelected position", 0, theActivity.mItemSelectedPosition);
+        assertFalse("onNothingSelected should not be called", theActivity.mNothingSelectedCalled);
+        
+        // try one more time - should move from 0 to 1
+        theActivity.resetItemListeners();
+        sendKeys("DPAD_DOWN");
+        
+        // now check for selection callbacks.
+        assertFalse("onItemClick should not be called", theActivity.mItemClickCalled);
+        assertTrue("onItemSelected should be called", theActivity.mItemSelectedCalled);
+        assertEquals("onItemSelected position", 1, theActivity.mItemSelectedPosition);
+        assertFalse("onNothingSelected should not be called", theActivity.mNothingSelectedCalled);
+    }
+
+    /** Test that arrow-up out of the popup calls the onNothingSelected callback */
+    @MediumTest
+    public void testPopupLeaveSelection() {
+        AutoCompleteTextViewSimple theActivity = getActivity();
+        AutoCompleteTextView textView = theActivity.getTextView();
+        final Instrumentation instrumentation = getInstrumentation();
+        
+        // focus and type
+        textView.requestFocus();
+        instrumentation.waitForIdleSync();
+        sendKeys("A");
+        
+        // move down into the popup
+        sendKeys("DPAD_DOWN");
+        
+        // now move back up out of the popup
+        theActivity.resetItemListeners();
+        sendKeys("DPAD_UP");
+
+        // now check for selection callbacks.
+        assertFalse("onItemClick should not be called", theActivity.mItemClickCalled);
+        assertFalse("onItemSelected should not be called", theActivity.mItemSelectedCalled);
+        assertTrue("onNothingSelected should be called", theActivity.mNothingSelectedCalled);
+    }
+
+}
diff --git a/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewPopup.java b/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewPopup.java
new file mode 100644
index 0000000..663b7a4
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewPopup.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2008 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.widget;
+
+import android.app.Instrumentation;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.MediumTest;
+
+/**
+ * A collection of tests on aspects of the AutoCompleteTextView's popup
+ */
+public class AutoCompleteTextViewPopup
+        extends ActivityInstrumentationTestCase2<AutoCompleteTextViewSimple> {
+
+    public AutoCompleteTextViewPopup() {
+        super("com.android.frameworktest", AutoCompleteTextViewSimple.class);
+    }
+    
+    /** Test that we can move the selection and it responds as expected */
+    @MediumTest
+    public void testPopupSetListSelection() throws Throwable {
+        AutoCompleteTextViewSimple theActivity = getActivity();
+        final AutoCompleteTextView textView = theActivity.getTextView();
+        final Instrumentation instrumentation = getInstrumentation();
+        
+        // focus and type
+        textView.requestFocus();
+        instrumentation.waitForIdleSync();
+        sendKeys("A");
+        
+        // No initial selection
+        assertEquals("getListSelection(-1)", 
+                ListView.INVALID_POSITION, textView.getListSelection());
+        
+        // set and check
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                textView.setListSelection(0);
+            }
+        });
+        instrumentation.waitForIdleSync();
+        assertEquals("set selection to (0)", 0, textView.getListSelection());
+        
+        // Use movement to cross-check the movement
+        sendKeys("DPAD_DOWN");
+        assertEquals("move selection to (1)", 1, textView.getListSelection());
+    }
+    
+    /** Test that we can look at the selection as we move around */
+    @MediumTest
+    public void testPopupGetListSelection() {
+        AutoCompleteTextViewSimple theActivity = getActivity();
+        AutoCompleteTextView textView = theActivity.getTextView();
+        final Instrumentation instrumentation = getInstrumentation();
+        
+        // focus and type
+        textView.requestFocus();
+        instrumentation.waitForIdleSync();
+        sendKeys("A");
+        
+        // No initial selection
+        assertEquals("getListSelection(-1)", 
+                ListView.INVALID_POSITION, textView.getListSelection());
+        
+        // check for selection position as expected
+        sendKeys("DPAD_DOWN");
+        assertEquals("move selection to (0)", 0, textView.getListSelection());
+        
+        // Repeat for one more movement
+        sendKeys("DPAD_DOWN");
+        assertEquals("move selection to (1)", 1, textView.getListSelection());
+    }
+    
+    /** Test that we can clear the selection */
+    @MediumTest
+    public void testPopupClearListSelection() throws Throwable {
+        AutoCompleteTextViewSimple theActivity = getActivity();
+        final AutoCompleteTextView textView = theActivity.getTextView();
+        final Instrumentation instrumentation = getInstrumentation();
+        
+        // focus and type
+        textView.requestFocus();
+        instrumentation.waitForIdleSync();
+        sendKeys("A");
+        
+        // No initial selection
+        assertEquals("getListSelection(-1)", 
+                ListView.INVALID_POSITION, textView.getListSelection());
+        
+        // check for selection position as expected
+        sendKeys("DPAD_DOWN");
+        assertEquals("getListSelection(0)", 0, textView.getListSelection());
+        
+        // clear it
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                textView.clearListSelection();
+            }
+        });
+        instrumentation.waitForIdleSync();
+        assertEquals("setListSelection(ListView.INVALID_POSITION)", 
+                ListView.INVALID_POSITION, textView.getListSelection());
+    }
+
+    /** Make sure we handle an empty adapter properly */
+    @MediumTest
+    public void testPopupNavigateNoAdapter() throws Throwable {
+        AutoCompleteTextViewSimple theActivity = getActivity();
+        final AutoCompleteTextView textView = theActivity.getTextView();
+        final Instrumentation instrumentation = getInstrumentation();
+
+        // focus and type
+        textView.requestFocus();
+        instrumentation.waitForIdleSync();
+        sendKeys("A");
+
+        // No initial selection
+        assertEquals("getListSelection(-1)",
+                ListView.INVALID_POSITION, textView.getListSelection());
+
+        // check for selection position as expected
+        sendKeys("DPAD_DOWN");
+        assertEquals("getListSelection(0)", 0, textView.getListSelection());
+
+        // Now get rid of the adapter
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                textView.setAdapter((ArrayAdapter<?>) null);
+            }
+        });
+        instrumentation.waitForIdleSync();
+
+        // now try moving "down" - nothing should happen since there's no longer an adapter
+        sendKeys("DPAD_DOWN");
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/android/widget/SimpleCursorAdapterTest.java b/tests/FrameworkTest/tests/src/android/widget/SimpleCursorAdapterTest.java
new file mode 100644
index 0000000..58f4ccb
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/android/widget/SimpleCursorAdapterTest.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2008 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.widget;
+
+import com.android.internal.database.ArrayListCursor;
+import com.google.android.collect.Lists;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.util.ArrayList;
+import java.util.Random;
+
+/**
+ * This is a series of tests of basic API contracts for SimpleCursorAdapter.  It is
+ * incomplete and can use work.
+ * 
+ * NOTE:  This contract holds for underlying cursor types too and these should
+ * be extracted into a set of tests that can be run on any descendant of CursorAdapter.
+ */
+public class SimpleCursorAdapterTest extends AndroidTestCase {
+    
+    String[] mFrom;
+    int[] mTo;
+    int mLayout;
+    Context mContext;
+    
+    ArrayList<ArrayList> mData2x2;
+    Cursor mCursor2x2;
+    
+    /**
+     * Set up basic columns and cursor for the tests
+     */
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        
+        // all the pieces needed for the various tests
+        mFrom = new String[]{"Column1", "Column2"};
+        mTo = new int[]{com.android.internal.R.id.text1, com.android.internal.R.id.text2};
+        mLayout = com.android.internal.R.layout.simple_list_item_2;
+        mContext = getContext();
+
+        // raw data for building a basic test cursor
+        mData2x2 = createTestList(2, 2);
+        mCursor2x2 = new ArrayListCursor(mFrom, mData2x2);
+    }
+    
+    /**
+     * Borrowed from CursorWindowTest.java
+     */
+    private ArrayList<ArrayList> createTestList(int rows, int cols) {
+        ArrayList<ArrayList> list = Lists.newArrayList();
+        Random generator = new Random();
+
+        for (int i = 0; i < rows; i++) {
+            ArrayList<Integer> col = Lists.newArrayList();
+            list.add(col);
+            for (int j = 0; j < cols; j++) {
+                // generate random number
+                Integer r = generator.nextInt();
+                col.add(r);
+            }
+        }
+        return list;
+    }
+
+    /**
+     * Test creating with a live cursor
+     */
+    @SmallTest
+    public void testCreateLive() {
+        SimpleCursorAdapter ca = new SimpleCursorAdapter(mContext, mLayout, mCursor2x2, mFrom, mTo);
+        
+        // Now see if we can pull 2 rows from the adapter
+        assertEquals(2, ca.getCount());
+    }
+    
+    /**
+     * Test creating with a null cursor
+     */
+    @SmallTest
+    public void testCreateNull() {
+        SimpleCursorAdapter ca = new SimpleCursorAdapter(mContext, mLayout, null, mFrom, mTo);
+        
+        // The adapter should report zero rows
+        assertEquals(0, ca.getCount());
+    }
+    
+    /**
+     * Test changeCursor() with live cursor
+     */
+    @SmallTest
+    public void testChangeCursorLive() {
+        SimpleCursorAdapter ca = new SimpleCursorAdapter(mContext, mLayout, mCursor2x2, mFrom, mTo);
+        
+        // Now see if we can pull 2 rows from the adapter
+        assertEquals(2, ca.getCount());
+        
+        // now put in a different cursor (5 rows)
+        ArrayList<ArrayList> data2 = createTestList(5, 2);
+        Cursor c2 = new ArrayListCursor(mFrom, data2);
+        ca.changeCursor(c2);
+        
+        // Now see if we can pull 5 rows from the adapter
+        assertEquals(5, ca.getCount());
+    }
+    
+    /**
+     * Test changeCursor() with null cursor
+     */
+    @SmallTest
+    public void testChangeCursorNull() {
+        SimpleCursorAdapter ca = new SimpleCursorAdapter(mContext, mLayout, mCursor2x2, mFrom, mTo);
+        
+        // Now see if we can pull 2 rows from the adapter
+        assertEquals(2, ca.getCount());
+        
+        // now put in null
+        ca.changeCursor(null);
+        
+        // The adapter should report zero rows
+        assertEquals(0, ca.getCount());
+    }
+    
+    /**
+     * Test changeCursor() with differing column layout.  This confirms that the Adapter can
+     * deal with cursors that have the same essential data (as defined by the original mFrom
+     * array) but it's OK if the physical structure of the cursor changes (columns rearranged).
+     */
+    @SmallTest
+    public void testChangeCursorColumns() {
+        TestSimpleCursorAdapter ca = new TestSimpleCursorAdapter(mContext, mLayout, mCursor2x2, 
+                mFrom, mTo);
+        
+        // check columns of original - mFrom and mTo should line up
+        int[] columns = ca.getConvertedFrom();
+        assertEquals(columns[0], 0);
+        assertEquals(columns[1], 1);
+
+        // Now make a new cursor with similar data but rearrange the columns
+        String[] swappedFrom = new String[]{"Column2", "Column1"};
+        Cursor c2 = new ArrayListCursor(swappedFrom, mData2x2);
+        ca.changeCursor(c2);
+        assertEquals(2, ca.getCount());
+
+        // check columns to see if rearrangement tracked (should be swapped now)
+        columns = ca.getConvertedFrom();
+        assertEquals(columns[0], 1);
+        assertEquals(columns[1], 0);
+    }
+    
+    /**
+     * Test that you can safely construct with a null cursor *and* null to/from arrays.
+     * This is new functionality added in 12/2008.
+     */
+    @SmallTest
+    public void testNullConstructor() {
+        SimpleCursorAdapter ca = new SimpleCursorAdapter(mContext, mLayout, null, null, null);
+        assertEquals(0, ca.getCount());
+    }
+    
+    /**
+     * Test going from a null cursor to a non-null cursor *and* setting the to/from arrays
+     * This is new functionality added in 12/2008.
+     */
+    @SmallTest
+    public void testChangeNullToMapped() {
+        TestSimpleCursorAdapter ca = new TestSimpleCursorAdapter(mContext, mLayout, null, null, null);
+        assertEquals(0, ca.getCount());
+
+        ca.changeCursorAndColumns(mCursor2x2, mFrom, mTo);
+        assertEquals(2, ca.getCount());
+        
+        // check columns of original - mFrom and mTo should line up
+        int[] columns = ca.getConvertedFrom();
+        assertEquals(2, columns.length);
+        assertEquals(0, columns[0]);
+        assertEquals(1, columns[1]);
+        int[] viewIds = ca.getTo();
+        assertEquals(2, viewIds.length);
+        assertEquals(com.android.internal.R.id.text1, viewIds[0]);
+        assertEquals(com.android.internal.R.id.text2, viewIds[1]);
+    }
+    
+    /**
+     * Test going from one mapping to a different mapping
+     * This is new functionality added in 12/2008.
+     */
+    @SmallTest
+    public void testChangeMapping() {
+        TestSimpleCursorAdapter ca = new TestSimpleCursorAdapter(mContext, mLayout, mCursor2x2, 
+                mFrom, mTo);
+        assertEquals(2, ca.getCount());
+
+        // Now create a new configuration with same cursor and just one column mapped
+        String[] singleFrom = new String[]{"Column1"};
+        int[] singleTo = new int[]{com.android.internal.R.id.text1};
+        ca.changeCursorAndColumns(mCursor2x2, singleFrom, singleTo);
+
+        // And examine the results, make sure they're still consistent
+        int[] columns = ca.getConvertedFrom();
+        assertEquals(1, columns.length);
+        assertEquals(0, columns[0]);
+        int[] viewIds = ca.getTo();
+        assertEquals(1, viewIds.length);
+        assertEquals(com.android.internal.R.id.text1, viewIds[0]);
+        
+        // And again, same cursor, different map
+        singleFrom = new String[]{"Column2"};
+        singleTo = new int[]{com.android.internal.R.id.text2};
+        ca.changeCursorAndColumns(mCursor2x2, singleFrom, singleTo);
+
+        // And examine the results, make sure they're still consistent
+        columns = ca.getConvertedFrom();
+        assertEquals(1, columns.length);
+        assertEquals(1, columns[0]);
+        viewIds = ca.getTo();
+        assertEquals(1, viewIds.length);
+        assertEquals(com.android.internal.R.id.text2, viewIds[0]);
+    }
+    
+    /**
+     * This is simply a way to sneak a look at the protected mFrom() array.  A more API-
+     * friendly way to do this would be to mock out a View and a ViewBinder and exercise
+     * it via those seams.
+     */
+    private static class TestSimpleCursorAdapter extends SimpleCursorAdapter {
+        
+        public TestSimpleCursorAdapter(Context context, int layout, Cursor c,
+                String[] from, int[] to) {
+            super(context, layout, c, from, to);
+        }
+
+        int[] getConvertedFrom() {
+            return mFrom;
+        }
+        
+        int[] getTo() {
+            return mTo;
+        }
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/AllTests.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/AllTests.java
new file mode 100644
index 0000000..e43ebb8
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/AllTests.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2008 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.frameworktest;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import android.test.suitebuilder.TestSuiteBuilder;
+
+public class AllTests extends TestSuite {
+
+    public static Test suite() {
+        return new TestSuiteBuilder(AllTests.class)
+                .includeAllPackagesUnderHere()
+                .includePackages("android.content")
+                .includePackages("android.widget")
+                .build();
+    }
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/drawable/DrawableBgMinSizeTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/drawable/DrawableBgMinSizeTest.java
new file mode 100644
index 0000000..ef6297d
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/drawable/DrawableBgMinSizeTest.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.drawable;
+
+import com.android.frameworktest.R;
+import com.android.frameworktest.drawable.DrawableBgMinSize;
+import android.test.TouchUtils;
+import android.test.suitebuilder.annotation.MediumTest;
+
+import android.graphics.drawable.Drawable;
+import android.test.ActivityInstrumentationTestCase;
+import android.view.View;
+import android.widget.AbsoluteLayout;
+import android.widget.Button;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+/**
+ * {@link DrawableBgMinSize} exercises Views to obey their background drawable's
+ * minimum sizes.
+ */
+public class DrawableBgMinSizeTest extends
+        ActivityInstrumentationTestCase<DrawableBgMinSize> {
+    private Button mChangeBackgroundsButton;
+    
+    private Drawable mBackgroundDrawable;
+    private Drawable mBigBackgroundDrawable;
+    
+    private TextView mTextView;
+    private LinearLayout mLinearLayout;
+    private RelativeLayout mRelativeLayout;
+    private FrameLayout mFrameLayout;
+    private AbsoluteLayout mAbsoluteLayout;
+    
+    public DrawableBgMinSizeTest() {
+        super("com.android.frameworktest", DrawableBgMinSize.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        final DrawableBgMinSize a = getActivity();
+
+        mChangeBackgroundsButton = (Button) a.findViewById(R.id.change_backgrounds);
+        mBackgroundDrawable = a.getResources().getDrawable(R.drawable.drawable_background);
+        mBigBackgroundDrawable = a.getResources().getDrawable(R.drawable.big_drawable_background);
+        mTextView = (TextView) a.findViewById(R.id.text_view);
+        mLinearLayout = (LinearLayout) a.findViewById(R.id.linear_layout);
+        mRelativeLayout = (RelativeLayout) a.findViewById(R.id.relative_layout);
+        mFrameLayout = (FrameLayout) a.findViewById(R.id.frame_layout);
+        mAbsoluteLayout = (AbsoluteLayout) a.findViewById(R.id.absolute_layout);
+    }
+
+    @MediumTest
+    public void testSetUpConditions() throws Exception {
+        assertNotNull(mChangeBackgroundsButton);
+        assertNotNull(mBackgroundDrawable);
+        assertNotNull(mBigBackgroundDrawable);
+        assertNotNull(mTextView);
+        assertNotNull(mLinearLayout);
+        assertNotNull(mRelativeLayout);
+        assertNotNull(mFrameLayout);
+        assertNotNull(mAbsoluteLayout);
+    }
+    
+    public void doMinimumSizeTest(View view) throws Exception {
+        assertTrue(view.getClass().getSimpleName() + " should respect the background Drawable's minimum width",
+                view.getWidth() >= mBackgroundDrawable.getMinimumWidth());
+        assertTrue(view.getClass().getSimpleName() + " should respect the background Drawable's minimum height",
+                view.getHeight() >= mBackgroundDrawable.getMinimumHeight());
+    }
+
+    @MediumTest
+    public void testTextViewMinimumSize() throws Exception {
+        doMinimumSizeTest(mTextView);
+    }
+    
+    @MediumTest
+    public void testLinearLayoutMinimumSize() throws Exception {
+        doMinimumSizeTest(mLinearLayout);
+    }
+    
+    @MediumTest
+    public void testRelativeLayoutMinimumSize() throws Exception {
+        doMinimumSizeTest(mRelativeLayout);
+    }
+    
+    @MediumTest
+    public void testAbsoluteLayoutMinimumSize() throws Exception {
+        doMinimumSizeTest(mAbsoluteLayout);
+    }
+    
+    @MediumTest
+    public void testFrameLayoutMinimumSize() throws Exception {
+        doMinimumSizeTest(mFrameLayout);
+    }
+    
+    public void doDiffBgMinimumSizeTest(final View view) throws Exception {
+        // Change to the bigger backgrounds
+        TouchUtils.tapView(this, mChangeBackgroundsButton);
+
+        assertTrue(view.getClass().getSimpleName()
+                + " should respect the different bigger background Drawable's minimum width", view
+                .getWidth() >= mBigBackgroundDrawable.getMinimumWidth());
+        assertTrue(view.getClass().getSimpleName()
+                + " should respect the different bigger background Drawable's minimum height", view
+                .getHeight() >= mBigBackgroundDrawable.getMinimumHeight());
+    }
+
+    @MediumTest
+    public void testTextViewDiffBgMinimumSize() throws Exception {
+        doDiffBgMinimumSizeTest(mTextView);
+    }
+    
+    @MediumTest
+    public void testLinearLayoutDiffBgMinimumSize() throws Exception {
+        doDiffBgMinimumSizeTest(mLinearLayout);
+    }
+    
+    @MediumTest
+    public void testRelativeLayoutDiffBgMinimumSize() throws Exception {
+        doDiffBgMinimumSizeTest(mRelativeLayout);
+    }
+    
+    @MediumTest
+    public void testAbsoluteLayoutDiffBgMinimumSize() throws Exception {
+        doDiffBgMinimumSizeTest(mAbsoluteLayout);
+    }
+    
+    @MediumTest
+    public void testFrameLayoutDiffBgMinimumSize() throws Exception {
+        doDiffBgMinimumSizeTest(mFrameLayout);
+    }
+    
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/drawable/MutateDrawableTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/drawable/MutateDrawableTest.java
new file mode 100644
index 0000000..53085ca
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/drawable/MutateDrawableTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.frameworktest.drawable;
+
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.View;
+
+public class MutateDrawableTest extends ActivityInstrumentationTestCase2<MutateDrawable> {
+    private View mFirstButton;
+    private View mSecondButton;
+
+    public MutateDrawableTest() {
+        super("com.android.frameworktest", MutateDrawable.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mFirstButton = getActivity().findViewById(com.android.frameworktest.R.id.a);
+        mSecondButton = getActivity().findViewById(com.android.frameworktest.R.id.b);
+    }
+
+    @MediumTest
+    public void testSetUpConditions() throws Exception {
+        assertNotNull(mFirstButton);
+        assertNotNull(mSecondButton);
+        assertNotSame(mFirstButton.getBackground(), mSecondButton.getBackground());
+    }
+
+    @MediumTest
+    public void testDrawableCanMutate() throws Exception {
+        assertNotSame(mFirstButton.getBackground().getConstantState(),
+                mSecondButton.getBackground().getConstantState());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/expandablelistview/ExpandableListBasicTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/expandablelistview/ExpandableListBasicTest.java
new file mode 100644
index 0000000..163e084
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/expandablelistview/ExpandableListBasicTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.expandablelistview;
+
+import com.android.frameworktest.expandablelistview.ExpandableListSimple;
+import com.android.frameworktest.util.ExpandableListScenario;
+import com.android.frameworktest.util.ListUtil;
+import com.android.frameworktest.util.ExpandableListScenario.MyGroup;
+
+import java.util.List;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.widget.BaseExpandableListAdapter;
+import android.widget.ExpandableListAdapter;
+import android.widget.ExpandableListView;
+
+public class ExpandableListBasicTest extends ActivityInstrumentationTestCase<ExpandableListSimple> {
+    private ExpandableListScenario mActivity;
+    private ExpandableListView mListView;
+    private ExpandableListAdapter mAdapter;
+    private ListUtil mListUtil;
+    
+    public ExpandableListBasicTest() {
+        super("com.android.frameworktest",
+                ExpandableListSimple.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        
+        mActivity = getActivity();
+        mListView = mActivity.getExpandableListView();
+        mAdapter = mListView.getExpandableListAdapter();
+        mListUtil = new ListUtil(mListView, getInstrumentation());
+    }
+    
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mListView);
+    }
+    
+    private int expandGroup(int numChildren, boolean atLeastOneChild) {
+        final int groupPos = mActivity.findGroupWithNumChildren(numChildren, atLeastOneChild);
+        
+        assertTrue("Could not find group to expand", groupPos >= 0);
+        assertFalse("Group is already expanded", mListView.isGroupExpanded(groupPos));
+        mListUtil.arrowScrollToSelectedPosition(groupPos);
+        getInstrumentation().waitForIdleSync();
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        getInstrumentation().waitForIdleSync();
+        assertTrue("Group did not expand", mListView.isGroupExpanded(groupPos));
+        
+        return groupPos;
+    }
+
+    @MediumTest
+    public void testExpandGroup() {
+        expandGroup(-1, true);
+    }
+    
+    @MediumTest
+    public void testCollapseGroup() {
+        final int groupPos = expandGroup(-1, true);
+        
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        getInstrumentation().waitForIdleSync();
+        assertFalse("Group did not collapse", mListView.isGroupExpanded(groupPos));
+    }
+    
+    @MediumTest
+    public void testExpandedGroupMovement() {
+
+        // Expand the first group
+        mListUtil.arrowScrollToSelectedPosition(0);
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        getInstrumentation().waitForIdleSync();
+
+        // Ensure it expanded
+        assertTrue("Group did not expand", mListView.isGroupExpanded(0));
+        
+        // Wait until that's all good
+        getInstrumentation().waitForIdleSync();
+        
+        // Make sure it expanded
+        assertTrue("Group did not expand", mListView.isGroupExpanded(0));
+        
+        // Insert a collapsed group in front of the one just expanded
+        List<MyGroup> groups = mActivity.getGroups();
+        MyGroup insertedGroup = new MyGroup(1);
+        groups.add(0, insertedGroup);
+        
+        // Notify data change
+        assertTrue("Adapter is not an instance of the base adapter",
+                mAdapter instanceof BaseExpandableListAdapter);
+        final BaseExpandableListAdapter adapter = (BaseExpandableListAdapter) mAdapter;
+     
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                adapter.notifyDataSetChanged();
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+        
+        // Make sure the right group is expanded
+        assertTrue("The expanded state didn't stay with the proper group",
+                mListView.isGroupExpanded(1));
+        assertFalse("The expanded state was given to the inserted group",
+                mListView.isGroupExpanded(0));
+    }
+    
+}
\ No newline at end of file
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/expandablelistview/ExpandableListWithHeadersTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/expandablelistview/ExpandableListWithHeadersTest.java
new file mode 100644
index 0000000..49b5106
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/expandablelistview/ExpandableListWithHeadersTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.expandablelistview;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.widget.ExpandableListView;
+
+import com.android.frameworktest.expandablelistview.ExpandableListWithHeaders;
+import com.android.frameworktest.util.ListUtil;
+
+public class ExpandableListWithHeadersTest extends ActivityInstrumentationTestCase<ExpandableListWithHeaders> {
+    private ExpandableListView mExpandableListView;
+    private ListUtil mListUtil;
+    
+    public ExpandableListWithHeadersTest() {
+        super("com.android.frameworktest",
+                ExpandableListWithHeaders.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        
+        mExpandableListView = getActivity().getExpandableListView();
+        mListUtil = new ListUtil(mExpandableListView, getInstrumentation());
+    }
+    
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mExpandableListView);
+    }
+    
+    @MediumTest
+    public void testExpandOnFirstPosition() {
+        // Should be a header, and hence the first group should NOT have expanded
+        mListUtil.arrowScrollToSelectedPosition(0);
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        getInstrumentation().waitForIdleSync();
+        assertFalse(mExpandableListView.isGroupExpanded(0));
+    }
+
+    @LargeTest
+    public void testExpandOnFirstGroup() {
+        mListUtil.arrowScrollToSelectedPosition(getActivity().getNumOfHeadersAndFooters());
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        getInstrumentation().waitForIdleSync();
+        assertTrue(mExpandableListView.isGroupExpanded(0));
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/DescendantFocusabilityTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/DescendantFocusabilityTest.java
new file mode 100644
index 0000000..6bdd416
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/DescendantFocusabilityTest.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.focus;
+
+import com.android.frameworktest.focus.DescendantFocusability;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.UiThreadTest;
+import android.test.TouchUtils;
+import android.view.ViewGroup;
+
+public class DescendantFocusabilityTest extends ActivityInstrumentationTestCase<DescendantFocusability> {
+
+    private DescendantFocusability a;
+
+    public DescendantFocusabilityTest() {
+        super("com.android.frameworktest", DescendantFocusability.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        a = getActivity();
+
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertEquals(ViewGroup.FOCUS_BEFORE_DESCENDANTS,
+            a.beforeDescendants.getDescendantFocusability());
+        assertEquals(ViewGroup.FOCUS_AFTER_DESCENDANTS,
+            a.afterDescendants.getDescendantFocusability());
+        assertEquals(ViewGroup.FOCUS_BLOCK_DESCENDANTS,
+            a.blocksDescendants.getDescendantFocusability());
+
+        assertTrue(a.beforeDescendantsChild.isFocusable());
+        assertTrue(a.afterDescendantsChild.isFocusable());
+        assertTrue(a.blocksDescendantsChild.isFocusable());
+    }
+
+    @UiThreadTest
+    @MediumTest
+    public void testBeforeDescendants() {
+        a.beforeDescendants.setFocusable(true);
+
+        assertTrue(a.beforeDescendants.requestFocus());
+        assertTrue(a.beforeDescendants.isFocused());
+
+        a.beforeDescendants.setFocusable(false);
+        a.beforeDescendants.requestFocus();
+        assertTrue(a.beforeDescendantsChild.isFocused());
+    }
+
+    @UiThreadTest
+    @MediumTest
+    public void testAfterDescendants() {
+        a.afterDescendants.setFocusable(true);
+
+        assertTrue(a.afterDescendants.requestFocus());
+        assertTrue(a.afterDescendantsChild.isFocused());
+
+        a.afterDescendants.setFocusable(false);
+        assertTrue(a.afterDescendants.requestFocus());
+        assertTrue(a.afterDescendantsChild.isFocused());
+    }
+
+    @UiThreadTest
+    @MediumTest
+    public void testBlocksDescendants() {
+        a.blocksDescendants.setFocusable(true);
+        assertTrue(a.blocksDescendants.requestFocus());
+        assertTrue(a.blocksDescendants.isFocused());
+        assertFalse(a.blocksDescendantsChild.isFocused());
+
+        a.blocksDescendants.setFocusable(false);
+        assertFalse(a.blocksDescendants.requestFocus());
+        assertFalse(a.blocksDescendants.isFocused());
+        assertFalse(a.blocksDescendantsChild.isFocused());
+    }
+
+    @UiThreadTest
+    @MediumTest
+    public void testChildOfDescendantBlockerRequestFocusFails() {
+        assertFalse(a.blocksDescendantsChild.requestFocus());
+    }
+
+    @LargeTest
+    public void testBeforeDescendantsEnterTouchMode() {
+        a.runOnUiThread(new Runnable() {
+            public void run() {
+                a.beforeDescendants.setFocusableInTouchMode(true);
+                a.beforeDescendantsChild.requestFocus();
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+        assertTrue(a.beforeDescendantsChild.isFocused());
+        assertFalse(a.beforeDescendantsChild.isInTouchMode());
+
+        TouchUtils.clickView(this, a.beforeDescendantsChild);
+        assertTrue(a.beforeDescendantsChild.isInTouchMode());
+        assertFalse(a.beforeDescendants.isFocused());        
+    }
+
+    @LargeTest
+    public void testAfterDescendantsEnterTouchMode() {
+        a.runOnUiThread(new Runnable() {
+            public void run() {
+                a.afterDescendants.setFocusableInTouchMode(true);
+                a.afterDescendantsChild.requestFocus();
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+        assertTrue(a.afterDescendantsChild.isFocused());
+        assertFalse(a.afterDescendantsChild.isInTouchMode());
+
+        TouchUtils.clickView(this, a.afterDescendantsChild);
+        assertTrue(a.afterDescendantsChild.isInTouchMode());
+        assertTrue(a.afterDescendants.isFocused());
+    }
+
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/FocusAfterRemovalTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/FocusAfterRemovalTest.java
new file mode 100644
index 0000000..8fb9b01
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/FocusAfterRemovalTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.focus;
+
+import com.android.frameworktest.focus.FocusAfterRemoval;
+import com.android.frameworktest.R;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.view.KeyEvent;
+import android.view.View;
+
+/**
+ * {@link FocusAfterRemoval} is set up to exercise cases where the views that
+ * have focus become invisible or GONE.
+ */
+public class FocusAfterRemovalTest extends ActivityInstrumentationTestCase<FocusAfterRemoval> {
+
+    private LinearLayout mLeftLayout;
+    private Button mTopLeftButton;
+    private Button mBottomLeftButton;
+    private Button mTopRightButton;
+    private Button mBottomRightButton;
+
+    public FocusAfterRemovalTest() {
+        super("com.android.frameworktest", FocusAfterRemoval.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        final FocusAfterRemoval a = getActivity();
+        mLeftLayout = (LinearLayout) a.findViewById(R.id.leftLayout);
+        mTopLeftButton = (Button) a.findViewById(R.id.topLeftButton);
+        mBottomLeftButton = (Button) a.findViewById(R.id.bottomLeftButton);
+        mTopRightButton = (Button) a.findViewById(R.id.topRightButton);
+        mBottomRightButton = (Button) a.findViewById(R.id.bottomRightButton);
+    }
+
+    // Test that setUp did what we expect it to do.  These asserts
+    // can't go in SetUp, or the test will hang.
+    @MediumTest
+    public void testSetUpConditions() throws Exception {
+        assertNotNull(mLeftLayout);
+        assertNotNull(mTopLeftButton);
+        assertNotNull(mTopRightButton);
+        assertNotNull(mBottomLeftButton);
+        assertNotNull(mBottomRightButton);
+
+        assertTrue(mTopLeftButton.hasFocus());
+    }
+
+    // if a parent layout becomes GONE when one of its children has focus,
+    // make sure the focus moves to something visible (bug 827087)
+    @MediumTest
+    public void testFocusLeavesWhenParentLayoutIsGone() throws Exception {
+
+        // clicking on this button makes its parent linear layout GONE
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        assertEquals(View.GONE, mLeftLayout.getVisibility());
+
+        assertTrue("focus should jump to visible button",
+                mTopRightButton.hasFocus());
+
+    }
+
+    @MediumTest
+    public void testFocusLeavesWhenParentLayoutInvisible() throws Exception {
+
+        // move down to bottom left button
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        assertTrue(mBottomLeftButton.hasFocus());
+
+        // clicking on this button makes its parent linear layout INVISIBLE
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        assertEquals(View.INVISIBLE,
+                getActivity().findViewById(R.id.leftLayout).getVisibility());
+
+        assertTrue("focus should jump to visible button",
+                mTopRightButton.hasFocus());
+    }
+
+    @MediumTest
+    public void testFocusLeavesWhenFocusedViewBecomesGone() throws Exception {
+
+        // move to top right
+        sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
+        assertTrue(mTopRightButton.hasFocus());
+
+        // click making it GONE
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        assertEquals(View.GONE, mTopRightButton.getVisibility());
+
+        assertTrue("focus should jump to visible button",
+                mTopLeftButton.hasFocus());
+    }
+
+    @MediumTest
+    public void testFocusLeavesWhenFocusedViewBecomesInvisible() throws Exception {
+
+        // move to bottom right
+        sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        assertTrue(mBottomRightButton.hasFocus());
+
+        // click making it INVISIBLE
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        assertEquals(View.INVISIBLE, mBottomRightButton.getVisibility());
+
+        assertTrue("focus should jump to visible button",
+                mTopLeftButton.hasFocus());
+    }
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/FocusChangeWithInterestingRectHintTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/FocusChangeWithInterestingRectHintTest.java
new file mode 100644
index 0000000..6bdb1ca
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/FocusChangeWithInterestingRectHintTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.focus;
+
+import com.android.frameworktest.focus.AdjacentVerticalRectLists;
+import com.android.frameworktest.util.InternalSelectionView;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+
+/**
+ * {@link android.view.FocusFinder#findNextFocus(android.view.ViewGroup, android.view.View, int)}
+ * and
+ * {@link android.view.View#requestFocus(int, android.graphics.Rect)}
+ * work together to give a newly focused item a hint about the most interesting
+ * rectangle of the previously focused view.  The view taking focus can use this
+ * to set an internal selection more appropriate using this rect.
+ *
+ * This tests that behavior using three adjacent {@link com.android.frameworktest.util.InternalSelectionView}
+ * that report interesting rects when giving up focus, and use interesting rects
+ * when taking focus to best select the internal row to show as selected.
+ *
+ */
+public class FocusChangeWithInterestingRectHintTest extends ActivityInstrumentationTestCase<AdjacentVerticalRectLists> {
+
+    private InternalSelectionView mLeftColumn;
+    private InternalSelectionView mMiddleColumn;
+    private InternalSelectionView mRightColumn;
+
+    public FocusChangeWithInterestingRectHintTest() {
+        super("com.android.frameworktest", AdjacentVerticalRectLists.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mLeftColumn = getActivity().getLeftColumn();
+        mMiddleColumn = getActivity().getMiddleColumn();
+        mRightColumn = getActivity().getRightColumn();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mLeftColumn);
+        assertNotNull(mMiddleColumn);
+        assertNotNull(mRightColumn);
+        assertTrue(mLeftColumn.hasFocus());
+        assertTrue("need at least 3 rows", mLeftColumn.getNumRows() > 2);
+        assertEquals(mLeftColumn.getNumRows(), mMiddleColumn.getNumRows());
+        assertEquals(mMiddleColumn.getNumRows(), mRightColumn.getNumRows());
+    }
+
+
+    @LargeTest
+    public void testSnakeBackAndForth() {
+        final int numRows = mLeftColumn.getNumRows();
+        for (int row = 0; row < numRows; row++) {
+
+            if ((row % 2) == 0) {
+                assertEquals("row " + row + ": should be at left column",
+                        row, mLeftColumn.getSelectedRow());
+
+                sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
+                assertTrue("row " + row + ": should be at middle column",
+                        mMiddleColumn.hasFocus());
+                assertEquals(row, mMiddleColumn.getSelectedRow());
+
+                sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
+                assertTrue("row " + row + ": should be at right column",
+                        mRightColumn.hasFocus());
+                assertEquals(row, mRightColumn.getSelectedRow());
+
+                if (row < numRows - 1) {
+                    sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+                    assertEquals(row + 1, mRightColumn.getSelectedRow());
+                }
+            } else {
+                assertTrue("row " + row + ": should be at right column",
+                        mRightColumn.hasFocus());
+
+                sendKeys(KeyEvent.KEYCODE_DPAD_LEFT);
+                assertTrue("row " + row + ": should be at middle column",
+                        mMiddleColumn.hasFocus());
+                assertEquals(row, mMiddleColumn.getSelectedRow());
+
+                sendKeys(KeyEvent.KEYCODE_DPAD_LEFT);
+                assertEquals("row " + row + ": should be at left column",
+                        row, mLeftColumn.getSelectedRow());
+
+                if (row < numRows - 1) {
+                    sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+                    assertEquals(row + 1, mLeftColumn.getSelectedRow());
+                }
+           }
+        }
+    }
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/GoneParentFocusedChildTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/GoneParentFocusedChildTest.java
new file mode 100644
index 0000000..a490322
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/GoneParentFocusedChildTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.focus;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.view.View;
+import com.android.frameworktest.focus.GoneParentFocusedChild;
+
+/**
+ * When a parent is GONE, key events shouldn't go to its children, even if they
+ * have focus. (part of investigation into issue 945150).
+ */
+public class GoneParentFocusedChildTest
+        extends ActivityInstrumentationTestCase<GoneParentFocusedChild> {
+
+
+    public GoneParentFocusedChildTest() {
+        super("com.android.frameworktest", GoneParentFocusedChild.class);
+    }
+
+    @MediumTest
+    public void testPreconditinos() {
+        assertNotNull(getActivity().getLayout());
+        assertNotNull(getActivity().getGoneGroup());
+        assertNotNull(getActivity().getButton());
+        assertTrue("button should have focus",
+                getActivity().getButton().hasFocus());
+        assertEquals("gone group should be, well, gone!",
+                View.GONE,
+                getActivity().getGoneGroup().getVisibility());
+        assertFalse("the activity should have received no key events",
+                getActivity().isUnhandledKeyEvent());
+    }
+
+    @MediumTest
+    public void testKeyEventGoesToActivity() {
+        sendKeys(KeyEvent.KEYCODE_J);
+        assertTrue(getActivity().isUnhandledKeyEvent());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/HorizontalFocusSearchTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/HorizontalFocusSearchTest.java
new file mode 100644
index 0000000..ca7cd7e
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/HorizontalFocusSearchTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.focus;
+
+import com.android.frameworktest.focus.HorizontalFocusSearch;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.Suppress;
+import android.widget.LinearLayout;
+import android.widget.Button;
+import android.view.View;
+
+import static com.android.frameworktest.focus.VerticalFocusSearchTest.FocusSearchAlg;
+import static com.android.frameworktest.focus.VerticalFocusSearchTest.NewFocusSearchAlg;
+
+/**
+ * Tests that focus searching works on a horizontal linear layout of buttons of
+ * various widths and vertical placements.
+ */
+// Suppress until bug http://b/issue?id=1416545 is fixed.
+@Suppress
+public class HorizontalFocusSearchTest extends ActivityInstrumentationTestCase<HorizontalFocusSearch> {
+
+    private FocusSearchAlg mFocusFinder;
+
+    private LinearLayout mLayout;
+    private Button mLeftTall;
+    private Button mMidShort1Top;
+    private Button mMidShort2Bottom;
+    private Button mRightTall;
+
+
+    public HorizontalFocusSearchTest() {
+        super("com.android.frameworktest", HorizontalFocusSearch.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mFocusFinder = new NewFocusSearchAlg();
+
+        mLayout = getActivity().getLayout();
+        mLeftTall = getActivity().getLeftTall();
+        mMidShort1Top = getActivity().getMidShort1Top();
+        mMidShort2Bottom = getActivity().getMidShort2Bottom();
+        mRightTall = getActivity().getRightTall();
+    }
+
+    public void testPreconditions() {
+        assertNotNull(mLayout);
+        assertNotNull(mLeftTall);
+        assertNotNull(mMidShort1Top);
+        assertNotNull(mMidShort2Bottom);
+        assertNotNull(mRightTall);
+    }
+
+    public void testSearchFromLeftButton() {
+        assertNull("going up from mLeftTall",
+                mFocusFinder.findNextFocus(mLayout, mLeftTall, View.FOCUS_UP));
+        assertNull("going down from mLeftTall",
+                mFocusFinder.findNextFocus(mLayout, mLeftTall, View.FOCUS_DOWN));
+        assertNull("going left from mLeftTall",
+                mFocusFinder.findNextFocus(mLayout, mLeftTall, View.FOCUS_LEFT));
+
+        assertEquals("going right from mLeftTall",
+                mMidShort1Top,
+                mFocusFinder.findNextFocus(mLayout, mLeftTall, View.FOCUS_RIGHT));
+    }
+
+    public void TODO_testSearchFromMiddleLeftButton() {
+        assertNull("going up from mMidShort1Top",
+                mFocusFinder.findNextFocus(mLayout, mMidShort1Top, View.FOCUS_UP));
+        assertEquals("going down from mMidShort1Top",
+                mMidShort2Bottom,
+                mFocusFinder.findNextFocus(mLayout, mMidShort1Top, View.FOCUS_DOWN));
+        assertEquals("going left from mMidShort1Top",
+                mLeftTall,
+                mFocusFinder.findNextFocus(mLayout, mMidShort1Top, View.FOCUS_LEFT));
+        assertEquals("going right from mMidShort1Top",
+                mMidShort2Bottom,
+                mFocusFinder.findNextFocus(mLayout, mMidShort1Top, View.FOCUS_RIGHT));
+    }
+
+    public void TODO_testSearchFromMiddleRightButton() {
+        assertEquals("going up from mMidShort2Bottom",
+                mMidShort1Top,
+                mFocusFinder.findNextFocus(mLayout, mMidShort2Bottom, View.FOCUS_UP));
+        assertNull("going down from mMidShort2Bottom",
+                mFocusFinder.findNextFocus(mLayout, mMidShort2Bottom, View.FOCUS_DOWN));
+        assertEquals("going left from mMidShort2Bottom",
+                mMidShort1Top,
+                mFocusFinder.findNextFocus(mLayout, mMidShort2Bottom, View.FOCUS_LEFT));
+        assertEquals("goind right from mMidShort2Bottom",
+                mRightTall,
+                mFocusFinder.findNextFocus(mLayout, mMidShort2Bottom, View.FOCUS_RIGHT));
+    }
+
+    public void testSearchFromRightButton() {
+        assertNull("going up from mRightTall",
+                mFocusFinder.findNextFocus(mLayout, mRightTall, View.FOCUS_UP));
+        assertNull("going down from mRightTall",
+                mFocusFinder.findNextFocus(mLayout, mRightTall, View.FOCUS_DOWN));
+        assertEquals("going left from mRightTall",
+                mMidShort2Bottom,
+                mFocusFinder.findNextFocus(mLayout, mRightTall, View.FOCUS_LEFT));
+        assertNull("going right from mRightTall",
+                mFocusFinder.findNextFocus(mLayout, mRightTall, View.FOCUS_RIGHT));
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/LinearLayoutGridTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/LinearLayoutGridTest.java
new file mode 100644
index 0000000..c26c331
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/LinearLayoutGridTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.focus;
+
+import android.test.SingleLaunchActivityTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.FocusFinder;
+import android.view.View;
+import android.view.ViewGroup;
+import com.android.frameworktest.focus.LinearLayoutGrid;
+
+/**
+ * Tests focus searching between buttons within a grid that are touching, for example,
+ * two buttons next two each other would have the left button's right equal to the
+ * right button's left.  Same goes for top and bottom edges.
+ *
+ * This exercises some edge cases of {@link android.view.FocusFinder}.
+ */
+public class LinearLayoutGridTest extends SingleLaunchActivityTestCase<LinearLayoutGrid> {
+    private ViewGroup mRootView;
+
+    public LinearLayoutGridTest() {
+        super("com.android.frameworktest", LinearLayoutGrid.class);
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        mRootView = getActivity().getRootView();
+    }
+
+    @MediumTest
+    public void testGoDownFromMiddle() {
+        assertEquals(getActivity().getButtonAt(2, 1),
+                FocusFinder.getInstance().findNextFocus(
+                        mRootView,
+                        getActivity().getButtonAt(1, 1),
+                        View.FOCUS_DOWN));
+    }
+
+    @MediumTest
+    public void testGoUpFromMiddle() {
+        assertEquals(getActivity().getButtonAt(0, 1),
+                FocusFinder.getInstance().findNextFocus(
+                        mRootView,
+                        getActivity().getButtonAt(1, 1),
+                        View.FOCUS_UP));
+    }
+
+    @MediumTest
+    public void testGoRightFromMiddle() {
+        assertEquals(getActivity().getButtonAt(1, 2),
+                FocusFinder.getInstance().findNextFocus(
+                        mRootView,
+                        getActivity().getButtonAt(1, 1),
+                        View.FOCUS_RIGHT));
+    }
+
+    @MediumTest
+    public void testGoLeftFromMiddle() {
+        assertEquals(getActivity().getButtonAt(1, 0),
+                FocusFinder.getInstance().findNextFocus(
+                        mRootView,
+                        getActivity().getButtonAt(1, 1),
+                        View.FOCUS_LEFT));
+    }
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/ListOfButtonsTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/ListOfButtonsTest.java
new file mode 100644
index 0000000..902fc1c
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/ListOfButtonsTest.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.focus;
+
+import com.android.frameworktest.focus.ListOfButtons;
+import com.android.frameworktest.R;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.ListAdapter;
+import android.widget.Button;
+import android.widget.ListView;
+import android.view.KeyEvent;
+import android.view.View;
+
+/**
+ * Tests that focus works as expected when navigating into and out of
+ * a {@link ListView} that has buttons in it.
+ */
+public class ListOfButtonsTest extends ActivityInstrumentationTestCase<ListOfButtons> {
+
+    private ListAdapter mListAdapter;
+    private Button mButtonAtTop;
+
+    private ListView mListView;
+
+    public ListOfButtonsTest() {
+        super("com.android.frameworktest", ListOfButtons.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        ListOfButtons a = getActivity();
+        mListAdapter = a.getListAdapter();
+        mButtonAtTop = (Button) a.findViewById(R.id.button);
+        mListView = a.getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mListAdapter);
+        assertNotNull(mButtonAtTop);
+        assertNotNull(mListView);
+
+        assertFalse(mButtonAtTop.hasFocus());
+        assertTrue(mListView.hasFocus());
+        assertEquals("expecting 0 index to be selected",
+                0, mListView.getSelectedItemPosition());
+    }
+
+    @MediumTest
+    public void testNavigateToButtonAbove() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+
+        assertTrue(mButtonAtTop.hasFocus());        
+        assertFalse(mListView.hasFocus());
+    }
+
+    @MediumTest
+    public void testNavigateToSecondItem() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+
+        assertTrue(mListView.hasFocus());
+
+        View childOne = mListView.getChildAt(1);
+        assertNotNull(childOne);
+        assertEquals(childOne, mListView.getFocusedChild());
+        assertTrue(childOne.hasFocus());
+    }
+
+    @MediumTest
+    public void testNavigateUpAboveAndBackOut() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+
+        assertFalse("button at top should have focus back",
+                mButtonAtTop.hasFocus());
+        assertTrue(mListView.hasFocus());
+    }
+
+    // TODO: this reproduces bug 981791
+    public void TODO_testNavigateThroughAllButtonsAndBack() {
+
+        String[] labels = getActivity().getLabels();
+        for (int i = 0; i < labels.length; i++) {
+            String label = labels[i];
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+            getInstrumentation().waitForIdleSync();
+
+            String indexInfo = "index: " + i + ", label: " + label;
+
+            assertTrue(indexInfo, mListView.hasFocus());
+            
+            Button button = (Button) mListView.getSelectedView();
+            assertNotNull(indexInfo, button);
+            assertEquals(indexInfo, label, button.getText().toString());
+            assertTrue(indexInfo, button.hasFocus());
+        }
+
+        // pressing down again shouldn't matter; make sure last item keeps focus
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+
+
+        for (int i = labels.length - 1; i >= 0; i--) {
+            String label = labels[i];
+
+            String indexInfo = "index: " + i + ", label: " + label;
+
+            assertTrue(indexInfo, mListView.hasFocus());
+
+            Button button = (Button) mListView.getSelectedView();
+            assertNotNull(indexInfo, button);
+            assertEquals(indexInfo, label, button.getText().toString());
+            assertTrue(indexInfo, button.hasFocus());
+
+            sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+            getInstrumentation().waitForIdleSync();
+        }
+
+        assertTrue("button at top should have focus back",
+                mButtonAtTop.hasFocus());
+        assertFalse(mListView.hasFocus());
+    }
+
+    @MediumTest
+    public void testGoInAndOutOfListWithItemsFocusable() {
+
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+
+        assertTrue(mButtonAtTop.hasFocus());
+
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+
+        final String firstButtonLabel = getActivity().getLabels()[0];
+        final Button firstButton = (Button) mListView.getSelectedView();
+
+        assertTrue(firstButton.isFocused());
+        assertEquals(firstButtonLabel, firstButton.getText());
+
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        assertTrue(mButtonAtTop.isFocused());
+
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        assertTrue(firstButton.isFocused());
+
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        assertTrue(mButtonAtTop.isFocused());
+
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        assertTrue(firstButton.isFocused());
+    }
+
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/ListWithFooterViewAndNewLabelsTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/ListWithFooterViewAndNewLabelsTest.java
new file mode 100644
index 0000000..c094882
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/ListWithFooterViewAndNewLabelsTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.focus;
+
+import com.android.frameworktest.focus.ListWithFooterViewAndNewLabels;
+import com.android.frameworktest.R;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.widget.Button;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+
+public class ListWithFooterViewAndNewLabelsTest
+        extends ActivityInstrumentationTestCase<ListWithFooterViewAndNewLabels> {
+
+    private Button mButton;
+
+    private ListAdapter mAdapter;
+
+    private ListView mListView;
+
+
+    public ListWithFooterViewAndNewLabelsTest() {
+        super("com.android.frameworktest",
+                ListWithFooterViewAndNewLabels.class);
+    }
+
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        ListWithFooterViewAndNewLabels a = getActivity();
+        mButton = (Button) a.findViewById(R.id.button);
+        mAdapter = a.getListAdapter();
+        mListView = a.getListView();
+    }
+
+    // bug 900885
+    public void FAILING_testPreconditions() {
+        assertNotNull(mButton);
+        assertNotNull(mAdapter);
+        assertNotNull(mListView);
+
+        assertTrue(mButton.hasFocus());
+        assertEquals("expected list adapter to have 1 item",
+                1, mAdapter.getCount());
+        assertEquals("expected list view to have 2 items (1 in adapter, plus " 
+                + "the footer view).",
+                2, mListView.getCount());
+
+        // fails here!!!
+        assertEquals("Expecting the selected index to be 0, the first non footer "
+                + "view item.",
+                0, mListView.getSelectedItemPosition());
+    }
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/RequestFocusTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/RequestFocusTest.java
new file mode 100644
index 0000000..5fb3a29
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/RequestFocusTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.focus;
+
+import com.android.frameworktest.focus.RequestFocus;
+import com.android.frameworktest.R;
+
+import android.os.Handler;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.Button;
+import android.util.AndroidRuntimeException;
+
+/**
+ * {@link RequestFocusTest} is set up to exercise cases where the views that
+ * have focus become invisible or GONE.
+ */
+public class RequestFocusTest extends ActivityInstrumentationTestCase<RequestFocus> {
+
+    private Button mTopLeftButton;
+    private Button mBottomLeftButton;
+    private Button mTopRightButton;
+    private Button mBottomRightButton;
+    private Handler mHandler;
+
+    public RequestFocusTest() {
+        super("com.android.frameworktest", RequestFocus.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        final RequestFocus a = getActivity();
+        mHandler = a.getHandler();
+        mTopLeftButton = (Button) a.findViewById(R.id.topLeftButton);
+        mBottomLeftButton = (Button) a.findViewById(R.id.bottomLeftButton);
+        mTopRightButton = (Button) a.findViewById(R.id.topRightButton);
+        mBottomRightButton = (Button) a.findViewById(R.id.bottomRightButton);
+    }
+
+    // Test that setUp did what we expect it to do.  These asserts
+    // can't go in SetUp, or the test will hang.
+    @MediumTest
+    public void testSetUpConditions() throws Exception {
+        assertNotNull(mHandler);
+        assertNotNull(mTopLeftButton);
+        assertNotNull(mTopRightButton);
+        assertNotNull(mBottomLeftButton);
+        assertNotNull(mBottomRightButton);
+        assertTrue("requestFocus() should work from onCreate.", mBottomRightButton.hasFocus());
+    }
+
+    // Test that a posted requestFocus works.
+    @LargeTest
+    public void testPostedRequestFocus() throws Exception {
+        mHandler.post(new Runnable() { public void run() {
+            mBottomLeftButton.requestFocus();
+        }});
+        synchronized(this) {
+            try {
+                wait(500);
+            } catch (InterruptedException e) {
+                // Don't care.
+            }
+        }
+        assertTrue("Focus should move to bottom left", mBottomLeftButton.hasFocus());
+    }
+
+    // Test that a requestFocus from the wrong thread fails.
+    @MediumTest
+    public void testWrongThreadRequestFocusFails() throws Exception {
+        try {
+            mTopRightButton.requestFocus();
+            fail("requestFocus from wrong thread should raise exception.");
+        } catch (AndroidRuntimeException e) {
+            // Expected.  The actual exception is not public, so we can't catch it.
+            assertEquals("android.view.ViewRoot$CalledFromWrongThreadException",
+                         e.getClass().getName());
+        }
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/ScrollingThroughListOfFocusablesTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/ScrollingThroughListOfFocusablesTest.java
new file mode 100644
index 0000000..07916ee
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/ScrollingThroughListOfFocusablesTest.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.focus;
+
+import android.graphics.Rect;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.widget.ListView;
+import com.android.frameworktest.focus.ListOfInternalSelectionViews;
+import com.android.frameworktest.util.InternalSelectionView;
+
+
+/**
+ * TODO: extract base test case that launches {@link ListOfInternalSelectionViews} with
+ * bundle params.
+ */
+public class ScrollingThroughListOfFocusablesTest extends InstrumentationTestCase {
+
+    Rect mTempRect = new Rect();
+
+    private ListOfInternalSelectionViews mActivity;
+    private ListView mListView;
+
+    private int mNumItems = 4;
+    private int mNumRowsPerItem = 5;
+    private double mScreenHeightFactor = 5 /4;
+
+    @Override
+    protected void setUp() throws Exception {
+        mActivity = launchActivity(
+                "com.android.frameworktest",
+                ListOfInternalSelectionViews.class,
+                ListOfInternalSelectionViews.getBundleFor(
+                    mNumItems,      // 4 items
+                    mNumRowsPerItem,      // 5 internally selectable rows per item
+                    mScreenHeightFactor)); // each item is 5 / 4 screen height tall
+        mListView = mActivity.getListView();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mActivity.finish();
+        super.tearDown();
+    }
+
+    @MediumTest
+    public void testPreconditions() throws Exception {
+        assertNotNull(mActivity);
+        assertNotNull(mListView);
+        assertEquals(mNumItems, mActivity.getNumItems());
+        assertEquals(mNumRowsPerItem, mActivity.getNumRowsPerItem());
+    }
+
+    @MediumTest
+    public void testScrollingDownInFirstItem() throws Exception {
+
+        for (int i = 0; i < mNumRowsPerItem; i++) {
+            assertEquals(0, mListView.getSelectedItemPosition());
+            InternalSelectionView view = mActivity.getSelectedView();
+
+            assertInternallySelectedRowOnScreen(view, i);
+
+            // move to next row
+            if (i < mNumRowsPerItem - 1) {
+                sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+                getInstrumentation().waitForIdleSync();
+            }
+        }
+
+        {
+            assertEquals(0, mListView.getSelectedItemPosition());
+            InternalSelectionView view = (InternalSelectionView)
+                    mListView.getSelectedView();
+
+            // 1 pixel tolerance in case height / 4 is not an even number
+            final int fadingEdge = mListView.getBottom() - mListView.getVerticalFadingEdgeLength();
+            assertTrue("bottom of view should be just above fading edge",
+                    view.getBottom() >= fadingEdge - 1 &&
+                    view.getBottom() <= fadingEdge);
+        }
+
+
+        // make sure fading edge is the expected view
+        {
+            assertEquals("should be a second view visible due to the fading edge",
+                            2, mListView.getChildCount());
+            InternalSelectionView peekingChild = (InternalSelectionView)
+                    mListView.getChildAt(1);
+            assertNotNull(peekingChild);
+            assertEquals("wrong value for peeking list item",
+                    mActivity.getLabelForPosition(1), peekingChild.getLabel());
+        }
+    }
+
+
+    @MediumTest
+    public void testScrollingToSecondItem() throws Exception {
+
+        for (int i = 0; i < mNumRowsPerItem; i++) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+            getInstrumentation().waitForIdleSync();
+        }
+
+        assertEquals("should have moved to second item",
+                1, mListView.getSelectedItemPosition());
+    }
+
+    @LargeTest
+    public void testNoFadingEdgeAtBottomOfLastItem() {
+
+        // move down to last item
+        for (int i = 0; i < mNumItems; i++) {
+            for (int j = 0; j < mNumRowsPerItem; j++) {
+                if (i < mNumItems - 1 || j < mNumRowsPerItem - 1) {
+                    sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+                    getInstrumentation().waitForIdleSync();
+                }
+            }
+        }
+
+        assertEquals(mNumItems - 1, mListView.getSelectedItemPosition());
+        InternalSelectionView view = mActivity.getSelectedView();
+        assertEquals(mNumRowsPerItem - 1, view.getSelectedRow());
+
+        view.getRectForRow(mTempRect, mNumRowsPerItem - 1);
+        mListView.offsetDescendantRectToMyCoords(view, mTempRect);
+
+        assertTrue("bottom of last row of last item should be at " +
+                "the bottom of the list view (no fading edge)",
+                mListView.getBottom() - mListView.getVerticalFadingEdgeLength() < mTempRect.bottom);
+    }
+
+    @LargeTest
+    public void testNavigatingUpThroughInternalSelection() throws Exception {
+
+        // get to bottom of second item
+        for (int i = 0; i < 2; i++) {
+            for (int j = 0; j < mNumRowsPerItem; j++) {
+                if (i < 1 || j < mNumRowsPerItem - 1) {
+                    sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+                    getInstrumentation().waitForIdleSync();
+                }
+            }
+        }
+
+
+        // (make sure we are at last row of second item)
+        {
+            assertEquals(1, mListView.getSelectedItemPosition());
+            InternalSelectionView view = mActivity.getSelectedView();
+            assertEquals(mNumRowsPerItem - 1, view.getSelectedRow());
+        }
+
+        // go back up to the top of the second item
+        for (int i = mNumRowsPerItem - 1; i >= 0; i--) {
+            assertEquals(1, mListView.getSelectedItemPosition());
+            InternalSelectionView view = mActivity.getSelectedView();
+
+            assertInternallySelectedRowOnScreen(view, i);
+
+            // move up to next row
+            if (i > 0) {
+                sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+                getInstrumentation().waitForIdleSync();
+            }
+        }
+
+        // now we are at top row, should have caused scrolling, and fading edge...
+        {
+            assertEquals(1, mListView.getSelectedItemPosition());
+            InternalSelectionView view = mActivity.getSelectedView();
+            assertEquals(0, view.getSelectedRow());
+
+            view.getDrawingRect(mTempRect);
+            mListView.offsetDescendantRectToMyCoords(view, mTempRect);
+            assertEquals("top of selected row should be just below top vertical fading edge",
+                    mListView.getVerticalFadingEdgeLength(),
+                    view.getTop());
+        }
+
+        // make sure fading edge is the view we expect
+        {
+            final InternalSelectionView view =
+                    (InternalSelectionView) mListView.getChildAt(0);
+            assertEquals(mActivity.getLabelForPosition(0), view.getLabel());
+        }
+
+
+    }
+
+    /**
+     * @param internalFocused The view to check
+     * @param row
+     */
+    private void assertInternallySelectedRowOnScreen(
+            InternalSelectionView internalFocused,
+            int row) {
+        assertEquals("expecting selected row",
+                row, internalFocused.getSelectedRow());
+
+        internalFocused.getRectForRow(mTempRect, row);
+        mListView.offsetDescendantRectToMyCoords(internalFocused, mTempRect);
+
+        assertTrue("top of row " + row + " should be on sreen",
+                mTempRect.top >= 0);
+        assertTrue("bottom of row " + row + " should be on sreen",
+                mTempRect.bottom < mActivity.getScreenHeight());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/VerticalFocusSearchTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/VerticalFocusSearchTest.java
new file mode 100644
index 0000000..47a81fb
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/focus/VerticalFocusSearchTest.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.focus;
+
+import com.android.frameworktest.focus.VerticalFocusSearch;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.Suppress;
+import android.view.FocusFinder;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.LinearLayout;
+
+/**
+ * Tests that focus searching works on a vertical linear layout of buttons of
+ * various widths and horizontal placements.
+ */
+// Suppress until bug http://b/issue?id=1416545 is fixed
+@Suppress 
+public class VerticalFocusSearchTest extends ActivityInstrumentationTestCase<VerticalFocusSearch> {
+
+    private LinearLayout mLayout;
+
+    private Button mTopWide;
+    private Button mMidSkinny1Left;
+    private Button mMidSkinny2Right;
+    private Button mBottomWide;
+
+    private FocusSearchAlg mFocusFinder;
+
+    // helps test old and new impls when figuring out why something that used
+    // to work doesn't anymore (or verifying that new works as well as old).
+    interface FocusSearchAlg {
+        View findNextFocus(ViewGroup root, View focused, int direction);
+    }
+
+    // calls new impl
+    static class NewFocusSearchAlg implements FocusSearchAlg {
+
+        public View findNextFocus(ViewGroup root, View focused, int direction) {
+            return FocusFinder.getInstance()
+                    .findNextFocus(root, focused, direction);
+        }
+    }
+
+    public VerticalFocusSearchTest() {
+        super("com.android.frameworktest", VerticalFocusSearch.class);
+    }
+
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mLayout = getActivity().getLayout();
+        mTopWide = getActivity().getTopWide();
+        mMidSkinny1Left = getActivity().getMidSkinny1Left();
+        mMidSkinny2Right = getActivity().getMidSkinny2Right();
+        mBottomWide = getActivity().getBottomWide();
+
+        mFocusFinder = new NewFocusSearchAlg();
+    }
+
+    public void testPreconditions() {
+        assertNotNull(mLayout);
+        assertNotNull(mTopWide);
+        assertNotNull(mMidSkinny1Left);
+        assertNotNull(mMidSkinny2Right);
+        assertNotNull(mBottomWide);
+    }
+
+    public void testSearchFromTopButton() {
+        assertNull("going up from mTopWide.",
+                mFocusFinder.findNextFocus(mLayout, mTopWide, View.FOCUS_UP));
+
+        assertNull("going left from mTopWide.",
+                mFocusFinder.findNextFocus(mLayout, mTopWide, View.FOCUS_LEFT));
+
+        assertNull("going right from mTopWide.",
+                mFocusFinder.findNextFocus(mLayout, mTopWide, View.FOCUS_RIGHT));
+
+        assertEquals("going down from mTopWide.",
+                mMidSkinny1Left,
+                mFocusFinder
+                .findNextFocus(mLayout, mTopWide, View.FOCUS_DOWN));
+    }
+
+    public void testSearchFromMidLeft() {
+        assertNull("going left should have no next focus",
+                mFocusFinder.findNextFocus(mLayout, mMidSkinny1Left, View.FOCUS_LEFT));
+
+        assertEquals("going right from mMidSkinny1Left should go to mMidSkinny2Right",
+                mMidSkinny2Right,
+                mFocusFinder.findNextFocus(mLayout, mMidSkinny1Left, View.FOCUS_RIGHT));
+
+        assertEquals("going up from mMidSkinny1Left should go to mTopWide",
+                mTopWide,
+                mFocusFinder.findNextFocus(mLayout, mMidSkinny1Left, View.FOCUS_UP));
+
+        assertEquals("going down from mMidSkinny1Left should go to mMidSkinny2Right",
+                mMidSkinny2Right,
+                mFocusFinder.findNextFocus(mLayout, mMidSkinny1Left, View.FOCUS_DOWN));
+    }
+
+    public void testSearchFromMidRight() {
+        assertEquals("going left from mMidSkinny2Right should go to mMidSkinny1Left",
+                mMidSkinny1Left,
+                mFocusFinder.findNextFocus(mLayout, mMidSkinny2Right, View.FOCUS_LEFT));
+
+        assertNull("going right should have no next focus",
+                mFocusFinder.findNextFocus(mLayout, mMidSkinny2Right, View.FOCUS_RIGHT));
+
+        assertEquals("going up from mMidSkinny2Right should go to mMidSkinny1Left",
+                mMidSkinny1Left,
+                mFocusFinder.findNextFocus(mLayout, mMidSkinny2Right, View.FOCUS_UP));
+        
+        assertEquals("going down from mMidSkinny2Right should go to mBottomWide",
+                mBottomWide,
+                mFocusFinder.findNextFocus(mLayout, mMidSkinny2Right, View.FOCUS_DOWN));
+
+    }
+
+    public void testSearchFromFromBottom() {
+        assertNull("going down from bottom button should have no next focus.",
+                mFocusFinder.findNextFocus(mLayout, mBottomWide, View.FOCUS_DOWN));
+
+        assertNull("going left from bottom button should have no next focus.",
+                mFocusFinder.findNextFocus(mLayout, mBottomWide, View.FOCUS_LEFT));
+
+        assertNull("going right from bottom button should have no next focus.",
+                mFocusFinder.findNextFocus(mLayout, mBottomWide, View.FOCUS_RIGHT));
+
+        assertEquals("going up from bottom button should go to mMidSkinny2Right.",
+                mMidSkinny2Right,
+                mFocusFinder.findNextFocus(mLayout, mBottomWide, View.FOCUS_UP));
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridInHorizontalTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridInHorizontalTest.java
new file mode 100644
index 0000000..8af6214
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridInHorizontalTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.GridView;
+
+import com.android.frameworktest.gridview.GridInHorizontal;
+
+public class GridInHorizontalTest extends ActivityInstrumentationTestCase<GridInHorizontal> {
+
+    private GridInHorizontal mActivity;
+    private GridView mGridView;
+    
+    public GridInHorizontalTest() {
+        super("com.android.frameworktest", GridInHorizontal.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mGridView = getActivity().getGridView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mGridView);
+        assertTrue("Grid has 0 width", mGridView.getMeasuredWidth() > 0);
+        assertTrue("Grid has 0 height", mGridView.getMeasuredHeight() > 0);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridInVerticalTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridInVerticalTest.java
new file mode 100644
index 0000000..61e1c8b
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridInVerticalTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.GridView;
+
+import com.android.frameworktest.gridview.GridInVertical;
+
+public class GridInVerticalTest extends ActivityInstrumentationTestCase<GridInVertical> {
+
+    private GridInVertical mActivity;
+    private GridView mGridView;
+    
+    public GridInVerticalTest() {
+        super("com.android.frameworktest", GridInVertical.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mGridView = getActivity().getGridView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mGridView);
+        assertTrue("Grid has 0 width", mGridView.getMeasuredWidth() > 0);
+        assertTrue("Grid has 0 height", mGridView.getMeasuredHeight() > 0);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridPaddingTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridPaddingTest.java
new file mode 100644
index 0000000..43581c6
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridPaddingTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.GridView;
+
+public class GridPaddingTest extends ActivityInstrumentationTestCase2<GridPadding> {
+    private GridView mGridView;
+
+    public GridPaddingTest() {
+        super("com.android.frameworktest", GridPadding.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        setActivityInitialTouchMode(true);
+        mGridView = getActivity().getGridView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mGridView);
+        assertTrue("Not in touch mode", mGridView.isInTouchMode());
+    }
+
+    @MediumTest
+    public void testResurrectSelection() {
+        sendKeys("DPAD_DOWN");
+        assertEquals("The first item should be selected", mGridView.getSelectedItemPosition(), 0);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridScrollListenerTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridScrollListenerTest.java
new file mode 100644
index 0000000..f939f16
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridScrollListenerTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import android.app.Instrumentation;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.TouchUtils;
+import android.view.KeyEvent;
+import android.widget.AbsListView;
+import android.widget.GridView;
+
+import com.android.frameworktest.gridview.GridScrollListener;
+
+public class GridScrollListenerTest extends ActivityInstrumentationTestCase<GridScrollListener> implements
+        AbsListView.OnScrollListener {
+    private GridScrollListener mActivity;
+    private GridView mGridView;
+    private int mFirstVisibleItem = -1;
+    private int mVisibleItemCount = -1;
+    private int mTotalItemCount = -1;
+
+    public GridScrollListenerTest() {
+        super("com.android.frameworktest", GridScrollListener.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mGridView = getActivity().getGridView();
+        mGridView.setOnScrollListener(this);
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mGridView);
+        
+        assertEquals(0, mFirstVisibleItem);
+    }
+    
+    @LargeTest
+    public void testKeyScrolling() {
+        Instrumentation inst = getInstrumentation();
+        
+        int firstVisibleItem = mFirstVisibleItem;
+        for (int i = 0; i < mVisibleItemCount * 2; i++) {
+            inst.sendCharacterSync(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+        inst.waitForIdleSync();
+        
+        assertTrue("Arrow scroll did not happen", mFirstVisibleItem > firstVisibleItem);
+        
+        firstVisibleItem = mFirstVisibleItem;
+        inst.sendCharacterSync(KeyEvent.KEYCODE_SPACE);
+        inst.waitForIdleSync();
+        
+        assertTrue("Page scroll did not happen", mFirstVisibleItem > firstVisibleItem);
+        
+        firstVisibleItem = mFirstVisibleItem;
+        KeyEvent down = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, 
+                KeyEvent.KEYCODE_DPAD_DOWN, 0, KeyEvent.META_ALT_ON);
+        KeyEvent up = new KeyEvent(0, 0, KeyEvent.ACTION_UP, 
+                KeyEvent.KEYCODE_DPAD_DOWN, 0, KeyEvent.META_ALT_ON);
+        inst.sendKeySync(down);
+        inst.sendKeySync(up);
+        inst.waitForIdleSync();
+        
+        assertTrue("Full scroll did not happen", mFirstVisibleItem > firstVisibleItem);
+        assertEquals("Full scroll did not happen", mTotalItemCount, 
+                mFirstVisibleItem + mVisibleItemCount);    
+    }
+
+    @LargeTest
+    public void testTouchScrolling() {
+        Instrumentation inst = getInstrumentation();
+        
+        int firstVisibleItem = mFirstVisibleItem;
+        TouchUtils.dragQuarterScreenUp(this);
+        TouchUtils.dragQuarterScreenUp(this);
+        assertTrue("Touch scroll did not happen", mFirstVisibleItem > firstVisibleItem);
+    }
+
+    
+    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
+        mFirstVisibleItem = firstVisibleItem;
+        mVisibleItemCount = visibleItemCount;
+        mTotalItemCount = totalItemCount;
+    }
+
+    public void onScrollStateChanged(AbsListView view, int scrollState) {
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridSetSelectionBaseTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridSetSelectionBaseTest.java
new file mode 100644
index 0000000..3ca9b09
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridSetSelectionBaseTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import com.android.frameworktest.util.GridScenario;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.ViewAsserts;
+import android.widget.GridView;
+
+public class GridSetSelectionBaseTest<T extends GridScenario> extends ActivityInstrumentationTestCase<T> {
+    private T mActivity;
+    private GridView mGridView;
+
+    protected GridSetSelectionBaseTest(Class<T> klass) {
+        super("com.android.frameworktest", klass);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mGridView = getActivity().getGridView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mGridView);
+
+        // First item should be selected
+        if (mGridView.isStackFromBottom()) {
+            assertEquals(mGridView.getAdapter().getCount() - 1,
+                    mGridView.getSelectedItemPosition());
+        } else {
+            assertEquals(0, mGridView.getSelectedItemPosition());
+        }
+    }
+
+    @MediumTest
+    public void testSetSelectionToTheEnd() {
+        final int target = mGridView.getAdapter().getCount() - 1;
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mGridView.setSelection(target);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+
+        assertEquals(mGridView.getSelectedItemPosition(), target);
+        assertNotNull(mGridView.getSelectedView());
+
+        ViewAsserts.assertOnScreen(mGridView, mGridView.getSelectedView());
+    }
+
+    @MediumTest
+    public void testSetSelectionToMiddle() {
+        final int target = mGridView.getAdapter().getCount() / 2;
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mGridView.setSelection(target);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+
+        assertEquals(mGridView.getSelectedItemPosition(), target);
+        assertNotNull(mGridView.getSelectedView());
+
+        ViewAsserts.assertOnScreen(mGridView, mGridView.getSelectedView());
+    }
+    
+    @MediumTest
+    public void testSetSelectionToTheTop() {
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mGridView.setSelection(0);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+
+        assertEquals(mGridView.getSelectedItemPosition(), 0);
+        assertNotNull(mGridView.getSelectedView());
+
+        ViewAsserts.assertOnScreen(mGridView, mGridView.getSelectedView());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridSetSelectionManyTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridSetSelectionManyTest.java
new file mode 100644
index 0000000..aadc185
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridSetSelectionManyTest.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import com.android.frameworktest.gridview.GridSetSelectionMany;
+
+public class GridSetSelectionManyTest extends GridSetSelectionBaseTest<GridSetSelectionMany> {
+    public GridSetSelectionManyTest() {
+        super(GridSetSelectionMany.class);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridSetSelectionStackFromBottomManyTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridSetSelectionStackFromBottomManyTest.java
new file mode 100644
index 0000000..831ba85
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridSetSelectionStackFromBottomManyTest.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import com.android.frameworktest.gridview.GridSetSelectionStackFromBottomMany;
+
+public class GridSetSelectionStackFromBottomManyTest extends GridSetSelectionBaseTest<GridSetSelectionStackFromBottomMany> {
+    public GridSetSelectionStackFromBottomManyTest() {
+        super(GridSetSelectionStackFromBottomMany.class);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridSetSelectionStackFromBottomTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridSetSelectionStackFromBottomTest.java
new file mode 100644
index 0000000..c4d0513
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridSetSelectionStackFromBottomTest.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import com.android.frameworktest.gridview.GridSetSelectionStackFromBottom;
+
+public class GridSetSelectionStackFromBottomTest extends GridSetSelectionBaseTest<GridSetSelectionStackFromBottom> {
+    public GridSetSelectionStackFromBottomTest() {
+        super(GridSetSelectionStackFromBottom.class);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridSetSelectionTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridSetSelectionTest.java
new file mode 100644
index 0000000..5a584a5
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridSetSelectionTest.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import com.android.frameworktest.gridview.GridSetSelection;
+
+public class GridSetSelectionTest extends GridSetSelectionBaseTest<GridSetSelection> {
+    public GridSetSelectionTest() {
+        super(GridSetSelection.class);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridSingleColumnTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridSingleColumnTest.java
new file mode 100644
index 0000000..b72a2e0
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridSingleColumnTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.GridView;
+
+import com.android.frameworktest.gridview.GridSingleColumn;
+
+public class GridSingleColumnTest extends ActivityInstrumentationTestCase<GridSingleColumn> {
+    private GridSingleColumn mActivity;
+    private GridView mGridView;
+
+    public GridSingleColumnTest() {
+        super("com.android.frameworktest", GridSingleColumn.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mGridView = getActivity().getGridView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mGridView);
+        assertEquals(0, mGridView.getSelectedItemPosition());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridStackFromBottomManyTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridStackFromBottomManyTest.java
new file mode 100644
index 0000000..a0b819e
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridStackFromBottomManyTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import com.android.frameworktest.gridview.GridStackFromBottomMany;
+
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.GridView;
+import android.test.ActivityInstrumentationTestCase;
+
+public class GridStackFromBottomManyTest extends ActivityInstrumentationTestCase<GridStackFromBottomMany> {
+    private GridStackFromBottomMany mActivity;
+    private GridView mGridView;
+
+    public GridStackFromBottomManyTest() {
+        super("com.android.frameworktest", GridStackFromBottomMany.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mGridView = getActivity().getGridView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mGridView);
+
+        // Last item should be selected
+        assertEquals(mGridView.getAdapter().getCount() - 1, mGridView.getSelectedItemPosition());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridStackFromBottomTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridStackFromBottomTest.java
new file mode 100644
index 0000000..821c7a5
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/GridStackFromBottomTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview;
+
+import com.android.frameworktest.gridview.GridStackFromBottom;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.GridView;
+
+public class GridStackFromBottomTest extends ActivityInstrumentationTestCase<GridStackFromBottom> {
+    private GridStackFromBottom mActivity;
+    private GridView mGridView;
+
+    public GridStackFromBottomTest() {
+        super("com.android.frameworktest", GridStackFromBottom.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mGridView = getActivity().getGridView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mGridView);
+
+        // Last item should be selected
+        assertEquals(mGridView.getAdapter().getCount() - 1, mGridView.getSelectedItemPosition());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/touch/GridTouchSetSelectionTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/touch/GridTouchSetSelectionTest.java
new file mode 100644
index 0000000..926d662
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/touch/GridTouchSetSelectionTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview.touch;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.TouchUtils;
+import android.view.View;
+import android.widget.GridView;
+
+import com.android.frameworktest.gridview.GridSimple;
+
+/**
+ * Tests setting the selection in touch mode
+ */
+public class GridTouchSetSelectionTest extends ActivityInstrumentationTestCase<GridSimple> {
+    private GridSimple mActivity;
+    private GridView mGridView;
+
+    public GridTouchSetSelectionTest() {
+        super("com.android.frameworktest", GridSimple.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mGridView = getActivity().getGridView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mGridView);
+    }
+    
+    @LargeTest
+    public void testSetSelection() {
+        TouchUtils.dragQuarterScreenDown(this);
+        TouchUtils.dragQuarterScreenUp(this);
+        
+        // Nothing should be selected
+        assertEquals("Selection still available after touch", -1, 
+                mGridView.getSelectedItemPosition());
+        
+        final int targetPosition = mGridView.getAdapter().getCount() / 2;
+        
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mGridView.setSelection(targetPosition);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+        
+        boolean found = false;
+        int childCount = mGridView.getChildCount();
+        for (int i=0; i<childCount; i++) {
+            View child = mGridView.getChildAt(i);
+            if (child.getId() == targetPosition) {
+                found = true;
+                break;
+            }
+        }
+        assertTrue("Selected item not visible in list", found);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/touch/GridTouchStackFromBottomManyTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/touch/GridTouchStackFromBottomManyTest.java
new file mode 100644
index 0000000..710617e
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/touch/GridTouchStackFromBottomManyTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview.touch;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.TouchUtils;
+import com.android.frameworktest.gridview.GridStackFromBottomMany;
+
+import android.widget.GridView;
+import android.view.View;
+import android.test.ActivityInstrumentationTestCase;
+
+public class GridTouchStackFromBottomManyTest extends ActivityInstrumentationTestCase<GridStackFromBottomMany> {
+    private GridStackFromBottomMany mActivity;
+    private GridView mGridView;
+
+    public GridTouchStackFromBottomManyTest() {
+        super("com.android.frameworktest", GridStackFromBottomMany.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mGridView = getActivity().getGridView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mGridView);
+
+        // Last item should be selected
+        assertEquals(mGridView.getAdapter().getCount() - 1, mGridView.getSelectedItemPosition());
+    }
+
+    @LargeTest
+    public void testScrollToTop() {
+        View firstChild;
+        TouchUtils.scrollToTop(this, mGridView);
+
+        // Nothing should be selected
+        assertEquals("Selection still available after touch", -1,
+                mGridView.getSelectedItemPosition());
+
+        firstChild = mGridView.getChildAt(0);
+
+        assertEquals("Item zero not the first child in the grid", 0, firstChild.getId());
+
+        assertEquals("Item zero not at the top of the grid",
+                mGridView.getListPaddingTop(), firstChild.getTop());
+    }
+
+    @MediumTest
+    public void testScrollToBottom() {
+        TouchUtils.scrollToBottom(this, mGridView);
+
+        // Nothing should be selected
+        assertEquals("Selection still available after touch", -1,
+                mGridView.getSelectedItemPosition());
+
+        View lastChild = mGridView.getChildAt(mGridView.getChildCount() - 1);
+
+        assertEquals("Grid is not scrolled to the bottom", mGridView.getAdapter().getCount() - 1,
+                lastChild.getId());
+
+        assertEquals("Last item is not touching the bottom edge",
+                mGridView.getHeight() - mGridView.getListPaddingBottom(), lastChild.getBottom());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/touch/GridTouchStackFromBottomTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/touch/GridTouchStackFromBottomTest.java
new file mode 100644
index 0000000..e085105
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/touch/GridTouchStackFromBottomTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview.touch;
+
+import com.android.frameworktest.gridview.GridStackFromBottom;
+import android.test.TouchUtils;
+import android.test.suitebuilder.annotation.MediumTest;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.widget.GridView;
+import android.view.View;
+
+public class GridTouchStackFromBottomTest extends ActivityInstrumentationTestCase<GridStackFromBottom> {
+    private GridStackFromBottom mActivity;
+    private GridView mGridView;
+
+    public GridTouchStackFromBottomTest() {
+        super("com.android.frameworktest", GridStackFromBottom.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mGridView = getActivity().getGridView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mGridView);
+
+        // First item should be selected
+        assertEquals(mGridView.getAdapter().getCount() - 1, mGridView.getSelectedItemPosition());
+    }
+
+    @MediumTest
+    public void testPushUp() {
+        TouchUtils.scrollToBottom(this, mGridView);
+
+        // Nothing should be selected
+        assertEquals("Selection still available after touch", -1,
+                mGridView.getSelectedItemPosition());
+
+        View lastChild = mGridView.getChildAt(mGridView.getChildCount() - 1);
+
+        assertEquals("Last item not the last child in the grid",
+                mGridView.getAdapter().getCount() - 1, lastChild.getId());
+
+        assertEquals("Last item not at the bottom of the grid",
+                mGridView.getHeight() - mGridView.getListPaddingBottom(), lastChild.getBottom());
+    }
+
+    @MediumTest
+    public void testPullDown() {
+        TouchUtils.scrollToTop(this, mGridView);
+
+        // Nothing should be selected
+        assertEquals("Selection still available after touch", -1,
+                mGridView.getSelectedItemPosition());
+
+        View lastChild = mGridView.getChildAt(mGridView.getChildCount() - 1);
+
+        assertEquals("Last item not the last child in the grid",
+                mGridView.getAdapter().getCount() - 1, lastChild.getId());
+
+        assertEquals("Last item not at the bottom of the grid",
+                mGridView.getHeight() - mGridView.getListPaddingBottom(), lastChild.getBottom());
+    }
+    
+    @MediumTest
+    public void testPushUpFast() {
+        TouchUtils.dragViewToTop(this, mGridView.getChildAt(mGridView.getChildCount() - 1), 2);
+
+        // Nothing should be selected
+        assertEquals("Selection still available after touch", -1,
+                mGridView.getSelectedItemPosition());
+
+        View lastChild = mGridView.getChildAt(mGridView.getChildCount() - 1);
+
+        assertEquals("Last item not the last child in the grid",
+                mGridView.getAdapter().getCount() - 1, lastChild.getId());
+
+        assertEquals("Last item not at the bottom of the grid",
+                mGridView.getHeight() - mGridView.getListPaddingBottom(), lastChild.getBottom());
+    }
+
+    @MediumTest
+    public void testPullDownFast() {
+        TouchUtils.dragViewToBottom(this, mGridView.getChildAt(0), 2);
+
+        // Nothing should be selected
+        assertEquals("Selection still available after touch", -1,
+                mGridView.getSelectedItemPosition());
+
+        View lastChild = mGridView.getChildAt(mGridView.getChildCount() - 1);
+
+        assertEquals("Last item not the last child in the grid",
+                mGridView.getAdapter().getCount() - 1, lastChild.getId());
+
+        assertEquals("Last item not at the bottom of the grid",
+                mGridView.getHeight() - mGridView.getListPaddingBottom(), lastChild.getBottom());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/touch/GridTouchVerticalSpacingStackFromBottomTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/touch/GridTouchVerticalSpacingStackFromBottomTest.java
new file mode 100644
index 0000000..3937c43
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/touch/GridTouchVerticalSpacingStackFromBottomTest.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview.touch;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.TouchUtils;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.widget.GridView;
+
+import com.android.frameworktest.gridview.GridVerticalSpacingStackFromBottom;
+
+public class GridTouchVerticalSpacingStackFromBottomTest extends ActivityInstrumentationTestCase<GridVerticalSpacingStackFromBottom> {
+    private GridVerticalSpacingStackFromBottom mActivity;
+    private GridView mGridView;
+
+    public GridTouchVerticalSpacingStackFromBottomTest() {
+        super("com.android.frameworktest", GridVerticalSpacingStackFromBottom.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mGridView = getActivity().getGridView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mGridView);
+
+        // Last item should be selected
+        assertEquals(mGridView.getAdapter().getCount() - 1, mGridView.getSelectedItemPosition());
+
+    }
+
+    @MediumTest
+    public void testNoScroll() {
+        View firstChild = mGridView.getChildAt(0);
+        View lastChild = mGridView.getChildAt(mGridView.getChildCount() - 1);
+        
+        int lastTop = lastChild.getTop();
+        
+        TouchUtils.dragViewBy(this, firstChild, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0,
+                ViewConfiguration.getTouchSlop());
+        
+        View newLastChild = mGridView.getChildAt(mGridView.getChildCount() - 1);
+        
+        assertEquals("View scrolled too early", lastTop, newLastChild.getTop());
+        assertEquals("Wrong view in last position", mGridView.getAdapter().getCount() - 1, 
+                newLastChild.getId());
+    }
+    
+    @LargeTest
+    public void testShortScroll() {
+        View firstChild = mGridView.getChildAt(0);
+        if (firstChild.getTop() < this.mGridView.getListPaddingTop()) {
+            firstChild = mGridView.getChildAt(1);
+        }
+            
+        View lastChild = mGridView.getChildAt(mGridView.getChildCount() - 1);
+        
+        int lastTop = lastChild.getTop();
+        
+        TouchUtils.dragViewBy(this, firstChild, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0,
+                ViewConfiguration.getTouchSlop() + 1 + 10);
+        
+        View newLastChild = mGridView.getChildAt(mGridView.getChildCount() - 1);
+        
+        assertEquals("View scrolled to wrong position", lastTop, newLastChild.getTop() - 10);
+        assertEquals("Wrong view in last position", mGridView.getAdapter().getCount() - 1,
+                newLastChild.getId());
+    }
+    
+    @LargeTest
+    public void testLongScroll() {
+        View firstChild = mGridView.getChildAt(0);
+        if (firstChild.getTop() < mGridView.getListPaddingTop()) {
+            firstChild = mGridView.getChildAt(1);
+        }
+
+        int firstTop = firstChild.getTop();
+
+        int distance = TouchUtils.dragViewBy(this, firstChild, 
+                Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 
+                (int) (mActivity.getWindowManager().getDefaultDisplay().getHeight() * 0.75f));
+        
+        assertEquals("View scrolled to wrong position", firstTop
+                + (distance - ViewConfiguration.getTouchSlop() - 1), firstChild.getTop());
+    } 
+    
+    @LargeTest
+    public void testManyScrolls() {
+        int originalCount = mGridView.getChildCount();
+        
+        View firstChild;
+        int firstId = Integer.MIN_VALUE;
+        int firstTop = Integer.MIN_VALUE; 
+        int prevId;
+        int prevTop; 
+        do {
+            prevId = firstId;
+            prevTop = firstTop;
+            TouchUtils.dragQuarterScreenDown(this);
+            assertTrue(String.format("Too many children created: %d expected no more than %d", 
+                    mGridView.getChildCount(), originalCount + 4), 
+                    mGridView.getChildCount() <= originalCount + 4);
+            firstChild = mGridView.getChildAt(0);
+            firstId = firstChild.getId();
+            firstTop = firstChild.getTop(); 
+        } while ((prevId != firstId) || (prevTop != firstTop));
+        
+        
+        firstChild = mGridView.getChildAt(0);
+        assertEquals("View scrolled to wrong position", 0, firstChild.getId());
+        
+        firstId = Integer.MIN_VALUE;
+        firstTop = Integer.MIN_VALUE; 
+        do {
+            prevId = firstId;
+            prevTop = firstTop;
+            TouchUtils.dragQuarterScreenUp(this);
+            assertTrue(String.format("Too many children created: %d expected no more than %d", 
+                    mGridView.getChildCount(), originalCount + 4), 
+                    mGridView.getChildCount() <= originalCount + 4);
+            firstChild = mGridView.getChildAt(0);
+            firstId = firstChild.getId();
+            firstTop = firstChild.getTop(); 
+        } while ((prevId != firstId) || (prevTop != firstTop));
+        
+        View lastChild = mGridView.getChildAt(mGridView.getChildCount() - 1);
+        assertEquals("Grid is not scrolled to the bottom", mGridView.getAdapter().getCount() - 1,
+                lastChild.getId());
+    } 
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/touch/GridTouchVerticalSpacingTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/touch/GridTouchVerticalSpacingTest.java
new file mode 100644
index 0000000..0b39909
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/gridview/touch/GridTouchVerticalSpacingTest.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.gridview.touch;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.TouchUtils;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.widget.GridView;
+
+import com.android.frameworktest.gridview.GridVerticalSpacing;
+
+public class GridTouchVerticalSpacingTest extends ActivityInstrumentationTestCase<GridVerticalSpacing> {
+    private GridVerticalSpacing mActivity;
+    private GridView mGridView;
+
+    public GridTouchVerticalSpacingTest() {
+        super("com.android.frameworktest", GridVerticalSpacing.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mGridView = getActivity().getGridView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mGridView);
+
+        assertEquals(0, mGridView.getSelectedItemPosition());
+    }
+
+    @MediumTest
+    public void testNoScroll() {
+        View firstChild = mGridView.getChildAt(0);
+        View lastChild = mGridView.getChildAt(mGridView.getChildCount() - 1);
+        
+        int firstTop = firstChild.getTop();
+        
+        TouchUtils.dragViewBy(this, lastChild, Gravity.TOP | Gravity.LEFT, 
+                0, -(ViewConfiguration.getTouchSlop()));
+        
+        View newFirstChild = mGridView.getChildAt(0);
+        
+        assertEquals("View scrolled too early", firstTop, newFirstChild.getTop());
+        assertEquals("Wrong view in first position", 0, newFirstChild.getId());
+    }
+    
+    @LargeTest
+    public void testShortScroll() {
+        View firstChild = mGridView.getChildAt(0);
+        View lastChild = mGridView.getChildAt(mGridView.getChildCount() - 1);
+        
+        int firstTop = firstChild.getTop();
+        
+        TouchUtils.dragViewBy(this, lastChild, Gravity.TOP | Gravity.LEFT,
+                0, -(ViewConfiguration.getTouchSlop() + 1 + 10));
+        
+        View newFirstChild = mGridView.getChildAt(0);
+        
+        assertEquals("View scrolled to wrong position", firstTop, newFirstChild.getTop() + 10);
+        assertEquals("Wrong view in first position", 0, newFirstChild.getId());
+    }
+    
+    @LargeTest
+    public void testLongScroll() {
+        View lastChild = mGridView.getChildAt(mGridView.getChildCount() - 1);
+        
+        int lastTop = lastChild.getTop();
+        
+        int distance = TouchUtils.dragViewToY(this, lastChild, Gravity.TOP | Gravity.LEFT,
+                mGridView.getTop());
+        
+        assertEquals("View scrolled to wrong position", 
+                lastTop - (distance - ViewConfiguration.getTouchSlop() - 1), lastChild.getTop());
+    }
+    
+    @LargeTest
+    public void testManyScrolls() {
+        int originalCount = mGridView.getChildCount();
+        
+        View firstChild;
+        int firstId = Integer.MIN_VALUE;
+        int firstTop = Integer.MIN_VALUE; 
+        int prevId;
+        int prevTop; 
+        do {
+            prevId = firstId;
+            prevTop = firstTop;
+            TouchUtils.dragQuarterScreenUp(this);
+            assertTrue(String.format("Too many children created: %d expected no more than %d", 
+                    mGridView.getChildCount(), originalCount + 4), 
+                    mGridView.getChildCount() <= originalCount + 4);
+            firstChild = mGridView.getChildAt(0);
+            firstId = firstChild.getId();
+            firstTop = firstChild.getTop(); 
+        } while ((prevId != firstId) || (prevTop != firstTop));
+
+        
+        View lastChild = mGridView.getChildAt(mGridView.getChildCount() - 1);
+        assertEquals("Grid is not scrolled to the bottom", mGridView.getAdapter().getCount() - 1,
+                lastChild.getId());
+        
+        firstId = Integer.MIN_VALUE;
+        firstTop = Integer.MIN_VALUE; 
+        do {
+            prevId = firstId;
+            prevTop = firstTop;
+            TouchUtils.dragQuarterScreenDown(this);
+            assertTrue(String.format("Too many children created: %d expected no more than %d", 
+                    mGridView.getChildCount(), originalCount + 4), 
+                    mGridView.getChildCount() <= originalCount + 4);
+            firstChild = mGridView.getChildAt(0);
+            firstId = firstChild.getId();
+            firstTop = firstChild.getTop(); 
+        } while ((prevId != firstId) || (prevTop != firstTop));
+        
+        firstChild = mGridView.getChildAt(0);
+        assertEquals("Grid is not scrolled to the top", 0, firstChild.getId());
+    } 
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/frame/FrameLayoutGravityTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/frame/FrameLayoutGravityTest.java
new file mode 100644
index 0000000..239bd7d
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/frame/FrameLayoutGravityTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.layout.frame;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.ViewAsserts;
+import android.app.Activity;
+import android.view.View;
+import com.android.frameworktest.layout.frame.FrameLayoutGravity;
+import com.android.frameworktest.R;
+
+public class FrameLayoutGravityTest extends ActivityInstrumentationTestCase<FrameLayoutGravity> {
+    private View mLeftView;
+    private View mRightView;
+    private View mCenterHorizontalView;
+    private View mLeftCenterVerticalView;
+    private View mRighCenterVerticalView;
+    private View mCenterView;
+    private View mLeftBottomView;
+    private View mRightBottomView;
+    private View mCenterHorizontalBottomView;
+    private View mParent;
+
+    public FrameLayoutGravityTest() {
+        super("com.android.frameworktest", FrameLayoutGravity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        final Activity activity = getActivity();
+
+        mParent = activity.findViewById(R.id.parent);
+
+        mLeftView = activity.findViewById(R.id.left);
+        mRightView = activity.findViewById(R.id.right);
+        mCenterHorizontalView = activity.findViewById(R.id.center_horizontal);
+
+        mLeftCenterVerticalView = activity.findViewById(R.id.left_center_vertical);
+        mRighCenterVerticalView = activity.findViewById(R.id.right_center_vertical);
+        mCenterView = activity.findViewById(R.id.center);
+
+        mLeftBottomView = activity.findViewById(R.id.left_bottom);
+        mRightBottomView = activity.findViewById(R.id.right_bottom);
+        mCenterHorizontalBottomView = activity.findViewById(R.id.center_horizontal_bottom);
+    }
+
+    @MediumTest
+    public void testSetUpConditions() throws Exception {
+        assertNotNull(mParent);
+        assertNotNull(mLeftView);
+        assertNotNull(mRightView);
+        assertNotNull(mCenterHorizontalView);
+        assertNotNull(mLeftCenterVerticalView);
+        assertNotNull(mRighCenterVerticalView);
+        assertNotNull(mCenterView);
+        assertNotNull(mLeftBottomView);
+        assertNotNull(mRightBottomView);
+        assertNotNull(mCenterHorizontalBottomView);
+    }
+
+    @MediumTest
+    public void testLeftTopAligned() throws Exception {
+        ViewAsserts.assertLeftAligned(mParent, mLeftView);
+        ViewAsserts.assertTopAligned(mParent, mLeftView);
+    }
+
+    @MediumTest
+    public void testRightTopAligned() throws Exception {
+        ViewAsserts.assertRightAligned(mParent, mRightView);
+        ViewAsserts.assertTopAligned(mParent, mRightView);
+    }
+
+    @MediumTest
+    public void testCenterHorizontalTopAligned() throws Exception {
+        ViewAsserts.assertHorizontalCenterAligned(mParent, mCenterHorizontalView);
+        ViewAsserts.assertTopAligned(mParent, mCenterHorizontalView);
+    }
+
+    @MediumTest
+    public void testLeftCenterVerticalAligned() throws Exception {
+        ViewAsserts.assertLeftAligned(mParent, mLeftCenterVerticalView);
+        ViewAsserts.assertVerticalCenterAligned(mParent, mLeftCenterVerticalView);
+    }
+
+    @MediumTest
+    public void testRightCenterVerticalAligned() throws Exception {
+        ViewAsserts.assertRightAligned(mParent, mRighCenterVerticalView);
+        ViewAsserts.assertVerticalCenterAligned(mParent, mRighCenterVerticalView);
+    }
+
+    @MediumTest
+    public void testCenterAligned() throws Exception {
+        ViewAsserts.assertHorizontalCenterAligned(mParent, mCenterView);
+        ViewAsserts.assertVerticalCenterAligned(mParent, mCenterView);
+    }
+
+    @MediumTest
+    public void testLeftBottomAligned() throws Exception {
+        ViewAsserts.assertLeftAligned(mParent, mLeftBottomView);
+        ViewAsserts.assertBottomAligned(mParent, mLeftBottomView);
+    }
+
+    @MediumTest
+    public void testRightBottomAligned() throws Exception {
+        ViewAsserts.assertRightAligned(mParent, mRightBottomView);
+        ViewAsserts.assertBottomAligned(mParent, mRightBottomView);
+    }
+
+    @MediumTest
+    public void testCenterHorizontalBottomAligned() throws Exception {
+        ViewAsserts.assertHorizontalCenterAligned(mParent, mCenterHorizontalBottomView);
+        ViewAsserts.assertBottomAligned(mParent, mCenterHorizontalBottomView);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/frame/FrameLayoutMarginTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/frame/FrameLayoutMarginTest.java
new file mode 100644
index 0000000..4df4805
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/frame/FrameLayoutMarginTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.layout.frame;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.ViewAsserts;
+import android.app.Activity;
+import android.view.View;
+import android.view.ViewGroup;
+import com.android.frameworktest.layout.frame.FrameLayoutMargin;
+import com.android.frameworktest.R;
+
+public class FrameLayoutMarginTest extends ActivityInstrumentationTestCase<FrameLayoutMargin> {
+    private View mLeftView;
+    private View mRightView;
+    private View mTopView;
+    private View mBottomView;
+    private View mParent;
+
+    public FrameLayoutMarginTest() {
+        super("com.android.frameworktest", FrameLayoutMargin.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        final Activity activity = getActivity();
+
+        mParent = activity.findViewById(R.id.parent);
+
+        mLeftView = activity.findViewById(R.id.left);
+        mRightView = activity.findViewById(R.id.right);
+        mTopView = activity.findViewById(R.id.top);
+        mBottomView = activity.findViewById(R.id.bottom);
+    }
+
+    @MediumTest
+    public void testSetUpConditions() throws Exception {
+        assertNotNull(mParent);
+        assertNotNull(mLeftView);
+        assertNotNull(mRightView);
+        assertNotNull(mTopView);
+        assertNotNull(mBottomView);
+    }
+
+    @MediumTest
+    public void testLeftMarginAligned() throws Exception {
+        ViewAsserts.assertLeftAligned(mParent, mLeftView,
+                ((ViewGroup.MarginLayoutParams) mLeftView.getLayoutParams()).leftMargin);
+    }
+
+    @MediumTest
+    public void testRightMarginAligned() throws Exception {
+        ViewAsserts.assertRightAligned(mParent, mRightView,
+                ((ViewGroup.MarginLayoutParams) mRightView.getLayoutParams()).rightMargin);
+    }
+
+    @MediumTest
+    public void testTopMarginAligned() throws Exception {
+        ViewAsserts.assertTopAligned(mParent, mTopView,
+                ((ViewGroup.MarginLayoutParams) mTopView.getLayoutParams()).topMargin);
+    }
+
+    @MediumTest
+    public void testBottomMarginAligned() throws Exception {
+        ViewAsserts.assertBottomAligned(mParent, mBottomView,
+                ((ViewGroup.MarginLayoutParams) mBottomView.getLayoutParams()).bottomMargin);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/linear/BaselineAlignmentCenterGravityTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/linear/BaselineAlignmentCenterGravityTest.java
new file mode 100644
index 0000000..0b6360e
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/linear/BaselineAlignmentCenterGravityTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.linear;
+
+import android.app.Activity;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.ViewAsserts;
+import android.view.View;
+import android.widget.Button;
+
+import com.android.frameworktest.R;
+import com.android.frameworktest.layout.linear.BaselineAlignmentCenterGravity;
+
+public class BaselineAlignmentCenterGravityTest extends ActivityInstrumentationTestCase<BaselineAlignmentCenterGravity> {
+    private Button mButton1;
+    private Button mButton2;
+    private Button mButton3;
+
+    public BaselineAlignmentCenterGravityTest() {
+        super("com.android.frameworktest", BaselineAlignmentCenterGravity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        final Activity activity = getActivity();
+        mButton1 = (Button) activity.findViewById(R.id.button1);
+        mButton2 = (Button) activity.findViewById(R.id.button2);
+        mButton3 = (Button) activity.findViewById(R.id.button3);
+    }
+
+    @MediumTest
+    public void testSetUpConditions() throws Exception {
+        assertNotNull(mButton1);
+        assertNotNull(mButton2);
+        assertNotNull(mButton3);
+    }
+
+    @MediumTest
+    public void testChildrenAligned() throws Exception {
+        final View parent = (View) mButton1.getParent();
+        ViewAsserts.assertTopAligned(mButton1, parent);
+        ViewAsserts.assertTopAligned(mButton2, parent);
+        ViewAsserts.assertTopAligned(mButton3, parent);
+        ViewAsserts.assertBottomAligned(mButton1, parent);
+        ViewAsserts.assertBottomAligned(mButton2, parent);
+        ViewAsserts.assertBottomAligned(mButton3, parent);
+        ViewAsserts.assertTopAligned(mButton1, mButton2);
+        ViewAsserts.assertTopAligned(mButton2, mButton3);
+        ViewAsserts.assertBottomAligned(mButton1, mButton2);
+        ViewAsserts.assertBottomAligned(mButton2, mButton3);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/linear/BaselineAlignmentSpinnerButton.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/linear/BaselineAlignmentSpinnerButton.java
new file mode 100644
index 0000000..050e053
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/linear/BaselineAlignmentSpinnerButton.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.linear;
+
+import android.app.Activity;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.ViewAsserts;
+import android.view.View;
+
+import com.android.frameworktest.R;
+import com.android.frameworktest.layout.linear.HorizontalOrientationVerticalAlignment;
+
+public class BaselineAlignmentSpinnerButton extends ActivityInstrumentationTestCase<HorizontalOrientationVerticalAlignment> {
+    private View mSpinner;
+    private View mButton;
+
+    public BaselineAlignmentSpinnerButton() {
+        super("com.android.frameworktest", HorizontalOrientationVerticalAlignment.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        final Activity activity = getActivity();
+        mSpinner = activity.findViewById(R.id.reminder_value);
+        mButton = activity.findViewById(R.id.reminder_remove);
+    }
+
+    @MediumTest
+    public void testSetUpConditions() throws Exception {
+        assertNotNull(mSpinner);
+        assertNotNull(mButton);
+    }
+
+    @MediumTest
+    public void testChildrenAligned() throws Exception {
+        ViewAsserts.assertBaselineAligned(mSpinner, mButton);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/linear/BaselineAlignmentZeroWidthAndWeightTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/linear/BaselineAlignmentZeroWidthAndWeightTest.java
new file mode 100644
index 0000000..a315d81
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/linear/BaselineAlignmentZeroWidthAndWeightTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.linear;
+
+import com.android.frameworktest.R;
+import com.android.frameworktest.layout.linear.BaselineAlignmentZeroWidthAndWeight;
+import com.android.frameworktest.layout.linear.ExceptionTextView;
+
+import android.app.Activity;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.widget.Button;
+
+public class BaselineAlignmentZeroWidthAndWeightTest extends ActivityInstrumentationTestCase<BaselineAlignmentZeroWidthAndWeight> {
+    private Button mShowButton;
+
+    public BaselineAlignmentZeroWidthAndWeightTest() {
+        super("com.android.frameworktest", BaselineAlignmentZeroWidthAndWeight.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        final Activity activity = getActivity();
+        mShowButton = (Button) activity.findViewById(R.id.show);
+    }
+
+    @MediumTest
+    public void testSetUpConditions() throws Exception {
+        assertNotNull(mShowButton);        
+    }
+
+    @MediumTest
+    public void testComputeTexViewWithoutIllegalArgumentException() throws Exception {
+        assertTrue(mShowButton.hasFocus());
+
+        // Pressing the button will show an ExceptionTextView that might set a failed bit if
+        // the test fails.
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        getInstrumentation().waitForIdleSync();
+
+        final ExceptionTextView etv = (ExceptionTextView) getActivity()
+                .findViewById(R.id.routeToField);
+        assertFalse("exception test view should not fail", etv.isFailed());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/linear/BaselineButtonsTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/linear/BaselineButtonsTest.java
new file mode 100644
index 0000000..9f2e138
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/linear/BaselineButtonsTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.linear;
+
+import android.app.Activity;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.View;
+import android.widget.ImageButton;
+
+import com.android.frameworktest.R;
+import com.android.frameworktest.layout.linear.BaselineButtons;
+
+public class BaselineButtonsTest extends ActivityInstrumentationTestCase<BaselineButtons> {
+    private View mCurrentTime;
+    private View mTotalTime;
+    private ImageButton mPrev;
+    private ImageButton mNext;
+    private ImageButton mPause;
+    private View mLayout;
+
+    public BaselineButtonsTest() {
+        super("com.android.frameworktest", BaselineButtons.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        final Activity activity = getActivity();
+        mCurrentTime = activity.findViewById(R.id.currenttime);
+        mTotalTime = activity.findViewById(R.id.totaltime);
+        mPrev = (ImageButton) activity.findViewById(R.id.prev);
+        mNext = (ImageButton) activity.findViewById(R.id.next);
+        mPause = (ImageButton) activity.findViewById(R.id.pause);
+        mLayout = activity.findViewById(R.id.layout);
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mCurrentTime);    
+        assertNotNull(mTotalTime);  
+        assertNotNull(mPrev);  
+        assertNotNull(mNext);  
+        assertNotNull(mPause);  
+        assertNotNull(mLayout);  
+    }
+    
+    @MediumTest
+    public void testLayout() {
+        int pauseHeight =  Math.max(mPause.getDrawable().getIntrinsicHeight()
+                + mPause.getPaddingTop() + mPause.getPaddingBottom(),
+                mPause.getBackground().getMinimumHeight());
+        int prevHeight = Math.max(mPrev.getDrawable().getIntrinsicHeight() + mPrev.getPaddingTop()
+                + mPrev.getPaddingBottom(),
+                mPrev.getBackground().getMinimumHeight());
+        int nextHeight = Math.max(mNext.getDrawable().getIntrinsicHeight() + mNext.getPaddingTop()
+                + mNext.getPaddingBottom(),
+                mNext.getBackground().getMinimumHeight());
+        assertEquals("Layout incorrect height", pauseHeight, mLayout.getHeight()); 
+        assertEquals("Pause incorrect height", pauseHeight, mPause.getHeight()); 
+        assertEquals("Prev incorrect height", prevHeight, mPrev.getHeight()); 
+        assertEquals("Next incorrect height", nextHeight, mNext.getHeight()); 
+        assertEquals("Pause wrong top", 0, mPause.getTop()); 
+        assertEquals("Prev wrong top", (pauseHeight - prevHeight) / 2, mPrev.getTop());
+        assertEquals("Next wrong top", (pauseHeight - nextHeight) / 2, mNext.getTop());
+        assertEquals("CurrentTime wrong bottom",  pauseHeight, mCurrentTime.getBottom());
+        assertEquals("TotalTime wrong bottom",  pauseHeight, mTotalTime.getBottom());
+        assertTrue("CurrentTime too tall", mCurrentTime.getTop() > 0);
+        assertTrue("TotalTime too tall", mTotalTime.getTop() > 0);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/linear/FillInWrapTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/linear/FillInWrapTest.java
new file mode 100644
index 0000000..0e7a4a0
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/linear/FillInWrapTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.linear;
+
+import android.app.Activity;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.View;
+
+import com.android.frameworktest.R;
+
+public class FillInWrapTest extends ActivityInstrumentationTestCase<FillInWrap> {
+    private View mChild;
+    private View mContainer;
+
+    public FillInWrapTest() {
+        super("com.android.frameworktest", FillInWrap.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        final Activity activity = getActivity();
+        mChild = activity.findViewById(R.id.data);
+        mContainer = activity.findViewById(R.id.layout);
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mChild);
+        assertNotNull(mContainer);
+    }
+
+    @MediumTest
+    public void testLayout() {
+        assertTrue("the child's height should be less than the parent's",
+                mChild.getMeasuredHeight() < mContainer.getMeasuredHeight());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/linear/LinearLayoutEditTextsTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/linear/LinearLayoutEditTextsTest.java
new file mode 100644
index 0000000..9dde62c
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/linear/LinearLayoutEditTextsTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.layout.linear;
+
+import com.android.frameworktest.layout.linear.LinearLayoutEditTexts;
+import com.android.frameworktest.R;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.View;
+import android.app.Activity;
+
+public class LinearLayoutEditTextsTest extends ActivityInstrumentationTestCase<LinearLayoutEditTexts> {
+    private View mChild;
+    private View mContainer;
+
+    public LinearLayoutEditTextsTest() {
+        super("com.android.frameworktest", LinearLayoutEditTexts.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        final Activity activity = getActivity();
+        mChild = activity.findViewById(R.id.editText1);
+        mContainer = activity.findViewById(R.id.layout);
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mChild);
+        assertNotNull(mContainer);
+    }
+
+    @MediumTest
+    public void testLayout() {
+        final int childHeight = mChild.getHeight();
+        final int containerHeight = mContainer.getHeight();
+
+        assertEquals(containerHeight, childHeight);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/linear/WeightSumTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/linear/WeightSumTest.java
new file mode 100644
index 0000000..a51743b
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/linear/WeightSumTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.linear;
+
+import android.app.Activity;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.View;
+
+import com.android.frameworktest.R;
+import com.android.frameworktest.layout.linear.WeightSum;
+
+public class WeightSumTest extends ActivityInstrumentationTestCase<WeightSum> {
+    private View mChild;
+    private View mContainer;
+
+    public WeightSumTest() {
+        super("com.android.frameworktest", WeightSum.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        final Activity activity = getActivity();
+        mChild = activity.findViewById(R.id.child);
+        mContainer = activity.findViewById(R.id.container);
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mChild);
+        assertNotNull(mContainer);
+    }
+
+    @MediumTest
+    public void testLayout() {
+        final int childWidth = mChild.getWidth();
+        final int containerWidth = mContainer.getWidth();
+
+        assertEquals(containerWidth / 2, childWidth);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/linear/WeightTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/linear/WeightTest.java
new file mode 100644
index 0000000..f7fec78
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/linear/WeightTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.linear;
+
+import android.app.Activity;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.ViewAsserts;
+import android.view.View;
+
+import com.android.frameworktest.R;
+import com.android.frameworktest.layout.linear.Weight;
+
+public class WeightTest extends ActivityInstrumentationTestCase<Weight> {
+    private View mChild;
+    private View mContainer;
+
+    public WeightTest() {
+        super("com.android.frameworktest", Weight.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        final Activity activity = getActivity();
+        mChild = activity.findViewById(R.id.child4);
+        mContainer = activity.findViewById(R.id.layout);
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mChild);
+        assertNotNull(mContainer);
+    }
+
+    @MediumTest
+    public void testLayout() {
+        ViewAsserts.assertRightAligned(mChild, mContainer);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/table/AddColumnTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/table/AddColumnTest.java
new file mode 100644
index 0000000..9d713c8
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/table/AddColumnTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.table;
+
+import com.android.frameworktest.layout.table.AddColumn;
+import com.android.frameworktest.R;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.widget.Button;
+import android.widget.TableLayout;
+import android.widget.TableRow;
+
+/**
+ * {@link com.android.frameworktest.layout.table.AddColumn} is
+ * setup to exercise the case of adding row programmatically in a table.
+ */
+public class AddColumnTest extends ActivityInstrumentationTestCase<AddColumn> {
+    private Button mAddRow;
+    private TableLayout mTable;
+
+    public AddColumnTest() {
+        super("com.android.frameworktest", AddColumn.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        final AddColumn activity = getActivity();
+        mAddRow = (Button) activity.findViewById(R.id.add_row_button);
+        mTable = (TableLayout) activity.findViewById(R.id.table);
+    }
+
+    @MediumTest
+    public void testSetUpConditions() throws Exception {
+        assertNotNull(mAddRow);
+        assertNotNull(mTable);
+        assertTrue(mAddRow.hasFocus());
+    }
+
+    @MediumTest
+    public void testWidths() throws Exception {
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        getInstrumentation().waitForIdleSync();
+
+        TableRow row1 = (TableRow) mTable.getChildAt(0);
+        TableRow row2 = (TableRow) mTable.getChildAt(1);
+
+        assertTrue(row1.getChildCount() < row2.getChildCount());
+
+        for (int i = 0; i < row1.getChildCount(); i++) {
+            assertEquals(row2.getChildAt(i).getWidth(), row1.getChildAt(i).getWidth());
+        }
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/table/CellSpanTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/table/CellSpanTest.java
new file mode 100644
index 0000000..85f9c2c
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/table/CellSpanTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.table;
+
+import com.android.frameworktest.layout.table.CellSpan;
+import com.android.frameworktest.R;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.View;
+
+/**
+ * {@link com.android.frameworktest.layout.table.CellSpan} is
+ * setup to exercise tables in which cells use spanning.
+ */
+public class CellSpanTest extends ActivityInstrumentationTestCase<CellSpan> {
+    private View mA;
+    private View mB;
+    private View mC;
+    private View mSpanThenCell;
+    private View mCellThenSpan;
+    private View mSpan;
+
+    public CellSpanTest() {
+        super("com.android.frameworktest", CellSpan.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        final CellSpan activity = getActivity();
+        mA            = activity.findViewById(R.id.a);
+        mB            = activity.findViewById(R.id.b);
+        mC            = activity.findViewById(R.id.c);
+        mSpanThenCell = activity.findViewById(R.id.spanThenCell);
+        mCellThenSpan = activity.findViewById(R.id.cellThenSpan);
+        mSpan         = activity.findViewById(R.id.span);
+    }
+
+    @MediumTest
+    public void testSetUpConditions() throws Exception {
+        assertNotNull(mA);
+        assertNotNull(mB);
+        assertNotNull(mC);
+        assertNotNull(mSpanThenCell);
+        assertNotNull(mCellThenSpan);
+        assertNotNull(mSpan);
+    }
+
+    @MediumTest
+    public void testSpanThenCell() throws Exception {
+        int spanWidth = mA.getMeasuredWidth() + mB.getMeasuredWidth();
+        assertEquals("span followed by cell is broken", spanWidth,
+                mSpanThenCell.getMeasuredWidth());
+    }
+
+    @MediumTest
+    public void testCellThenSpan() throws Exception {
+        int spanWidth = mB.getMeasuredWidth() + mC.getMeasuredWidth();
+        assertEquals("cell followed by span is broken", spanWidth,
+                mCellThenSpan.getMeasuredWidth());
+    }
+
+    @MediumTest
+    public void testSpan() throws Exception {
+        int spanWidth = mA.getMeasuredWidth() + mB.getMeasuredWidth() +
+                mC.getMeasuredWidth();
+        assertEquals("span is broken", spanWidth, mSpan.getMeasuredWidth());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/table/FixedWidthTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/table/FixedWidthTest.java
new file mode 100644
index 0000000..a54d503
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/table/FixedWidthTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.table;
+
+import com.android.frameworktest.layout.table.FixedWidth;
+import com.android.frameworktest.R;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.View;
+
+/**
+ * {@link com.android.frameworktest.layout.table.FixedWidth} is
+ * setup to exercise tables in which cells use fixed width and height.
+ */
+public class FixedWidthTest extends ActivityInstrumentationTestCase<FixedWidth> {
+    private View mFixedWidth;
+    private View mFixedHeight;
+    private View mNonFixedWidth;
+
+    public FixedWidthTest() {
+        super("com.android.frameworktest", FixedWidth.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        final FixedWidth activity = getActivity();
+        mFixedWidth = activity.findViewById(R.id.fixed_width);
+        mNonFixedWidth = activity.findViewById(R.id.non_fixed_width);
+        mFixedHeight = activity.findViewById(R.id.fixed_height);
+    }
+
+    @MediumTest
+    public void testSetUpConditions() throws Exception {
+        assertNotNull(mFixedWidth);
+        assertNotNull(mFixedHeight);
+        assertNotNull(mNonFixedWidth);
+    }
+
+    @MediumTest
+    public void testFixedWidth() throws Exception {
+        assertEquals(150, mFixedWidth.getWidth());
+        assertEquals(mFixedWidth.getWidth(), mNonFixedWidth.getWidth());
+    }
+
+    @MediumTest
+    public void testFixedHeight() throws Exception {
+        assertEquals(48, mFixedHeight.getHeight());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/table/HorizontalGravityTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/table/HorizontalGravityTest.java
new file mode 100644
index 0000000..1355cb3
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/table/HorizontalGravityTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.table;
+
+import com.android.frameworktest.layout.table.HorizontalGravity;
+import com.android.frameworktest.R;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.ViewAsserts;
+import android.view.View;
+
+/**
+ * {@link com.android.frameworktest.layout.table.HorizontalGravity} is
+ * setup to exercise tables in which cells use horizontal gravity.
+ */
+public class HorizontalGravityTest extends ActivityInstrumentationTestCase<HorizontalGravity> {
+    private View mReference;
+    private View mCenter;
+    private View mBottomRight;
+    private View mLeft;
+
+    public HorizontalGravityTest() {
+        super("com.android.frameworktest", HorizontalGravity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        final HorizontalGravity activity = getActivity();
+        mReference   = activity.findViewById(R.id.reference);
+        mCenter      = activity.findViewById(R.id.center);
+        mBottomRight = activity.findViewById(R.id.bottomRight);
+        mLeft        = activity.findViewById(R.id.left);
+    }
+
+    @MediumTest
+    public void testSetUpConditions() throws Exception {
+        assertNotNull(mReference);
+        assertNotNull(mCenter);
+        assertNotNull(mBottomRight);
+        assertNotNull(mLeft);
+    }
+
+    @MediumTest
+    public void testCenterGravity() throws Exception {
+        ViewAsserts.assertHorizontalCenterAligned(mReference, mCenter);
+    }
+
+    @MediumTest
+    public void testLeftGravity() throws Exception {
+        ViewAsserts.assertLeftAligned(mReference, mLeft);
+    }
+
+    @MediumTest
+    public void testRightGravity() throws Exception {
+        ViewAsserts.assertRightAligned(mReference, mBottomRight);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/table/VerticalGravityTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/table/VerticalGravityTest.java
new file mode 100644
index 0000000..de3e68b
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/table/VerticalGravityTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.table;
+
+import com.android.frameworktest.layout.table.VerticalGravity;
+import com.android.frameworktest.R;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.ViewAsserts;
+import android.view.View;
+
+/**
+ * {@link com.android.frameworktest.layout.table.VerticalGravity} is
+ * setup to exercise tables in which cells use vertical gravity.
+ */
+public class VerticalGravityTest extends ActivityInstrumentationTestCase<VerticalGravity> {
+    private View mReference1;
+    private View mReference2;
+    private View mReference3;
+    private View mTop;
+    private View mCenter;
+    private View mBottom;
+
+    public VerticalGravityTest() {
+        super("com.android.frameworktest", VerticalGravity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        final VerticalGravity activity = getActivity();
+        mReference1 = activity.findViewById(R.id.reference1);
+        mReference2 = activity.findViewById(R.id.reference2);
+        mReference3 = activity.findViewById(R.id.reference3);
+        mTop        = activity.findViewById(R.id.cell_top);
+        mCenter     = activity.findViewById(R.id.cell_center);
+        mBottom     = activity.findViewById(R.id.cell_bottom);
+    }
+
+    @MediumTest
+    public void testSetUpConditions() throws Exception {
+        assertNotNull(mReference1);
+        assertNotNull(mReference2);
+        assertNotNull(mReference3);
+        assertNotNull(mTop);
+        assertNotNull(mCenter);
+        assertNotNull(mBottom);
+    }
+
+    @MediumTest
+    public void testTopGravity() throws Exception {
+        ViewAsserts.assertTopAligned(mReference1, mTop);
+    }
+
+    @MediumTest
+    public void testCenterGravity() throws Exception {
+        ViewAsserts.assertVerticalCenterAligned(mReference2, mCenter);
+    }
+
+    @MediumTest
+    public void testBottomGravity() throws Exception {
+        ViewAsserts.assertBottomAligned(mReference3, mBottom);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/table/WeightTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/table/WeightTest.java
new file mode 100644
index 0000000..9e20686
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/layout/table/WeightTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.layout.table;
+
+import com.android.frameworktest.layout.table.Weight;
+import com.android.frameworktest.R;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.View;
+
+/**
+ * {@link com.android.frameworktest.layout.table.Weight} is
+ * setup to exercise tables in which cells use a weight.
+ */
+public class WeightTest extends ActivityInstrumentationTestCase<Weight> {
+    private View mCell1;
+    private View mCell2;
+    private View mCell3;
+    private View mRow;
+
+    public WeightTest() {
+        super("com.android.frameworktest", Weight.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        final Weight activity = getActivity();
+        mCell1 = activity.findViewById(R.id.cell1);
+        mCell3 = activity.findViewById(R.id.cell2);
+        mCell2 = activity.findViewById(R.id.cell3);
+        mRow = activity.findViewById(R.id.row);
+    }
+
+    @MediumTest
+    public void testSetUpConditions() throws Exception {
+        assertNotNull(mCell1);
+        assertNotNull(mCell2);
+        assertNotNull(mCell3);
+        assertNotNull(mRow);
+    }
+
+    @MediumTest
+    public void testAllCellsFillParent() throws Exception {
+        assertEquals(mCell1.getWidth() + mCell2.getWidth() + mCell3.getWidth(), mRow.getWidth());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListBottomGravityManyTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListBottomGravityManyTest.java
new file mode 100644
index 0000000..d36e343
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListBottomGravityManyTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.ListView;
+
+import com.android.frameworktest.listview.ListBottomGravityMany;
+
+public class ListBottomGravityManyTest extends ActivityInstrumentationTestCase<ListBottomGravityMany> {
+    private ListBottomGravityMany mActivity;
+    private ListView mListView;
+
+    public ListBottomGravityManyTest() {
+        super("com.android.frameworktest", ListBottomGravityMany.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mListView = getActivity().getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mListView);
+        
+        // Last item should be selected
+        assertEquals(mListView.getAdapter().getCount() - 1, mListView.getSelectedItemPosition());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListBottomGravityTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListBottomGravityTest.java
new file mode 100644
index 0000000..79556cf
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListBottomGravityTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.ListView;
+
+import com.android.frameworktest.listview.ListBottomGravity;
+
+public class ListBottomGravityTest extends ActivityInstrumentationTestCase<ListBottomGravity> {
+    private ListBottomGravity mActivity;
+    private ListView mListView;
+
+    public ListBottomGravityTest() {
+        super("com.android.frameworktest", ListBottomGravity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mListView = getActivity().getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mListView);
+        
+        // Last item should be selected
+        assertEquals(mListView.getAdapter().getCount() - 1, mListView.getSelectedItemPosition());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListEmptyViewTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListEmptyViewTest.java
new file mode 100644
index 0000000..ca12154
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListEmptyViewTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.listview;
+
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.ListView;
+
+public class ListEmptyViewTest extends ActivityInstrumentationTestCase<ListWithEmptyView> {
+    private ListWithEmptyView mActivity;
+    private ListView mListView;
+
+
+    public ListEmptyViewTest() {
+        super("com.android.frameworktest", ListWithEmptyView.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mListView = getActivity().getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mListView);
+        
+        assertTrue("Empty view not shown", mListView.getVisibility() == View.GONE);
+    }
+    
+    @MediumTest
+    public void testZeroToOne() {
+        Instrumentation inst = getInstrumentation();
+       
+        inst.invokeMenuActionSync(mActivity, mActivity.MENU_ADD, 0);
+        inst.waitForIdleSync();
+        assertTrue("Empty view still shown", mActivity.getEmptyView().getVisibility() == View.GONE);
+        assertTrue("List not shown", mActivity.getListView().getVisibility() == View.VISIBLE);
+    }
+    
+    @MediumTest
+    public void testZeroToOneForwardBack() {
+        Instrumentation inst = getInstrumentation();
+       
+        inst.invokeMenuActionSync(mActivity, mActivity.MENU_ADD, 0);
+        inst.waitForIdleSync();
+        assertTrue("Empty view still shown", mActivity.getEmptyView().getVisibility() == View.GONE);
+        assertTrue("List not shown", mActivity.getListView().getVisibility() == View.VISIBLE);
+        
+        // Navigate forward
+        Intent intent = new Intent();
+        intent.setClass(mActivity, ListWithEmptyView.class);
+        mActivity.startActivity(intent);
+        
+        // Navigate backward
+        inst.sendCharacterSync(KeyEvent.KEYCODE_BACK);
+        inst.waitForIdleSync();
+        assertTrue("Empty view still shown", mActivity.getEmptyView().getVisibility() == View.GONE);
+        assertTrue("List not shown", mActivity.getListView().getVisibility() == View.VISIBLE);
+
+    }
+    
+    @LargeTest
+    public void testZeroToManyToZero() {
+        Instrumentation inst = getInstrumentation();
+       
+        int i;
+
+        for (i = 0; i < 10; i++) {
+            inst.invokeMenuActionSync(mActivity, mActivity.MENU_ADD, 0);
+            inst.waitForIdleSync();
+            assertTrue("Empty view still shown",
+                    mActivity.getEmptyView().getVisibility() == View.GONE);
+            assertTrue("List not shown", mActivity.getListView().getVisibility() == View.VISIBLE);
+        }
+
+        for (i = 0; i < 10; i++) {
+            inst.invokeMenuActionSync(mActivity, mActivity.MENU_REMOVE, 0);
+            inst.waitForIdleSync();
+            if (i < 9) {
+                assertTrue("Empty view still shown",
+                        mActivity.getEmptyView().getVisibility() == View.GONE);
+                assertTrue("List not shown",
+                        mActivity.getListView().getVisibility() == View.VISIBLE);
+            } else {
+                assertTrue("Empty view not shown",
+                        mActivity.getEmptyView().getVisibility() == View.VISIBLE);
+                assertTrue("List still shown",
+                        mActivity.getListView().getVisibility() == View.GONE);
+            }
+        }
+        
+        // Navigate forward
+        Intent intent = new Intent();
+        intent.setClass(mActivity, ListWithEmptyView.class);
+        mActivity.startActivity(intent);
+        
+        // Navigate backward
+        inst.sendCharacterSync(KeyEvent.KEYCODE_BACK);
+        inst.waitForIdleSync();
+        assertTrue("Empty view not shown", mActivity.getEmptyView().getVisibility() == View.VISIBLE);
+        assertTrue("List still shown", mActivity.getListView().getVisibility() == View.GONE);
+    }
+    
+    
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListFocusableTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListFocusableTest.java
new file mode 100644
index 0000000..1bb1f1c
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListFocusableTest.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.ListView;
+import android.widget.ListAdapter;
+import android.widget.ArrayAdapter;
+
+public class ListFocusableTest extends ActivityInstrumentationTestCase<ListTopGravity> {
+    private ListTopGravity mActivity;
+    private ListView mListView;
+
+    public ListFocusableTest() {
+        super("com.android.frameworktest", ListTopGravity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mListView = getActivity().getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mListView);
+
+        // First item should be selected
+        assertEquals(0, mListView.getSelectedItemPosition());
+    }
+
+    @MediumTest
+    public void testAdapterFull() {
+        setFullAdapter();
+        assertTrue(mListView.isFocusable());
+    }
+
+    @MediumTest
+    public void testAdapterEmpty() {
+        setEmptyAdapter();
+        assertFalse(mListView.isFocusable());
+    }
+
+    @MediumTest
+    public void testAdapterNull() {
+        setNullAdapter();
+        assertFalse(mListView.isFocusable());
+    }
+
+    @MediumTest
+    public void testAdapterFullSetFocusable() {
+        assertTrue(mListView.isFocusable());
+
+        setFocusable();
+        assertTrue(mListView.isFocusable());
+    }
+
+    @MediumTest
+    public void testAdapterFullSetNonFocusable() {
+        assertTrue(mListView.isFocusable());
+
+        setNonFocusable();
+        assertFalse(mListView.isFocusable());
+    }
+
+    @MediumTest
+    public void testAdapterEmptySetFocusable() {
+        setEmptyAdapter();
+        assertFalse(mListView.isFocusable());
+
+        setFocusable();
+        assertFalse(mListView.isFocusable());
+    }
+
+    @MediumTest
+    public void testAdapterEmptySetNonFocusable() {
+        setEmptyAdapter();
+        assertFalse(mListView.isFocusable());
+
+        setNonFocusable();
+        assertFalse(mListView.isFocusable());
+    }
+
+    @MediumTest
+    public void testAdapterNullSetFocusable() {
+        setNullAdapter();
+        assertFalse(mListView.isFocusable());
+
+        setFocusable();
+        assertFalse(mListView.isFocusable());
+    }
+
+    @MediumTest
+    public void testAdapterNullSetNonFocusable() {
+        setNullAdapter();
+        assertFalse(mListView.isFocusable());
+
+        setNonFocusable();
+        assertFalse(mListView.isFocusable());
+    }
+
+    @MediumTest
+    public void testFocusableSetAdapterFull() {
+        assertTrue(mListView.isFocusable());
+
+        setFullAdapter();
+        assertTrue(mListView.isFocusable());
+    }
+
+    @MediumTest
+    public void testNonFocusableSetAdapterFull() {
+        assertTrue(mListView.isFocusable());
+
+        setNonFocusable();
+        assertFalse(mListView.isFocusable());
+
+        setFullAdapter();
+        assertFalse(mListView.isFocusable());
+    }
+
+    @MediumTest
+    public void testFocusableSetAdapterEmpty() {
+        assertTrue(mListView.isFocusable());
+
+        setEmptyAdapter();
+        assertFalse(mListView.isFocusable());
+    }
+
+    @MediumTest
+    public void testNonFocusableSetAdapterEmpty() {
+        assertTrue(mListView.isFocusable());
+
+        setNonFocusable();
+        assertFalse(mListView.isFocusable());
+
+        setEmptyAdapter();
+        assertFalse(mListView.isFocusable());
+    }
+
+    @MediumTest
+    public void testFocusableSetAdapterNull() {
+        assertTrue(mListView.isFocusable());
+
+        setNullAdapter();
+        assertFalse(mListView.isFocusable());
+    }
+
+    @MediumTest
+    public void testNonFocusableSetAdapterNull() {
+        assertTrue(mListView.isFocusable());
+
+        setNonFocusable();
+        assertFalse(mListView.isFocusable());
+
+        setNullAdapter();
+        assertFalse(mListView.isFocusable());
+    }
+
+    private ListAdapter createFullAdapter() {
+        return new ArrayAdapter<String>(mActivity, android.R.layout.simple_list_item_1,
+                new String[] { "Android", "Robot" });
+    }
+
+    private ListAdapter createEmptyAdapter() {
+        return new ArrayAdapter<String>(mActivity, android.R.layout.simple_list_item_1,
+                new String[] { });
+    }
+
+
+    private void setFullAdapter() {
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mListView.setAdapter(createFullAdapter());
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+    }
+
+    private void setEmptyAdapter() {
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mListView.setAdapter(createEmptyAdapter());
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+    }
+
+    private void setNullAdapter() {
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mListView.setAdapter(null);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+    }
+
+    private void setFocusable() {
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mListView.setFocusable(true);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+    }
+
+    private void setNonFocusable() {
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mListView.setFocusable(false);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListHeterogeneousTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListHeterogeneousTest.java
new file mode 100644
index 0000000..0e48993
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListHeterogeneousTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.app.Instrumentation;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.widget.ListView;
+
+import com.android.frameworktest.listview.ListHeterogeneous;
+
+public class ListHeterogeneousTest extends ActivityInstrumentationTestCase<ListHeterogeneous> {
+    private ListHeterogeneous mActivity;
+    private ListView mListView;
+
+
+    public ListHeterogeneousTest() {
+        super("com.android.frameworktest", ListHeterogeneous.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mListView = getActivity().getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mListView);
+    }
+    
+    @LargeTest
+    public void testKeyScrolling() {
+        Instrumentation inst = getInstrumentation();
+        
+        int count = mListView.getAdapter().getCount();
+
+        
+        for (int i = 0; i < count - 1; i++) {
+            inst.sendCharacterSync(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+        inst.waitForIdleSync();
+        int convertMissesBefore = mActivity.getConvertMisses();
+        
+        assertEquals("Unexpected convert misses", 0, convertMissesBefore);
+        
+        for (int i = 0; i < count - 1; i++) {
+            inst.sendCharacterSync(KeyEvent.KEYCODE_DPAD_UP);
+        }
+        inst.waitForIdleSync();
+        int convertMissesAfter = mActivity.getConvertMisses();
+        
+        assertEquals("Unexpected convert misses", 0, convertMissesAfter);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListInHorizontalTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListInHorizontalTest.java
new file mode 100644
index 0000000..1432576
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListInHorizontalTest.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.listview;
+
+import com.android.frameworktest.listview.ListInHorizontal;
+
+public class ListInHorizontalTest extends ListUnspecifiedMeasure<ListInHorizontal> {
+    public ListInHorizontalTest() {
+        super(ListInHorizontal.class);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListInVerticalTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListInVerticalTest.java
new file mode 100644
index 0000000..73078b9
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListInVerticalTest.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.listview;
+
+import com.android.frameworktest.listview.ListInVertical;
+
+public class ListInVerticalTest extends ListUnspecifiedMeasure<ListInVertical> {
+    public ListInVerticalTest() {
+        super(ListInVertical.class);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListItemRequestRectAboveThinFirstItemTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListItemRequestRectAboveThinFirstItemTest.java
new file mode 100644
index 0000000..16c4d39
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListItemRequestRectAboveThinFirstItemTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.graphics.Rect;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.View;
+import android.view.KeyEvent;
+import android.widget.ListView;
+import com.android.frameworktest.listview.ListOfThinItems;
+
+public class ListItemRequestRectAboveThinFirstItemTest
+        extends ActivityInstrumentationTestCase<ListOfThinItems> {
+    private ListView mListView;
+
+    public ListItemRequestRectAboveThinFirstItemTest() {
+        super("com.android.frameworktest", ListOfThinItems.class);
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        mListView = getActivity().getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+
+        assertTrue("first child needs to be within fading edge height",
+                mListView.getChildAt(0).getBottom() < mListView.getVerticalFadingEdgeLength());
+        assertTrue("should be at least two visible children",
+                mListView.getChildCount() >= 2);
+    }
+
+    // reproduce bug 998501: when first item fits within fading edge,
+    // having the second item call requestRectangleOnScreen with a rect above
+    // the bounds of the list, it was scrolling too far
+    @MediumTest
+    public void testSecondItemRequestRectAboveTop() throws Exception {
+
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        assertEquals("selected position", 1, mListView.getSelectedItemPosition());
+
+        final View second = mListView.getChildAt(1);
+        final Rect rect = new Rect();
+        second.getDrawingRect(rect);
+        rect.offset(0, -2 * second.getBottom());
+
+        getActivity().requestRectangleOnScreen(1, rect);
+        getInstrumentation().waitForIdleSync();        
+
+        assertEquals("top of first item",
+                mListView.getListPaddingTop(), mListView.getChildAt(0).getTop());
+
+    }
+
+    // same thing, but at bottom
+    @LargeTest
+    public void testSecondToLastItemRequestRectBelowBottom() throws Exception {
+
+        final int secondToLastPos = mListView.getCount() - 2;
+
+        while (mListView.getSelectedItemPosition() < secondToLastPos) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+        assertEquals("selected position", secondToLastPos,
+                mListView.getSelectedItemPosition());
+
+        final View secondToLast = mListView.getSelectedView();
+        final Rect rect = new Rect();
+        secondToLast.getDrawingRect(rect);
+        rect.offset(0,
+                2 * (mListView.getBottom() - secondToLast.getTop()));
+
+        final int secondToLastIndex = mListView.getChildCount() - 2;
+        getActivity().requestRectangleOnScreen(secondToLastIndex, rect);
+        getInstrumentation().waitForIdleSync();
+
+        int listBottom = mListView.getHeight() - mListView.getPaddingBottom();
+        assertEquals("bottom of last item should be at bottom of list",
+                listBottom,
+                mListView.getChildAt(mListView.getChildCount() - 1).getBottom());
+    }
+
+
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListManagedCursorTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListManagedCursorTest.java
new file mode 100644
index 0000000..0251dfb
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListManagedCursorTest.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.listview;
+
+import android.app.Instrumentation;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.FlakyTest;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.widget.ListView;
+import android.test.TouchUtils;
+
+/**
+ * Tests restoring the scroll position in a list with a managed cursor.
+ */
+public class ListManagedCursorTest extends ActivityInstrumentationTestCase<ListManagedCursor> {
+    private ListManagedCursor mActivity;
+    private ListView mListView;
+
+    public ListManagedCursorTest() {
+        super("com.android.frameworktest", ListManagedCursor.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mListView = getActivity().getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mListView);
+        
+        assertEquals(0, mListView.getFirstVisiblePosition());
+    }
+    
+    /**
+     * Scroll the list using arrows, launch new activity, hit back, make sure we're still scrolled.
+     */
+    @LargeTest
+    public void testKeyScrolling() {
+        Instrumentation inst = getInstrumentation();
+        
+        int firstVisiblePosition = arrowScroll(inst);
+        
+        inst.sendCharacterSync(KeyEvent.KEYCODE_BACK);
+        inst.waitForIdleSync();
+        
+        assertTrue("List changed to touch mode", !mListView.isInTouchMode()); 
+        assertTrue("List did not preserve scroll position", 
+                firstVisiblePosition == mListView.getFirstVisiblePosition()); 
+    }
+
+    /**
+     * Scroll the list using touch, launch new activity, hit back, make sure we're still scrolled.
+     */
+    @LargeTest
+    public void testTouchScrolling() {
+        Instrumentation inst = getInstrumentation();
+        
+       int firstVisiblePosition = touchScroll(inst);
+        
+        inst.sendCharacterSync(KeyEvent.KEYCODE_BACK);
+        inst.waitForIdleSync();
+        
+        assertTrue("List not in touch mode", mListView.isInTouchMode()); 
+        assertTrue("List did not preserve scroll position", 
+                firstVisiblePosition == mListView.getFirstVisiblePosition()); 
+    }
+    
+    /**
+     * Scroll the list using arrows, launch new activity, change to touch mode, hit back, make sure
+     * we're still scrolled.
+     */
+    @LargeTest
+    public void testKeyScrollingToTouchMode() {
+        Instrumentation inst = getInstrumentation();
+        
+        int firstVisiblePosition = arrowScroll(inst);
+        
+        TouchUtils.dragQuarterScreenUp(this);
+        inst.sendCharacterSync(KeyEvent.KEYCODE_BACK);
+        inst.waitForIdleSync();
+        
+        assertTrue("List did not change to touch mode", mListView.isInTouchMode()); 
+        assertTrue("List did not preserve scroll position", 
+                firstVisiblePosition == mListView.getFirstVisiblePosition()); 
+    }
+
+
+    /**
+     * Scroll the list using touch, launch new activity, change to trackball mode, hit back, make
+     * sure we're still scrolled.
+     */
+    @FlakyTest(tolerance=3)
+    @LargeTest
+    public void testTouchScrollingToTrackballMode() {
+        Instrumentation inst = getInstrumentation();
+
+        int firstVisiblePosition = touchScroll(inst);
+
+        inst.sendCharacterSync(KeyEvent.KEYCODE_DPAD_DOWN);
+        inst.waitForIdleSync();
+        inst.sendCharacterSync(KeyEvent.KEYCODE_DPAD_DOWN);
+        inst.waitForIdleSync();
+        inst.sendCharacterSync(KeyEvent.KEYCODE_BACK);
+        inst.waitForIdleSync();
+        assertTrue("List not in trackball mode", !mListView.isInTouchMode());
+        assertTrue("List did not preserve scroll position", firstVisiblePosition == mListView
+                .getFirstVisiblePosition());
+    }
+    
+    public int arrowScroll(Instrumentation inst) {
+        int count = mListView.getChildCount();
+
+        for (int i = 0; i < count * 2; i++) {
+            inst.sendCharacterSync(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+        inst.waitForIdleSync();
+
+        int firstVisiblePosition = mListView.getFirstVisiblePosition();
+        assertTrue("Arrow scroll did not happen", firstVisiblePosition > 0);
+        assertTrue("List still in touch mode", !mListView.isInTouchMode());
+
+        inst.sendCharacterSync(KeyEvent.KEYCODE_DPAD_CENTER);
+        inst.waitForIdleSync();
+
+        try {
+            Thread.sleep(3000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+
+        return firstVisiblePosition;
+    }
+
+    public int touchScroll(Instrumentation inst) {
+        TouchUtils.dragQuarterScreenUp(this);
+        inst.waitForIdleSync();
+        TouchUtils.dragQuarterScreenUp(this);
+        inst.waitForIdleSync();
+        TouchUtils.dragQuarterScreenUp(this);
+        inst.waitForIdleSync();
+        TouchUtils.dragQuarterScreenUp(this);
+        inst.waitForIdleSync();
+
+        int firstVisiblePosition = mListView.getFirstVisiblePosition();
+        assertTrue("Touch scroll did not happen", firstVisiblePosition > 0);
+        assertTrue("List not in touch mode", mListView.isInTouchMode());
+
+        TouchUtils.clickView(this, mListView.getChildAt(mListView.getChildCount() - 1));
+        inst.waitForIdleSync();
+
+        try {
+            Thread.sleep(3000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+
+        return firstVisiblePosition;
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListRetainsFocusAcrossLayoutsTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListRetainsFocusAcrossLayoutsTest.java
new file mode 100644
index 0000000..02a8beb
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListRetainsFocusAcrossLayoutsTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.listview;
+
+import com.android.frameworktest.listview.ListItemFocusablesClose;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+
+public class ListRetainsFocusAcrossLayoutsTest extends ActivityInstrumentationTestCase<ListItemFocusablesClose> {
+
+    public ListRetainsFocusAcrossLayoutsTest() {
+        super("com.android.frameworktest", ListItemFocusablesClose.class);
+    }
+
+    private void requestLayoutOnList() {
+        getActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                getActivity().getListView().requestLayout();
+            }
+        });
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertTrue("top button at position 0 should be focused",
+                getActivity().getChildOfItem(0, 0).isFocused());
+    }
+
+    @MediumTest
+    public void testBottomButtonRetainsFocusAfterLayout() throws Exception {
+
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+
+        assertTrue("bottom botton at position 0 should be focused",
+                getActivity().getChildOfItem(0, 2).isFocused());
+
+        requestLayoutOnList();
+        getInstrumentation().waitForIdleSync();
+
+        assertTrue("bottom botton at position 0 should be focused after layout",
+                getActivity().getChildOfItem(0, 2).isFocused());
+    }
+
+    @MediumTest
+    public void testTopButtonOfSecondPositionRetainsFocusAfterLayout() {
+        sendRepeatedKeys(2, KeyEvent.KEYCODE_DPAD_DOWN);
+
+        assertTrue("top botton at position 1 should be focused",
+                getActivity().getChildOfItem(1, 0).isFocused());
+
+        requestLayoutOnList();
+        getInstrumentation().waitForIdleSync();
+
+        assertTrue("top botton at position 1 should be focused after layout",
+                getActivity().getChildOfItem(1, 0).isFocused());
+
+    }
+
+    @MediumTest
+    public void testBottomButtonOfSecondPositionRetainsFocusAfterLayout() {
+        sendRepeatedKeys(3, KeyEvent.KEYCODE_DPAD_DOWN);
+
+        assertTrue("bottom botton at position 1 should be focused",
+                getActivity().getChildOfItem(1, 2).isFocused());
+
+        requestLayoutOnList();
+        getInstrumentation().waitForIdleSync();
+
+        assertTrue("bottom botton at position 1 should be focused after layout",
+                getActivity().getChildOfItem(1, 2).isFocused());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListScrollListenerTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListScrollListenerTest.java
new file mode 100644
index 0000000..44958d9
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListScrollListenerTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.app.Instrumentation;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.widget.AbsListView;
+import android.widget.ListView;
+
+import android.test.TouchUtils;
+
+public class ListScrollListenerTest extends ActivityInstrumentationTestCase<ListScrollListener> implements
+        AbsListView.OnScrollListener {
+    private ListScrollListener mActivity;
+    private ListView mListView;
+    private int mFirstVisibleItem = -1;
+    private int mVisibleItemCount = -1;
+    private int mTotalItemCount = -1;
+
+    public ListScrollListenerTest() {
+        super("com.android.frameworktest", ListScrollListener.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mListView = getActivity().getListView();
+        mListView.setOnScrollListener(this);
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mListView);
+        
+        assertEquals(0, mFirstVisibleItem);
+    }
+    
+    @LargeTest
+    public void testKeyScrolling() {
+        Instrumentation inst = getInstrumentation();
+        
+        int firstVisibleItem = mFirstVisibleItem;
+        for (int i = 0; i < mVisibleItemCount * 2; i++) {
+            inst.sendCharacterSync(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+        inst.waitForIdleSync();
+        assertTrue("Arrow scroll did not happen", mFirstVisibleItem > firstVisibleItem);
+        
+        firstVisibleItem = mFirstVisibleItem;
+        inst.sendCharacterSync(KeyEvent.KEYCODE_SPACE);
+        inst.waitForIdleSync();
+        assertTrue("Page scroll did not happen", mFirstVisibleItem > firstVisibleItem);
+        
+        firstVisibleItem = mFirstVisibleItem;
+        KeyEvent down = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, 
+                KeyEvent.KEYCODE_DPAD_DOWN, 0, KeyEvent.META_ALT_ON);
+        KeyEvent up = new KeyEvent(0, 0, KeyEvent.ACTION_UP, 
+                KeyEvent.KEYCODE_DPAD_DOWN, 0, KeyEvent.META_ALT_ON);
+        inst.sendKeySync(down);
+        inst.sendKeySync(up);
+        inst.waitForIdleSync();
+        
+        assertTrue("Full scroll did not happen", mFirstVisibleItem > firstVisibleItem);
+        assertEquals("Full scroll did not happen", mTotalItemCount, 
+                mFirstVisibleItem + mVisibleItemCount);    
+    }
+
+    @LargeTest
+    public void testTouchScrolling() {
+        int firstVisibleItem = mFirstVisibleItem;
+        TouchUtils.dragQuarterScreenUp(this);
+        TouchUtils.dragQuarterScreenUp(this);
+        assertTrue("Touch scroll did not happen", mFirstVisibleItem > firstVisibleItem);
+    }
+
+    
+    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
+        mFirstVisibleItem = firstVisibleItem;
+        mVisibleItemCount = visibleItemCount;
+        mTotalItemCount = totalItemCount;
+    }
+
+    public void onScrollStateChanged(AbsListView view, int scrollState) {        
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListSetSelectionTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListSetSelectionTest.java
new file mode 100644
index 0000000..e35d894
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListSetSelectionTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.ListView;
+
+/**
+ * Basic tests of setting & clearing the selection
+ */
+public class ListSetSelectionTest extends ActivityInstrumentationTestCase2<ListSimple> {
+    private ListSimple mActivity;
+    private ListView mListView;
+
+    public ListSetSelectionTest() {
+        super("com.android.frameworktest", ListSimple.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mListView = getActivity().getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mListView);
+    }
+    
+    /** Confirm that we can set the selection to each specific position */
+    @MediumTest
+    @UiThreadTest
+    public void testSetSelection() {
+        // Set the selection to each position
+        int childCount = mListView.getChildCount();
+        for (int i=0; i<childCount; i++) {
+            mListView.setSelection(i);
+            assertEquals("Set selection", i, mListView.getSelectedItemPosition());
+        }
+    }
+    
+    /** Confirm that you cannot unset the selection using the same API */
+    @MediumTest
+    @UiThreadTest
+    public void testClearSelection() {
+        // Set the selection to first position
+        mListView.setSelection(0);
+        assertEquals("Set selection", 0, mListView.getSelectedItemPosition());
+
+        // Clear the selection
+        mListView.setSelection(ListView.INVALID_POSITION);
+        assertEquals("Set selection", 0, mListView.getSelectedItemPosition());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListUnspecifiedMeasure.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListUnspecifiedMeasure.java
new file mode 100644
index 0000000..55a57ef
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListUnspecifiedMeasure.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.listview;
+
+import com.android.frameworktest.R;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.app.Activity;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.ListView;
+
+public class ListUnspecifiedMeasure<T extends Activity> extends ActivityInstrumentationTestCase<T> {
+    private T mActivity;
+    private ListView mListView;
+
+    protected ListUnspecifiedMeasure(Class<T> klass) {
+        super("com.android.frameworktest", klass);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mListView = (ListView) mActivity.findViewById(R.id.list);
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mListView);
+    }
+
+    @MediumTest
+    public void testWasMeasured() {
+        assertTrue(mListView.getMeasuredWidth() > 0);
+        assertTrue(mListView.getWidth() > 0);
+        assertTrue(mListView.getMeasuredHeight() > 0);
+        assertTrue(mListView.getHeight() > 0);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListViewHeightTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListViewHeightTest.java
new file mode 100644
index 0000000..d5bdf8b
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/ListViewHeightTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview;
+
+import android.app.Instrumentation;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.Button;
+import android.widget.ListView;
+
+import com.android.frameworktest.R;
+import com.android.frameworktest.listview.ListViewHeight;
+
+public class ListViewHeightTest extends ActivityInstrumentationTestCase<ListViewHeight> {
+    private ListViewHeight mActivity;
+
+
+    public ListViewHeightTest() {
+        super("com.android.frameworktest", ListViewHeight.class);
+    }
+    
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+    }
+
+    @MediumTest
+    public void testButtons() {
+        Instrumentation inst = getInstrumentation();
+        final Button button1 = (Button) mActivity.findViewById(R.id.button1);
+        final Button button2 = (Button) mActivity.findViewById(R.id.button2);
+        final Button button3 = (Button) mActivity.findViewById(R.id.button3);
+        
+
+        ListView list = (ListView) mActivity.findViewById(R.id.inner_list);
+        assertEquals("Unexpected items in adapter", 0, list.getCount());
+        assertEquals("Unexpected children in list view", 0, list.getChildCount());
+        
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                button1.performClick();
+            }
+        });
+        inst.waitForIdleSync();
+        assertTrue("List not be visible after clicking button1", list.isShown());
+        assertTrue("List incorrect height", list.getHeight() == 200);
+        
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                button2.performClick();
+            }
+        });
+        inst.waitForIdleSync();
+        assertTrue("List not be visible after clicking button2", list.isShown());
+
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                button3.performClick();
+            }
+        });
+        inst.waitForIdleSync();
+        assertFalse("List should not be visible clicking button3", list.isShown());
+    }
+    
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListInterleaveFocusablesTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListInterleaveFocusablesTest.java
new file mode 100644
index 0000000..1fe75c4
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListInterleaveFocusablesTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview.arrowscroll;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.ListView;
+import android.view.KeyEvent;
+import android.view.View;
+
+import com.android.frameworktest.listview.ListInterleaveFocusables;
+import com.android.frameworktest.util.ListUtil;
+
+public class ListInterleaveFocusablesTest extends ActivityInstrumentationTestCase<ListInterleaveFocusables> {
+    private ListView mListView;
+    private ListUtil mListUtil;
+
+    public ListInterleaveFocusablesTest() {
+        super("com.android.frameworktest", ListInterleaveFocusables.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mListView = getActivity().getListView();
+        mListUtil = new ListUtil(mListView, getInstrumentation());
+    }
+
+    @LargeTest
+    public void testPreconditions() {
+        assertEquals(7, mListView.getChildCount());
+        assertTrue(mListView.getChildAt(1).isFocusable());
+        assertTrue(mListView.getChildAt(3).isFocusable());
+        assertTrue(mListView.getChildAt(6).isFocusable());
+    }
+
+    @MediumTest
+    public void testGoingFromUnFocusableSelectedToFocusable() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+
+        assertEquals("selected item position", 1, mListView.getSelectedItemPosition());
+        assertSelectedViewFocus(true);
+    }
+
+    // go down from an item that isn't focusable, make sure it finds the focusable
+    // below (instead of above).  this exposes a (now fixed) bug where the focus search
+    // was not starting from the right spot
+    @MediumTest
+    public void testGoingDownFromUnFocusableSelectedToFocusableWithOtherFocusableAbove() {
+        mListUtil.setSelectedPosition(2);
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        assertEquals("selected item position", 3, mListView.getSelectedItemPosition());
+        assertSelectedViewFocus(true);
+    }
+
+    // same, but going up
+    @MediumTest
+    public void testGoingUpFromUnFocusableSelectedToFocusableWithOtherFocusableAbove() {
+        mListUtil.setSelectedPosition(2);
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        assertEquals("selected item position", 1, mListView.getSelectedItemPosition());
+        assertSelectedViewFocus(true);
+    }
+
+    /**
+     * Go down from a focusable when there is a focusable below, but it is more than
+     * one item away; make sure it won't give that item focus because it is too far away.
+     */
+    @MediumTest
+    public void testGoingDownFromFocusableToUnfocusableWhenFocusableIsBelow() {
+        mListUtil.setSelectedPosition(3);
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        assertEquals("selected item position", 4, mListView.getSelectedItemPosition());
+        assertSelectedViewFocus(false);
+    }
+
+    // same but going up
+    @MediumTest
+    public void testGoingUpFromFocusableToUnfocusableWhenFocusableIsBelow() {
+        mListUtil.setSelectedPosition(6);
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        assertEquals("selected item position", 5, mListView.getSelectedItemPosition());
+        assertSelectedViewFocus(false);
+    }
+
+    public void assertSelectedViewFocus(boolean isFocused) {
+        final View view = mListView.getSelectedView();
+        assertEquals("selected view focused", isFocused, view.isFocused());
+        assertEquals("selected position's isSelected should be the inverse "
+                + "of it having focus", !isFocused, view.isSelected());
+    }
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListItemFocusableAboveUnfocusableTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListItemFocusableAboveUnfocusableTest.java
new file mode 100644
index 0000000..6ff9181
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListItemFocusableAboveUnfocusableTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview.arrowscroll;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.ListView;
+import android.view.KeyEvent;
+import com.android.frameworktest.listview.ListItemFocusableAboveUnfocusable;
+
+public class ListItemFocusableAboveUnfocusableTest extends ActivityInstrumentationTestCase<ListItemFocusableAboveUnfocusable> {
+    private ListView mListView;
+
+    public ListItemFocusableAboveUnfocusableTest() {
+        super("com.android.frameworktest", ListItemFocusableAboveUnfocusable.class);
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mListView = getActivity().getListView();
+    }
+
+
+    @MediumTest
+    public void testPreconditions() {
+        assertEquals("selected position", 0, mListView.getSelectedItemPosition());
+        assertTrue(mListView.getChildAt(0).isFocused());
+        assertFalse(mListView.getChildAt(1).isFocusable());
+    }
+
+    @MediumTest
+    public void testMovingToUnFocusableTakesFocusAway() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+
+        assertFalse("focused item should have lost focus",
+                mListView.getChildAt(0).isFocused());
+        assertEquals("selected position", 1, mListView.getSelectedItemPosition());
+    }
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListItemFocusablesCloseTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListItemFocusablesCloseTest.java
new file mode 100644
index 0000000..07356ba
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListItemFocusablesCloseTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview.arrowscroll;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import com.android.frameworktest.listview.ListItemFocusablesClose;
+
+public class ListItemFocusablesCloseTest extends ActivityInstrumentationTestCase<ListItemFocusablesClose> {
+    private ListView mListView;
+    private int mListTop;
+    private int mListBottom;
+
+    public ListItemFocusablesCloseTest() {
+        super("com.android.frameworktest", ListItemFocusablesClose.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception{
+        super.setUp();
+        mListView = getActivity().getListView();
+        mListTop = mListView.getListPaddingTop();
+        mListBottom = mListView.getHeight() - mListView.getListPaddingBottom();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mListView);
+        assertTrue(mListView.getAdapter().areAllItemsEnabled());
+        assertTrue(mListView.getItemsCanFocus());
+        assertEquals(0, mListView.getSelectedItemPosition());
+        final LinearLayout first = (LinearLayout) mListView.getSelectedView();
+        getInstrumentation().waitForIdleSync();
+        assertEquals("first item should be at top of screen",
+                mListView.getListPaddingTop(),
+                first.getTop());
+        assertTrue("first button of first list item should have focus",
+                first.getChildAt(0).isFocused());
+        assertTrue("item should be shorter than list for this test to make sense",
+                first.getHeight() < mListView.getHeight());
+        assertEquals("two items should be on screen",
+                2, mListView.getChildCount());
+        assertTrue("first button of second item should be on screen",
+                getActivity().getChildOfItem(1, 0).getBottom() < mListBottom);
+    }
+
+
+    @MediumTest
+    public void testChangeFocusWithinItem() {
+        final LinearLayout first = (LinearLayout) mListView.getSelectedView();
+        final int topOfFirstItemBefore = first.getTop();
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        assertTrue("focus should have moved to second button of first item",
+                first.getChildAt(2).isFocused());
+        assertEquals("selection should not have changed",
+                0, mListView.getSelectedItemPosition());
+        assertEquals("list item should not have been shifted",
+                topOfFirstItemBefore, first.getTop());
+
+
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        assertTrue("focus should have moved back to first button of first item",
+                first.getChildAt(0).isFocused());
+        assertEquals("list item should not have been shifted",
+                topOfFirstItemBefore, first.getTop());
+    }
+
+    @MediumTest
+    public void testMoveDownToButtonInDifferentSelection() {
+        final LinearLayout first = (LinearLayout) mListView.getSelectedView();
+        final int topOfFirstItemBefore = first.getTop();
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+
+        assertEquals("selection should have moved to second item",
+                1, mListView.getSelectedItemPosition());
+        final LinearLayout selectedItem = (LinearLayout) mListView.getSelectedView();
+        assertTrue("first button of second item should have focus",
+                selectedItem.getChildAt(0).isFocused());
+        assertEquals("list item should not have been shifted",
+                topOfFirstItemBefore, first.getTop());
+    }
+
+    @MediumTest
+    public void testMoveUpToButtonInDifferentSelection() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        assertEquals(1, mListView.getSelectedItemPosition());
+        assertTrue("first button of second item should have focus",
+                getActivity().getChildOfItem(1, 0).hasFocus());
+
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        assertEquals("first list item should have selection", 0,
+                mListView.getSelectedItemPosition());
+        assertTrue("second button of first item should have focus",
+                getActivity().getChildOfItem(0, 2).hasFocus());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListItemFocusablesFarApartTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListItemFocusablesFarApartTest.java
new file mode 100644
index 0000000..951e021
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListItemFocusablesFarApartTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview.arrowscroll;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ListView;
+import com.android.frameworktest.listview.ListItemFocusablesFarApart;
+
+public class ListItemFocusablesFarApartTest extends ActivityInstrumentationTestCase<ListItemFocusablesFarApart> {
+    private ListView mListView;
+    private int mListTop;
+    private int mListBottom;
+
+    public ListItemFocusablesFarApartTest() {
+        super("com.android.frameworktest", ListItemFocusablesFarApart.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mListView = getActivity().getListView();
+        mListTop = mListView.getListPaddingTop();
+        mListBottom = mListView.getHeight() - mListView.getListPaddingBottom();
+    }
+
+    /**
+     * Get the child of a list item.
+     * @param listIndex The index of the currently visible items
+     * @param index The index of the child.
+     */
+    public View getChildOfItem(int listIndex, int index) {
+        return ((ViewGroup) mListView.getChildAt(listIndex)).getChildAt(index);
+
+    }
+
+    public int getTopOfChildOfItem(int listIndex, int index) {
+        ViewGroup listItem = (ViewGroup) mListView.getChildAt(listIndex);
+        View child = listItem.getChildAt(index);
+        return child.getTop() + listItem.getTop();
+    }
+
+    public int getBottomOfChildOfItem(int listIndex, int index) {
+        ViewGroup listItem = (ViewGroup) mListView.getChildAt(listIndex);
+        View child = listItem.getChildAt(index);
+        return child.getBottom() + listItem.getTop();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mListView);
+        assertEquals("should only be one visible list item",
+                1, mListView.getChildCount());
+        int topOfFirstButton = getTopOfChildOfItem(0, 0);
+        int topOfSecondButton = getTopOfChildOfItem(0, 2);
+        assertTrue("second button should be more than max scroll away from first",
+                topOfSecondButton - topOfFirstButton > mListView.getMaxScrollAmount());
+    }
+
+
+    @MediumTest
+    public void testPanWhenNextFocusableTooFarDown() {
+
+        int expectedTop = mListView.getChildAt(0).getTop();
+
+        final Button topButton = (Button) getChildOfItem(0, 0);
+
+        int counter = 0;
+        while(getTopOfChildOfItem(0, 2) > mListBottom) {
+            // just to make sure we never end up with an infinite loop
+            if (counter > 5) fail("couldn't reach next button within " + counter + " downs");
+
+            if (getBottomOfChildOfItem(0, 0) < mListTop) {
+                assertFalse("after " + counter + " downs, top button not visible, should not have focus",
+                        topButton.isFocused());
+                assertFalse("after " + counter + " downs, neither top button nor botom button visible, nothng within first list " +
+                        "item should have focus", mListView.getChildAt(0).hasFocus());
+            } else {
+                assertTrue("after " + counter + " downs, top button still visible, should have focus",
+                        topButton.isFocused());
+            }
+
+            assertEquals("after " + counter + " downs, " +
+                    "should have panned by max scroll amount",
+                    expectedTop, mListView.getChildAt(0).getTop());
+
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+            expectedTop -= mListView.getMaxScrollAmount();
+            counter++;
+        }
+
+        // at this point, the second button is visible on screen.
+        // it should have focus
+        assertTrue("second button should have focus",
+                getChildOfItem(0, 2).isFocused());
+    }
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListItemsExpandOnSelectionTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListItemsExpandOnSelectionTest.java
new file mode 100644
index 0000000..f61ce7b
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListItemsExpandOnSelectionTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview.arrowscroll;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.ListView;
+import android.view.KeyEvent;
+import com.android.frameworktest.listview.ListItemsExpandOnSelection;
+
+public class ListItemsExpandOnSelectionTest extends ActivityInstrumentationTestCase<ListItemsExpandOnSelection> {
+    private ListView mListView;
+    private int mListTop;
+    private int mListBottom;
+    private int mExpandedHeight;
+    private int mNormalHeight;
+
+    public ListItemsExpandOnSelectionTest() {
+        super("com.android.frameworktest",
+                ListItemsExpandOnSelection.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mListView = getActivity().getListView();
+        mListTop = mListView.getListPaddingTop();
+        mListBottom = mListView.getHeight() - mListView.getListPaddingBottom();
+        mExpandedHeight = mListView.getChildAt(0).getHeight();
+        mNormalHeight = mListView.getChildAt(1).getHeight();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertEquals(0, mListView.getSelectedItemPosition());
+        assertEquals("selected item should be 1.5 times taller than the others",
+                mExpandedHeight, (int) (mNormalHeight * 1.5));
+    }
+
+    @MediumTest
+    public void testMoveSelectionDownNotRequiringScroll() {
+
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+
+        assertEquals(1, mListView.getSelectedItemPosition());
+        assertEquals("first item's top should not have shifted",
+                mListTop, mListView.getChildAt(0).getTop());
+
+    }
+
+    @MediumTest
+    public void testMoveSelectionUpNotRequiringScroll() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+
+        assertEquals(1, mListView.getSelectedItemPosition());
+        final int oldBottom = mListView.getSelectedView().getBottom();
+
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+
+        assertEquals("bottom of 2nd itme should have stayed the same when " +
+                "moving back up",
+                oldBottom,
+                mListView.getChildAt(1).getBottom());
+    }
+
+    @MediumTest
+    public void testMoveSelectionDownRequiringScroll() {
+        int lastItemIndex = mListView.getChildCount() - 1;
+
+        for(int i = 0; i < lastItemIndex; i++) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+        getInstrumentation().waitForIdleSync();
+
+        assertEquals("list position", lastItemIndex, mListView.getSelectedItemPosition());
+        assertEquals("expanded height", mExpandedHeight, mListView.getSelectedView().getHeight());
+        assertEquals("should be above bottom fading edge",
+                mListBottom - mListView.getVerticalFadingEdgeLength(),
+                mListView.getSelectedView().getBottom());
+    }
+
+    @LargeTest
+    public void testMoveSelectionUpRequiringScroll() {
+        int childrenPerScreen = mListView.getChildCount();
+
+        // go down past last child on screen
+        for(int i = 0; i < childrenPerScreen; i++) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+
+        // go back up to second to last
+        for(int i = 0; i < childrenPerScreen - 1; i++) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        }
+        getInstrumentation().waitForIdleSync();
+
+        assertEquals("list position", 1, mListView.getSelectedItemPosition());
+        assertEquals("expanded height", mExpandedHeight, mListView.getSelectedView().getHeight());
+        assertEquals("should be below top fading edge",
+                mListTop + mListView.getVerticalFadingEdgeLength(),
+                mListView.getSelectedView().getTop());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListLastItemPartiallyVisibleTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListLastItemPartiallyVisibleTest.java
new file mode 100644
index 0000000..38f4b0e
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListLastItemPartiallyVisibleTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview.arrowscroll;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.ListView;
+import android.view.View;
+import android.view.KeyEvent;
+import com.android.frameworktest.listview.ListLastItemPartiallyVisible;
+
+public class ListLastItemPartiallyVisibleTest extends ActivityInstrumentationTestCase<ListLastItemPartiallyVisible> {
+    private ListView mListView;
+    private int mListBottom;
+
+
+    public ListLastItemPartiallyVisibleTest() {
+        super("com.android.frameworktest", ListLastItemPartiallyVisible.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mListView = getActivity().getListView();
+        mListBottom = mListView.getHeight() - mListView.getPaddingBottom();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertEquals("number of elements visible should be the same as number of items " +
+                "in adapter", mListView.getCount(), mListView.getChildCount());
+
+        final View lastChild = mListView.getChildAt(mListView.getChildCount() - 1);
+        assertTrue("last item should be partially off screen",
+                lastChild.getBottom() > mListBottom);
+        assertEquals("selected position", 0, mListView.getSelectedItemPosition());
+    }
+
+    // reproduce bug 998094
+    @MediumTest
+    public void testMovingDownToFullyVisibleNoScroll() {
+        final View firstChild = mListView.getChildAt(0);
+        final int firstBottom = firstChild.getBottom();
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        assertEquals("shouldn't have scrolled: bottom of first child changed.",
+                firstBottom, firstChild.getBottom());
+    }
+
+    // reproduce bug 998094
+    @MediumTest
+    public void testMovingUpToFullyVisibleNoScroll() {
+        int numMovesToLast = mListView.getCount() - 1;
+        for (int i = 0; i < numMovesToLast; i++) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+        assertEquals("should have moved to last position",
+                mListView.getChildCount() - 1, mListView.getSelectedItemPosition());
+
+        final View lastChild = mListView.getSelectedView();
+        final int lastTop = lastChild.getTop();
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        assertEquals("shouldn't have scrolled: top of last child changed.",
+                lastTop, lastChild.getTop());
+    }
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListOfItemsShorterThanScreenTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListOfItemsShorterThanScreenTest.java
new file mode 100644
index 0000000..126eea2
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListOfItemsShorterThanScreenTest.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview.arrowscroll;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.ListView;
+import android.widget.TextView;
+import com.android.frameworktest.listview.ListOfItemsShorterThanScreen;
+
+public class ListOfItemsShorterThanScreenTest
+        extends ActivityInstrumentationTestCase<ListOfItemsShorterThanScreen> {
+    private ListView mListView;
+    private ListOfItemsShorterThanScreen mActivity;
+
+
+    public ListOfItemsShorterThanScreenTest() {
+        super("com.android.frameworktest", ListOfItemsShorterThanScreen.class);
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+        mListView = getActivity().getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertEquals(0, mListView.getSelectedItemPosition());
+        assertTrue(mListView.getChildAt(0).isSelected());
+        assertEquals(mListView.getListPaddingTop(), mListView.getSelectedView().getTop());
+    }
+
+    @MediumTest
+    public void testMoveDownToOnScreenNextItem() {
+        final View next = mListView.getChildAt(1);
+        assertFalse(next.isSelected());
+        final int secondPosition = mListView.getSelectedView().getBottom();
+        assertEquals("second item should be positioned item height pixels from top.",
+                secondPosition,
+                next.getTop());
+
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        assertEquals(1, mListView.getSelectedItemPosition());
+        assertTrue(next.isSelected());
+        assertEquals("next selected item shouldn't have moved",
+                secondPosition,
+                next.getTop());
+    }
+
+    @MediumTest
+    public void testMoveUpToOnScreenItem() {
+        // move down one, then back up
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        assertEquals(0, mListView.getSelectedItemPosition());
+    }
+
+    @MediumTest
+    public void testMoveDownToItemRequiringScrolling() {
+        final int lastOnScreenItemIndex = mListView.getChildCount() - 1;
+        final View lastItem = mListView.getChildAt(lastOnScreenItemIndex);
+        assertTrue("last item should be partially off screen",
+                lastItem.getBottom() > mListView.getBottom());
+        assertEquals(mListView.getListPaddingTop(), mListView.getSelectedView().getTop());
+
+        for (int i = 0; i < lastOnScreenItemIndex; i++) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+
+        assertEquals(lastOnScreenItemIndex, mListView.getSelectedItemPosition());
+        assertEquals(
+                getTopOfBottomFadingEdge(),
+                mListView.getSelectedView().getBottom());
+
+        // there should be a peeking view
+
+        // the current view isn't the last anymore...
+        assertEquals(mListView.getSelectedView(), mListView.getChildAt(mListView.getChildCount() - 2));
+
+        // peeking view is now last
+        final TextView view = (TextView) mListView.getChildAt(mListView.getChildCount() - 1);
+        assertEquals(mActivity.getValueAtPosition(lastOnScreenItemIndex + 1), view.getText());
+        assertFalse(view.isSelected());
+    }
+
+    @MediumTest
+    public void testMoveUpToItemRequiringScrolling() {
+        // go down to one past last item, then back up to the second item.  this will
+        // require scrolling to get it back on screen, and will need a peeking edge
+
+        int numItemsOnScreen = mListView.getChildCount();
+        for (int i = 0; i < numItemsOnScreen; i++) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+        for (int i = 0; i < numItemsOnScreen - 1; i++) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        }
+
+        assertEquals(1, mListView.getSelectedItemPosition());
+        assertEquals("top should be just below vertical fading edge",
+                mListView.getVerticalFadingEdgeLength() + mListView.getListPaddingTop(),
+                mListView.getSelectedView().getTop());
+    }
+
+    @MediumTest
+    public void testPressUpWhenAlreadyAtTop() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+
+        assertEquals(0, mListView.getSelectedItemPosition());
+    }
+
+    @MediumTest
+    public void testPressDownWhenAlreadyAtBottom() {
+        final int lastItemPosition = mListView.getAdapter().getCount() - 1;
+        for (int i = 0; i < lastItemPosition; i++) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+        assertEquals(lastItemPosition, mListView.getSelectedItemPosition());
+
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        assertEquals(lastItemPosition, mListView.getSelectedItemPosition());
+    }
+
+    @MediumTest
+    public void testNoVerticalFadingEdgeWhenMovingToBottom() {
+        final int lastItemPosition = mListView.getAdapter().getCount() - 1;
+        for (int i = 0; i < lastItemPosition; i++) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+        assertEquals(lastItemPosition, mListView.getSelectedItemPosition());
+
+        assertEquals("bottom of last item should be just above padding; no fading edge.",
+                mListView.getHeight() - mListView.getListPaddingBottom(),
+                mListView.getSelectedView().getBottom());
+
+    }
+
+    // the top of the bottom fading edge takes into account the list padding at the bottom,
+    // and the fading edge size
+    private int getTopOfBottomFadingEdge() {
+        return mListView.getHeight() - (mListView.getVerticalFadingEdgeLength() + mListView.getListPaddingBottom());
+    }
+
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListOfItemsTallerThanScreenTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListOfItemsTallerThanScreenTest.java
new file mode 100644
index 0000000..ec3a15c
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListOfItemsTallerThanScreenTest.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview.arrowscroll;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.ListView;
+import android.view.View;
+import android.view.KeyEvent;
+import com.android.frameworktest.listview.ListOfItemsTallerThanScreen;
+
+public class ListOfItemsTallerThanScreenTest
+        extends ActivityInstrumentationTestCase<ListOfItemsTallerThanScreen> {
+
+    private ListView mListView;
+    private ListOfItemsTallerThanScreen mActivity;
+
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+        mListView = getActivity().getListView();
+    }
+
+    public ListOfItemsTallerThanScreenTest() {
+        super("com.android.frameworktest", ListOfItemsTallerThanScreen.class);
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mListView);
+        assertEquals("should only be one visible child", 1, mListView.getChildCount());
+        final int amountOffScreen = mListView.getChildAt(0).getBottom() - (mListView.getBottom() - mListView.getListPaddingBottom());
+        assertTrue("must be more than max scroll off screen for this test to work",
+                amountOffScreen > mListView.getMaxScrollAmount());
+    }
+
+    @MediumTest
+    public void testScrollDownAcrossItem() {
+        final View view = mListView.getSelectedView();
+        assertTrue(view.isSelected());
+
+        assertEquals(mListView.getListPaddingTop(),
+                view.getTop());
+
+        assertTrue("view must be taller than screen for this test to be worth anything",
+                view.getBottom() > mListView.getBottom());
+
+        // scroll down until next view is peeking ahead
+        int numScrollsUntilNextViewVisible = getNumDownPressesToScrollDownAcrossSelected();
+
+        for (int i = 0; i < numScrollsUntilNextViewVisible; i++) {
+            assertEquals("after " + i + " down scrolls across tall item",
+                    mListView.getListPaddingTop() - mListView.getMaxScrollAmount() * i,
+                    view.getTop());
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+
+        // at this point, next view should be on screen peeking ahead, but we haven't given
+        // it selection yet
+        assertEquals("child count", 2, mListView.getChildCount());
+        assertEquals("selected position", 0, mListView.getSelectedItemPosition());
+        assertTrue("same view should be selected", view.isSelected());
+        final View peekingView = mListView.getChildAt(1);
+        assertEquals(view.getBottom(), peekingView.getTop());
+    }
+
+    @MediumTest
+    public void testScrollDownToNextItem() {
+        final int numPresses = getNumDownPressesToScrollDownAcrossSelected();
+        assertEquals(1, mListView.getChildCount());
+
+        for (int i = 0; i < numPresses; i++) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+        // remember top of peeking child
+        final int topOfPeekingNext = mListView.getChildAt(1).getTop();
+
+        // next view is peeking, now press one more time
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+
+        // old view should not have selection
+        assertFalse(mListView.getChildAt(0).isSelected());
+
+        // next view should now have selection, and be scrolled another a third of the list
+        // height
+        assertEquals(2, mListView.getChildCount());
+        final View next = mListView.getChildAt(1);
+        assertTrue("has selection", next.isSelected());
+        assertEquals(topOfPeekingNext - (mListView.getMaxScrollAmount()), next.getTop());
+    }
+
+    @MediumTest
+    public void testScrollFirstItemOffScreen() {
+        int numDownsToGetFirstItemOffScreen =
+                (mListView.getSelectedView().getHeight() / mListView.getMaxScrollAmount()) + 1;
+
+        for (int i = 0; i < numDownsToGetFirstItemOffScreen; i++) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+        getInstrumentation().waitForIdleSync();
+
+        assertEquals("should be at next item",
+                1, mListView.getSelectedItemPosition());
+
+        final int listTop = mListView.getTop() + mListView.getListPaddingTop();
+        assertTrue("top of selected view should be above top of list",
+                mListView.getSelectedView().getTop() < listTop);
+
+        assertEquals("off screen item shouldn't be a child of list view",
+                1, mListView.getChildCount());
+    }
+
+    @LargeTest
+    public void testScrollDownToLastItem() {
+        final int numItems = mListView.getAdapter().getCount();
+
+        int maxDowns = 20;
+        while (mListView.getSelectedItemPosition() < (numItems - 1)) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+            if (--maxDowns <= 0) {
+                fail("couldn't get to last item within 20 down arrows");
+            }
+        }
+        getInstrumentation().waitForIdleSync();
+
+        // press down enough times to get to bottom of last item
+        final int numDownsLeft = getNumDownPressesToScrollDownAcrossSelected();
+        assertTrue(numDownsLeft > 0);
+        for (int i = 0; i < numDownsLeft; i++) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+        // one more time to get across last item
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        getInstrumentation().waitForIdleSync();
+
+        assertEquals(numItems - 1, mListView.getSelectedItemPosition());
+        final int realBottom = mListView.getHeight() - mListView.getListPaddingBottom();
+        assertEquals(realBottom, mListView.getSelectedView().getBottom());
+
+        assertEquals("views scrolled off screen should be removed from view group",
+                1, mListView.getChildCount());
+    }
+
+    @MediumTest
+    public void testScrollUpAcrossFirstItem() {
+        final int listTop = mListView.getListPaddingTop();
+        assertEquals(listTop, mListView.getSelectedView().getTop());
+        final int numPresses = getNumDownPressesToScrollDownAcrossSelected();
+        for (int i = 0; i < numPresses; i++) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+        assertEquals(2, mListView.getChildCount());
+        for (int i = 0; i < numPresses; i++) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+            assertEquals(1, mListView.getChildCount());
+        }
+        assertEquals(listTop, mListView.getSelectedView().getTop());
+    }
+
+    /**
+     * Assuming the selected view is overlapping the bottom edge, how many times
+     * do I have to press down to get beyond it so that either:
+     * a) the next view is peeking in
+     * b) the selected view is the last item in the list, and we are scrolled to the bottom
+     * @return
+     */
+    private int getNumDownPressesToScrollDownAcrossSelected() {
+        View selected = mListView.getSelectedView();
+        int realBottom = mListView.getBottom() - mListView.getListPaddingBottom();
+        assertTrue("view should be overlapping bottom",
+                selected.getBottom() > realBottom);
+        assertTrue("view should be overlapping bottom",
+                selected.getTop() < realBottom);
+
+        int pixelsOffScreen = selected.getBottom() - realBottom;
+        return (pixelsOffScreen / mListView.getMaxScrollAmount()) + 1;
+    }
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListOfShortShortTallShortShortTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListOfShortShortTallShortShortTest.java
new file mode 100644
index 0000000..e218099
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListOfShortShortTallShortShortTest.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview.arrowscroll;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.widget.ListView;
+import com.android.frameworktest.listview.ListOfShortShortTallShortShort;
+import com.android.frameworktest.util.ListUtil;
+
+public class ListOfShortShortTallShortShortTest extends ActivityInstrumentationTestCase<ListOfShortShortTallShortShort> {
+    private ListView mListView;
+    private ListUtil mListUtil;
+
+    public ListOfShortShortTallShortShortTest() {
+        super("com.android.frameworktest", ListOfShortShortTallShortShort.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mListView = getActivity().getListView();
+        mListUtil = new ListUtil(mListView, getInstrumentation());
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertEquals("list item count", 5, mListView.getCount());
+        assertEquals("list visible child count", 3, mListView.getChildCount());
+        int firstTwoHeight = mListView.getChildAt(0).getHeight() + mListView.getChildAt(1).getHeight();
+        assertTrue("first two items should fit within fading edge",
+                firstTwoHeight <= mListView.getVerticalFadingEdgeLength());
+        assertTrue("first two items should fit within list max scroll",
+                firstTwoHeight <= mListView.getMaxScrollAmount());
+    }
+
+    @MediumTest
+    public void testFadeTopTwoItemsOut() {
+        // put 2nd item selected
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+
+        // one more to get two items scrolled off
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+
+        assertEquals("selected item position", 2, mListView.getSelectedItemPosition());
+        assertTrue("selected item top should be above list top",
+                mListView.getSelectedView().getTop() < mListUtil.getListTop());
+        assertTrue("selected item bottom should be below list bottom",
+                mListView.getSelectedView().getBottom() > mListUtil.getListBottom());
+        assertEquals("should only be 1 child of list (2 should have been scrolled off and removed",
+                1, mListView.getChildCount());
+    }
+
+    @LargeTest
+    public void testFadeInTwoBottomItems() {
+        // put 2nd item selected
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+
+        // one more to get two items scrolled off
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        assertEquals("number of list children", 1, mListView.getChildCount());
+
+        // last down brings bottom two items into view
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        assertEquals("should have scrolled two extra views onto screen",
+                3, mListView.getChildCount());
+        assertEquals("new view position", 3, mListView.getChildAt(1).getId());
+        assertEquals("new view position", 4, mListView.getChildAt(2).getId());
+
+        assertTrue("bottom most view shouldn't be above list bottom",
+                mListView.getChildAt(2).getBottom() >= mListUtil.getListBottom());
+    }
+
+    @LargeTest
+    public void testFadeOutBottomTwoItems() throws Exception {
+        mListUtil.arrowScrollToSelectedPosition(4);
+
+        // go up to tall item
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+
+        // one more time to scroll off bottom two items
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+
+
+        assertEquals("selected item position", 2, mListView.getSelectedItemPosition());
+        assertTrue("selected item top should be at or above list top",
+                mListView.getSelectedView().getTop() <= mListUtil.getListTop());
+        assertTrue("selected item bottom should be below list bottom",
+                mListView.getSelectedView().getBottom() > mListUtil.getListBottom());
+        assertEquals("should only be 1 child of list (2 should have been scrolled off and removed",
+                1, mListView.getChildCount());        
+    }
+
+    @LargeTest
+    public void testFadeInTopTwoItems() throws Exception {
+        mListUtil.arrowScrollToSelectedPosition(4);
+
+        // put 2nd item selected
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+
+        // one more to get two items scrolled off
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        assertEquals("number of list children", 1, mListView.getChildCount());
+
+        // last down brings top two items into view
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        assertEquals("should have scrolled two extra views onto screen",
+                3, mListView.getChildCount());
+        assertEquals("new view position", 0, mListView.getChildAt(0).getId());
+        assertEquals("new view position", 1, mListView.getChildAt(1).getId());
+
+        assertTrue("top most view shouldn't be above list top",
+                mListView.getChildAt(0).getTop() <= mListUtil.getListTop());
+    }
+
+    
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListOfShortTallShortTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListOfShortTallShortTest.java
new file mode 100644
index 0000000..6a83ada
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListOfShortTallShortTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview.arrowscroll;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.ListView;
+import android.view.KeyEvent;
+import com.android.frameworktest.listview.ListOfShortTallShort;
+
+public class ListOfShortTallShortTest extends ActivityInstrumentationTestCase<ListOfShortTallShort> {
+    private ListView mListView;
+
+    public ListOfShortTallShortTest() {
+        super("com.android.frameworktest", ListOfShortTallShort.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mListView = getActivity().getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertTrue("second item should be taller than screen",
+                mListView.getChildAt(1).getHeight() > mListView.getHeight());
+    }
+
+    @MediumTest
+    public void testGoDownFromShortToTall() {
+        int topBeforeMove = mListView.getChildAt(1).getTop();
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+
+        assertEquals("selection should have moved to tall item below",
+                1, mListView.getSelectedItemPosition());
+        assertEquals("should not have scrolled; top should be the same.",
+                topBeforeMove,
+                mListView.getSelectedView().getTop());
+    }
+
+    @MediumTest
+    public void testGoUpFromShortToTall() {
+        int maxMoves = 8;
+        while (mListView.getSelectedItemPosition() != 2 && maxMoves > 0) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+        assertEquals("couldn't get to 3rd item",
+                2,
+                mListView.getSelectedItemPosition());
+
+        assertEquals("should only be two items on screen",
+                2, mListView.getChildCount());
+        assertEquals("selected item should be last item on screen",
+                mListView.getChildAt(1), mListView.getSelectedView());
+
+        final int bottomBeforeMove = mListView.getChildAt(0).getBottom();
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        assertEquals("should have moved selection to tall item above",
+                1, mListView.getSelectedItemPosition());
+        assertEquals("should not have scrolled, top should be the same",
+                bottomBeforeMove,
+                mListView.getChildAt(0).getBottom());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListOfThinItemsTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListOfThinItemsTest.java
new file mode 100644
index 0000000..e8dbbec
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListOfThinItemsTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview.arrowscroll;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.ListView;
+import com.android.frameworktest.listview.ListOfThinItems;
+
+public class ListOfThinItemsTest extends ActivityInstrumentationTestCase<ListOfThinItems> {
+    private ListView mListView;
+
+    public ListOfThinItemsTest() {
+        super("com.android.frameworktest", ListOfThinItems.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception{
+        super.setUp();
+        mListView = getActivity().getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mListView);
+        assertTrue("need item height less than fading edge length",
+                mListView.getSelectedView().getHeight() < mListView.getVerticalFadingEdgeLength());
+        assertTrue("need items off screen",
+                mListView.getChildCount() < mListView.getAdapter().getCount());
+    }
+
+    @LargeTest
+    public void testScrollToBottom() {
+        final int numItems = mListView.getAdapter().getCount();
+        final int listBottom = mListView.getHeight() - mListView.getListPaddingBottom();
+        for (int i = 0; i < numItems; i++) {
+            assertEquals("wrong selection at position " + i,
+                    i, mListView.getSelectedItemPosition());
+            final int bottomFadingEdge = listBottom - mListView.getVerticalFadingEdgeLength();
+            final View lastChild = mListView.getChildAt(mListView.getChildCount() - 1);
+            final int lastVisiblePosition = lastChild.getId();
+
+
+            int bottomThreshold = (lastVisiblePosition < mListView.getAdapter().getCount() - 1) ?
+                    bottomFadingEdge : listBottom;
+
+            String prefix = "after " + i + " down presses, ";
+
+            assertTrue(prefix + "selected item is below bottom threshold (fading edge or bottom as " +
+                    "appropriate)",
+                    mListView.getSelectedView().getBottom() <= bottomThreshold);
+            assertTrue(prefix + "first item in list must be at very top or just above",
+                    mListView.getChildAt(0).getTop() <= 0);
+            assertTrue(prefix + "last item in list should be at very bottom or just below",
+                    lastChild.getBottom() >= listBottom);
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+    }
+
+    @LargeTest
+    public void testScrollToTop() {
+        final int numItems = mListView.getAdapter().getCount();
+
+        for (int i = 0; i < numItems - 1; i++) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+        assertEquals("should have moved to last position",
+                numItems - 1, mListView.getSelectedItemPosition());
+
+        int listTop = mListView.getListPaddingTop();
+        final int listBottom = mListView.getHeight() - mListView.getListPaddingBottom();
+
+        for (int i = 0; i < numItems; i++) {
+            int expectedPostion = numItems - (i + 1);
+            assertEquals("wrong selection at position " + expectedPostion,
+                    expectedPostion, mListView.getSelectedItemPosition());
+            final int topFadingEdge = listTop + mListView.getVerticalFadingEdgeLength();
+            final View firstChild = mListView.getChildAt(0);
+            final View lastChild = mListView.getChildAt(mListView.getChildCount() - 1);
+            final int firstVisiblePosition = firstChild.getId();
+
+
+            int topThreshold = (firstVisiblePosition > 0) ?
+                    topFadingEdge : listTop;
+
+            String prefix = "after " + i + " up presses, ";
+
+            assertTrue(prefix + "selected item is above top threshold (fading edge or top as " +
+                    "appropriate)",
+                    mListView.getSelectedView().getTop() >= topThreshold);
+            assertTrue(prefix + "first item in list must be at very top or just above",
+                    firstChild.getTop() <= 0);
+            assertTrue(prefix + "last item in list should be at very bottom or just below",
+                    lastChild.getBottom() >= listBottom);
+            sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        }
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListWithFirstScreenUnSelectableTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListWithFirstScreenUnSelectableTest.java
new file mode 100644
index 0000000..307c39d
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListWithFirstScreenUnSelectableTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.frameworktest.listview.arrowscroll;
+
+import com.android.frameworktest.listview.ListWithFirstScreenUnSelectable;
+import android.test.ActivityInstrumentationTestCase2;
+import android.view.KeyEvent;
+import android.widget.ListView;
+import android.widget.AdapterView;
+
+public class ListWithFirstScreenUnSelectableTest
+        extends ActivityInstrumentationTestCase2<ListWithFirstScreenUnSelectable> {
+    private ListView mListView;
+
+    public ListWithFirstScreenUnSelectableTest() {
+        super("com.android.frameworktest", ListWithFirstScreenUnSelectable.class);
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        setActivityInitialTouchMode(true);
+
+        mListView = getActivity().getListView();
+    }
+
+    public void testPreconditions() {
+        assertTrue(mListView.isInTouchMode());
+        assertEquals(1, mListView.getChildCount());
+        assertFalse(mListView.getAdapter().isEnabled(0));
+        assertEquals(AdapterView.INVALID_POSITION, mListView.getSelectedItemPosition());
+    }
+    
+    public void testRessurectSelection() {
+        sendKeys(KeyEvent.KEYCODE_SPACE);
+        assertEquals(AdapterView.INVALID_POSITION, mListView.getSelectedItemPosition());
+    }
+
+    public void testScrollUpDoesNothing() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        assertEquals(AdapterView.INVALID_POSITION, mListView.getSelectedItemPosition());
+        assertEquals(1, mListView.getChildCount());
+        assertEquals(0, mListView.getFirstVisiblePosition());
+    }
+
+    public void testScrollDownPansNextItemOn() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        assertEquals(2, mListView.getChildCount());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListWithNoFadingEdgeTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListWithNoFadingEdgeTest.java
new file mode 100644
index 0000000..449e048
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListWithNoFadingEdgeTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.listview.arrowscroll;
+
+import com.android.frameworktest.listview.ListWithNoFadingEdge;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.ListView;
+import android.view.KeyEvent;
+
+public class ListWithNoFadingEdgeTest extends ActivityInstrumentationTestCase<ListWithNoFadingEdge> {
+
+    private ListView mListView;
+
+    public ListWithNoFadingEdgeTest() {
+        super("com.android.frameworktest", ListWithNoFadingEdge.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mListView = getActivity().getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mListView);
+        assertEquals("listview vertical fading edge", 0, mListView.getVerticalFadingEdgeLength());
+        assertTrue("expecting that not all views fit on screen",
+                mListView.getChildCount() < mListView.getCount());
+    }
+
+    @MediumTest
+    public void testScrollDownToBottom() {
+        final int numItems = mListView.getCount();
+
+        for (int i = 0; i < numItems; i++) {
+            assertEquals("selected position", i, mListView.getSelectedItemPosition());
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+        assertEquals("selected position", numItems - 1, mListView.getSelectedItemPosition());            
+    }
+
+    @LargeTest
+    public void testScrollFromBottomToTop() {
+        final int numItems = mListView.getCount();
+
+        getActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                mListView.setSelection(numItems - 1);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+
+        for (int i = numItems - 1; i >=0; i--) {
+            assertEquals(i, mListView.getSelectedItemPosition());
+            sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        }
+
+        assertEquals("selected position", 0, mListView.getSelectedItemPosition());
+    }
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListWithOffScreenNextSelectableTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListWithOffScreenNextSelectableTest.java
new file mode 100644
index 0000000..6e62ccb
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListWithOffScreenNextSelectableTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview.arrowscroll;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.ListView;
+import android.widget.TextView;
+import com.android.frameworktest.listview.ListWithOffScreenNextSelectable;
+
+public class ListWithOffScreenNextSelectableTest
+        extends ActivityInstrumentationTestCase<ListWithOffScreenNextSelectable> {
+    private ListView mListView;
+
+    public ListWithOffScreenNextSelectableTest() {
+        super("com.android.frameworktest", ListWithOffScreenNextSelectable.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mListView = getActivity().getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mListView);
+        assertEquals(5, mListView.getAdapter().getCount());
+        assertFalse(mListView.getAdapter().areAllItemsEnabled());
+        assertFalse(mListView.getAdapter().isEnabled(1));
+        assertFalse(mListView.getAdapter().isEnabled(2));
+        assertFalse(mListView.getAdapter().isEnabled(3));
+        assertEquals("only 4 children should be on screen (so that next selectable is off " +
+                "screen) for this test to be meaningful.",
+                4, mListView.getChildCount());
+        assertEquals(0, mListView.getSelectedItemPosition());
+    }
+
+    // when the next items on screen are not selectable, we pan until the next selectable item
+    // is (partially visible), then we jump to it
+    @MediumTest
+    public void testGoDownToOffScreenSelectable() {
+
+        final int listBottom = mListView.getHeight() - mListView.getListPaddingBottom();
+
+        final View lastVisibleView = mListView.getChildAt(mListView.getChildCount() - 1);
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        assertEquals("expecting view to be panned to just above fading edge",
+                listBottom - mListView.getVerticalFadingEdgeLength(), lastVisibleView.getBottom());
+        assertEquals("selection should not have moved yet",
+                0, mListView.getSelectedItemPosition());
+        
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        assertEquals("selection should have moved",
+                4, mListView.getSelectedItemPosition());
+        assertEquals("wrong view created when scrolling",
+                getActivity().getValueAtPosition(4), ((TextView) mListView.getSelectedView()).getText());
+        assertEquals(listBottom, mListView.getSelectedView().getBottom());
+    }
+
+    @MediumTest
+    public void testGoUpToOffScreenSelectable() {
+        final int listBottom = mListView.getHeight() - mListView.getListPaddingBottom();
+        final int listTop = mListView.getListPaddingTop();
+
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+
+        assertEquals(4, mListView.getSelectedItemPosition());
+        assertEquals(listBottom, mListView.getSelectedView().getBottom());
+
+        // now we have the reverse situation: the next selectable position upward is off screen
+        final View firstVisibleView = mListView.getChildAt(0);
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        assertEquals("should have panned top view just below vertical fading edge",
+                listTop + mListView.getVerticalFadingEdgeLength(), firstVisibleView.getTop());
+        assertEquals("selection should not have moved yet",
+                4, mListView.getSelectedItemPosition());
+
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        assertEquals("selection should have moved",
+                0, mListView.getSelectedItemPosition());
+        assertEquals(getActivity().getValueAtPosition(0),((TextView) mListView.getSelectedView()).getText());
+        assertEquals(listTop, mListView.getSelectedView().getTop());
+
+    }
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListWithOnItemSelectedActionTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListWithOnItemSelectedActionTest.java
new file mode 100644
index 0000000..0a8af45
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListWithOnItemSelectedActionTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview.arrowscroll;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.view.KeyEvent;
+import com.android.frameworktest.listview.ListWithOnItemSelectedAction;
+
+public class ListWithOnItemSelectedActionTest extends ActivityInstrumentationTestCase<ListWithOnItemSelectedAction> {
+    private ListView mListView;
+
+    public ListWithOnItemSelectedActionTest() {
+        super("com.android.frameworktest", ListWithOnItemSelectedAction.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mListView = getActivity().getListView();
+    }
+
+    private String getValueOfSelectedTextView() {
+        return ((TextView) mListView.getSelectedView()).getText().toString();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertEquals(0, mListView.getSelectedItemPosition());
+        assertEquals("header text field should be echoing contents of selected item",
+                getValueOfSelectedTextView(),
+                getActivity().getHeaderValue());
+    }
+
+    @MediumTest
+    public void testHeaderEchoesSelectionAfterMove() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+
+        assertEquals(1, mListView.getSelectedItemPosition());
+        assertEquals("header text field should be echoing contents of selected item",
+                getValueOfSelectedTextView(),
+                getActivity().getHeaderValue());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListWithScreenOfNoSelectablesTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListWithScreenOfNoSelectablesTest.java
new file mode 100644
index 0000000..0c0084e
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListWithScreenOfNoSelectablesTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.listview.arrowscroll;
+
+import com.android.frameworktest.listview.ListWithScreenOfNoSelectables;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.ListView;
+
+public class ListWithScreenOfNoSelectablesTest extends ActivityInstrumentationTestCase<ListWithScreenOfNoSelectables> {
+
+    private ListView mListView;
+
+    public ListWithScreenOfNoSelectablesTest() {
+        super("com.android.frameworktest", ListWithScreenOfNoSelectables.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mListView = getActivity().getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertTrue("expecting first position to be selectable",
+                mListView.getAdapter().isEnabled(0));
+        final int numItems = mListView.getCount();
+        for (int i = 1; i < numItems; i++) {
+            assertFalse("expecting item to be unselectable (index " + i +")",
+                    mListView.getAdapter().isEnabled(i));
+        }
+        assertTrue("expecting that not all views fit on screen",
+                mListView.getChildCount() < mListView.getCount());
+    }
+
+
+    @MediumTest
+    public void testGoFromSelectedViewExistsToNoSelectedViewExists() {
+
+        // go down untile first (and only selectable) item is off screen
+        View first = mListView.getChildAt(0);
+        while (first.getParent() != null) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+
+        // nothing should be selected
+        assertEquals("selected position", ListView.INVALID_POSITION, mListView.getSelectedItemPosition());
+        assertNull("selected view", mListView.getSelectedView());
+    }
+
+    @LargeTest
+    public void testPanDownAcrossUnselectableChildrenToBottom() {
+        final int lastPosition = mListView.getCount() - 1;
+        final int maxDowns = 20;
+        for(int count = 0; count < maxDowns && mListView.getLastVisiblePosition() <= lastPosition; count++) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+        assertEquals("last visible position not the last position in the list even "
+                + "after " + maxDowns + " downs", lastPosition, mListView.getLastVisiblePosition());
+    }
+
+    @MediumTest
+    public void testGoFromNoSelectionToSelectionExists() {
+        // go down untile first (and only selectable) item is off screen
+        View first = mListView.getChildAt(0);
+        while (first.getParent() != null) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+
+        // nothing should be selected
+        assertEquals("selected position", ListView.INVALID_POSITION, mListView.getSelectedItemPosition());
+        assertNull("selected view", mListView.getSelectedView());
+
+        // go up once to bring the selectable back on screen
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        assertEquals("first visible position", 0, mListView.getFirstVisiblePosition());
+        assertEquals("selected position", ListView.INVALID_POSITION, mListView.getSelectedItemPosition());
+
+
+        // up once more should give it selection
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        assertEquals("selected position", 0, mListView.getSelectedItemPosition());
+
+    }
+
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListWithSeparatorsTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListWithSeparatorsTest.java
new file mode 100644
index 0000000..fdeaa4a
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/arrowscroll/ListWithSeparatorsTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview.arrowscroll;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.ListView;
+import android.view.KeyEvent;
+import com.android.frameworktest.listview.ListWithSeparators;
+
+public class ListWithSeparatorsTest extends ActivityInstrumentationTestCase<ListWithSeparators> {
+    private ListWithSeparators mActivity;
+    private ListView mListView;
+
+    public ListWithSeparatorsTest() {
+        super("com.android.frameworktest", ListWithSeparators.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mListView = getActivity().getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mListView);
+        assertFalse(mListView.getAdapter().areAllItemsEnabled());
+        assertFalse(mListView.getAdapter().isEnabled(0));
+        assertFalse(mListView.getAdapter().isEnabled(2));
+        assertEquals(1, mListView.getSelectedItemPosition());
+    }
+
+    @MediumTest
+    public void testGoingUpDoesnNotHitUnselectableItem() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        assertEquals("selected position should remain the same",
+                1, mListView.getSelectedItemPosition());
+
+        assertEquals("seperator should be scrolled flush with top",
+                mListView.getListPaddingTop(), mListView.getChildAt(0).getTop());
+    }
+
+    @MediumTest
+    public void testGoingDownSkipsOverUnselectable() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        assertEquals("should have skipped to next selectable ",
+                3,
+                mListView.getSelectedItemPosition());
+    }
+        
+    @MediumTest
+    public void testGoingUpSkippingOverUnselectable() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        assertEquals(1, mListView.getSelectedItemPosition());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/focus/AdjacentListsWithAdjacentISVsInsideTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/focus/AdjacentListsWithAdjacentISVsInsideTest.java
new file mode 100644
index 0000000..2c0c2d8
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/focus/AdjacentListsWithAdjacentISVsInsideTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.listview.focus;
+
+import com.android.frameworktest.listview.AdjacentListsWithAdjacentISVsInside;
+import com.android.frameworktest.util.InternalSelectionView;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.widget.ListView;
+
+public class AdjacentListsWithAdjacentISVsInsideTest extends ActivityInstrumentationTestCase<AdjacentListsWithAdjacentISVsInside> {
+
+    private ListView mLeftListView;
+    private InternalSelectionView mLeftIsv;
+    private InternalSelectionView mLeftMiddleIsv;
+    private ListView mRightListView;
+    private InternalSelectionView mRightMiddleIsv;
+    private InternalSelectionView mRightIsv;
+
+    public AdjacentListsWithAdjacentISVsInsideTest() {
+        super("com.android.frameworktest", AdjacentListsWithAdjacentISVsInside.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        final AdjacentListsWithAdjacentISVsInside a = getActivity();
+        mLeftListView = a.getLeftListView();
+        mLeftIsv = a.getLeftIsv();
+        mLeftMiddleIsv = a.getLeftMiddleIsv();
+        mRightListView = a.getRightListView();
+        mRightMiddleIsv = a.getRightMiddleIsv();
+        mRightIsv = a.getRightIsv();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertTrue(mLeftListView.hasFocus());
+        assertTrue(mLeftIsv.isFocused());
+        assertEquals(0, mLeftIsv.getSelectedRow());
+    }
+
+    /**
+     * rockinist test name to date!
+     */
+    @MediumTest
+    public void testFocusedRectAndFocusHintWorkWithinListItemHorizontal() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        assertEquals(1, mLeftIsv.getSelectedRow());
+
+        sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
+        assertTrue(mLeftListView.hasFocus());
+        assertTrue(mLeftMiddleIsv.isFocused());
+        assertEquals("mLeftMiddleIsv.getSelectedRow()", 1, mLeftMiddleIsv.getSelectedRow());
+
+        sendKeys(KeyEvent.KEYCODE_DPAD_LEFT);
+        assertTrue(mLeftIsv.isFocused());
+        assertEquals("mLeftIsv.getSelectedRow()", 1, mLeftIsv.getSelectedRow());
+    }
+
+    @MediumTest
+    public void testFocusTransfersOutsideOfListWhenNoCandidateInsideHorizontal() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT);
+
+        assertTrue(mLeftListView.hasFocus());
+        assertTrue(mLeftMiddleIsv.isFocused());
+        assertEquals(2, mLeftMiddleIsv.getSelectedRow());
+
+        sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
+        assertTrue("mRightListView.hasFocus()", mRightListView.hasFocus());
+        assertTrue("mRightMiddleIsv.isFocused()", mRightMiddleIsv.isFocused());
+        assertEquals("mRightMiddleIsv.getSelectedRow()", 2, mRightMiddleIsv.getSelectedRow());  
+    }    
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/focus/ListButtonsDiagonalAcrossItemsTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/focus/ListButtonsDiagonalAcrossItemsTest.java
new file mode 100644
index 0000000..c54add3
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/focus/ListButtonsDiagonalAcrossItemsTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.listview.focus;
+
+import com.android.frameworktest.listview.ListButtonsDiagonalAcrossItems;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.FocusFinder;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ListView;
+
+/**
+ * Test that ListView will override default behavior of focus searching to
+ * make sure going right and left doesn't change selection
+ */
+public class ListButtonsDiagonalAcrossItemsTest extends ActivityInstrumentationTestCase<ListButtonsDiagonalAcrossItems> {
+
+    private Button mLeftButton;
+    private Button mCenterButton;
+    private Button mRightButton;
+    private ListView mListView;
+
+    public ListButtonsDiagonalAcrossItemsTest() {
+        super("com.android.frameworktest", ListButtonsDiagonalAcrossItems.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mLeftButton = getActivity().getLeftButton();
+        mCenterButton = getActivity().getCenterButton();
+        mRightButton = getActivity().getRightButton();
+
+        mListView = getActivity().getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        final ListView lv = mListView;
+        assertEquals("num children", 3, lv.getChildCount());
+
+        assertEquals("selected position", 0, lv.getSelectedItemPosition());
+        assertTrue("left button focused", mLeftButton.isFocused());
+
+        assertTrue("left left of center",
+                mLeftButton.getRight()
+                        < mCenterButton.getLeft());
+
+        assertTrue("center left of right",
+                mCenterButton.getRight()
+                        < mRightButton.getLeft());
+
+        assertEquals("focus search right from left button should be center button",
+            mCenterButton,
+            FocusFinder.getInstance().findNextFocus(mListView, mLeftButton, View.FOCUS_RIGHT));
+        assertEquals("focus search right from center button should be right button",
+            mRightButton,
+            FocusFinder.getInstance().findNextFocus(mListView, mCenterButton, View.FOCUS_RIGHT));
+        assertEquals("focus search left from centr button should be left button",
+            mLeftButton,
+            FocusFinder.getInstance().findNextFocus(mListView, mCenterButton, View.FOCUS_LEFT));
+    }
+
+    @MediumTest
+    public void testGoingRightDoesNotChangeSelection() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
+
+        assertEquals("selected position shouldn't have changed",
+                0,
+                mListView.getSelectedItemPosition());
+        assertTrue("left should still be focused", mLeftButton.isFocused());
+    }
+
+    @MediumTest
+    public void testGoingLeftDoesNotChangeSelection() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        assertEquals("list view postion", 1, mListView.getSelectedItemPosition());
+        assertTrue("mCenterButton.isFocused()", mCenterButton.isFocused());
+
+        sendKeys(KeyEvent.KEYCODE_DPAD_LEFT);
+        assertEquals("selected position shouldn't have changed",
+                1,
+                mListView.getSelectedItemPosition());
+        assertTrue("center should still be focused", mCenterButton.isFocused());
+    }
+    
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/focus/ListHorizontalFocusWithinItemWinsTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/focus/ListHorizontalFocusWithinItemWinsTest.java
new file mode 100644
index 0000000..35f9b06
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/focus/ListHorizontalFocusWithinItemWinsTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.listview.focus;
+
+import com.android.frameworktest.listview.ListHorizontalFocusWithinItemWins;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.FocusFinder;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ListView;
+
+public class ListHorizontalFocusWithinItemWinsTest extends ActivityInstrumentationTestCase<ListHorizontalFocusWithinItemWins> {
+
+    private ListView mListView;
+    private Button mTopLeftButton;
+    private Button mTopRightButton;
+    private Button mBottomMiddleButton;
+
+    public ListHorizontalFocusWithinItemWinsTest() {
+        super("com.android.frameworktest", ListHorizontalFocusWithinItemWins.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mListView = getActivity().getListView();
+        mTopLeftButton = getActivity().getTopLeftButton();
+        mTopRightButton = getActivity().getTopRightButton();
+        mBottomMiddleButton = getActivity().getBottomMiddleButton();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertEquals("list position", 0, mListView.getSelectedItemPosition());
+        assertTrue("mTopLeftButton.isFocused()", mTopLeftButton.isFocused());
+        assertEquals("global focus search to right from top left is bottom middle",
+                mBottomMiddleButton,
+                FocusFinder.getInstance().findNextFocus(mListView, mTopLeftButton, View.FOCUS_RIGHT));
+        assertEquals("global focus search to left from top right is bottom middle",
+                mBottomMiddleButton,
+                FocusFinder.getInstance().findNextFocus(mListView, mTopRightButton, View.FOCUS_LEFT));
+    }
+
+    @MediumTest
+    public void testOptionWithinItemTrumpsGlobal() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
+
+        assertEquals("list position", 0, mListView.getSelectedItemPosition());
+        assertTrue("mTopRightButton.isFocused()", mTopRightButton.isFocused());
+
+        sendKeys(KeyEvent.KEYCODE_DPAD_LEFT);
+        assertEquals("list position", 0, mListView.getSelectedItemPosition());
+        assertTrue("mTopLeftButton.isFocused()", mTopLeftButton.isFocused());
+    }
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/focus/ListWithEditTextHeaderTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/focus/ListWithEditTextHeaderTest.java
new file mode 100644
index 0000000..dea689f
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/focus/ListWithEditTextHeaderTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.listview.focus;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.FlakyTest;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.TouchUtils;
+import android.view.KeyEvent;
+import android.widget.AbsListView;
+import android.widget.ListView;
+import com.android.frameworktest.listview.ListWithEditTextHeader;
+
+public class ListWithEditTextHeaderTest extends ActivityInstrumentationTestCase<ListWithEditTextHeader> {
+    private ListView mListView;
+
+    public ListWithEditTextHeaderTest() {
+        super("com.android.frameworktest", ListWithEditTextHeader.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mListView = getActivity().getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertTrue("listview.getItemsCanFocus()", mListView.getItemsCanFocus());
+        assertFalse("out of touch-mode", mListView.isInTouchMode());
+        assertEquals("header view count", 1, mListView.getHeaderViewsCount());
+        assertTrue("header has focus", mListView.getChildAt(0).isFocused());
+    }
+
+    @FlakyTest(tolerance=2)
+    @LargeTest
+    public void testClickingHeaderKeepsFocus() {
+        TouchUtils.clickView(this, mListView.getChildAt(0));
+        assertTrue("header has focus", mListView.getChildAt(0).isFocused());
+        assertEquals("nothing selected", AbsListView.INVALID_POSITION, mListView.getSelectedItemPosition());
+    }
+
+    @LargeTest
+    public void testClickingHeaderWhenOtherItemHasFocusGivesHeaderFocus() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        assertEquals("selected position", 1, mListView.getSelectedItemPosition());
+        TouchUtils.clickView(this, mListView.getChildAt(0));
+        assertTrue("header has focus", mListView.getChildAt(0).isFocused());        
+        assertEquals("nothing selected", AbsListView.INVALID_POSITION, mListView.getSelectedItemPosition());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/touch/ListGetSelectedViewTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/touch/ListGetSelectedViewTest.java
new file mode 100644
index 0000000..3a75f93
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/touch/ListGetSelectedViewTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview.touch;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.TouchUtils;
+import android.widget.ListView;
+import android.view.View;
+
+import com.android.frameworktest.listview.ListGetSelectedView;
+
+/**
+ * This test is made to check that getSelectedView() will return
+ * null in touch mode.
+ */
+public class ListGetSelectedViewTest extends ActivityInstrumentationTestCase<ListGetSelectedView> {
+    private ListGetSelectedView mActivity;
+    private ListView mListView;
+
+    public ListGetSelectedViewTest() {
+        super("com.android.frameworktest", ListGetSelectedView.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mListView = getActivity().getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mListView);
+
+        assertEquals(0, mListView.getSelectedItemPosition());
+    }
+
+    @LargeTest
+    public void testGetSelectedView() {
+        View last = mListView.getChildAt(1);
+        TouchUtils.clickView(this, last);
+
+        assertNull(mListView.getSelectedItem());
+        assertNull(mListView.getSelectedView());
+        assertEquals(-1, mListView.getSelectedItemPosition());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/touch/ListOfTouchablesTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/touch/ListOfTouchablesTest.java
new file mode 100644
index 0000000..f8b384d
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/touch/ListOfTouchablesTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview.touch;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.widget.ListView;
+
+import com.android.frameworktest.listview.ListOfTouchables;
+import android.test.TouchUtils;
+
+/**
+ * Touch tests for a list where all of the items fit on the screen.
+ */
+public class ListOfTouchablesTest extends ActivityInstrumentationTestCase<ListOfTouchables> {
+    private ListOfTouchables mActivity;
+    private ListView mListView;
+
+    public ListOfTouchablesTest() {
+        super("com.android.frameworktest", ListOfTouchables.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mListView = getActivity().getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mListView);
+    }
+    
+    @LargeTest
+    public void testShortScroll() {
+        View firstChild = mListView.getChildAt(0);
+        View lastChild = mListView.getChildAt(mListView.getChildCount() - 1);
+        
+        int firstTop = firstChild.getTop();
+        
+        TouchUtils.dragViewBy(this, lastChild, Gravity.TOP | Gravity.LEFT,
+                0, -(ViewConfiguration.getTouchSlop() + 1 + 10));
+        
+        View newFirstChild = mListView.getChildAt(0);
+        
+        assertEquals("View scrolled too early", firstTop, newFirstChild.getTop() + 10);
+        assertEquals("Wrong view in first position", 0, newFirstChild.getId());
+    }
+    
+    @LargeTest
+    public void testLongScroll() {
+        View lastChild = mListView.getChildAt(mListView.getChildCount() - 1);
+        
+        int lastTop = lastChild.getTop();
+        
+        int distance = TouchUtils.dragViewToY(this, lastChild, 
+                Gravity.TOP | Gravity.LEFT, mListView.getTop());
+        
+        assertEquals("View scrolled to wrong position", 
+                lastTop - (distance - ViewConfiguration.getTouchSlop() - 1), lastChild.getTop());
+    } 
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/touch/ListSetSelectionTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/touch/ListSetSelectionTest.java
new file mode 100644
index 0000000..c3d7264
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/touch/ListSetSelectionTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview.touch;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.TouchUtils;
+import android.view.View;
+import android.widget.ListView;
+
+import com.android.frameworktest.listview.ListSimple;
+
+/**
+ * Tests setting the selection in touch mode
+ */
+public class ListSetSelectionTest extends ActivityInstrumentationTestCase<ListSimple> {
+    private ListSimple mActivity;
+    private ListView mListView;
+
+    public ListSetSelectionTest() {
+        super("com.android.frameworktest", ListSimple.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mListView = getActivity().getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mListView);
+    }
+    
+    @LargeTest
+    public void testSetSelection() {
+        TouchUtils.dragQuarterScreenDown(this);
+        TouchUtils.dragQuarterScreenUp(this);
+        
+        // Nothing should be selected
+        assertEquals("Selection still available after touch", -1, 
+                mListView.getSelectedItemPosition());
+        
+        final int targetPosition = mListView.getAdapter().getCount() / 2;
+        
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mListView.setSelection(targetPosition);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+        
+        boolean found = false;
+        int childCount = mListView.getChildCount();
+        for (int i=0; i<childCount; i++) {
+            View child = mListView.getChildAt(i);
+            if (child.getId() == targetPosition) {
+                found = true;
+                break;
+            }
+        }
+        assertTrue("Selected item not visible in list", found);
+    }
+ 
+    @LargeTest
+    public void testSetSelectionFromTop() {
+        TouchUtils.dragQuarterScreenDown(this);
+        TouchUtils.dragQuarterScreenUp(this);
+        
+        // Nothing should be selected
+        assertEquals("Selection still available after touch", -1, 
+                mListView.getSelectedItemPosition());
+        
+        final int targetPosition = mListView.getAdapter().getCount() / 2;
+        
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mListView.setSelectionFromTop(targetPosition, 100);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+        
+        View target = null;
+        boolean found = false;
+        int childCount = mListView.getChildCount();
+        for (int i=0; i<childCount; i++) {
+            View child = mListView.getChildAt(i);
+            if (child.getId() == targetPosition) {
+                target = child;
+                found = true;
+                break;
+            }
+        }
+        assertTrue("Selected item not visible in list", found);
+        
+        if (target != null) {
+            assertEquals("Selection not at correct location", 100 + mListView.getPaddingTop(), 
+                    target.getTop());
+        }
+    }
+
+    @LargeTest
+    public void testSetSelection0() {
+        TouchUtils.dragQuarterScreenDown(this);
+        TouchUtils.dragQuarterScreenDown(this);
+        TouchUtils.dragQuarterScreenDown(this);
+
+        // Nothing should be selected
+        assertEquals("Selection still available after touch", -1,
+                mListView.getSelectedItemPosition());
+
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mListView.setSelection(0);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+
+        boolean found = false;
+        int childCount = mListView.getChildCount();
+        for (int i=0; i<childCount; i++) {
+            View child = mListView.getChildAt(i);
+            if (child.getId() == 0 && i == 0) {
+                found = true;
+                break;
+            }
+        }
+        assertTrue("Selected item not visible in list", found);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/touch/ListTouchBottomGravityManyTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/touch/ListTouchBottomGravityManyTest.java
new file mode 100644
index 0000000..d271564
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/touch/ListTouchBottomGravityManyTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview.touch;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.TouchUtils;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.widget.ListView;
+
+import com.android.frameworktest.listview.ListBottomGravityMany;
+
+/**
+ * Touch tests for a list where all of the items do not fit on the screen, and the list 
+ * stacks from the bottom.
+ */
+public class ListTouchBottomGravityManyTest extends ActivityInstrumentationTestCase<ListBottomGravityMany> {
+    private ListBottomGravityMany mActivity;
+    private ListView mListView;
+
+    public ListTouchBottomGravityManyTest() {
+        super("com.android.frameworktest", ListBottomGravityMany.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mListView = getActivity().getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mListView);
+        
+        // Last item should be selected
+        assertEquals(mListView.getAdapter().getCount() - 1, mListView.getSelectedItemPosition());
+    }
+    
+    @LargeTest
+    public void testPullDown() {     
+        int originalCount = mListView.getChildCount();
+        
+        TouchUtils.scrollToTop(this, mListView);
+        
+        // Nothing should be selected
+        assertEquals("Selection still available after touch", -1, 
+                mListView.getSelectedItemPosition());
+        
+        View firstChild = mListView.getChildAt(0);
+        
+        assertEquals("Item zero not the first child in the list", 0, firstChild.getId());
+        
+        assertEquals("Item zero not at the top of the list", mListView.getListPaddingTop(),
+                firstChild.getTop());
+        
+        assertTrue(String.format("Too many children created: %d expected no more than %d", 
+                mListView.getChildCount(), originalCount + 1), 
+                mListView.getChildCount() <= originalCount + 1);
+    }
+    
+    @MediumTest
+    public void testPushUp() {
+        TouchUtils.scrollToBottom(this, mListView);
+
+        // Nothing should be selected
+        assertEquals("Selection still available after touch", -1, 
+                mListView.getSelectedItemPosition());
+
+        View lastChild = mListView.getChildAt(mListView.getChildCount() - 1);
+
+        assertEquals("List is not scrolled to the bottom", mListView.getAdapter().getCount() - 1,
+                lastChild.getId());
+
+        assertEquals("Last item is not touching the bottom edge", 
+                mListView.getHeight() - mListView.getListPaddingBottom(), lastChild.getBottom());
+    }
+    
+    @MediumTest
+    public void testNoScroll() {
+        View firstChild = mListView.getChildAt(0);
+        View lastChild = mListView.getChildAt(mListView.getChildCount() - 1);
+        
+        int lastTop = lastChild.getTop();
+        
+        TouchUtils.dragViewBy(this, firstChild, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL,
+                0, ViewConfiguration.getTouchSlop());
+        
+        View newLastChild = mListView.getChildAt(mListView.getChildCount() - 1);
+        
+        assertEquals("View scrolled too early", lastTop, newLastChild.getTop());
+        assertEquals("Wrong view in last position", mListView.getAdapter().getCount() - 1, 
+                newLastChild.getId());
+    }
+    
+    @LargeTest
+    public void testShortScroll() {
+        View firstChild = mListView.getChildAt(0);
+        if (firstChild.getTop() < this.mListView.getListPaddingTop()) {
+            firstChild = mListView.getChildAt(1);
+        }
+            
+        View lastChild = mListView.getChildAt(mListView.getChildCount() - 1);
+        
+        int lastTop = lastChild.getTop();
+        
+        TouchUtils.dragViewBy(this, firstChild, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL,
+                0, ViewConfiguration.getTouchSlop() + 1 + 10);
+        
+        View newLastChild = mListView.getChildAt(mListView.getChildCount() - 1);
+        
+        assertEquals("View scrolled to wrong position", lastTop, newLastChild.getTop() - 10);
+        assertEquals("Wrong view in last position", mListView.getAdapter().getCount() - 1,
+                newLastChild.getId());
+    }
+    
+    @LargeTest
+    public void testLongScroll() {
+        View firstChild = mListView.getChildAt(0);
+        if (firstChild.getTop() < mListView.getListPaddingTop()) {
+            firstChild = mListView.getChildAt(1);
+        }
+
+        int firstTop = firstChild.getTop();
+
+        int distance = TouchUtils.dragViewBy(this, firstChild, 
+                Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 
+                (int)(mActivity.getWindowManager().getDefaultDisplay().getHeight() * 0.75f));
+        
+        assertEquals("View scrolled to wrong position", firstTop
+                + (distance - ViewConfiguration.getTouchSlop() - 1), firstChild.getTop());
+    } 
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/touch/ListTouchBottomGravityTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/touch/ListTouchBottomGravityTest.java
new file mode 100644
index 0000000..78d39fb
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/touch/ListTouchBottomGravityTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview.touch;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.TouchUtils;
+import android.view.View;
+import android.widget.ListView;
+
+import com.android.frameworktest.listview.ListBottomGravity;
+
+/**
+ * Touch tests for a list where all of the items fit on the screen, and the list 
+ * stacks from the bottom.
+ */
+public class ListTouchBottomGravityTest extends ActivityInstrumentationTestCase<ListBottomGravity> {
+    private ListBottomGravity mActivity;
+    private ListView mListView;
+
+    public ListTouchBottomGravityTest() {
+        super("com.android.frameworktest", ListBottomGravity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mListView = getActivity().getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mListView);
+        
+        // First item should be selected
+        assertEquals(mListView.getAdapter().getCount() - 1, mListView.getSelectedItemPosition());
+    }
+    
+    @MediumTest
+    public void testPullDown() {
+        View firstChild = mListView.getChildAt(0);
+        
+        TouchUtils.dragViewToBottom(this, firstChild);
+        
+        View lastChild = mListView.getChildAt(mListView.getChildCount() - 1);
+        
+        // Nothing should be selected
+        assertEquals("Selection still available after touch", -1, 
+                mListView.getSelectedItemPosition());
+        
+        assertEquals("List is not scrolled to the bottom", mListView.getAdapter().getCount() - 1,
+                lastChild.getId());
+
+        assertEquals("Last item is not touching the bottom edge", 
+                mListView.getHeight() - mListView.getListPaddingBottom(), lastChild.getBottom());
+    }
+    
+    @MediumTest
+    public void testPushUp() {
+        View lastChild = mListView.getChildAt(mListView.getChildCount() - 1);
+        
+        TouchUtils.dragViewToTop(this, lastChild);
+
+        lastChild = mListView.getChildAt(mListView.getChildCount() - 1);
+        
+        // Nothing should be selected
+        assertEquals("Selection still available after touch", -1, 
+                mListView.getSelectedItemPosition());
+        
+        assertEquals("List is not scrolled to the bottom", mListView.getAdapter().getCount() - 1,
+                lastChild.getId());
+
+        assertEquals("Last item is not touching the bottom edge",  
+                mListView.getHeight() - mListView.getListPaddingBottom(), lastChild.getBottom());
+    }
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/touch/ListTouchManyTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/touch/ListTouchManyTest.java
new file mode 100644
index 0000000..ef085f84
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/touch/ListTouchManyTest.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview.touch;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.TouchUtils;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.widget.ListView;
+
+import com.android.frameworktest.listview.ListTopGravityMany;
+
+/**
+ * Touch tests for a list where all of the items do not fit on the screen.
+ */
+public class ListTouchManyTest extends ActivityInstrumentationTestCase<ListTopGravityMany> {
+    private ListTopGravityMany mActivity;
+    private ListView mListView;
+
+    public ListTouchManyTest() {
+        super("com.android.frameworktest", ListTopGravityMany.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mListView = getActivity().getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mListView);
+        
+        // First item should be selected
+        assertEquals(0, mListView.getSelectedItemPosition());
+    }
+    
+    @MediumTest
+    public void testPullDown() {
+        TouchUtils.scrollToTop(this, mListView);
+        
+        // Nothing should be selected
+        assertEquals("Selection still available after touch", -1, 
+                mListView.getSelectedItemPosition());
+        
+        View firstChild = mListView.getChildAt(0);
+        
+        assertEquals("Item zero not the first child in the list", 0, firstChild.getId());
+        
+        assertEquals("Item zero not at the top of the list", mListView.getListPaddingTop(),
+                firstChild.getTop());
+    }
+    
+    @LargeTest
+    public void testPushUp() {
+        int originalCount = mListView.getChildCount();
+        
+        TouchUtils.scrollToBottom(this, mListView);
+
+        // Nothing should be selected
+        assertEquals("Selection still available after touch", -1, 
+                mListView.getSelectedItemPosition());
+
+        View lastChild = mListView.getChildAt(mListView.getChildCount() - 1);
+
+        assertEquals("List is not scrolled to the bottom", mListView.getAdapter().getCount() - 1,
+                lastChild.getId());
+
+        assertEquals("Last item is not touching the bottom edge",  
+                mListView.getHeight() - mListView.getListPaddingBottom(), lastChild.getBottom());
+        
+        assertTrue(String.format("Too many children created: %d expected no more than %d", 
+                mListView.getChildCount(), originalCount + 1), 
+                mListView.getChildCount() <= originalCount + 1);
+    }
+
+    @LargeTest
+    public void testPress() {
+        int i;
+        int count = mListView.getChildCount();
+        mActivity.setClickedPosition(-1);
+        mActivity.setLongClickedPosition(-1);
+        
+        for (i = 0; i < count; i++) {
+            View child = mListView.getChildAt(i);
+            if ((child.getTop() >= mListView.getListPaddingTop())
+                    && (child.getBottom() <= 
+                        mListView.getHeight() - mListView.getListPaddingBottom())) {
+                TouchUtils.clickView(this, child);
+                
+                assertEquals("Incorrect view position reported being clicked", i, 
+                        mActivity.getClickedPosition());
+                assertEquals("View falsely reported being long clicked", -1, 
+                        mActivity.getLongClickedPosition());
+                try {
+                    Thread.sleep((long)(ViewConfiguration.getLongPressTimeout() * 1.25f));
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+    
+    @LargeTest
+    public void testLongPress() {
+        int i;
+        int count = mListView.getChildCount();
+        mActivity.enableLongPress();
+        mActivity.setClickedPosition(-1);
+        mActivity.setLongClickedPosition(-1);
+        
+        for (i = 0; i < count; i++) {
+            View child = mListView.getChildAt(i);
+            if ((child.getTop() >= mListView.getListPaddingTop())
+                    && (child.getBottom() <= 
+                        mListView.getHeight() - mListView.getListPaddingBottom())) {
+                TouchUtils.longClickView(this, child);
+                assertEquals("Incorrect view position reported being long clicked", i, 
+                        mActivity.getLongClickedPosition());
+                assertEquals("View falsely reported being clicked", -1, 
+                        mActivity.getClickedPosition());
+            }
+        }
+    }
+    
+    @MediumTest
+    public void testNoScroll() {
+        View firstChild = mListView.getChildAt(0);
+        View lastChild = mListView.getChildAt(mListView.getChildCount() - 1);
+        
+        int firstTop = firstChild.getTop();
+        
+        TouchUtils.dragViewBy(this, lastChild, Gravity.TOP | Gravity.LEFT, 
+                0, -(ViewConfiguration.getTouchSlop()));
+        
+        View newFirstChild = mListView.getChildAt(0);
+        
+        assertEquals("View scrolled too early", firstTop, newFirstChild.getTop());
+        assertEquals("Wrong view in first position", 0, newFirstChild.getId());
+    }
+    
+    @LargeTest
+    public void testShortScroll() {
+        View firstChild = mListView.getChildAt(0);
+        View lastChild = mListView.getChildAt(mListView.getChildCount() - 1);
+        
+        int firstTop = firstChild.getTop();
+        
+        TouchUtils.dragViewBy(this, lastChild, Gravity.TOP | Gravity.LEFT,
+                0, -(ViewConfiguration.getTouchSlop() + 1 + 10));
+        
+        View newFirstChild = mListView.getChildAt(0);
+        
+        assertEquals("View scrolled too early", firstTop, newFirstChild.getTop() + 10);
+        assertEquals("Wrong view in first position", 0, newFirstChild.getId());
+    }
+    
+    @LargeTest
+    public void testLongScroll() {
+        View lastChild = mListView.getChildAt(mListView.getChildCount() - 1);
+        
+        int lastTop = lastChild.getTop();
+        
+        int distance = TouchUtils.dragViewToY(this, lastChild, 
+                Gravity.TOP | Gravity.LEFT, mListView.getTop());
+        
+        assertEquals("View scrolled to wrong position", 
+                lastTop - (distance - ViewConfiguration.getTouchSlop() - 1), lastChild.getTop());
+    } 
+
+    
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/touch/ListTouchTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/touch/ListTouchTest.java
new file mode 100644
index 0000000..4e5c423
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/listview/touch/ListTouchTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.listview.touch;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.TouchUtils;
+import android.view.View;
+import android.widget.ListView;
+
+import com.android.frameworktest.listview.ListTopGravity;
+
+/**
+ * Touch tests for a list where all of the items fit on the screen.
+ */
+public class ListTouchTest extends ActivityInstrumentationTestCase<ListTopGravity> {
+    private ListTopGravity mActivity;
+    private ListView mListView;
+
+    public ListTouchTest() {
+        super("com.android.frameworktest", ListTopGravity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mListView = getActivity().getListView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertNotNull(mListView);
+        
+        // First item should be selected
+        assertEquals(0, mListView.getSelectedItemPosition());
+    }
+    
+    @MediumTest
+    public void testPullDown() {
+        View firstChild = mListView.getChildAt(0);
+        
+        TouchUtils.dragViewToBottom(this, firstChild);
+        
+        // Nothing should be selected
+        assertEquals("Selection still available after touch", -1, 
+                mListView.getSelectedItemPosition());
+        
+        firstChild = mListView.getChildAt(0);
+        
+        assertEquals("Item zero not the first child in the list", 0, firstChild.getId());
+        
+        assertEquals("Item zero not at the top of the list", mListView.getListPaddingTop(),
+                firstChild.getTop());
+    }
+    
+    @MediumTest
+    public void testPushUp() {
+        View lastChild = mListView.getChildAt(mListView.getChildCount() - 1);
+        
+        TouchUtils.dragViewToTop(this, lastChild);
+
+        // Nothing should be selected
+        assertEquals("Selection still available after touch", -1, 
+                mListView.getSelectedItemPosition());
+
+        View firstChild = mListView.getChildAt(0);
+
+        assertEquals("Item zero not the first child in the list", 0, firstChild.getId());
+        
+        assertEquals("Item zero not at the top of the list", mListView.getListPaddingTop(),
+                firstChild.getTop());
+    }
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/menus/MenuLayoutLandscapeTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/menus/MenuLayoutLandscapeTest.java
new file mode 100644
index 0000000..38cb6a1
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/menus/MenuLayoutLandscapeTest.java
@@ -0,0 +1,230 @@
+/**
+ * Copyright (C) 2008 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.frameworktest.menus;
+
+import com.android.frameworktest.util.KeyUtils;
+import com.android.internal.view.menu.IconMenuView;
+import com.android.internal.view.menu.MenuBuilder;
+
+import android.content.pm.ActivityInfo;
+import android.test.ActivityInstrumentationTestCase;
+
+public class MenuLayoutLandscapeTest extends ActivityInstrumentationTestCase<MenuLayoutLandscape> {
+    private static final String LONG_TITLE = "Really really really really really really really really really really long title";
+    private static final String SHORT_TITLE = "Item";
+
+    private MenuLayout mActivity;
+    
+    public MenuLayoutLandscapeTest() {
+        super("com.android.frameworktest", MenuLayoutLandscape.class);
+    }
+    
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+    }
+
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+    }
+
+    private void toggleMenu() {
+        getInstrumentation().waitForIdleSync();
+        KeyUtils.tapMenuKey(this);
+        getInstrumentation().waitForIdleSync();
+    }
+
+    /**
+     * Asserts the layout of the menu.
+     * 
+     * @param expectedLayout The number of parameters is the number of rows, and
+     *            each parameter is how many items on that row (the first
+     *            parameter is the top-most row).
+     */
+    private void assertLayout(Integer... expectedLayout) {
+        toggleMenu();
+        
+        IconMenuView iconMenuView = ((IconMenuView) mActivity.getMenuView(MenuBuilder.TYPE_ICON));
+        int[] layout = iconMenuView.getLayout();
+        int layoutNumRows = iconMenuView.getLayoutNumRows(); 
+        
+        int expectedRows = expectedLayout.length;
+        assertEquals("Row mismatch", expectedRows, layoutNumRows);
+        
+        for (int row = 0; row < expectedRows; row++) {
+            assertEquals("Col mismatch on row " + row, expectedLayout[row].intValue(),
+                    layout[row]);
+        }
+    }
+    
+    public void test1ShortItem() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(1)
+                .setItemTitle(0, SHORT_TITLE));
+        assertLayout(1);
+    }
+
+    public void test1LongItem() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(1)
+                .setItemTitle(0, LONG_TITLE));
+        assertLayout(1);
+    }
+
+    public void test2LongItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(2)
+                .setItemTitle(0, LONG_TITLE)
+                .setItemTitle(1, LONG_TITLE));
+        assertLayout(1, 1);
+    }
+
+    public void test2ShortItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(2)
+                .setItemTitle(0, SHORT_TITLE)
+                .setItemTitle(1, SHORT_TITLE));
+        assertLayout(2);
+    }
+
+    public void test3ShortItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(3)
+                .setItemTitle(0, SHORT_TITLE)
+                .setItemTitle(1, SHORT_TITLE)
+                .setItemTitle(2, SHORT_TITLE));
+        assertLayout(3);
+    }
+    
+    public void test3VarietyItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(3)
+                .setItemTitle(0, SHORT_TITLE)
+                .setItemTitle(1, LONG_TITLE)
+                .setItemTitle(2, SHORT_TITLE));
+        assertLayout(1, 2);
+    }
+
+    public void test3VarietyItems2() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(3)
+                .setItemTitle(0, LONG_TITLE)
+                .setItemTitle(1, SHORT_TITLE)
+                .setItemTitle(2, SHORT_TITLE));
+        assertLayout(1, 2);
+    }
+
+    public void test4LongItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(4)
+                .setItemTitle(0, LONG_TITLE)
+                .setItemTitle(1, LONG_TITLE)
+                .setItemTitle(2, LONG_TITLE)
+                .setItemTitle(3, LONG_TITLE));
+        assertLayout(2, 2);
+    }
+
+    public void test4ShortItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(4)
+                .setItemTitle(0, SHORT_TITLE)
+                .setItemTitle(1, SHORT_TITLE)
+                .setItemTitle(2, SHORT_TITLE)
+                .setItemTitle(3, SHORT_TITLE));
+        assertLayout(4);
+    }
+    
+    public void test4VarietyItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(4)
+                .setItemTitle(0, LONG_TITLE)
+                .setItemTitle(1, SHORT_TITLE)
+                .setItemTitle(2, SHORT_TITLE)
+                .setItemTitle(3, SHORT_TITLE));
+        assertLayout(2, 2);
+    }
+
+    public void test5ShortItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(5)
+                .setItemTitle(0, SHORT_TITLE)
+                .setItemTitle(1, SHORT_TITLE)
+                .setItemTitle(2, SHORT_TITLE)
+                .setItemTitle(3, SHORT_TITLE)
+                .setItemTitle(4, SHORT_TITLE));
+        assertLayout(5);
+    }
+
+    public void test5LongItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(5)
+                .setItemTitle(0, LONG_TITLE)
+                .setItemTitle(1, LONG_TITLE)
+                .setItemTitle(2, LONG_TITLE)
+                .setItemTitle(3, LONG_TITLE)
+                .setItemTitle(4, LONG_TITLE));
+        assertLayout(2, 3);
+    }
+
+    public void test5VarietyItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(5)
+                .setItemTitle(0, LONG_TITLE)
+                .setItemTitle(1, SHORT_TITLE)
+                .setItemTitle(2, LONG_TITLE)
+                .setItemTitle(3, SHORT_TITLE)
+                .setItemTitle(4, LONG_TITLE));
+        assertLayout(2, 3);
+    }
+
+    public void test6LongItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(6)
+                .setItemTitle(0, LONG_TITLE)
+                .setItemTitle(1, LONG_TITLE)
+                .setItemTitle(2, LONG_TITLE)
+                .setItemTitle(3, LONG_TITLE)
+                .setItemTitle(4, LONG_TITLE)
+                .setItemTitle(5, LONG_TITLE));
+        assertLayout(3, 3);
+    }
+
+    public void test6ShortItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(6)
+                .setItemTitle(0, SHORT_TITLE)
+                .setItemTitle(1, SHORT_TITLE)
+                .setItemTitle(2, SHORT_TITLE)
+                .setItemTitle(3, SHORT_TITLE)
+                .setItemTitle(4, SHORT_TITLE)
+                .setItemTitle(5, SHORT_TITLE));
+        assertLayout(6);
+    }
+
+    public void test6VarietyItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(6)
+                .setItemTitle(0, SHORT_TITLE)
+                .setItemTitle(1, LONG_TITLE)
+                .setItemTitle(2, SHORT_TITLE)
+                .setItemTitle(3, LONG_TITLE)
+                .setItemTitle(4, SHORT_TITLE)
+                .setItemTitle(5, SHORT_TITLE));
+        assertLayout(3, 3);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/menus/MenuLayoutPortraitTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/menus/MenuLayoutPortraitTest.java
new file mode 100644
index 0000000..a04ec62
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/menus/MenuLayoutPortraitTest.java
@@ -0,0 +1,231 @@
+/**
+ * Copyright (C) 2008 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.frameworktest.menus;
+
+import com.android.frameworktest.util.KeyUtils;
+import com.android.internal.view.menu.IconMenuView;
+import com.android.internal.view.menu.MenuBuilder;
+
+import android.content.pm.ActivityInfo;
+import android.test.ActivityInstrumentationTestCase;
+
+public class MenuLayoutPortraitTest extends ActivityInstrumentationTestCase<MenuLayoutPortrait> {
+    private static final String LONG_TITLE = "Really really really really really really really really really really long title";
+    private static final String SHORT_TITLE = "Item";
+
+    private MenuLayout mActivity;
+    
+    public MenuLayoutPortraitTest() {
+        super("com.android.frameworktest", MenuLayoutPortrait.class);
+    }
+    
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+    }
+
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+    }
+
+    private void toggleMenu() {
+        getInstrumentation().waitForIdleSync();
+        KeyUtils.tapMenuKey(this);
+        getInstrumentation().waitForIdleSync();
+    }
+
+    /**
+     * Asserts the layout of the menu.
+     * 
+     * @param expectedLayout The number of parameters is the number of rows, and
+     *            each parameter is how many items on that row.
+     */
+    private void assertLayout(Integer... expectedLayout) {
+        toggleMenu();
+        
+        IconMenuView iconMenuView = ((IconMenuView) mActivity.getMenuView(MenuBuilder.TYPE_ICON));
+        int[] layout = iconMenuView.getLayout();
+        int layoutNumRows = iconMenuView.getLayoutNumRows(); 
+        
+        int expectedRows = expectedLayout.length;
+        assertEquals("Row mismatch", expectedRows, layoutNumRows);
+        
+        for (int row = 0; row < expectedRows; row++) {
+            assertEquals("Col mismatch on row " + row, expectedLayout[row].intValue(),
+                    layout[row]);
+        }
+    }
+    
+    public void test1ShortItem() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(1)
+                .setItemTitle(0, SHORT_TITLE));
+        assertLayout(1);
+    }
+
+    public void test1LongItem() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(1)
+                .setItemTitle(0, LONG_TITLE));
+        assertLayout(1);
+    }
+
+    public void test2LongItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(2)
+                .setItemTitle(0, LONG_TITLE)
+                .setItemTitle(1, LONG_TITLE));
+        assertLayout(1, 1);
+    }
+
+    public void test2ShortItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(2)
+                .setItemTitle(0, SHORT_TITLE)
+                .setItemTitle(1, SHORT_TITLE));
+        assertLayout(2);
+    }
+
+    public void test3ShortItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(3)
+                .setItemTitle(0, SHORT_TITLE)
+                .setItemTitle(1, SHORT_TITLE)
+                .setItemTitle(2, SHORT_TITLE));
+        assertLayout(3);
+    }
+    
+    public void test3VarietyItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(3)
+                .setItemTitle(0, SHORT_TITLE)
+                .setItemTitle(1, LONG_TITLE)
+                .setItemTitle(2, SHORT_TITLE));
+        // We maintain the order added, so there must be 3 rows
+        assertLayout(1, 1, 1);
+    }
+
+    public void test3VarietyItems2() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(3)
+                .setItemTitle(0, LONG_TITLE)
+                .setItemTitle(1, SHORT_TITLE)
+                .setItemTitle(2, SHORT_TITLE));
+        // The long can fit in first row, and two shorts in second
+        assertLayout(1, 2);
+    }
+
+    public void test4LongItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(4)
+                .setItemTitle(0, LONG_TITLE)
+                .setItemTitle(1, LONG_TITLE)
+                .setItemTitle(2, LONG_TITLE)
+                .setItemTitle(3, LONG_TITLE));
+        assertLayout(1, 1, 2);
+    }
+
+    public void test4ShortItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(4)
+                .setItemTitle(0, SHORT_TITLE)
+                .setItemTitle(1, SHORT_TITLE)
+                .setItemTitle(2, SHORT_TITLE)
+                .setItemTitle(3, SHORT_TITLE));
+        assertLayout(2, 2);
+    }
+    
+    public void test4VarietyItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(4)
+                .setItemTitle(0, LONG_TITLE)
+                .setItemTitle(1, SHORT_TITLE)
+                .setItemTitle(2, SHORT_TITLE)
+                .setItemTitle(3, SHORT_TITLE));
+        assertLayout(1, 1, 2);
+    }
+
+    public void test5ShortItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(5)
+                .setItemTitle(0, SHORT_TITLE)
+                .setItemTitle(1, SHORT_TITLE)
+                .setItemTitle(2, SHORT_TITLE)
+                .setItemTitle(3, SHORT_TITLE)
+                .setItemTitle(4, SHORT_TITLE));
+        assertLayout(2, 3);
+    }
+
+    public void test5LongItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(5)
+                .setItemTitle(0, LONG_TITLE)
+                .setItemTitle(1, LONG_TITLE)
+                .setItemTitle(2, LONG_TITLE)
+                .setItemTitle(3, LONG_TITLE)
+                .setItemTitle(4, LONG_TITLE));
+        assertLayout(1, 2, 2);
+    }
+
+    public void test5VarietyItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(5)
+                .setItemTitle(0, LONG_TITLE)
+                .setItemTitle(1, SHORT_TITLE)
+                .setItemTitle(2, LONG_TITLE)
+                .setItemTitle(3, SHORT_TITLE)
+                .setItemTitle(4, LONG_TITLE));
+        assertLayout(1, 2, 2);
+    }
+
+    public void test6LongItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(6)
+                .setItemTitle(0, LONG_TITLE)
+                .setItemTitle(1, LONG_TITLE)
+                .setItemTitle(2, LONG_TITLE)
+                .setItemTitle(3, LONG_TITLE)
+                .setItemTitle(4, LONG_TITLE)
+                .setItemTitle(5, LONG_TITLE));
+        assertLayout(2, 2, 2);
+    }
+
+    public void test6ShortItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(6)
+                .setItemTitle(0, SHORT_TITLE)
+                .setItemTitle(1, SHORT_TITLE)
+                .setItemTitle(2, SHORT_TITLE)
+                .setItemTitle(3, SHORT_TITLE)
+                .setItemTitle(4, SHORT_TITLE)
+                .setItemTitle(5, SHORT_TITLE));
+        assertLayout(3, 3);
+    }
+
+    public void test6VarietyItems() {
+        mActivity.setParams(new MenuScenario.Params()
+                .setNumItems(6)
+                .setItemTitle(0, SHORT_TITLE)
+                .setItemTitle(1, LONG_TITLE)
+                .setItemTitle(2, SHORT_TITLE)
+                .setItemTitle(3, LONG_TITLE)
+                .setItemTitle(4, SHORT_TITLE)
+                .setItemTitle(5, SHORT_TITLE));
+        assertLayout(2, 2, 2);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/menus/MenuWith1ItemTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/menus/MenuWith1ItemTest.java
new file mode 100644
index 0000000..286533c
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/menus/MenuWith1ItemTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.menus;
+
+import com.android.frameworktest.menus.MenuWith1Item;
+import com.android.frameworktest.util.KeyUtils;
+import com.android.internal.view.menu.MenuBuilder;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.TouchUtils;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.view.KeyEvent;
+import android.view.View;
+
+public class MenuWith1ItemTest extends ActivityInstrumentationTestCase<MenuWith1Item> {
+    private MenuWith1Item mActivity;
+    
+    public MenuWith1ItemTest() {
+        super("com.android.frameworktest", MenuWith1Item.class);
+    }
+    
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mActivity);
+        assertFalse(mActivity.getButton().isInTouchMode());
+    }
+
+    @MediumTest
+    public void testItemClick() {
+
+        // Open menu, click on an item
+        KeyUtils.tapMenuKey(this);
+        getInstrumentation().waitForIdleSync();
+        assertFalse("Item seems to have been clicked before we clicked on it", mActivity
+                .wasItemClicked(0));
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        assertTrue("Item doesn't seem to have registered our click", mActivity.wasItemClicked(0));
+    }
+
+    @LargeTest
+    public void testTouchModeTransfersRemovesFocus() throws Exception {
+        // open menu, move around to give it focus
+        sendKeys(KeyEvent.KEYCODE_MENU, KeyEvent.KEYCODE_DPAD_LEFT);
+        final View menuItem = mActivity.getItemView(MenuBuilder.TYPE_ICON, 0);
+        assertTrue("menuItem.isFocused()", menuItem.isFocused());
+
+        // close the menu
+        sendKeys(KeyEvent.KEYCODE_MENU);
+        Thread.sleep(500);
+
+        // touch the screen
+        TouchUtils.clickView(this, mActivity.getButton());
+        assertTrue("should be in touch mode after touching button",
+                mActivity.getButton().isInTouchMode());
+
+        // open the menu, menu item shouldn't be focused, because we are not
+        // in touch mode
+        sendKeys(KeyEvent.KEYCODE_MENU);
+        assertTrue("menuItem.isInTouchMode()", menuItem.isInTouchMode());
+        assertFalse("menuItem.isFocused()", menuItem.isFocused());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/scroll/ButtonAboveTallInternalSelectionViewTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/scroll/ButtonAboveTallInternalSelectionViewTest.java
new file mode 100644
index 0000000..e4dd2b8
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/scroll/ButtonAboveTallInternalSelectionViewTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.scroll;
+
+import com.android.frameworktest.scroll.ButtonAboveTallInternalSelectionView;
+import com.android.frameworktest.util.InternalSelectionView;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+
+public class ButtonAboveTallInternalSelectionViewTest extends
+        ActivityInstrumentationTestCase<ButtonAboveTallInternalSelectionView> {
+
+    public ButtonAboveTallInternalSelectionViewTest() {
+        super("com.android.frameworktest", ButtonAboveTallInternalSelectionView.class);
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertTrue("expecting the top button to have focus",
+                getActivity().getButtonAbove().isFocused());
+        assertEquals("scrollview scroll y",
+                0,
+                getActivity().getScrollView().getScrollY());
+        assertTrue("internal selection view should be taller than screen",
+                getActivity().getIsv().getHeight() > getActivity().getScrollView().getHeight());
+
+        assertTrue("top of ISV should be on screen",
+                getActivity().getIsv().getTop() >
+                getActivity().getScrollView().getScrollY());
+
+    }
+
+    @MediumTest
+    public void testMovingFocusDownToItemTallerThanScreenStillOnScreen() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        getInstrumentation().waitForIdleSync();
+
+        final InternalSelectionView isv = getActivity().getIsv();
+        assertTrue("internal selection view should have taken focus",
+                isv.isFocused());
+        assertEquals("internal selection view selected row",
+                0, isv.getSelectedRow());
+        assertTrue("top of ISV should still be on screen",
+                getActivity().getIsv().getTop() >
+                getActivity().getScrollView().getScrollY());
+    }
+
+    
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/scroll/RequestRectangleVisibleTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/scroll/RequestRectangleVisibleTest.java
new file mode 100644
index 0000000..3eec37b
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/scroll/RequestRectangleVisibleTest.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.scroll;
+
+import com.android.frameworktest.scroll.RequestRectangleVisible;
+import com.android.frameworktest.R;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.ViewAsserts;
+import android.widget.Button;
+import android.widget.ScrollView;
+import android.widget.TextView;
+import android.view.View;
+import android.view.KeyEvent;
+
+/**
+ * {@link RequestRectangleVisible} is set up to exercise the cases of moving a
+ * rectangle that is either off screen or not entirely on the screen onto the screen.
+ */
+public class RequestRectangleVisibleTest extends ActivityInstrumentationTestCase<RequestRectangleVisible> {
+
+    private ScrollView mScrollView;
+
+    private Button mClickToScrollFromAbove;
+    private Button mClickToScrollToUpperBlob;
+    private TextView mTopBlob;
+
+    private View mChildToScrollTo;
+
+    private TextView mBottomBlob;
+    private Button mClickToScrollToBlobLowerBlob;
+    private Button mClickToScrollFromBelow;
+
+    public RequestRectangleVisibleTest() {
+        super("com.android.frameworktest", RequestRectangleVisible.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        RequestRectangleVisible a = getActivity();
+
+        mScrollView = (ScrollView) a.findViewById(R.id.scrollView);
+        mClickToScrollFromAbove = (Button) a.findViewById(R.id.scrollToRectFromTop);
+        mClickToScrollToUpperBlob = (Button) a.findViewById(R.id.scrollToRectFromTop2);
+        mTopBlob = (TextView) a.findViewById(R.id.topBlob);
+        mChildToScrollTo = a.findViewById(R.id.childToMakeVisible);
+        mBottomBlob = (TextView) a.findViewById(R.id.bottomBlob);
+        mClickToScrollToBlobLowerBlob = (Button) a.findViewById(R.id.scrollToRectFromBottom2);
+        mClickToScrollFromBelow = (Button) a.findViewById(R.id.scrollToRectFromBottom);
+
+        
+    }
+
+    
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mScrollView);
+        assertNotNull(mClickToScrollFromAbove);
+        assertNotNull(mClickToScrollToUpperBlob);
+        assertNotNull(mTopBlob);
+        assertNotNull(mChildToScrollTo);
+        assertNotNull(mBottomBlob);
+        assertNotNull(mClickToScrollToBlobLowerBlob);
+        assertNotNull(mClickToScrollFromBelow);
+
+        assertTrue("top blob needs to be taller than the screen for many of the "
+                + "tests below to work.",
+                mTopBlob.getHeight() > mScrollView.getHeight());
+
+        assertTrue("bottom blob needs to be taller than the screen for many of the "
+                + "tests below to work.",
+                mBottomBlob.getHeight() > mScrollView.getHeight());
+
+        assertTrue("top blob needs to be lower than the fading edge region",
+                mTopBlob.getTop() > mScrollView.getVerticalFadingEdgeLength());
+    }
+
+    @MediumTest
+    public void testScrollToOffScreenRectangleFromTop() {
+        // view is off screen
+        assertTrue(mClickToScrollFromAbove.hasFocus());
+        ViewAsserts.assertOffScreenBelow(mScrollView, mChildToScrollTo);
+
+        // click
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        getInstrumentation().waitForIdleSync();  // wait for scrolling to finish
+
+        // should be on screen, positioned at the bottom (with room for
+        // fading edge)
+        ViewAsserts.assertOnScreen(mScrollView, mChildToScrollTo);
+        ViewAsserts.assertHasScreenCoordinates(
+                mScrollView, mChildToScrollTo,
+                0,
+                mScrollView.getHeight()
+                        - mChildToScrollTo.getHeight()
+                        - mScrollView.getVerticalFadingEdgeLength());
+    }
+
+    @MediumTest
+    public void testScrollToPartiallyOffScreenRectFromTop() {
+        pressDownUntilViewInFocus(mClickToScrollToUpperBlob, 4);
+
+        // make sure the blob is indeed partially on screen below
+        assertOnBottomEdgeOfScreen(mScrollView, mTopBlob);
+
+        // click
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        getInstrumentation().waitForIdleSync();  // wait for scrolling to finish
+
+        // blob should have moved so top of it is at top of screen (with
+        // room for the vertical fading edge
+        ViewAsserts.assertHasScreenCoordinates(
+                mScrollView, mTopBlob, 0, mScrollView.getVerticalFadingEdgeLength());
+    }
+
+    @LargeTest
+    public void testScrollToOffScreenRectangleFromBottom() {
+        // go to bottom button
+        pressDownUntilViewInFocus(mClickToScrollFromBelow, 10);
+
+        // view is off screen above
+        assertTrue(mClickToScrollFromBelow.hasFocus());
+        ViewAsserts.assertOffScreenAbove(mScrollView, mChildToScrollTo);
+
+        // click
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        getInstrumentation().waitForIdleSync();  // wait for scrolling to finish
+
+        // on screen, positioned at top (with room for fading edge)
+        ViewAsserts.assertOnScreen(mScrollView, mChildToScrollTo);
+        ViewAsserts.assertHasScreenCoordinates(
+                mScrollView, mChildToScrollTo, 0, mScrollView.getVerticalFadingEdgeLength());
+    }
+
+
+    @LargeTest
+    public void testScrollToPartiallyOffScreenRectFromBottom() {
+        pressDownUntilViewInFocus(mClickToScrollToBlobLowerBlob, 10);
+
+        // make sure the blob is indeed partially on screen above
+        assertOnTopEdgeOfScreen(mScrollView, mBottomBlob);
+
+        // click
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        getInstrumentation().waitForIdleSync();  // wait for scrolling to finish
+
+        // blob should have moved so bottom of it is at bottom of screen
+        // with room for vertical fading edge
+        ViewAsserts.assertHasScreenCoordinates(
+                mScrollView, mBottomBlob,
+                0,
+                mScrollView.getHeight() - mBottomBlob.getHeight()
+                    - mScrollView.getVerticalFadingEdgeLength());
+    }
+
+
+    /**
+     * Press the down key until a particular view is in focus
+     * @param view The view to get in focus.
+     * @param maxKeyPress The maximum times to press down before failing.
+     */
+    private void pressDownUntilViewInFocus(View view, int maxKeyPress) {
+        int count = 0;
+        while(!view.hasFocus()) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+            getInstrumentation().waitForIdleSync();
+
+            // just in case...
+            if (++count > maxKeyPress) {
+                fail("couldn't move down to bottom button within "
+                        + maxKeyPress + " key presses.");
+            }
+        }
+    }
+
+    /**
+     * Assert that view overlaps the bottom edge of the screen
+     * @param origin The root view of the screen.
+     * @param view The view
+     */
+    static public void assertOnBottomEdgeOfScreen(View origin, View view) {
+        int[] xy = new int[2];
+        view.getLocationOnScreen(xy);
+
+        int[] xyRoot = new int[2];
+        origin.getLocationOnScreen(xyRoot);
+
+        int bottom = xy[1] + view.getHeight();
+        int bottomOfRoot = xyRoot[1] + origin.getHeight();
+
+        assertTrue(bottom > bottomOfRoot);
+
+        assertTrue(xy[1] < bottomOfRoot);
+        assertTrue(bottom > bottomOfRoot);
+    }
+
+    /**
+     * Assert that view overlaps the bottom edge of the screen
+     * @param origin The root view of the screen.
+     * @param view The view
+     */
+    static public void assertOnTopEdgeOfScreen(View origin, View view) {
+        int[] xy = new int[2];
+        view.getLocationOnScreen(xy);
+
+        int[] xyRoot = new int[2];
+        origin.getLocationOnScreen(xyRoot);
+
+        int bottom = xy[1] + view.getHeight();
+        int bottomOfRoot = xyRoot[1] + origin.getHeight();
+
+        assertTrue(bottom < bottomOfRoot);
+        assertTrue(bottom > xyRoot[1]);
+
+        assertTrue(xy[1] < xyRoot[1]);
+    }
+
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/scroll/RequestRectangleVisibleWithInternalScrollTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/scroll/RequestRectangleVisibleWithInternalScrollTest.java
new file mode 100644
index 0000000..5d71466
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/scroll/RequestRectangleVisibleWithInternalScrollTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.scroll;
+
+import com.android.frameworktest.R;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.ViewAsserts;
+import android.test.suitebuilder.annotation.Suppress;
+import android.view.KeyEvent;
+import android.widget.Button;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+/**
+ * This is suppressed because {@link TextView#scrollBy} isn't working.
+ */
+@Suppress
+public class RequestRectangleVisibleWithInternalScrollTest
+        extends ActivityInstrumentationTestCase<RequestRectangleVisibleWithInternalScroll> {
+
+    private TextView mTextBlob;
+    private Button mScrollToBlob;
+
+    private ScrollView mScrollView;
+
+
+    public RequestRectangleVisibleWithInternalScrollTest() {
+        super("com.android.frameworktest",
+                RequestRectangleVisibleWithInternalScroll.class);
+    }
+
+    
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mTextBlob = getActivity().getTextBlob();
+        mScrollToBlob = getActivity().getScrollToBlob();
+
+        mScrollView = (ScrollView) getActivity().findViewById(R.id.scrollView);
+    }
+
+    public void testPreconditions() {
+        assertNotNull(mTextBlob);
+        assertNotNull(mScrollToBlob);
+        assertEquals(getActivity().getScrollYofBlob(), mTextBlob.getScrollY());
+    }
+
+    public void testMoveToChildWithScrollYBelow() {
+        assertTrue(mScrollToBlob.hasFocus());
+
+        ViewAsserts.assertOffScreenBelow(mScrollView, mTextBlob);
+
+        // click
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        getInstrumentation().waitForIdleSync();  // wait for scrolling to finish
+
+        // should be on screen, positioned at the bottom (with enough room for
+        // fading edge)
+        ViewAsserts.assertOnScreen(mScrollView, mTextBlob);
+        ViewAsserts.assertHasScreenCoordinates(
+                mScrollView, mTextBlob,
+                0,
+                mScrollView.getHeight()
+                        - mTextBlob.getHeight()
+                        - mScrollView.getVerticalFadingEdgeLength());
+
+    }
+
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/scroll/ScrollViewButtonsAndLabelsTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/scroll/ScrollViewButtonsAndLabelsTest.java
new file mode 100644
index 0000000..b23b567
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/scroll/ScrollViewButtonsAndLabelsTest.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.scroll;
+
+import com.android.frameworktest.scroll.ScrollViewButtonsAndLabels;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+import android.view.KeyEvent;
+
+
+public class ScrollViewButtonsAndLabelsTest
+        extends ActivityInstrumentationTestCase<ScrollViewButtonsAndLabels> {
+
+    private ScrollView mScrollView;
+    private LinearLayout mLinearLayout;
+    private int mScreenBottom;
+    private int mScreenTop;
+
+    public ScrollViewButtonsAndLabelsTest() {
+        super("com.android.frameworktest",
+              ScrollViewButtonsAndLabels.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mScrollView = getActivity().getScrollView();
+        mLinearLayout = getActivity().getLinearLayout();
+
+        int origin[] = {0, 0};
+        mScrollView.getLocationOnScreen(origin);
+        mScreenTop = origin[1];
+        mScreenBottom = origin[1] + mScrollView.getHeight();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertTrue("vertical fading edge width needs to be non-zero for this "
+                + "test to be worth anything",
+                mScrollView.getVerticalFadingEdgeLength() > 0);
+    }
+
+    // moving down to something off screen should move the element
+    // onto the screen just above the vertical fading edge
+    @LargeTest
+    public void testArrowScrollDownOffScreenVerticalFadingEdge() {
+
+        int offScreenIndex = findFirstButtonOffScreenTop2Bottom();
+        Button firstButtonOffScreen = getActivity().getButton(offScreenIndex);
+
+        for (int i = 0; i < offScreenIndex; i++) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+        getInstrumentation().waitForIdleSync();
+        assertTrue(firstButtonOffScreen.hasFocus());
+
+        assertTrue("the button we've moved to off screen must not be the last "
+                + "button in the scroll view for this test to work (since we "
+                + "are expecting the fading edge to be there).",
+                offScreenIndex < getActivity().getNumButtons());
+
+        // now we are at the first button off screen
+        int buttonLoc[] = {0, 0};
+        firstButtonOffScreen.getLocationOnScreen(buttonLoc);
+        int buttonBottom = buttonLoc[1] + firstButtonOffScreen.getHeight();
+
+        int verticalFadingEdgeLength = mScrollView
+                .getVerticalFadingEdgeLength();
+        assertEquals("bottom of button should be verticalFadingEdgeLength "
+                + "above the bottom of the screen",
+                buttonBottom, mScreenBottom - verticalFadingEdgeLength);
+    }
+
+    // there should be no offset for vertical fading edge
+    // if the item is the last one on screen
+    @LargeTest
+    public void testArrowScrollDownToBottomElementOnScreen() {
+
+        int numGroups = getActivity().getNumButtons();
+        Button lastButton = getActivity().getButton(numGroups - 1);
+
+        assertEquals("button needs to be at the very bottom of the layout for "
+                + "this test to work",
+                mLinearLayout.getHeight(), lastButton.getBottom());
+
+        // move down to last button
+        for (int i = 0; i < numGroups; i++) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+        getInstrumentation().waitForIdleSync();
+        assertTrue("last button should have focus", lastButton.hasFocus());
+
+        int buttonLoc[] = {0, 0};
+        lastButton.getLocationOnScreen(buttonLoc);
+        int buttonBottom = buttonLoc[1] + lastButton.getHeight();
+        assertEquals("button should be at very bottom of screen",
+                mScreenBottom, buttonBottom);
+    }
+
+    @LargeTest
+    public void testArrowScrollUpOffScreenVerticalFadingEdge() {
+        // get to bottom button
+        int numGroups = goToBottomButton();
+
+        // go up to first off screen button
+        int offScreenIndex = findFirstButtonOffScreenBottom2Top();
+        Button offScreenButton = getActivity().getButton(offScreenIndex);
+        int clicksToOffScreenIndex = numGroups - offScreenIndex - 1;
+        for (int i = 0; i < clicksToOffScreenIndex; i++) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        }
+        getInstrumentation().waitForIdleSync();
+        assertTrue("we want to be at offScreenButton", offScreenButton.hasFocus());
+
+        // top should take into account fading edge
+        int buttonLoc[] = {0, 0};
+        offScreenButton.getLocationOnScreen(buttonLoc);
+        assertEquals("top should take into account fading edge",
+            mScreenTop + mScrollView.getVerticalFadingEdgeLength(), buttonLoc[1]);
+    }
+
+
+    @LargeTest
+    public void testArrowScrollUpToTopElementOnScreen() {
+        // get to bottom button
+        int numButtons = goToBottomButton();
+
+        // go back to the top
+        for (int i = 0; i < numButtons; i++) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        }
+        getInstrumentation().waitForIdleSync();
+
+        Button topButton = getActivity().getButton(0);
+        assertTrue("should be back at top button", topButton.hasFocus());
+
+
+        int buttonLoc[] = {0, 0};
+        topButton.getLocationOnScreen(buttonLoc);
+        assertEquals("top of top button should be at top of screen; no need to take"
+                + " into account vertical fading edge.",
+                mScreenTop, buttonLoc[1]);
+    }
+
+    private int goToBottomButton() {
+        int numButtons = getActivity().getNumButtons();
+        Button lastButton = getActivity().getButton(numButtons - 1);
+
+        for (int i = 0; i < numButtons; i++) {
+          sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+        getInstrumentation().waitForIdleSync();
+        assertTrue("we want to be at the last button", lastButton.hasFocus());
+        return numButtons;
+    }
+
+    // search from top to bottom for the first button off screen
+    private int findFirstButtonOffScreenTop2Bottom() {
+        int origin[] = {0, 0};
+        mScrollView.getLocationOnScreen(origin);
+        int screenHeight = mScrollView.getHeight();
+
+        for (int i = 0; i < getActivity().getNumButtons(); i++) {
+
+            int buttonLoc[] = {0, 0};
+            Button button = getActivity().getButton(i);
+            button.getLocationOnScreen(buttonLoc);
+
+            if (buttonLoc[1] - origin[1] > screenHeight) {
+                return i;
+            }
+        }
+        fail("couldn't find first button off screen");
+        return -1; // this won't execute, but the compiler needs it
+    }
+
+    private int findFirstButtonOffScreenBottom2Top() {
+        int origin[] = {0, 0};
+        mScrollView.getLocationOnScreen(origin);
+
+        for (int i = getActivity().getNumButtons() - 1; i >= 0; i--) {
+
+            int buttonLoc[] = {0, 0};
+            Button button = getActivity().getButton(i);
+            button.getLocationOnScreen(buttonLoc);
+
+            if (buttonLoc[1] < 0) {
+                return i;
+            }
+        }
+        fail("couldn't find first button off screen");
+        return -1; // this won't execute, but the compiler needs it
+    }
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/scroll/arrowscroll/ButtonsWithTallTextViewInBetweenTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/scroll/arrowscroll/ButtonsWithTallTextViewInBetweenTest.java
new file mode 100644
index 0000000..6b78560
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/scroll/arrowscroll/ButtonsWithTallTextViewInBetweenTest.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.scroll.arrowscroll;
+
+import com.android.frameworktest.scroll.ButtonsWithTallTextViewInBetween;
+
+import android.graphics.Rect;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+public class ButtonsWithTallTextViewInBetweenTest
+        extends ActivityInstrumentationTestCase<ButtonsWithTallTextViewInBetween> {
+
+    private ScrollView mScrollView;
+    private Button mTopButton;
+    private TextView mMiddleFiller;
+    private TextView mBottomButton;
+
+    public ButtonsWithTallTextViewInBetweenTest() {
+        super("com.android.frameworktest", ButtonsWithTallTextViewInBetween.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mScrollView = getActivity().getScrollView();
+        mTopButton = getActivity().getTopButton();
+        mMiddleFiller = getActivity().getMiddleFiller();
+        mBottomButton = getActivity().getBottomButton();
+    }
+
+    private Rect mTempRect = new Rect();
+
+    private int getTopWithinScrollView(View descendant) {
+        descendant.getDrawingRect(mTempRect);
+        mScrollView.offsetDescendantRectToMyCoords(descendant, mTempRect);
+        return mTempRect.top;
+    }
+
+    private int getBottomWithinScrollView(View descendant) {
+        descendant.getDrawingRect(mTempRect);
+        mScrollView.offsetDescendantRectToMyCoords(descendant, mTempRect);
+        return mTempRect.bottom;
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertTrue("top button should be shorter than max scroll amount",
+                mTopButton.getHeight() <
+                mScrollView.getMaxScrollAmount());
+        assertTrue("bottom button should be further than max scroll amount off screen",
+                getTopWithinScrollView(mBottomButton)- mScrollView.getBottom() > mScrollView.getMaxScrollAmount());
+    }
+
+    @MediumTest
+    public void testPanTopButtonOffScreenLosesFocus() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+
+        assertEquals("scroll view should be scrolled by the max amount for one "
+                + "arrow navigation",
+                mScrollView.getMaxScrollAmount(),
+                mScrollView.getScrollY());
+
+        assertTrue("top button should be off screen",
+                getBottomWithinScrollView(mTopButton) < mScrollView.getScrollY());
+
+        assertFalse("top button should have lost focus",
+                mTopButton.isFocused());
+
+        assertTrue("scroll view should be focused", mScrollView.isFocused());
+    }
+
+    @MediumTest
+    public void testScrollDownToBottomButton() throws Exception {
+        final int screenBottom = mScrollView.getScrollY() + mScrollView.getHeight();
+        final int numDownsToButtonButton =
+                ((getBottomWithinScrollView(mBottomButton) - screenBottom)) / mScrollView.getMaxScrollAmount() + 1;
+
+        for (int i = 0; i < numDownsToButtonButton; i++) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+
+        assertTrue("bottombutton.isFocused", mBottomButton.isFocused());
+
+        assertEquals("should be fully scrolled to bottom",
+                getActivity().getLinearLayout().getHeight() - mScrollView.getHeight(),
+                mScrollView.getScrollY());
+    }
+
+    @MediumTest
+    public void testPanBottomButtonOffScreenLosesFocus() throws Exception {
+        mBottomButton.post(new Runnable() {
+            public void run() {
+                mBottomButton.requestFocus();
+            }
+        });
+
+        getInstrumentation().waitForIdleSync();
+
+        assertTrue("bottombutton.isFocused", mBottomButton.isFocused());
+        final int maxScroll = getActivity().getLinearLayout().getHeight()
+                - mScrollView.getHeight();
+        assertEquals("should be fully scrolled to bottom",
+                maxScroll,
+                mScrollView.getScrollY());
+
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+
+        assertEquals("scroll view should have scrolled by the max amount for one "
+                + "arrow navigation",
+                maxScroll - mScrollView.getMaxScrollAmount(),
+                mScrollView.getScrollY());
+
+        assertTrue("bottom button should be off screen",
+                getTopWithinScrollView(mBottomButton) > mScrollView.getScrollY() + mScrollView.getHeight());
+
+        assertFalse("bottom button should have lost focus",
+                mBottomButton.isFocused());
+
+        assertTrue("scroll view should be focused", mScrollView.isFocused());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/scroll/arrowscroll/ShortButtonsTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/scroll/arrowscroll/ShortButtonsTest.java
new file mode 100644
index 0000000..689eb19
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/scroll/arrowscroll/ShortButtonsTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.scroll.arrowscroll;
+
+import com.android.frameworktest.scroll.ShortButtons;
+
+import android.graphics.Rect;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.widget.Button;
+import android.widget.ScrollView;
+
+public class ShortButtonsTest extends ActivityInstrumentationTestCase<ShortButtons> {
+
+    private ScrollView mScrollView;
+
+    public ShortButtonsTest() {
+        super("com.android.frameworktest", ShortButtons.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mScrollView = getActivity().getScrollView();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertTrue("buttons should be shorter than screen",
+                getActivity().getButtonAt(0).getHeight()
+                        < mScrollView.getHeight());
+
+        assertTrue("should be enough buttons to have some scrolled off screen",
+                getActivity().getLinearLayout().getHeight()
+                        > getActivity().getScrollView().getHeight());
+    }
+
+    @LargeTest
+    public void testScrollDownToBottomThroughButtons() throws Exception {
+        final int numButtons = getActivity().getNumButtons();
+
+        for (int i = 0; i < numButtons; i++) {
+            String prefix = "after " + i + " downs expected button " + i;
+            final Button button = getActivity().getButtonAt(i);
+            assertTrue(prefix + "  to have focus", button.isFocused());
+            assertTrue(prefix + " to be on screen", isButtonOnScreen(button));
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+
+        assertEquals("should be fully scrolled to bottom",
+                getActivity().getLinearLayout().getHeight() - mScrollView.getHeight(),
+                mScrollView.getScrollY());        
+    }
+
+    @LargeTest
+    public void testScrollFromBottomToTopThroughButtons() throws Exception {
+        final int numButtons = getActivity().getNumButtons();
+
+        final Button lastButton = getActivity().getButtonAt(numButtons - 1);
+
+        lastButton.post(new Runnable() {
+            public void run() {
+                lastButton.requestFocus();
+            }
+        });
+
+        getInstrumentation().waitForIdleSync();
+
+        assertTrue("lastButton.isFocused()", lastButton.isFocused());
+
+        for (int i = numButtons - 1; i >= 0; i--) {
+            String prefix = "after " + i + " ups expected button " + i;
+            final Button button = getActivity().getButtonAt(i);
+            assertTrue(prefix + "  to have focus", button.isFocused());
+            assertTrue(prefix + " to be on screen", isButtonOnScreen(button));
+            sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        }
+
+        assertEquals("should be fully scrolled to top",
+                0,
+                mScrollView.getScrollY());        
+    }
+
+    private Rect mTempRect = new Rect();
+    protected boolean isButtonOnScreen(Button b) {
+        b.getDrawingRect(mTempRect);
+        mScrollView.offsetDescendantRectToMyCoords(b, mTempRect);
+        return mTempRect.bottom >= mScrollView.getScrollY()
+                && mTempRect.top <= (mScrollView.getScrollY() + mScrollView.getHeight());
+    }
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/scroll/arrowscroll/TallTextAboveButtonTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/scroll/arrowscroll/TallTextAboveButtonTest.java
new file mode 100644
index 0000000..573045d
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/scroll/arrowscroll/TallTextAboveButtonTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.scroll.arrowscroll;
+
+import com.android.frameworktest.scroll.TallTextAboveButton;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+public class TallTextAboveButtonTest extends ActivityInstrumentationTestCase<TallTextAboveButton> {
+    private ScrollView mScrollView;
+    private TextView mTopText;
+    private TextView mBottomButton;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mScrollView = getActivity().getScrollView();
+        mTopText = getActivity().getContentChildAt(0);
+        mBottomButton = getActivity().getContentChildAt(1);
+    }
+
+    public TallTextAboveButtonTest() {
+        super("com.android.frameworktest", TallTextAboveButton.class);
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertTrue("top text should be larger than screen",
+                mTopText.getHeight() > mScrollView.getHeight());
+        assertTrue("scroll view should have focus (because nothing else focusable "
+                + "is on screen), but " + getActivity().getScrollView().findFocus() + " does instead",
+                getActivity().getScrollView().isFocused());
+    }
+
+    @MediumTest
+    public void testGainFocusAsScrolledOntoScreen() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+
+        assertTrue("button should have scrolled onto screen",
+                mBottomButton.getBottom() >= mScrollView.getBottom());
+        assertTrue("button should have gained focus as it was scrolled completely "
+                + "into view", mBottomButton.isFocused());
+
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        assertTrue("scroll view should have focus, but " + getActivity().getScrollView().findFocus() + " does instead",
+                getActivity().getScrollView().isFocused());
+    }
+
+    @MediumTest
+    public void testScrollingButtonOffScreenLosesFocus() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        assertTrue("button should have focus", mBottomButton.isFocused());
+        sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+        assertTrue("scroll view should have focus, but " + getActivity().getScrollView().findFocus() + " does instead",
+                getActivity().getScrollView().isFocused());
+    }
+    
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/settings/RingtonePickerActivityTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/settings/RingtonePickerActivityTest.java
new file mode 100644
index 0000000..42888ff
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/settings/RingtonePickerActivityTest.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.settings;
+
+import com.android.frameworktest.settings.RingtonePickerActivityLauncher;
+
+import android.app.Instrumentation;
+import android.database.Cursor;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.provider.MediaStore;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.Suppress;
+import android.view.KeyEvent;
+
+/**
+ * Tests the RingtonePickerActivity.
+ * <p>
+ * There is a launcher for launching the RingtonePickerActivity (RPA) since the RPA needs
+ * to be a subactivity.  We don't have a reference to the actual RPA.
+ * <p>
+ * This relies heavily on keypresses getting to the right widget.  It depends on:
+ * <li> Less than NUM_RINGTONES_AND_SOME ringtones on the system
+ * <li> Pressing arrow-down a ton will eventually end up on the 'Cancel' button
+ * <li> From the 'Cancel' button, pressing arrow-left will end up on 'OK' button
+ */
+@Suppress
+public class RingtonePickerActivityTest extends ActivityInstrumentationTestCase<RingtonePickerActivityLauncher> {
+
+    private static final int NUM_RINGTONES_AND_SOME = 20;
+    private RingtonePickerActivityLauncher mActivity;
+    private Instrumentation mInstrumentation;
+    
+    public RingtonePickerActivityTest() {
+        super("com.android.frameworktest", RingtonePickerActivityLauncher.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        
+        mActivity = getActivity();
+        mInstrumentation = getInstrumentation();
+        assertNotNull(mActivity);
+        assertFalse(mActivity.resultReceived);
+        assertNotNull(mInstrumentation);
+    }
+    
+    public void testDefault() {
+        mActivity.launchRingtonePickerActivity(true, null, RingtoneManager.TYPE_ALL);
+        mInstrumentation.waitForIdleSync();
+        
+        // Go to top
+        goTo(true);
+        // Select default ringtone 
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        // Go to bottom/cancel button
+        goTo(false);
+        // Select OK button
+        sendKeys(KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_CENTER);
+        
+        mInstrumentation.waitForIdleSync();
+        
+        assertTrue(mActivity.resultReceived);
+        assertNotNull(mActivity.result);
+        assertTrue(RingtoneManager.isDefault(mActivity.pickedUri));
+    }
+    
+    public void testFirst() {
+        mActivity.launchRingtonePickerActivity(true, null, RingtoneManager.TYPE_ALL);
+        mInstrumentation.waitForIdleSync();
+        
+        // Go to top
+        goTo(true);
+        // Select first (non-default) ringtone 
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
+        // Go to bottom/cancel button
+        goTo(false);
+        // Select OK button
+        sendKeys(KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_CENTER);
+        
+        mInstrumentation.waitForIdleSync();
+        
+        assertTrue(mActivity.resultReceived);
+        assertNotNull(mActivity.result);
+        assertNotNull(mActivity.pickedUri);
+        assertFalse(RingtoneManager.isDefault(mActivity.pickedUri));
+    }
+
+    public void testExisting() {
+        // We need to get an existing ringtone first, so launch it, pick first,
+        // and keep that URI
+        testFirst();
+        Uri firstUri = mActivity.pickedUri;
+        
+        mActivity.launchRingtonePickerActivity(true, firstUri, RingtoneManager.TYPE_ALL);
+        mInstrumentation.waitForIdleSync();
+
+        //// Hit cancel:
+        
+        // Go to bottom
+        goTo(false);
+        // Select Cancel button
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        
+        mInstrumentation.waitForIdleSync();
+        
+        assertTrue(mActivity.resultReceived);
+        assertEquals(mActivity.pickedUri, firstUri);
+    }
+    
+    public void testExistingButDifferent() {
+        // We need to get an existing ringtone first, so launch it, pick first,
+        // and keep that URI
+        testFirst();
+        Uri firstUri = mActivity.pickedUri;
+        
+        mActivity.launchRingtonePickerActivity(true, firstUri, RingtoneManager.TYPE_ALL);
+        mInstrumentation.waitForIdleSync();
+
+        //// Pick second:
+        
+        // Go to top
+        goTo(true);
+        // Select second (non-default) ringtone 
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_DOWN,
+                KeyEvent.KEYCODE_DPAD_CENTER);
+        // Go to bottom/cancel button
+        goTo(false);
+        // Select OK button
+        sendKeys(KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_CENTER);
+        
+        mInstrumentation.waitForIdleSync();
+        
+        assertTrue(mActivity.resultReceived);
+        assertNotNull(mActivity.result);
+        assertTrue(!firstUri.equals(mActivity.pickedUri));
+    }
+    
+    public void testCancel() {
+        mActivity.launchRingtonePickerActivity(true, null, RingtoneManager.TYPE_ALL);
+        mInstrumentation.waitForIdleSync();
+        
+        // Go to bottom
+        goTo(false);
+        // Select Cancel button
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        
+        mInstrumentation.waitForIdleSync();
+        
+        assertTrue(mActivity.resultReceived);
+        assertNull(mActivity.result);
+    }
+
+    public void testNoDefault() {
+        mActivity.launchRingtonePickerActivity(false, null, RingtoneManager.TYPE_ALL);
+        mInstrumentation.waitForIdleSync();
+        
+        // Go to top
+        goTo(true);
+        // Select first (non-default) ringtone 
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        // Go to bottom/cancel button
+        goTo(false);
+        // Select OK button
+        sendKeys(KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_CENTER);
+        
+        mInstrumentation.waitForIdleSync();
+        
+        assertTrue(mActivity.resultReceived);
+        assertNotNull(mActivity.result);
+        assertNotNull(mActivity.pickedUri);
+        assertFalse(RingtoneManager.isDefault(mActivity.pickedUri));
+    }
+    
+    public void testNotifications() {
+        mActivity.launchRingtonePickerActivity(false, null, RingtoneManager.TYPE_NOTIFICATION);
+        mInstrumentation.waitForIdleSync();
+        
+        // Move to top of list
+        goTo(true);
+        // Select first ringtone in list
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        // Move all the way down (will focus 'Cancel')
+        goTo(false);
+        // Move left and click (will click 'Ok')
+        sendKeys(KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_CENTER);
+
+        // Wait until main thread is idle
+        mInstrumentation.waitForIdleSync();
+
+        assertTrue(mActivity.resultReceived);
+        assertNotNull(mActivity.result);
+        assertNotNull(mActivity.pickedUri);
+        
+        // Get the path of the picked ringtone
+        Uri uri = mActivity.pickedUri;
+        Cursor c = mActivity.getContentResolver().query(uri, new String[] { "_data" },
+                null, null, null);
+        assertTrue("Query for selected ringtone URI does not have a result", c.moveToFirst());
+        String path = c.getString(0);
+        // Quick check to see if the ringtone is a notification
+        assertTrue("The path of the selected ringtone did not contain \"notification\"",
+                path.contains("notifications"));
+    }
+    
+    private void goTo(boolean top) {
+        // Get to the buttons at the bottom (top == false), or the top (top == true)
+        for (int i = 0; i < NUM_RINGTONES_AND_SOME; i++) {
+            sendKeys(top ? KeyEvent.KEYCODE_DPAD_UP : KeyEvent.KEYCODE_DPAD_DOWN);
+        }
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/text/HtmlTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/text/HtmlTest.java
new file mode 100644
index 0000000..9b309c4
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/text/HtmlTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.text;
+
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.text.Html;
+import android.text.Spanned;
+import android.text.style.StyleSpan;
+import android.graphics.Typeface;
+
+public class HtmlTest extends InstrumentationTestCase {
+
+    @MediumTest
+    public void testSingleTagOnWhileString() {
+        Spanned spanned = Html.fromHtml("<b>hello</b>");
+        Object[] spans = spanned.getSpans(-1, 100, Object.class);
+        assertEquals(1, spans.length);
+        Object span = spans[0];
+        assertEquals(0, spanned.getSpanStart(span));
+        assertEquals(5, spanned.getSpanEnd(span));
+    }
+
+    @MediumTest
+    public void testEmptyFontTag() {
+        Spanned spanned = Html.fromHtml("Hello <font color=\"#ff00ff00\"></font>");
+        Object[] spans = spanned.getSpans(0, 100, Object.class);
+        // TODO: figure out what the spans should be after the crashes are fixed and assert them.
+    }
+
+    /** Tests that the parser can handle mal-formed HTML. */
+    @MediumTest
+    public void testBadHtml() {
+        Spanned spanned = Html.fromHtml("Hello <b>b<i>bi</b>i</i>");
+        Object[] spans = spanned.getSpans(0, 100, Object.class);
+        assertEquals(Typeface.ITALIC, ((StyleSpan) spans[0]).getStyle());
+        assertEquals(7, spanned.getSpanStart(spans[0]));
+        assertEquals(9, spanned.getSpanEnd(spans[0]));
+        assertEquals(Typeface.BOLD, ((StyleSpan) spans[1]).getStyle());
+        assertEquals(6, spanned.getSpanStart(spans[1]));
+        assertEquals(9, spanned.getSpanEnd(spans[1]));
+        assertEquals(Typeface.ITALIC, ((StyleSpan) spans[2]).getStyle());
+        assertEquals(9, spanned.getSpanStart(spans[2]));
+        assertEquals(10, spanned.getSpanEnd(spans[2]));
+    }
+
+    @MediumTest
+    public void testSymbols() {
+        String spanned = Html.fromHtml("&copy; &gt; &lt").toString();
+        assertEquals("\u00a9 > <", spanned);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/text/SpannableStringBuilderTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/text/SpannableStringBuilderTest.java
new file mode 100644
index 0000000..a807977
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/text/SpannableStringBuilderTest.java
@@ -0,0 +1,11 @@
+package com.android.frameworktest.text;
+
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
+
+public class SpannableStringBuilderTest extends SpannableTest {
+
+    protected Spannable newSpannableWithText(String text) {
+        return new SpannableStringBuilder(text);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/text/SpannableStringTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/text/SpannableStringTest.java
new file mode 100644
index 0000000..311df23
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/text/SpannableStringTest.java
@@ -0,0 +1,11 @@
+package com.android.frameworktest.text;
+
+import android.text.Spannable;
+import android.text.SpannableString;
+
+public class SpannableStringTest extends SpannableTest {
+
+    protected Spannable newSpannableWithText(String text) {
+        return new SpannableString(text);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/text/SpannableTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/text/SpannableTest.java
new file mode 100644
index 0000000..a5f6836
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/text/SpannableTest.java
@@ -0,0 +1,34 @@
+package com.android.frameworktest.text;
+
+import android.test.InstrumentationTestCase;
+import android.test.MoreAsserts;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.text.Spannable;
+
+public abstract class SpannableTest extends InstrumentationTestCase {
+
+    protected abstract Spannable newSpannableWithText(String text);
+
+    @MediumTest
+    public void testGetSpans() {
+        Spannable spannable = newSpannableWithText("abcdef");
+        Object emptySpan = new Object();
+        spannable.setSpan(emptySpan, 1, 1, 0);
+        Object unemptySpan = new Object();
+        spannable.setSpan(unemptySpan, 1, 2, 0);
+
+        Object[] spans;
+
+        // Empty spans are included when they merely abut the query region
+        // but other spans are not, unless the query region is empty, in
+        // in which case any abutting spans are returned.
+        spans = spannable.getSpans(0, 1, Object.class);
+        MoreAsserts.assertEquals(new Object[]{emptySpan}, spans);
+        spans = spannable.getSpans(0, 2, Object.class);
+        MoreAsserts.assertEquals(new Object[]{emptySpan, unemptySpan}, spans);
+        spans = spannable.getSpans(1, 2, Object.class);
+        MoreAsserts.assertEquals(new Object[]{emptySpan, unemptySpan}, spans);
+        spans = spannable.getSpans(2, 2, Object.class);
+        MoreAsserts.assertEquals(new Object[]{unemptySpan}, spans);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/touchmode/ChangeTouchModeTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/touchmode/ChangeTouchModeTest.java
new file mode 100644
index 0000000..d274d0d
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/touchmode/ChangeTouchModeTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.touchmode;
+
+import com.android.frameworktest.layout.linear.LLOfButtons1;
+import com.android.frameworktest.layout.linear.LLOfButtons2;
+import static com.android.frameworktest.util.TouchModeFlexibleAsserts.assertInTouchModeAfterClick;
+import static com.android.frameworktest.util.TouchModeFlexibleAsserts.assertNotInTouchModeAfterKey;
+import static com.android.frameworktest.util.TouchModeFlexibleAsserts.assertInTouchModeAfterTap;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+
+/**
+ * Tests that the touch mode changes from various events, and that the state
+ * persists across activities.
+ */
+public class ChangeTouchModeTest extends ActivityInstrumentationTestCase<LLOfButtons1> {
+
+    public ChangeTouchModeTest() {
+        super("com.android.frameworktest", LLOfButtons1.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @MediumTest
+    public void testPreconditions() throws Exception {
+        assertFalse("touch mode", getActivity().isInTouchMode());
+    }
+
+    @MediumTest
+    public void testTouchingScreenEntersTouchMode() throws Exception {
+        assertInTouchModeAfterTap(this, getActivity().getFirstButton());
+        assertTrue("touch mode", getActivity().isInTouchMode());
+    }
+
+    // TODO: reenable when more reliable
+    public void DISABLE_testDpadDirectionLeavesTouchMode() throws Exception {
+        assertInTouchModeAfterClick(this, getActivity().getFirstButton());
+        sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
+        assertNotInTouchModeAfterKey(this, KeyEvent.KEYCODE_DPAD_RIGHT, getActivity().getFirstButton());
+        assertFalse("touch mode", getActivity().isInTouchMode());
+    }
+
+    public void TODO_touchTrackBallMovementLeavesTouchMode() throws Exception {
+
+    }
+
+    @MediumTest
+    public void testTouchModeFalseAcrossActivites() throws Exception {
+
+        getInstrumentation().waitForIdleSync();
+
+        LLOfButtons2 otherActivity = null;
+        try {
+            otherActivity =
+                    launchActivity("com.android.frameworktest", LLOfButtons2.class, null);
+            assertNotNull(otherActivity);
+            assertFalse(otherActivity.isInTouchMode());
+        } finally {
+            if (otherActivity != null) {
+                otherActivity.finish();
+            }
+        }
+    }
+
+    @LargeTest
+    public void testTouchModeTrueAcrossActivites() throws Exception {
+        assertInTouchModeAfterClick(this, getActivity().getFirstButton());
+        LLOfButtons2 otherActivity = null;
+        try {
+            otherActivity =
+                    launchActivity("com.android.frameworktest", LLOfButtons2.class, null);
+            assertNotNull(otherActivity);
+            assertTrue(otherActivity.isInTouchMode());
+        } finally {
+            if (otherActivity != null) {
+                otherActivity.finish();
+            }
+        }
+    }
+
+    @LargeTest
+    public void testTouchModeChangedInOtherActivity() throws Exception {
+
+        assertFalse("touch mode", getActivity().isInTouchMode());
+
+        LLOfButtons2 otherActivity = null;
+        try {
+            otherActivity =
+                    launchActivity("com.android.frameworktest", LLOfButtons2.class, null);
+            assertNotNull(otherActivity);
+            assertFalse(otherActivity.isInTouchMode());
+            assertInTouchModeAfterClick(this, otherActivity.getFirstButton());
+            assertTrue(otherActivity.isInTouchMode());
+        } finally {
+            if (otherActivity != null) {
+                otherActivity.finish();
+            }
+        }
+
+        // need to wait for async update back to window to occur
+        Thread.sleep(200);
+        
+        assertTrue("touch mode", getActivity().isInTouchMode());
+    }
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/touchmode/FocusableInTouchModeClickTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/touchmode/FocusableInTouchModeClickTest.java
new file mode 100644
index 0000000..7cd6444
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/touchmode/FocusableInTouchModeClickTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.touchmode;
+
+import com.android.frameworktest.layout.linear.LLOfTwoFocusableInTouchMode;
+
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.TouchUtils;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+
+public class FocusableInTouchModeClickTest extends ActivityInstrumentationTestCase2<LLOfTwoFocusableInTouchMode> {
+
+    public FocusableInTouchModeClickTest() {
+        super("com.android.frameworktest", LLOfTwoFocusableInTouchMode.class);
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        setActivityInitialTouchMode(true);
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertTrue("should start in touch mode", getActivity().getButton1().isInTouchMode());
+        assertTrue(getActivity().getButton1().isFocused());
+    }
+
+    @LargeTest
+    public void testClickGivesFocusNoClickFired() {
+        TouchUtils.clickView(this, getActivity().getButton2());
+        assertTrue("click should give focusable in touch mode focus",
+                getActivity().getButton2().isFocused());
+        assertFalse("getting focus should result in no on click",
+                getActivity().isB2Fired());
+
+        TouchUtils.clickView(this, getActivity().getButton2());
+        assertTrue("subsequent click while focused should fire on click",
+                getActivity().isB2Fired());
+    }
+
+    @MediumTest
+    public void testTapGivesFocusNoClickFired() {
+        TouchUtils.touchAndCancelView(this, getActivity().getButton2());
+        assertFalse("button shouldn't have fired click", getActivity().isB2Fired());
+        assertFalse("button shouldn't have focus", getActivity().getButton2().isFocused());
+    }
+
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/touchmode/StartInTouchWithViewInFocusTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/touchmode/StartInTouchWithViewInFocusTest.java
new file mode 100644
index 0000000..6403435
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/touchmode/StartInTouchWithViewInFocusTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.touchmode;
+
+import com.android.frameworktest.layout.linear.LLEditTextThenButton;
+import static com.android.frameworktest.util.TouchModeFlexibleAsserts.assertNotInTouchModeAfterKey;
+
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.widget.Button;
+import android.widget.EditText;
+
+public class StartInTouchWithViewInFocusTest extends 
+        ActivityInstrumentationTestCase2<LLEditTextThenButton> {
+
+    private EditText mEditText;
+
+    private Button mButton;
+
+    public StartInTouchWithViewInFocusTest() {
+        super("com.android.frameworktest", LLEditTextThenButton.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        this.setActivityInitialTouchMode(true);
+        mEditText = getActivity().getEditText();
+        mButton = getActivity().getButton();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertTrue("should start in touch mode", mEditText.isInTouchMode());
+        assertTrue("edit text is focusable in touch mode, should have focus", mEditText.isFocused());
+    }
+
+    // TODO: reenable when more reliable
+    public void DISABLE_testKeyDownLeavesTouchModeAndGoesToNextView() {
+        assertNotInTouchModeAfterKey(this, KeyEvent.KEYCODE_DPAD_DOWN, mEditText);
+        assertFalse("should have left touch mode", mEditText.isInTouchMode());
+        assertTrue("should have given focus to next view", mButton.isFocused());
+    }
+
+    // TODO: reenable when more reliable
+    public void DISABLE_testNonDirectionalKeyExitsTouchMode() {
+        assertNotInTouchModeAfterKey(this, KeyEvent.KEYCODE_A, mEditText);
+        assertFalse("should have left touch mode", mEditText.isInTouchMode());
+        assertTrue("edit text should still have focus", mEditText.isFocused());        
+    }
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/touchmode/TouchModeFocusChangeTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/touchmode/TouchModeFocusChangeTest.java
new file mode 100644
index 0000000..1a0c833
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/touchmode/TouchModeFocusChangeTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.touchmode;
+
+import com.android.frameworktest.layout.linear.LLOfButtons1;
+import static com.android.frameworktest.util.TouchModeFlexibleAsserts.assertInTouchModeAfterClick;
+import static com.android.frameworktest.util.TouchModeFlexibleAsserts.assertInTouchModeAfterTap;
+import static com.android.frameworktest.util.TouchModeFlexibleAsserts.assertNotInTouchModeAfterKey;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.widget.Button;
+
+/**
+ * Make sure focus isn't kept by buttons when entering touch mode.
+ *
+ * When in touch mode and hitting the d-pad, we should leave touch mode and the
+ * top most focusable gets focus.
+ */
+public class TouchModeFocusChangeTest extends ActivityInstrumentationTestCase<LLOfButtons1> {
+    private LLOfButtons1 mActivity;
+    private Button mFirstButton;
+
+    public TouchModeFocusChangeTest() {
+        super("com.android.frameworktest", LLOfButtons1.class);
+    }
+
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mFirstButton = mActivity.getFirstButton();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertFalse("we should not be in touch mode", mActivity.isInTouchMode());
+        assertTrue("top button should have focus", mFirstButton.isFocused());
+    }
+
+    @MediumTest
+    public void testTouchButtonNotTakeFocus() {
+        assertInTouchModeAfterTap(this, mFirstButton);
+
+        assertTrue("should be in touch mode", mActivity.isInTouchMode());
+        assertFalse("button.isFocused",
+                mFirstButton.isFocused());
+        assertFalse("button.hasFocus",
+                mFirstButton.hasFocus());
+        assertNull("activity shouldn't have focus", mActivity.getCurrentFocus());
+        assertFalse("linear layout should not have focus",
+                mActivity.getLayout().hasFocus());
+
+        assertTrue("button's onClickListener should have fired",
+                mActivity.buttonClickListenerFired());
+    }
+
+    // TODO: reenable when more reliable
+    public void DISABLE_testLeaveTouchModeWithDpadEvent() {
+        assertInTouchModeAfterClick(this, mFirstButton);
+
+        assertTrue("should be in touch mode", mActivity.isInTouchMode());
+        assertFalse("button should not have focus when touched",
+                mFirstButton.isFocused());
+
+        assertNotInTouchModeAfterKey(this, KeyEvent.KEYCODE_DPAD_RIGHT, mFirstButton);
+        assertFalse("should be out of touch mode", mActivity.isInTouchMode());
+        assertTrue("first button (the top most focusable) should have gained focus",
+                mFirstButton.isFocused());
+    }
+
+
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/touchmode/TouchModeFocusableTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/touchmode/TouchModeFocusableTest.java
new file mode 100644
index 0000000..86925b5
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/touchmode/TouchModeFocusableTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.touchmode;
+
+import com.android.frameworktest.layout.linear.LLEditTextThenButton;
+import static com.android.frameworktest.util.TouchModeFlexibleAsserts.assertInTouchModeAfterTap;
+import static com.android.frameworktest.util.TouchModeFlexibleAsserts.assertInTouchModeAfterClick;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.widget.Button;
+import android.widget.EditText;
+
+/**
+ * Some views, like edit texts, can keep and gain focus even when in touch mode.
+ */
+public class TouchModeFocusableTest extends ActivityInstrumentationTestCase<LLEditTextThenButton> {
+    private EditText mEditText;
+    private Button mButton;
+
+
+    public TouchModeFocusableTest() {
+        super("com.android.frameworktest", LLEditTextThenButton.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mEditText = getActivity().getEditText();
+        mButton = getActivity().getButton();
+    }
+
+    @MediumTest
+    public void testPreconditions() {
+        assertFalse("should not be in touch mode to start off", mButton.isInTouchMode());
+        assertTrue("edit text should have focus", mEditText.isFocused());
+        assertTrue("edit text should be focusable in touch mode", mEditText.isFocusableInTouchMode());
+    }
+
+    @MediumTest
+    public void testClickButtonEditTextKeepsFocus() {
+        assertInTouchModeAfterTap(this, mButton);
+        assertTrue("should be in touch mode", mButton.isInTouchMode());
+        assertTrue("edit text should still have focus", mEditText.isFocused());
+    }
+
+    @LargeTest
+    public void testClickEditTextGivesItFocus() {
+        // go down to button
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        assertTrue("button should have focus", mButton.isFocused());
+
+        assertInTouchModeAfterClick(this, mEditText);
+        assertTrue("clicking edit text should have entered touch mode", mButton.isInTouchMode());
+        assertTrue("clicking edit text should have given it focus", mEditText.isFocused());
+    }
+
+
+    // entering touch mode takes focus away from the currently focused item if it
+    // isn't focusable in touch mode.
+    @LargeTest
+    public void testEnterTouchModeGivesFocusBackToFocusableInTouchMode() {
+        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+
+        assertTrue("button should have focus",
+                mButton.isFocused());
+        
+        assertInTouchModeAfterClick(this, mButton);
+        assertTrue("should be in touch mode", mButton.isInTouchMode());
+        assertNull("nothing should have focus", getActivity().getCurrentFocus());
+        assertFalse("layout should not have focus",
+                getActivity().getLayout().hasFocus());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/view/BigCacheTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/BigCacheTest.java
new file mode 100644
index 0000000..b5e7473
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/BigCacheTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.view;
+
+import com.android.frameworktest.view.BigCache;
+import com.android.frameworktest.R;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.graphics.Bitmap;
+
+/**
+ * Builds the drawing cache of two Views, one smaller than the maximum cache size,
+ * one larger than the maximum cache size. The latter should always have a null
+ * drawing cache.
+ */
+public class BigCacheTest extends ActivityInstrumentationTestCase<BigCache> {
+    private View mTiny;
+    private View mLarge;
+
+    public BigCacheTest() {
+        super("com.android.frameworktest", BigCache.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        final BigCache activity = getActivity();
+        mTiny = activity.findViewById(R.id.a);
+        mLarge = activity.findViewById(R.id.b);
+    }
+
+    @MediumTest
+    public void testSetUpConditions() throws Exception {
+        assertNotNull(mTiny);
+        assertNotNull(mLarge);
+    }
+
+    @MediumTest
+    public void testDrawingCacheBelowMaximumSize() throws Exception {
+        final int max = ViewConfiguration.getMaximumDrawingCacheSize();
+        assertTrue(mTiny.getWidth() * mTiny.getHeight() * 2 < max);
+        assertNotNull(createCacheForView(mTiny));
+    }
+
+    @MediumTest
+    public void testDrawingCacheAboveMaximumSize() throws Exception {
+        final int max = ViewConfiguration.getMaximumDrawingCacheSize();
+        assertTrue(mLarge.getWidth() * mLarge.getHeight() * 2 > max);
+        assertNull(createCacheForView(mLarge));
+    }
+
+    private Bitmap createCacheForView(final View view) {
+        final Bitmap[] cache = new Bitmap[1];
+        getActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                view.setDrawingCacheEnabled(true);
+                view.invalidate();
+                view.buildDrawingCache();
+                cache[0] = view.getDrawingCache();
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+        return cache[0];
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/view/DisabledLongpressTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/DisabledLongpressTest.java
new file mode 100644
index 0000000..ef3ecee
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/DisabledLongpressTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.view;
+
+import com.android.frameworktest.view.Longpress;
+import com.android.frameworktest.R;
+import com.android.frameworktest.util.KeyUtils;
+import android.test.TouchUtils;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.view.View;
+import android.view.View.OnLongClickListener;
+
+/**
+ * Exercises {@link android.view.View}'s longpress plumbing by testing the
+ * disabled case.
+ */
+public class DisabledLongpressTest extends ActivityInstrumentationTestCase<Longpress> {
+    private View mSimpleView;
+    private boolean mLongClicked;
+    
+    public DisabledLongpressTest() {
+        super("com.android.frameworktest", Longpress.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        final Longpress a = getActivity();
+        mSimpleView = a.findViewById(R.id.simple_view);
+        mSimpleView.setOnLongClickListener(new OnLongClickListener() {
+            public boolean onLongClick(View v) {
+                mLongClicked = true;
+                return true;
+            }
+        });
+        // The View#setOnLongClickListener will ensure the View is long
+        // clickable, we reverse that here
+        mSimpleView.setLongClickable(false);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+
+        mLongClicked = false;
+    }
+
+    @MediumTest
+    public void testSetUpConditions() throws Exception {
+        assertNotNull(mSimpleView);
+        assertTrue(mSimpleView.hasFocus());
+        assertFalse(mLongClicked);
+    }
+
+    @LargeTest
+    public void testKeypadLongClick() throws Exception {
+        mSimpleView.requestFocus();
+        getInstrumentation().waitForIdleSync();
+        KeyUtils.longClick(this);
+        
+        getInstrumentation().waitForIdleSync();
+        assertFalse(mLongClicked);
+    }
+
+    @LargeTest
+    public void testTouchLongClick() throws Exception {
+        TouchUtils.longClickView(this, mSimpleView);
+        getInstrumentation().waitForIdleSync();
+        assertFalse(mLongClicked);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/view/DisabledTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/DisabledTest.java
new file mode 100644
index 0000000..d9ed033
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/DisabledTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.view;
+
+import com.android.frameworktest.R;
+import android.test.TouchUtils;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.widget.Button;
+import android.view.KeyEvent;
+import android.view.View;
+
+/**
+ * Exercises {@link android.view.View}'s disabled property.
+ */
+public class DisabledTest extends ActivityInstrumentationTestCase<Disabled> {
+    private Button mDisabled;
+    private View mDisabledParent;
+    private boolean mClicked;
+    private boolean mParentClicked;
+
+    public DisabledTest() {
+        super("com.android.frameworktest", Disabled.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        final Disabled a = getActivity();
+        mDisabled = (Button) a.findViewById(R.id.disabledButton);
+        mDisabled.setOnClickListener(new View.OnClickListener() {
+            public void onClick(View v) {
+                mClicked = true;
+            }
+        });
+
+        mDisabledParent = a.findViewById(R.id.clickableParent);
+        mDisabledParent.setOnClickListener(new View.OnClickListener() {
+            public void onClick(View v) {
+                mParentClicked = true;
+            }
+        });
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+
+        mClicked = false;
+        mParentClicked = false;
+    }
+
+    @MediumTest
+    public void testSetUpConditions() throws Exception {
+        assertNotNull(mDisabled);
+        assertNotNull(mDisabledParent);
+        assertFalse(mDisabled.isEnabled());
+        assertTrue(mDisabledParent.isEnabled());
+        assertTrue(mDisabled.hasFocus());
+    }
+
+    @MediumTest
+    public void testKeypadClick() throws Exception {
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        getInstrumentation().waitForIdleSync();
+        assertFalse(mClicked);
+        assertFalse(mParentClicked);
+    }
+
+    @LargeTest
+    public void testTouchClick() throws Exception {
+        TouchUtils.clickView(this, mDisabled);
+        getInstrumentation().waitForIdleSync();
+        assertFalse(mClicked);
+        assertFalse(mParentClicked);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/view/GlobalFocusChangeTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/GlobalFocusChangeTest.java
new file mode 100644
index 0000000..8a8d728
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/GlobalFocusChangeTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.view;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.FlakyTest;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.TouchUtils;
+import android.view.View;
+import android.view.KeyEvent;
+import com.android.frameworktest.R;
+
+public class GlobalFocusChangeTest extends ActivityInstrumentationTestCase<GlobalFocusChange> {
+    private GlobalFocusChange mActivity;
+    private View mLeft;
+    private View mRight;
+
+    public GlobalFocusChangeTest() {
+        super("com.android.frameworktest", GlobalFocusChange.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+        mLeft = mActivity.findViewById(R.id.left);
+        mRight = mActivity.findViewById(R.id.right);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mActivity.reset();
+        super.tearDown();
+    }
+
+    @FlakyTest(tolerance = 4)
+    @LargeTest
+    public void testFocusChange() throws Exception {
+        sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
+
+        assertFalse(mLeft.isFocused());
+        assertTrue(mRight.isFocused());
+
+        assertSame(mLeft, mActivity.mOldFocus);
+        assertSame(mRight, mActivity.mNewFocus);        
+    }
+
+    @FlakyTest(tolerance = 4)
+    @MediumTest
+    public void testEnterTouchMode() throws Exception {
+        assertTrue(mLeft.isFocused());
+
+        TouchUtils.tapView(this, mLeft);
+
+        assertSame(mLeft, mActivity.mOldFocus);
+        assertSame(null, mActivity.mNewFocus);        
+    }
+
+    @FlakyTest(tolerance = 4)
+    @MediumTest
+    public void testLeaveTouchMode() throws Exception {
+        assertTrue(mLeft.isFocused());
+
+        TouchUtils.tapView(this, mLeft);
+        sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
+
+        assertTrue(mLeft.isFocused());
+
+        assertSame(null, mActivity.mOldFocus);
+        assertSame(mLeft, mActivity.mNewFocus);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/view/IncludeTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/IncludeTest.java
new file mode 100644
index 0000000..dd1382d
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/IncludeTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.view;
+
+import com.android.frameworktest.view.Include;
+import com.android.frameworktest.R;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class IncludeTest extends ActivityInstrumentationTestCase<Include> {
+    public IncludeTest() {
+        super("com.android.frameworktest", Include.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @MediumTest
+    public void testIncluded() throws Exception {
+        final Include activity = getActivity();
+
+        final View button1 = activity.findViewById(R.id.included_button);
+        assertNotNull("The layout include_button was not included", button1);
+
+        final View button2 = activity.findViewById(R.id.included_button_overriden);
+        assertNotNull("The layout include_button was not included with overriden id", button2);
+    }
+
+    @MediumTest
+    public void testIncludedWithLayoutParams() throws Exception {
+        final Include activity = getActivity();
+
+        final View button1 = activity.findViewById(R.id.included_button);
+        final View button2 = activity.findViewById(R.id.included_button_overriden);
+
+        assertTrue("Both buttons should have different width",
+                button1.getLayoutParams().width != button2.getLayoutParams().width);
+        assertTrue("Both buttons should have different height",
+                button1.getLayoutParams().height != button2.getLayoutParams().height);
+    }
+
+    @MediumTest
+    public void testIncludedWithVisibility() throws Exception {
+        final Include activity = getActivity();
+        final View button1 = activity.findViewById(R.id.included_button_visibility);
+
+        assertEquals("Included button should be invisible", View.INVISIBLE, button1.getVisibility());
+    }
+
+    @MediumTest
+    public void testIncludedWithSize() throws Exception {
+        final Include activity = getActivity();
+        final View button1 = activity.findViewById(R.id.included_button_with_size);
+
+        final ViewGroup.LayoutParams lp = button1.getLayoutParams();
+        assertEquals("Included button should be 23dip x 23dip", 23, lp.width);
+        assertEquals("Included button should be 23dip x 23dip", 23, lp.height);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/view/LongpressTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/LongpressTest.java
new file mode 100644
index 0000000..37106f6
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/LongpressTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.view;
+
+import com.android.frameworktest.view.Longpress;
+import com.android.frameworktest.R;
+import com.android.frameworktest.util.KeyUtils;
+import android.test.TouchUtils;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.view.View;
+import android.view.View.OnLongClickListener;
+
+/**
+ * Exercises {@link android.view.View}'s longpress plumbing.
+ */
+public class LongpressTest extends ActivityInstrumentationTestCase<Longpress> {
+    private View mSimpleView;
+    private boolean mLongClicked;
+    
+    public LongpressTest() {
+        super("com.android.frameworktest", Longpress.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        final Longpress a = getActivity();
+        mSimpleView = a.findViewById(R.id.simple_view);
+        mSimpleView.setOnLongClickListener(new OnLongClickListener() {
+            public boolean onLongClick(View v) {
+                mLongClicked = true;
+                return true;
+            }
+        });
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+
+        mLongClicked = false;
+    }
+
+    @MediumTest
+    public void testSetUpConditions() throws Exception {
+        assertNotNull(mSimpleView);
+        assertTrue(mSimpleView.hasFocus());
+        assertFalse(mLongClicked);
+    }
+
+    @LargeTest
+    public void testKeypadLongClick() throws Exception {
+        mSimpleView.requestFocus();
+        getInstrumentation().waitForIdleSync();
+        KeyUtils.longClick(this);
+        
+        getInstrumentation().waitForIdleSync();
+        assertTrue(mLongClicked);
+    }
+
+    @LargeTest
+    public void testTouchLongClick() throws Exception {
+        TouchUtils.longClickView(this, mSimpleView);
+        getInstrumentation().waitForIdleSync();
+        assertTrue(mLongClicked);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/view/MergeTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/MergeTest.java
new file mode 100644
index 0000000..612ebd4
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/MergeTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.view;
+
+import com.android.frameworktest.view.Merge;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.ViewGroup;
+
+public class MergeTest extends ActivityInstrumentationTestCase<Merge> {
+    public MergeTest() {
+        super("com.android.frameworktest", Merge.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @MediumTest
+    public void testMerged() throws Exception {
+        final Merge activity = getActivity();
+        final ViewGroup layout = activity.getLayout();
+
+        assertEquals("The layout wasn't merged", 7, layout.getChildCount());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/view/RemoteViewsActivityTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/RemoteViewsActivityTest.java
new file mode 100644
index 0000000..3dcb252
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/RemoteViewsActivityTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2008 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.frameworktest.view;
+
+import android.os.Parcel;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.InflateException;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.RemoteViews;
+
+import com.android.frameworktest.R;
+import com.android.frameworktest.view.RemoteViewsActivity;
+
+public class RemoteViewsActivityTest extends ActivityInstrumentationTestCase<RemoteViewsActivity> {
+    public RemoteViewsActivityTest() {
+        super("com.android.frameworktest", RemoteViewsActivity.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @MediumTest
+    public void testGood() throws Exception {
+        final RemoteViewsActivity activity = getActivity();
+
+        RemoteViews orig = new RemoteViews("com.android.frameworktest",
+                R.layout.remote_view_test_good);
+        Parcel p = Parcel.obtain();
+        orig.writeToParcel(p, 0);
+        p.setDataPosition(0);
+        
+        RemoteViews r = RemoteViews.CREATOR.createFromParcel(p);
+        
+        ViewGroup parent = (ViewGroup) activity.findViewById(R.id.parent);
+        
+        View result = r.apply(activity, parent);
+        
+        p.recycle();
+        
+        assertTrue("LinearLayout not inflated", result.findViewById(R.id.linear) != null);
+        assertTrue("TextView not inflated", result.findViewById(R.id.text) != null);
+        assertTrue("ImageView not inflated", result.findViewById(R.id.image) != null);
+        assertTrue("FrameLayout not inflated", result.findViewById(R.id.frame) != null);
+        assertTrue("RelateiveLayout not inflated", result.findViewById(R.id.relative) != null);
+        assertTrue("AbsoluteLayout not inflated", result.findViewById(R.id.absolute) != null);
+        assertTrue("ProgressBar not inflated", result.findViewById(R.id.progress) != null);
+        assertTrue("ImageButton not inflated", result.findViewById(R.id.image_button) != null);
+        assertTrue("Button not inflated", result.findViewById(R.id.button) != null);
+    }
+    
+    @MediumTest
+    public void testDerivedClass() throws Exception {
+        final RemoteViewsActivity activity = getActivity();
+        
+        RemoteViews orig = new RemoteViews("com.android.frameworktest",
+                R.layout.remote_view_test_bad_1);
+        Parcel p = Parcel.obtain();
+        orig.writeToParcel(p, 0);
+        p.setDataPosition(0);
+        
+        RemoteViews r = RemoteViews.CREATOR.createFromParcel(p);
+        
+        ViewGroup parent = (ViewGroup) activity.findViewById(R.id.parent);
+        
+        boolean exceptionThrown = false;
+        View result = null;
+        
+        try {
+            result = r.apply(activity, parent);
+        } catch (InflateException e) {
+            exceptionThrown = true;
+        }
+        
+        p.recycle();
+        
+        assertTrue("Derived class (EditText) allowed to be inflated", exceptionThrown);
+        assertNull("Derived class (EditText) allowed to be inflated", result);
+    }
+    
+    @MediumTest
+    public void testWebView() throws Exception {
+        final RemoteViewsActivity activity = getActivity();
+        
+        RemoteViews orig = new RemoteViews("com.android.frameworktest",
+                R.layout.remote_view_test_bad_2);
+        Parcel p = Parcel.obtain();
+        orig.writeToParcel(p, 0);
+        p.setDataPosition(0);
+        
+        RemoteViews r = RemoteViews.CREATOR.createFromParcel(p);
+        
+        ViewGroup parent = (ViewGroup) activity.findViewById(R.id.parent);
+        
+        boolean exceptionThrown = false;
+        View result = null;
+        
+        try {
+            result = r.apply(activity, parent);
+        } catch (InflateException e) {
+            exceptionThrown = true;
+        }
+        
+        p.recycle();
+        
+        assertTrue("WebView allowed to be inflated", exceptionThrown);
+        assertNull("WebView allowed to be inflated", result);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/view/RunQueueTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/RunQueueTest.java
new file mode 100644
index 0000000..dc8fcd8
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/RunQueueTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.view;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+
+public class RunQueueTest extends ActivityInstrumentationTestCase<RunQueue> {
+    public RunQueueTest() {
+        super("com.android.frameworktest", RunQueue.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @MediumTest
+    public void testRunnableRan() throws Exception {
+        final RunQueue activity = getActivity();
+        getInstrumentation().waitForIdleSync();
+        assertTrue("The runnable did not run", activity.runnableRan);
+    }
+
+    @MediumTest
+    public void testRunnableCancelled() throws Exception {
+        final RunQueue activity = getActivity();
+        getInstrumentation().waitForIdleSync();
+        assertTrue("The runnable was not cancelled", activity.runnableCancelled);
+    }
+
+    @MediumTest
+    public void testListenerFired() throws Exception {
+        final RunQueue activity = getActivity();
+        getInstrumentation().waitForIdleSync();
+        assertTrue("The global layout listener did not fire", activity.globalLayout);
+    }
+
+    @MediumTest
+    public void testTreeObserverKilled() throws Exception {
+        final RunQueue activity = getActivity();
+        getInstrumentation().waitForIdleSync();
+        assertFalse("The view tree observer is still alive", activity.viewTreeObserver.isAlive());
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/view/ViewGroupChildrenTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/ViewGroupChildrenTest.java
new file mode 100644
index 0000000..fceec51
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/ViewGroupChildrenTest.java
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.view;
+
+import com.android.frameworktest.R;
+import com.android.frameworktest.view.ViewGroupChildren;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.ViewAsserts;
+import android.test.UiThreadTest;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+/**
+ * Exercises {@link android.view.ViewGroup}'s ability to add/remove children.
+ */
+public class ViewGroupChildrenTest extends ActivityInstrumentationTestCase<ViewGroupChildren> {
+    private ViewGroup mGroup;
+
+    public ViewGroupChildrenTest() {
+        super("com.android.frameworktest", ViewGroupChildren.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        final ViewGroupChildren a = getActivity();
+        mGroup = (ViewGroup) a.findViewById(R.id.group);
+    }
+
+    @MediumTest
+    public void testSetUpConditions() throws Exception {
+        assertNotNull(mGroup);
+    }
+
+    @MediumTest
+    public void testStartsEmpty() throws Exception {
+        assertEquals("A ViewGroup should have no child by default", 0, mGroup.getChildCount());
+    }
+
+    @UiThreadTest
+    @MediumTest
+    public void testAddChild() throws Exception {
+        View view = createView("1");
+        mGroup.addView(view);
+
+        assertEquals(1, mGroup.getChildCount());
+        ViewAsserts.assertGroupIntegrity(mGroup);
+        ViewAsserts.assertGroupContains(mGroup, view);
+    }
+
+    @UiThreadTest
+    @MediumTest
+    public void testAddChildAtFront() throws Exception {
+        // 24 should be greater than ViewGroup.ARRAY_CAPACITY_INCREMENT
+        for (int i = 0; i < 24; i++) {
+            View view = createView(String.valueOf(i + 1));
+            mGroup.addView(view);
+        }
+
+        View view = createView("X");
+        mGroup.addView(view, 0);
+
+        assertEquals(25, mGroup.getChildCount());
+        ViewAsserts.assertGroupIntegrity(mGroup);
+        ViewAsserts.assertGroupContains(mGroup, view);
+        assertSame(view, mGroup.getChildAt(0));
+    }
+
+    @UiThreadTest
+    @MediumTest
+    public void testAddChildInMiddle() throws Exception {
+        // 24 should be greater than ViewGroup.ARRAY_CAPACITY_INCREMENT
+        for (int i = 0; i < 24; i++) {
+            View view = createView(String.valueOf(i + 1));
+            mGroup.addView(view);
+        }
+
+        View view = createView("X");
+        mGroup.addView(view, 12);
+
+        assertEquals(25, mGroup.getChildCount());
+        ViewAsserts.assertGroupIntegrity(mGroup);
+        ViewAsserts.assertGroupContains(mGroup, view);
+        assertSame(view, mGroup.getChildAt(12));
+    }
+
+    @UiThreadTest
+    @MediumTest
+    public void testAddChildren() throws Exception {
+        // 24 should be greater than ViewGroup.ARRAY_CAPACITY_INCREMENT
+        for (int i = 0; i < 24; i++) {
+            View view = createView(String.valueOf(i + 1));
+            mGroup.addView(view);
+
+            ViewAsserts.assertGroupContains(mGroup, view);
+        }
+        assertEquals(24, mGroup.getChildCount());
+    }
+
+    @UiThreadTest
+    @MediumTest
+    public void testRemoveChild() throws Exception {
+        View view = createView("1");
+        mGroup.addView(view);
+
+        ViewAsserts.assertGroupIntegrity(mGroup);
+
+        mGroup.removeView(view);
+
+        ViewAsserts.assertGroupIntegrity(mGroup);
+        ViewAsserts.assertGroupNotContains(mGroup, view);
+
+        assertEquals(0, mGroup.getChildCount());
+        assertNull(view.getParent());
+    }
+
+    @UiThreadTest
+    @MediumTest
+    public void testRemoveChildren() throws Exception {
+        // 24 should be greater than ViewGroup.ARRAY_CAPACITY_INCREMENT
+        final View[] views = new View[24];
+
+        for (int i = 0; i < views.length; i++) {
+            views[i] = createView(String.valueOf(i + 1));
+            mGroup.addView(views[i]);
+        }
+
+        for (int i = views.length - 1; i >= 0; i--) {
+            mGroup.removeViewAt(i);
+            ViewAsserts.assertGroupIntegrity(mGroup);
+            ViewAsserts.assertGroupNotContains(mGroup, views[i]);
+            assertNull(views[i].getParent());
+        }
+
+        assertEquals(0, mGroup.getChildCount());
+    }
+
+    @UiThreadTest
+    @MediumTest
+    public void testRemoveChildrenBulk() throws Exception {
+        // 24 should be greater than ViewGroup.ARRAY_CAPACITY_INCREMENT
+        final View[] views = new View[24];
+
+        for (int i = 0; i < views.length; i++) {
+            views[i] = createView(String.valueOf(i + 1));
+            mGroup.addView(views[i]);
+        }
+
+        mGroup.removeViews(6, 7);
+        ViewAsserts.assertGroupIntegrity(mGroup);
+        for (int i = 6; i < 13; i++) {
+            ViewAsserts.assertGroupNotContains(mGroup, views[i]);
+            assertNull(views[i].getParent());
+        }
+
+        assertEquals(17, mGroup.getChildCount());
+    }
+
+    @UiThreadTest
+    @MediumTest
+    public void testRemoveChildrenBulkAtFront() throws Exception {
+        // 24 should be greater than ViewGroup.ARRAY_CAPACITY_INCREMENT
+        final View[] views = new View[24];
+
+        for (int i = 0; i < views.length; i++) {
+            views[i] = createView(String.valueOf(i + 1));
+            mGroup.addView(views[i]);
+        }
+
+        mGroup.removeViews(0, 7);
+        ViewAsserts.assertGroupIntegrity(mGroup);
+        for (int i = 0; i < 7; i++) {
+            ViewAsserts.assertGroupNotContains(mGroup, views[i]);
+            assertNull(views[i].getParent());
+        }
+
+        assertEquals("8", ((TextView) mGroup.getChildAt(0)).getText());
+        assertEquals(17, mGroup.getChildCount());
+    }
+
+    @UiThreadTest
+    @MediumTest
+    public void testRemoveChildrenBulkAtEnd() throws Exception {
+        // 24 should be greater than ViewGroup.ARRAY_CAPACITY_INCREMENT
+        final View[] views = new View[24];
+
+        for (int i = 0; i < views.length; i++) {
+            views[i] = createView(String.valueOf(i + 1));
+            mGroup.addView(views[i]);
+        }
+
+        mGroup.removeViews(17, 7);
+        ViewAsserts.assertGroupIntegrity(mGroup);
+        for (int i = 17; i < 24; i++) {
+            ViewAsserts.assertGroupNotContains(mGroup, views[i]);
+            assertNull(views[i].getParent());
+        }
+        assertEquals("17", ((TextView) mGroup.getChildAt(mGroup.getChildCount() - 1)).getText());
+        assertEquals(17, mGroup.getChildCount());
+    }
+
+    @UiThreadTest
+    @MediumTest
+    public void testRemoveChildAtFront() throws Exception {
+        // 24 should be greater than ViewGroup.ARRAY_CAPACITY_INCREMENT
+        final View[] views = new View[24];
+
+        for (int i = 0; i < views.length; i++) {
+            views[i] = createView(String.valueOf(i + 1));
+            mGroup.addView(views[i]);
+        }
+
+        mGroup.removeViewAt(0);
+        ViewAsserts.assertGroupIntegrity(mGroup);
+        ViewAsserts.assertGroupNotContains(mGroup, views[0]);
+        assertNull(views[0].getParent());
+
+        assertEquals(views.length - 1, mGroup.getChildCount());
+    }
+
+    @UiThreadTest
+    @MediumTest
+    public void testRemoveChildInMiddle() throws Exception {
+        // 24 should be greater than ViewGroup.ARRAY_CAPACITY_INCREMENT
+        final View[] views = new View[24];
+
+        for (int i = 0; i < views.length; i++) {
+            views[i] = createView(String.valueOf(i + 1));
+            mGroup.addView(views[i]);
+        }
+
+        mGroup.removeViewAt(12);
+        ViewAsserts.assertGroupIntegrity(mGroup);
+        ViewAsserts.assertGroupNotContains(mGroup, views[12]);
+        assertNull(views[12].getParent());
+
+        assertEquals(views.length - 1, mGroup.getChildCount());        
+    }
+
+    private TextView createView(String text) {
+        TextView view = new TextView(getActivity());
+        view.setText(text);
+        view.setLayoutParams(new LinearLayout.LayoutParams(
+                LinearLayout.LayoutParams.FILL_PARENT,
+                LinearLayout.LayoutParams.WRAP_CONTENT
+        ));
+        return view;
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/view/ViewStubTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/ViewStubTest.java
new file mode 100644
index 0000000..89bd646
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/ViewStubTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.view;
+
+import com.android.frameworktest.view.StubbedView;
+import com.android.frameworktest.R;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.UiThreadTest;
+import android.view.View;
+import android.view.ViewStub;
+
+public class ViewStubTest extends ActivityInstrumentationTestCase<StubbedView> {
+    public ViewStubTest() {
+        super("com.android.frameworktest", StubbedView.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @MediumTest
+    public void testStubbed() throws Exception {
+        final StubbedView activity = getActivity();
+
+        final View stub = activity.findViewById(R.id.viewStub);
+        assertNotNull("The ViewStub does not exist", stub);
+    }
+
+    @UiThreadTest
+    @MediumTest
+    public void testInflated() throws Exception {
+        final StubbedView activity = getActivity();
+
+        final ViewStub stub = (ViewStub) activity.findViewById(R.id.viewStub);
+        final View swapped = stub.inflate();
+
+        assertNotNull("The inflated view is null", swapped);
+    }
+
+    @UiThreadTest
+    @MediumTest
+    public void testInflatedId() throws Exception {
+        final StubbedView activity = getActivity();
+
+        final ViewStub stub = (ViewStub) activity.findViewById(R.id.viewStubWithId);
+        final View swapped = stub.inflate();
+
+        assertNotNull("The inflated view is null", swapped);
+        assertTrue("The inflated view has no id", swapped.getId() != View.NO_ID);
+        assertTrue("The inflated view has the wrong id", swapped.getId() == R.id.stub_inflated);
+    }
+
+    @UiThreadTest
+    @MediumTest
+    public void testInflatedLayoutParams() throws Exception {
+        final StubbedView activity = getActivity();
+
+        final ViewStub stub = (ViewStub) activity.findViewById(R.id.viewStubWithId);
+        final View swapped = stub.inflate();
+
+        assertNotNull("The inflated view is null", swapped);
+
+        assertEquals("Both stub and inflated should same width",
+                stub.getLayoutParams().width, swapped.getLayoutParams().width);
+        assertEquals("Both stub and inflated should same height",
+                stub.getLayoutParams().height, swapped.getLayoutParams().height);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/view/VisibilityTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/VisibilityTest.java
new file mode 100644
index 0000000..77b281d
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/VisibilityTest.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.view;
+
+import com.android.frameworktest.view.Visibility;
+import com.android.frameworktest.R;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.Button;
+import android.widget.TextView;
+import android.view.View;
+import static android.view.KeyEvent.*;
+
+/**
+ * Exercises {@link android.view.View}'s ability to change visibility between
+ * GONE, VISIBLE and INVISIBLE.
+ */
+public class VisibilityTest extends ActivityInstrumentationTestCase<Visibility> {
+    private TextView mRefUp;
+    private TextView mRefDown;
+    private TextView mVictim;
+    private Button mVisible;
+    private Button mInvisible;
+    private Button mGone;
+
+    public VisibilityTest() {
+        super("com.android.frameworktest", Visibility.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        final Visibility a = getActivity();
+        mRefUp = (TextView) a.findViewById(R.id.refUp);
+        mRefDown = (TextView) a.findViewById(R.id.refDown);
+        mVictim = (TextView) a.findViewById(R.id.victim);
+        mVisible = (Button) a.findViewById(R.id.vis);
+        mInvisible = (Button) a.findViewById(R.id.invis);
+        mGone = (Button) a.findViewById(R.id.gone);
+    }
+
+    @MediumTest
+    public void testSetUpConditions() throws Exception {
+        assertNotNull(mRefUp);
+        assertNotNull(mRefDown);
+        assertNotNull(mVictim);
+        assertNotNull(mVisible);
+        assertNotNull(mInvisible);
+        assertNotNull(mGone);
+
+        assertTrue(mVisible.hasFocus());
+    }
+
+    @MediumTest
+    public void testVisibleToInvisible() throws Exception {
+        sendKeys("DPAD_RIGHT");
+        assertTrue(mInvisible.hasFocus());
+
+        int oldTop = mVictim.getTop();
+
+        sendKeys("DPAD_CENTER");
+        assertEquals(View.INVISIBLE, mVictim.getVisibility());
+
+        int newTop = mVictim.getTop();
+        assertEquals(oldTop, newTop);
+    }
+
+    @MediumTest
+    public void testVisibleToGone() throws Exception {
+        //sendKeys("2*DPAD_RIGHT");
+        sendRepeatedKeys(2, KEYCODE_DPAD_RIGHT);
+        assertTrue(mGone.hasFocus());
+
+        int oldTop = mVictim.getTop();
+
+        sendKeys("DPAD_CENTER");
+        assertEquals(View.GONE, mVictim.getVisibility());
+
+        int refDownTop = mRefDown.getTop();
+        assertEquals(oldTop, refDownTop);
+    }
+
+    @LargeTest
+    public void testGoneToVisible() throws Exception {
+        sendKeys("2*DPAD_RIGHT");
+        assertTrue(mGone.hasFocus());
+
+        int oldTop = mVictim.getTop();
+
+        sendKeys("DPAD_CENTER");
+        assertEquals(View.GONE, mVictim.getVisibility());
+
+        int refDownTop = mRefDown.getTop();
+        assertEquals(oldTop, refDownTop);
+
+        sendKeys("2*DPAD_LEFT DPAD_CENTER");
+        assertEquals(View.VISIBLE, mVictim.getVisibility());
+
+        int newTop = mVictim.getTop();
+        assertEquals(oldTop, newTop);
+    }
+
+    @MediumTest
+    public void testGoneToInvisible() throws Exception {
+        sendKeys("2*DPAD_RIGHT");
+        assertTrue(mGone.hasFocus());
+
+        int oldTop = mVictim.getTop();
+
+        sendKeys("DPAD_CENTER");
+        assertEquals(View.GONE, mVictim.getVisibility());
+
+        int refDownTop = mRefDown.getTop();
+        assertEquals(oldTop, refDownTop);
+
+        sendKeys(KEYCODE_DPAD_LEFT, KEYCODE_DPAD_CENTER);
+        assertEquals(View.INVISIBLE, mVictim.getVisibility());
+
+        int newTop = mVictim.getTop();
+        assertEquals(oldTop, newTop);
+    }
+
+    @MediumTest
+    public void testInvisibleToVisible() throws Exception {
+        sendKeys("DPAD_RIGHT");
+        assertTrue(mInvisible.hasFocus());
+
+        int oldTop = mVictim.getTop();
+
+        sendKeys("DPAD_CENTER");
+        assertEquals(View.INVISIBLE, mVictim.getVisibility());
+
+        int newTop = mVictim.getTop();
+        assertEquals(oldTop, newTop);
+
+        sendKeys("DPAD_LEFT DPAD_CENTER");
+        assertEquals(View.VISIBLE, mVictim.getVisibility());
+
+        newTop = mVictim.getTop();
+        assertEquals(oldTop, newTop);
+    }
+
+    @MediumTest
+    public void testInvisibleToGone() throws Exception {
+        sendKeys("DPAD_RIGHT");        
+        assertTrue(mInvisible.hasFocus());
+
+        int oldTop = mVictim.getTop();
+
+        sendKeys("DPAD_CENTER");
+        assertEquals(View.INVISIBLE, mVictim.getVisibility());
+
+        int newTop = mVictim.getTop();
+        assertEquals(oldTop, newTop);
+
+        sendKeys("DPAD_RIGHT DPAD_CENTER");
+        assertEquals(View.GONE, mVictim.getVisibility());
+
+        int refDownTop = mRefDown.getTop();
+        assertEquals(oldTop, refDownTop);
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/view/ZeroSizedTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/ZeroSizedTest.java
new file mode 100644
index 0000000..cd646e4
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/view/ZeroSizedTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2007 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.frameworktest.view;
+
+import com.android.frameworktest.view.ZeroSized;
+import com.android.frameworktest.R;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.View;
+import android.graphics.Bitmap;
+
+/**
+ * Builds the drawing cache of Views of various dimension. The assumption is that
+ * a View with a 0-sized dimension (width or height) will always have a null
+ * drawing cache.
+ */
+public class ZeroSizedTest extends ActivityInstrumentationTestCase<ZeroSized> {
+    private View mWithDimension;
+    private View mWithNoWdith;
+    private View mWithNoHeight;
+    private View mWithNoDimension;
+
+    public ZeroSizedTest() {
+        super("com.android.frameworktest", ZeroSized.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        final ZeroSized activity = getActivity();
+        mWithDimension = activity.findViewById(R.id.dimension);
+        mWithNoWdith = activity.findViewById(R.id.noWidth);
+        mWithNoHeight = activity.findViewById(R.id.noHeight);
+        mWithNoDimension = activity.findViewById(R.id.noDimension);
+    }
+
+    @MediumTest
+    public void testSetUpConditions() throws Exception {
+        assertNotNull(mWithDimension);
+        assertNotNull(mWithNoWdith);
+        assertNotNull(mWithNoHeight);
+        assertNotNull(mWithNoDimension);
+    }
+
+    @MediumTest
+    public void testDrawingCacheWithDimension() throws Exception {
+        assertTrue(mWithDimension.getWidth() > 0);
+        assertTrue(mWithDimension.getHeight() > 0);
+        assertNotNull(createCacheForView(mWithDimension));
+    }
+
+    @MediumTest
+    public void testDrawingCacheWithNoWidth() throws Exception {
+        assertTrue(mWithNoWdith.getWidth() == 0);
+        assertTrue(mWithNoWdith.getHeight() > 0);
+        assertNull(createCacheForView(mWithNoWdith));
+    }
+
+    @MediumTest
+    public void testDrawingCacheWithNoHeight() throws Exception {
+        assertTrue(mWithNoHeight.getWidth() > 0);
+        assertTrue(mWithNoHeight.getHeight() == 0);
+        assertNull(createCacheForView(mWithNoHeight));
+    }
+
+    @MediumTest
+    public void testDrawingCacheWithNoDimension() throws Exception {
+        assertTrue(mWithNoDimension.getWidth() == 0);
+        assertTrue(mWithNoDimension.getHeight() == 0);
+        assertNull(createCacheForView(mWithNoDimension));
+    }
+
+    private Bitmap createCacheForView(final View view) {
+        final Bitmap[] cache = new Bitmap[1];
+        getActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                view.setDrawingCacheEnabled(true);
+                view.invalidate();
+                view.buildDrawingCache();
+                cache[0] = view.getDrawingCache();
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+        return cache[0];
+    }
+}
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/widget/ListViewTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/widget/ListViewTest.java
new file mode 100644
index 0000000..ecb7d3a
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/widget/ListViewTest.java
@@ -0,0 +1,139 @@
+package com.android.frameworktest.widget;
+
+import com.google.android.collect.Lists;
+
+import junit.framework.Assert;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.test.InstrumentationTestCase;
+import android.test.mock.MockContext;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+import java.util.List;
+
+/**
+ * Copyright (C) 2007 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.
+ */
+
+public class ListViewTest extends InstrumentationTestCase {
+
+    /**
+     * If a view in a ListView requests a layout it should be remeasured.
+     */
+    @MediumTest
+    public void testRequestLayout() throws Exception {
+        MockContext context = new MockContext2();
+        ListView listView = new ListView(context);
+        List<String> items = Lists.newArrayList("hello");
+        Adapter<String> adapter = new Adapter<String>(context, 0, items);
+        listView.setAdapter(adapter);
+
+        int measureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY);
+
+        adapter.notifyDataSetChanged();
+        listView.measure(measureSpec, measureSpec);
+        listView.layout(0, 0, 100, 100);
+
+        MockView childView = (MockView) listView.getChildAt(0);
+
+        childView.requestLayout();
+        childView.onMeasureCalled = false;
+        listView.measure(measureSpec, measureSpec);
+        listView.layout(0, 0, 100, 100);
+        Assert.assertTrue(childView.onMeasureCalled);
+    }
+
+    /**
+     * The list view should handle the disappearance of the only selected item, even when that item
+     * was selected before its disappearance.
+     *
+     */
+    @MediumTest
+    public void testNoSelectableItems() throws Exception {
+        MockContext context = new MockContext2();
+        ListView listView = new ListView(context);
+        // We use a header as the unselectable item to remain after the selectable one is removed.
+        listView.addHeaderView(new View(context), null, false);
+        List<String> items = Lists.newArrayList("hello");
+        Adapter<String> adapter = new Adapter<String>(context, 0, items);
+        listView.setAdapter(adapter);
+
+        listView.setSelection(1);
+
+        int measureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY);
+
+        adapter.notifyDataSetChanged();
+        listView.measure(measureSpec, measureSpec);
+        listView.layout(0, 0, 100, 100);
+
+        items.remove(0);
+
+        adapter.notifyDataSetChanged();
+        listView.measure(measureSpec, measureSpec);
+        listView.layout(0, 0, 100, 100);
+    }
+
+    private class MockContext2 extends MockContext {
+
+        @Override
+        public Resources getResources() {
+            return getInstrumentation().getTargetContext().getResources();
+        }
+
+        @Override
+        public Resources.Theme getTheme() {
+            return getInstrumentation().getTargetContext().getTheme();
+        }
+
+        @Override
+        public Object getSystemService(String name) {
+            if (Context.LAYOUT_INFLATER_SERVICE.equals(name)) {
+                return getInstrumentation().getTargetContext().getSystemService(name);
+            }
+            return super.getSystemService(name);
+        }
+    }
+    
+    private class MockView extends View {
+
+        public boolean onMeasureCalled = false;
+
+        public MockView(Context context) {
+            super(context);
+        }
+
+        @Override
+        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+            onMeasureCalled = true;
+        }
+    }
+
+    private class Adapter<T> extends ArrayAdapter<T> {
+
+        public Adapter(Context context, int resource, List<T> objects) {
+            super(context, resource, objects);
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            return new MockView(getContext());
+        }
+    }
+
+}