auto import from //depot/cupcake/@135843
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);
+    }
+}