Create BasicAccessibility sample

Sample to demonstrate basic changes to an application to support
accessibility. Covers contentDescription, nextFocusUp/Down,
and adding AccessibilityEvent support to a custom view.

Change-Id: I99b7d9b469a352d7c73e1aa95de16b4cd4799ac0
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/build.gradle b/ui/accessibility/BasicAccessibility/BasicAccessibility/build.gradle
new file mode 100644
index 0000000..f8f1c8a
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/build.gradle
@@ -0,0 +1,23 @@
+buildscript {
+    repositories {
+        maven { url 'http://repo1.maven.org/maven2' }
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:0.4'
+    }
+}
+apply plugin: 'android'
+
+dependencies {
+    compile files('libs/android-support-v4.jar')
+}
+
+android {
+    compileSdkVersion 17
+    buildToolsVersion "17.0.0"
+
+    defaultConfig {
+        minSdkVersion 7
+        targetSdkVersion 16
+    }
+}
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/libs/android-support-v4.jar b/ui/accessibility/BasicAccessibility/BasicAccessibility/libs/android-support-v4.jar
new file mode 100644
index 0000000..428bdbc
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/libs/android-support-v4.jar
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/AndroidManifest.xml b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..3c0e66a
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/AndroidManifest.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.ui.accessibility.BasicAccessibility"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="11"
+        android:targetSdkVersion="16" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name="com.example.android.ui.accessibility.BasicAccessibility.MainActivity"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/ic_launcher-web.png b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/ic_launcher-web.png
new file mode 100644
index 0000000..6967d3e
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/ic_launcher-web.png
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/java/com/example/android/ui/accessibility/BasicAccessibility/DialView.java b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/java/com/example/android/ui/accessibility/BasicAccessibility/DialView.java
new file mode 100644
index 0000000..1fc5e0c
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/java/com/example/android/ui/accessibility/BasicAccessibility/DialView.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.ui.accessibility.BasicAccessibility;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+
+/**
+ * Custom view to demonstrate accessibility.
+ *
+ * <p>This view does not use any framework widgets, so does not get any accessibility features
+ * automatically. Instead, we use {@link AccessibilityEvent} to provide accessibility hints to
+ * the OS.
+ *
+ * <p>For example, if TalkBack is enabled, users will be able to receive spoken feedback as they
+ * interact with this view.
+ *
+ * <p>More generally, this view renders a multi-position "dial" that can be used to select a value
+ * between 1 and 4. Each time the dial is clicked, the next position will be selected (modulo
+ * the maximum number of positions).
+ */
+public class DialView extends View {
+    private static int SELECTION_COUNT = 4;
+
+    private static float FONT_SIZE = 40f;
+    private float mWidth;
+    private float mHeight;
+    private float mWidthPadded;
+    private float mHeightPadded;
+    private Paint mTextPaint;
+    private Paint mDialPaint;
+    private float mRadius;
+    private int mActiveSelection;
+
+    /**
+     * Constructor that is called when inflating a view from XML. This is called
+     * when a view is being constructed from an XML file, supplying attributes
+     * that were specified in the XML file.
+     *
+     * <p>In our case, this constructor just calls init().
+     *
+     * @param context The Context the view is running in, through which it can
+     *                access the current theme, resources, etc.
+     * @param attrs   The attributes of the XML tag that is inflating the view.
+     * @see #View(android.content.Context, android.util.AttributeSet, int)
+     */
+    public DialView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    /**
+     * Helper method to initialize instance variables. Called by constructor.
+     */
+    private void init() {
+        // Paint styles used for rendering are created here, rather than at render-time. This
+        // is a performance optimization, since onDraw() will get called frequently.
+        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        mTextPaint.setColor(Color.BLACK);
+        mTextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+        mTextPaint.setTextAlign(Paint.Align.CENTER);
+        mTextPaint.setTextSize(FONT_SIZE);
+
+        mDialPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        mDialPaint.setColor(Color.GRAY);
+
+        // Initialize current selection. This will store where the dial's "indicator" is pointing.
+        mActiveSelection = 0;
+
+        // Setup onClick listener for this view. Rotates between each of the different selection
+        // states on each click.
+        //
+        // Notice that we call sendAccessibilityEvent here. Some AccessibilityEvents are generated
+        // by the system. However, custom views will typically need to send events manually as the
+        // user interacts with the view. The type of event sent will vary, depending on the nature
+        // of the view and how the user interacts with it.
+        //
+        // In this case, we are sending TYPE_VIEW_SELECTED rather than TYPE_VIEW_CLICKED, because
+        // clicking on this view selects a new value.
+        //
+        // We will give our AccessibilityEvent further information about the state of the view in
+        // onPopulateAccessibilityEvent(), which will be called automatically by the system
+        // for each AccessibilityEvent.
+        setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                // Rotate selection to the next valid choice.
+                mActiveSelection = (mActiveSelection + 1) % SELECTION_COUNT;
+                // Send an AccessibilityEvent, since the user has interacted with the view.
+                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
+                // Redraw the entire view. (Inefficient, but this is sufficient for demonstration
+                // purposes.)
+                invalidate();
+            }
+        });
+    }
+
+    /**
+     * This is where a View should populate outgoing accessibility events with its text content.
+     * While this method is free to modify event attributes other than text content, doing so
+     * should normally be performed in
+     * {@link #onInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent)}.
+     * <p/>
+     * <p>Note that the behavior of this method will typically vary, depending on the type of
+     * accessibility event is passed into it. The allowed values also very, and are documented
+     * in {@link android.view.accessibility.AccessibilityEvent}.
+     * <p/>
+     * <p>Typically, this is where you'll describe the state of your custom view. You may also
+     * want to provide custom directions when the user has focused your view.
+     *
+     * @param event The accessibility event which to populate.
+     */
+    // BEGIN_INCLUDE (on_populate_accessibility_event)
+    @Override
+    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
+    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+        super.onPopulateAccessibilityEvent(event);
+
+        // Detect what type of accessibility event is being passed in.
+        int eventType = event.getEventType();
+
+        // Common case: The user has interacted with our view in some way. State may or may not
+        // have been changed. Read out the current status of the view.
+        //
+        // We also set some other metadata which is not used by TalkBack, but could be used by
+        // other TTS engines.
+        if (eventType == AccessibilityEvent.TYPE_VIEW_SELECTED ||
+                eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) {
+            event.getText().add("Mode selected: " + Integer.toString(mActiveSelection + 1) + ".");
+            event.setItemCount(SELECTION_COUNT);
+            event.setCurrentItemIndex(mActiveSelection);
+        }
+
+        // When a user first focuses on our view, we'll also read out some simple instructions to
+        // make it clear that this is an interactive element.
+        if (eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) {
+            event.getText().add("Tap to change.");
+        }
+    }
+    // END_INCLUDE (on_populate_accessibility_event)
+
+    /**
+     * This is called during layout when the size of this view has changed. If
+     * you were just added to the view hierarchy, you're called with the old
+     * values of 0.
+     *
+     * <p>This is where we determine the drawing bounds for our custom view.
+     *
+     * @param w    Current width of this view.
+     * @param h    Current height of this view.
+     * @param oldw Old width of this view.
+     * @param oldh Old height of this view.
+     */
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        // Account for padding
+        float xPadding = (float) (getPaddingLeft() + getPaddingRight());
+        float yPadding = (float) (getPaddingTop() + getPaddingBottom());
+
+        // Compute available width/height
+        mWidth = w;
+        mHeight = h;
+        mWidthPadded = w - xPadding;
+        mHeightPadded = h - yPadding;
+        mRadius = (float) (Math.min(mWidth, mHeight) / 2 * 0.8);
+    }
+
+    /**
+     * Render view content.
+     *
+     * <p>We render an outer grey circle to serve as our "dial", and then render a smaller black
+     * circle to server as our indicator. The position for the indicator is determined based
+     * on mActiveSelection.
+     *
+     * @param canvas the canvas on which the background will be drawn
+     */
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+        // Draw dial
+        canvas.drawCircle(mWidth / 2, mHeight / 2, (float) mRadius, mDialPaint);
+
+        // Draw text labels
+        final float labelRadius = mRadius + 10;
+        for (int i = 0; i < SELECTION_COUNT; i++) {
+            float[] xyData = computeXYForPosition(i, labelRadius);
+            float x = xyData[0];
+            float y = xyData[1];
+            canvas.drawText(Integer.toString(i + 1), x, y, mTextPaint);
+        }
+
+        // Draw indicator mark
+        final float markerRadius = mRadius - 35;
+        float[] xyData = computeXYForPosition(mActiveSelection, markerRadius);
+        float x = xyData[0];
+        float y = xyData[1];
+        canvas.drawCircle(x, y, 20, mTextPaint);
+    }
+
+    /**
+     * Compute the X/Y-coordinates for a label or indicator, given the position number and radius
+     * where the label should be drawn.
+     *
+     * @param pos    Zero based position index
+     * @param radius Radius where label/indicator is to be drawn.
+     * @return 2-element array. Element 0 is X-coordinate, element 1 is Y-coordinate.
+     */
+    private float[] computeXYForPosition(final int pos, final float radius) {
+        float[] result = new float[2];
+        Double startAngle = Math.PI * (9 / 8d);   // Angles are in radiansq
+        Double angle = startAngle + (pos * (Math.PI / 4));
+        result[0] = (float) (radius * Math.cos(angle)) + (mWidth / 2);
+        result[1] = (float) (radius * Math.sin(angle)) + (mHeight / 2);
+        return result;
+    }
+}
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/java/com/example/android/ui/accessibility/BasicAccessibility/MainActivity.java b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/java/com/example/android/ui/accessibility/BasicAccessibility/MainActivity.java
new file mode 100644
index 0000000..869301d
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/java/com/example/android/ui/accessibility/BasicAccessibility/MainActivity.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.ui.accessibility.BasicAccessibility;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * Basic activity class.
+ *
+ * <p>Responsible for rendering layout, and displaying some toasts to give buttons feedback.
+ * There's nothing terribly interesting in this class. All the interesting stuff is in
+ * res/layout/activity_main.xml and {@link DialView}.
+ */
+public class MainActivity extends Activity {
+
+    /**
+     * Standard onCreate() implementation. Sets R.layout.activity_main as the layout.
+     */
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+    }
+}
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-hdpi/ic_action_discard.png b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-hdpi/ic_action_discard.png
new file mode 100644
index 0000000..ece5ad8
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-hdpi/ic_action_discard.png
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-hdpi/ic_action_info.png b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-hdpi/ic_action_info.png
new file mode 100644
index 0000000..da65dea
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-hdpi/ic_action_info.png
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-hdpi/ic_launcher.png b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..6c0b5ee
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-hdpi/partly_cloudy.png b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-hdpi/partly_cloudy.png
new file mode 100644
index 0000000..b1b380c
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-hdpi/partly_cloudy.png
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-mdpi/ic_action_discard.png b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-mdpi/ic_action_discard.png
new file mode 100644
index 0000000..93483b6
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-mdpi/ic_action_discard.png
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-mdpi/ic_action_info.png b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-mdpi/ic_action_info.png
new file mode 100644
index 0000000..7f7e0a3
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-mdpi/ic_action_info.png
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-mdpi/ic_launcher.png b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..4ce0b82
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-xhdpi/ic_action_discard.png b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-xhdpi/ic_action_discard.png
new file mode 100644
index 0000000..94f7c8c
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-xhdpi/ic_action_discard.png
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-xhdpi/ic_action_info.png b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-xhdpi/ic_action_info.png
new file mode 100644
index 0000000..4ede9ce
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-xhdpi/ic_action_info.png
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-xhdpi/ic_launcher.png b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..6ded707
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-xxhdpi/ic_launcher.png b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..74ae891
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/layout/activity_main.xml b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..394c72f
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/layout/activity_main.xml
@@ -0,0 +1,206 @@
+<!--
+Copyright (C) 2013 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              xmlns:tools="http://schemas.android.com/tools"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:gravity="center_horizontal">
+    <ScrollView
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:fillViewport="false">
+        <RelativeLayout
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:paddingLeft="@dimen/activity_horizontal_margin"
+                android:paddingRight="@dimen/activity_horizontal_margin"
+                android:paddingTop="@dimen/activity_vertical_margin"
+                android:paddingBottom="@dimen/activity_vertical_margin"
+                tools:context=".MainActivity"
+                >
+
+            <!-- Notice the presence of nextFocusDown/nextFocusUp on the elements below. You can
+            also use nextFocusLeft/nextFocusRight. This tells the system in what order elements
+            should be navigated through. If not present, the system will make a guess based on
+            element location in the layout. -->
+            <TextView
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="Buttons"
+                    android:id="@+id/buttonsLabel"
+                    android:layout_alignParentTop="true"
+                    android:layout_alignParentLeft="true"
+                    android:nextFocusDown="@+id/composeButton"/>
+
+            <!-- This is a regular, text-based button. No contentDescription is needed, since the
+                 text field sufficiently describes the action performed. -->
+            <Button
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/composeButtonLabel"
+                    android:id="@+id/composeButton"
+                    android:layout_below="@+id/buttonsLabel"
+                    android:layout_alignLeft="@+id/buttonsLabel"
+                    android:nextFocusUp="@+id/buttonsLabel"
+                    android:nextFocusDown="@+id/checkboxesLabel"
+                    />
+
+            <!-- The next two buttons are different types of image-based buttons. -->
+
+            <!-- BEGIN_INCLUDE (image_content_description) -->
+            <!-- Adding a contentDescription is needed for accessibility, since no text is present.
+            Since the contentDescription is read verbatim, you may want to be a bit more
+            descriptive than usual, such as adding "button" to the end of your description, if
+            appropriate. -->
+            <ImageButton
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:id="@+id/discardButton"
+                    android:layout_alignTop="@+id/composeButton"
+                    android:layout_toRightOf="@+id/composeButton"
+                    android:src="@drawable/ic_action_discard"
+                    android:layout_alignBottom="@+id/composeButton"
+                    android:contentDescription="@string/discardButtonDescription"
+                    android:scaleType="fitCenter"
+                    android:nextFocusUp="@+id/buttonsLabel"
+                    android:nextFocusDown="@+id/checkboxesLabel"
+                    />
+            <!-- END_INCLUDE (image_content_description) -->
+
+            <ImageButton
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:id="@+id/infoButton"
+                    android:layout_alignTop="@+id/discardButton"
+                    android:layout_toRightOf="@+id/discardButton"
+                    android:src="@drawable/ic_action_info"
+                    android:layout_alignBottom="@+id/discardButton"
+                    android:layout_alignRight="@+id/hyperspaceCheckbox"
+                    android:scaleType="fitCenter"
+                    android:background="?android:selectableItemBackground"
+                    android:padding="5dp"
+                    android:contentDescription="@string/infoButtonDescription"
+                    android:nextFocusUp="@+id/buttonsLabel"
+                    android:nextFocusDown="@+id/checkboxesLabel"
+            />
+
+            <TextView
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/checkboxesLabel"
+                    android:id="@+id/checkboxesLabel"
+                    android:layout_below="@+id/composeButton"
+                    android:layout_alignLeft="@+id/composeButton"
+                    android:nextFocusUp="@+id/composeButton"
+                    android:nextFocusDown="@+id/jetpackCheckbox"
+                    />
+
+            <!-- Like a text-based button, checkboxes with text will often work correctly as-is.
+                 If your checkboxes do not have a text attribute, you will need to add a
+                 contentDescriptoin. -->
+            <CheckBox
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/jetpackCheckboxLabel"
+                    android:id="@+id/jetpackCheckbox"
+                    android:layout_below="@+id/checkboxesLabel"
+                    android:layout_alignLeft="@+id/checkboxesLabel"
+                    android:checked="false"
+                    android:nextFocusUp="@+id/checkboxesLabel"
+                    android:nextFocusDown="@+id/hyperspaceCheckbox"
+                    />
+
+            <CheckBox
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/hyperspaceCheckboxLabel"
+                    android:id="@+id/hyperspaceCheckbox"
+                    android:layout_below="@+id/jetpackCheckbox"
+                    android:layout_alignLeft="@+id/jetpackCheckbox"
+                    android:checked="false"
+                    android:nextFocusUp="@+id/jetpackCheckbox"
+                    android:nextFocusDown="@+id/imagesAndTextLabel"
+                    />
+
+            <TextView
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/imagesAndTextLabel"
+                    android:id="@+id/imagesAndTextLabel"
+                    android:layout_below="@+id/hyperspaceCheckbox"
+                    android:layout_alignLeft="@+id/hyperspaceCheckbox"
+                    android:nextFocusUp="@+id/hyperspaceCheckbox"
+                    android:nextFocusDown="@+id/partlyCloudImage"
+                    />
+
+            <!-- Images should have a contentDescription if they convey any meaningful
+                 information. Images that are purely decorative may not need a contentDescription,
+                 however. -->
+            <ImageView
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:id="@+id/partlyCloudyImage"
+                    android:layout_below="@+id/imagesAndTextLabel"
+                    android:layout_alignLeft="@+id/imagesAndTextLabel"
+                    android:src="@drawable/partly_cloudy"
+                    android:contentDescription="@string/partlyCloudyDescription"
+                    android:layout_alignRight="@+id/discardButton"
+                    android:nextFocusUp="@+id/imagesAndTextLabel"
+                    android:nextFocusDown="@+id/customViewLabel"
+                    />
+
+            <!-- TextViews are typically self describing, so do not need extra modifications. -->
+            <TextView
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:textAppearance="?android:attr/textAppearanceLarge"
+                    android:text="@string/temperature"
+                    android:textSize="60sp"
+                    android:id="@+id/temperatureText"
+                    android:layout_alignTop="@+id/partlyCloudyImage"
+                    android:layout_toRightOf="@+id/partlyCloudyImage"
+                    android:layout_alignBottom="@+id/partlyCloudyImage"
+                    android:gravity="center_vertical"
+                    android:nextFocusUp="@+id/imagesAndTextLabel"
+                    android:nextFocusDown="@+id/customViewLabel"
+                    />
+
+            <TextView
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/customViewLabel"
+                    android:id="@+id/customViewLabel"
+                    android:layout_below="@+id/partlyCloudyImage"
+                    android:layout_alignLeft="@+id/partlyCloudyImage"
+                    android:nextFocusUp="@+id/partlyCloudImage"
+                    android:nextFocusDown="@+id/dialView"
+                    />
+
+            <!-- Custom views require additonal code changes. See DialView.java for more
+                 details. -->
+            <com.example.android.ui.accessibility.BasicAccessibility.DialView
+                    android:layout_width="200dp"
+                    android:layout_height="200dp"
+                    android:id="@+id/dialView"
+                    android:layout_below="@+id/customViewLabel"
+                    android:layout_alignLeft="@+id/partlyCloudyImage"
+                    android:nextFocusUp="@+id/customViewLabel"
+                    />
+
+        </RelativeLayout>
+    </ScrollView>
+</LinearLayout>
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values-sw600dp/dimens.xml b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values-sw600dp/dimens.xml
new file mode 100644
index 0000000..d0946b3
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values-sw600dp/dimens.xml
@@ -0,0 +1,20 @@
+<!--
+Copyright (C) 2013 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<resources>
+    <!-- Customize dimensions originally defined in res/values/dimens.xml (such as
+         screen margins) for sw600dp devices (e.g. 7" tablets) here. -->
+</resources>
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values-sw720dp-land/dimens.xml b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values-sw720dp-land/dimens.xml
new file mode 100644
index 0000000..2c2d431
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values-sw720dp-land/dimens.xml
@@ -0,0 +1,21 @@
+<!--
+Copyright (C) 2013 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<resources>
+    <!-- Customize dimensions originally defined in res/values/dimens.xml (such as
+         screen margins) for sw720dp devices (e.g. 10" tablets) in landscape here. -->
+    <dimen name="activity_horizontal_margin">128dp</dimen>
+</resources>
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values-v11/styles.xml b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values-v11/styles.xml
new file mode 100644
index 0000000..5b1a3f2
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values-v11/styles.xml
@@ -0,0 +1,27 @@
+<!--
+Copyright (C) 2013 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<resources>
+
+    <!--
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+        <!-- API 11 theme customizations can go here. -->
+    </style>
+
+</resources>
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values-v14/styles.xml b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values-v14/styles.xml
new file mode 100644
index 0000000..b16c97b
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values-v14/styles.xml
@@ -0,0 +1,28 @@
+<!--
+Copyright (C) 2013 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<resources>
+
+    <!--
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+        <!-- API 14 theme customizations can go here. -->
+    </style>
+
+</resources>
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values/dimens.xml b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..a5e4ebe
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values/dimens.xml
@@ -0,0 +1,20 @@
+<!--
+Copyright (C) 2013 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<resources>
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+</resources>
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values/strings.xml b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values/strings.xml
new file mode 100644
index 0000000..57b8e49
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2013 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<resources>
+
+    <string name="app_name" >Accessibility Sample</string>
+    <string name="composeButtonPressed">(Compose button pressed.)</string>
+    <string name="discardButtonPressed">(Discard button pressed.)</string>
+    <string name="infoButtonPressed">(Info button pressed.)</string>
+    <string name="composeButtonLabel">Compose</string>
+    <string name="discardButtonDescription">Discard Button</string>
+    <string name="infoButtonDescription">Info Button</string>
+    <string name="partlyCloudyDescription">Partly Cloudy</string>
+    <string name="checkboxesLabel">Checkboxes</string>
+    <string name="jetpackCheckboxLabel">Enable Jetpack</string>
+    <string name="hyperspaceCheckboxLabel">Enable Hyperspace Engines</string>
+    <string name="imagesAndTextLabel">Images &amp; Text</string>
+    <string name="temperature">53 °F</string>
+    <string name="customViewLabel">Custom View</string>
+</resources>
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values/styles.xml b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values/styles.xml
new file mode 100644
index 0000000..b0e6075
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values/styles.xml
@@ -0,0 +1,36 @@
+<!--
+Copyright (C) 2013 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+</resources>
diff --git a/ui/accessibility/BasicAccessibility/build.gradle b/ui/accessibility/BasicAccessibility/build.gradle
new file mode 100644
index 0000000..495c503
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/build.gradle
@@ -0,0 +1 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
diff --git a/ui/accessibility/BasicAccessibility/settings.gradle b/ui/accessibility/BasicAccessibility/settings.gradle
new file mode 100644
index 0000000..1c4fa86
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/settings.gradle
@@ -0,0 +1 @@
+include ':BasicAccessibility'