Merge "VideoEditor: Issue ID:3396697 Missing Files added"
diff --git a/api/current.xml b/api/current.xml
index 5f732e1..968b8ed6 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -257571,6 +257571,21 @@
 <parameter name="started" type="boolean">
 </parameter>
 </method>
+<method name="setDisplayedChild"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="viewId" type="int">
+</parameter>
+<parameter name="childIndex" type="int">
+</parameter>
+</method>
 <method name="setDouble"
  return="void"
  abstract="false"
@@ -265605,7 +265620,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="arg0" type="T">
+<parameter name="t" type="T">
 </parameter>
 </method>
 </interface>
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index f74e3c8..9e6bcc8 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -116,9 +116,7 @@
 
 #ifdef FWDUMP_bcm4329
     run_command("DUMP WIFI STATUS", 20,
-            "su", "root", "dhdutil", "-i", "eth0", "dump", NULL);
-    run_command("DUMP WIFI FIRMWARE LOG", 60,
-            "su", "root", "dhdutil", "-i", "eth0", "upload", "/data/local/tmp/wlan_crash.dump", NULL);
+            "su", "root", "dhdutil", "-i", "wlan0", "dump", NULL);
     run_command("DUMP WIFI INTERNAL COUNTERS", 20,
             "su", "root", "wlutil", "counters", NULL);
 #endif
diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java
index 3f03a2a..9c36b12 100644
--- a/core/java/android/net/LinkAddress.java
+++ b/core/java/android/net/LinkAddress.java
@@ -19,6 +19,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.net.Inet4Address;
 import java.net.InetAddress;
 import java.net.InterfaceAddress;
 import java.net.UnknownHostException;
@@ -38,12 +39,13 @@
      */
     private final int prefixLength;
 
-    public LinkAddress(InetAddress address, InetAddress mask) {
-        this.address = address;
-        this.prefixLength = computeprefixLength(mask);
-    }
-
     public LinkAddress(InetAddress address, int prefixLength) {
+        if (address == null || prefixLength < 0 ||
+                ((address instanceof Inet4Address) && prefixLength > 32) ||
+                (prefixLength > 128)) {
+            throw new IllegalArgumentException("Bad LinkAddress params " + address +
+                    prefixLength);
+        }
         this.address = address;
         this.prefixLength = prefixLength;
     }
@@ -53,18 +55,6 @@
         this.prefixLength = interfaceAddress.getNetworkPrefixLength();
     }
 
-    private static int computeprefixLength(InetAddress mask) {
-        int count = 0;
-        for (byte b : mask.getAddress()) {
-            for (int i = 0; i < 8; ++i) {
-                if ((b & (1 << i)) != 0) {
-                    ++count;
-                }
-            }
-        }
-        return count;
-    }
-
     @Override
     public String toString() {
         return (address == null ? "" : (address.getHostAddress() + "/" + prefixLength));
diff --git a/core/java/android/provider/Calendar.java b/core/java/android/provider/Calendar.java
index c007605..de71763 100644
--- a/core/java/android/provider/Calendar.java
+++ b/core/java/android/provider/Calendar.java
@@ -59,6 +59,10 @@
     public static final String EVENT_BEGIN_TIME = "beginTime";
     public static final String EVENT_END_TIME = "endTime";
 
+    /**
+     * This must not be changed or horrible, unspeakable things could happen.
+     * For instance, the Calendar app might break. Also, the db might not work.
+     */
     public static final String AUTHORITY = "com.android.calendar";
 
     /**
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 8f922e2..b05b078 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -3843,60 +3843,6 @@
          * @hide
          */
         public static final String SNIPPET_ARGS_PARAM_KEY = "snippet_args";
-
-        /**
-         * The ID of the data row that was matched by the filter.
-         *
-         * @hide
-         * @deprecated
-         */
-        @Deprecated
-        public static final String SNIPPET_DATA_ID = "snippet_data_id";
-
-        /**
-         * The type of data that was matched by the filter.
-         *
-         * @hide
-         * @deprecated
-         */
-        @Deprecated
-        public static final String SNIPPET_MIMETYPE = "snippet_mimetype";
-
-        /**
-         * The {@link Data#DATA1} field of the data row that was matched by the filter.
-         *
-         * @hide
-         * @deprecated
-         */
-        @Deprecated
-        public static final String SNIPPET_DATA1 = "snippet_data1";
-
-        /**
-         * The {@link Data#DATA2} field of the data row that was matched by the filter.
-         *
-         * @hide
-         * @deprecated
-         */
-        @Deprecated
-        public static final String SNIPPET_DATA2 = "snippet_data2";
-
-        /**
-         * The {@link Data#DATA3} field of the data row that was matched by the filter.
-         *
-         * @hide
-         * @deprecated
-         */
-        @Deprecated
-        public static final String SNIPPET_DATA3 = "snippet_data3";
-
-        /**
-         * The {@link Data#DATA4} field of the data row that was matched by the filter.
-         *
-         * @hide
-         * @deprecated
-         */
-        @Deprecated
-        public static final String SNIPPET_DATA4 = "snippet_data4";
     }
 
     /**
diff --git a/core/java/android/server/BluetoothInputProfileHandler.java b/core/java/android/server/BluetoothInputProfileHandler.java
new file mode 100644
index 0000000..7ffa5ae
--- /dev/null
+++ b/core/java/android/server/BluetoothInputProfileHandler.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothDeviceProfileState;
+import android.bluetooth.BluetoothInputDevice;
+import android.bluetooth.BluetoothProfileState;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Message;
+import android.provider.Settings;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * This handles all the operations on the HID profile.
+ * All functions are called by BluetoothService, as Bluetooth Service
+ * is the Service handler for the HID profile.
+ */
+final class BluetoothInputProfileHandler {
+    private static final String TAG = "BluetoothInputProfileHandler";
+    private static final boolean DBG = true;
+
+    public static BluetoothInputProfileHandler sInstance;
+    private Context mContext;
+    private BluetoothService mBluetoothService;
+    private final HashMap<BluetoothDevice, Integer> mInputDevices;
+    private final BluetoothProfileState mHidProfileState;
+
+    private BluetoothInputProfileHandler(Context context, BluetoothService service) {
+        mContext = context;
+        mBluetoothService = service;
+        mInputDevices = new HashMap<BluetoothDevice, Integer>();
+        mHidProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.HID);
+        mHidProfileState.start();
+    }
+
+    static synchronized BluetoothInputProfileHandler getInstance(Context context,
+            BluetoothService service) {
+        if (sInstance == null) sInstance = new BluetoothInputProfileHandler(context, service);
+        return sInstance;
+    }
+
+    synchronized boolean connectInputDevice(BluetoothDevice device,
+                                            BluetoothDeviceProfileState state) {
+        String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
+        if (objectPath == null ||
+            getInputDeviceState(device) != BluetoothInputDevice.STATE_DISCONNECTED ||
+            getInputDevicePriority(device) == BluetoothInputDevice.PRIORITY_OFF) {
+            return false;
+        }
+        if (state != null) {
+            Message msg = new Message();
+            msg.arg1 = BluetoothDeviceProfileState.CONNECT_HID_OUTGOING;
+            msg.obj = state;
+            mHidProfileState.sendMessage(msg);
+            return true;
+        }
+        return false;
+    }
+
+    synchronized boolean connectInputDeviceInternal(BluetoothDevice device) {
+        String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
+        handleInputDeviceStateChange(device, BluetoothInputDevice.STATE_CONNECTING);
+        if (!mBluetoothService.connectInputDeviceNative(objectPath)) {
+            handleInputDeviceStateChange(device, BluetoothInputDevice.STATE_DISCONNECTED);
+            return false;
+        }
+        return true;
+    }
+
+    synchronized boolean disconnectInputDevice(BluetoothDevice device,
+                                               BluetoothDeviceProfileState state) {
+        String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
+        if (objectPath == null ||
+                getInputDeviceState(device) == BluetoothInputDevice.STATE_DISCONNECTED) {
+            return false;
+        }
+        if (state != null) {
+            Message msg = new Message();
+            msg.arg1 = BluetoothDeviceProfileState.DISCONNECT_HID_OUTGOING;
+            msg.obj = state;
+            mHidProfileState.sendMessage(msg);
+            return true;
+        }
+        return false;
+    }
+
+    synchronized boolean disconnectInputDeviceInternal(BluetoothDevice device) {
+        String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
+        handleInputDeviceStateChange(device, BluetoothInputDevice.STATE_DISCONNECTING);
+        if (!mBluetoothService.disconnectInputDeviceNative(objectPath)) {
+            handleInputDeviceStateChange(device, BluetoothInputDevice.STATE_CONNECTED);
+            return false;
+        }
+        return true;
+    }
+
+    synchronized int getInputDeviceState(BluetoothDevice device) {
+        if (mInputDevices.get(device) == null) {
+            return BluetoothInputDevice.STATE_DISCONNECTED;
+        }
+        return mInputDevices.get(device);
+    }
+
+    synchronized List<BluetoothDevice> getConnectedInputDevices() {
+        List<BluetoothDevice> devices = lookupInputDevicesMatchingStates(
+            new int[] {BluetoothInputDevice.STATE_CONNECTED});
+        return devices;
+    }
+
+    synchronized int getInputDevicePriority(BluetoothDevice device) {
+        return Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.getBluetoothInputDevicePriorityKey(device.getAddress()),
+                BluetoothInputDevice.PRIORITY_UNDEFINED);
+    }
+
+    synchronized boolean setInputDevicePriority(BluetoothDevice device, int priority) {
+        if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
+            return false;
+        }
+        return Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Secure.getBluetoothInputDevicePriorityKey(device.getAddress()),
+                priority);
+    }
+
+    synchronized List<BluetoothDevice> lookupInputDevicesMatchingStates(int[] states) {
+        List<BluetoothDevice> inputDevices = new ArrayList<BluetoothDevice>();
+
+        for (BluetoothDevice device: mInputDevices.keySet()) {
+            int inputDeviceState = getInputDeviceState(device);
+            for (int state : states) {
+                if (state == inputDeviceState) {
+                    inputDevices.add(device);
+                    break;
+                }
+            }
+        }
+        return inputDevices;
+    }
+
+    private synchronized void handleInputDeviceStateChange(BluetoothDevice device, int state) {
+        int prevState;
+        if (mInputDevices.get(device) == null) {
+            prevState = BluetoothInputDevice.STATE_DISCONNECTED;
+        } else {
+            prevState = mInputDevices.get(device);
+        }
+        if (prevState == state) return;
+
+        mInputDevices.put(device, state);
+
+        if (getInputDevicePriority(device) >
+              BluetoothInputDevice.PRIORITY_OFF &&
+            state == BluetoothInputDevice.STATE_CONNECTING ||
+            state == BluetoothInputDevice.STATE_CONNECTED) {
+            // We have connected or attempting to connect.
+            // Bump priority
+            setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_AUTO_CONNECT);
+        }
+
+        Intent intent = new Intent(BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED);
+        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
+        intent.putExtra(BluetoothInputDevice.EXTRA_PREVIOUS_INPUT_DEVICE_STATE, prevState);
+        intent.putExtra(BluetoothInputDevice.EXTRA_INPUT_DEVICE_STATE, state);
+        mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM);
+
+        debugLog("InputDevice state : device: " + device + " State:" + prevState + "->" + state);
+        mBluetoothService.sendConnectionStateChange(device, state, prevState);
+    }
+
+    synchronized void handleInputDevicePropertyChange(String address, boolean connected) {
+        int state = connected ? BluetoothInputDevice.STATE_CONNECTED :
+            BluetoothInputDevice.STATE_DISCONNECTED;
+        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+        BluetoothDevice device = adapter.getRemoteDevice(address);
+        handleInputDeviceStateChange(device, state);
+    }
+
+    synchronized void setInitialInputDevicePriority(BluetoothDevice device, int state) {
+        switch (state) {
+            case BluetoothDevice.BOND_BONDED:
+                if (getInputDevicePriority(device) == BluetoothInputDevice.PRIORITY_UNDEFINED) {
+                    setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_ON);
+                }
+                break;
+            case BluetoothDevice.BOND_NONE:
+                setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_UNDEFINED);
+                break;
+        }
+    }
+
+    private static void debugLog(String msg) {
+        if (DBG) Log.d(TAG, msg);
+    }
+
+    private static void errorLog(String msg) {
+        Log.e(TAG, msg);
+    }
+}
diff --git a/core/java/android/server/BluetoothPanProfileHandler.java b/core/java/android/server/BluetoothPanProfileHandler.java
new file mode 100644
index 0000000..fb96439
--- /dev/null
+++ b/core/java/android/server/BluetoothPanProfileHandler.java
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothPan;
+import android.bluetooth.BluetoothTetheringDataTracker;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources.NotFoundException;
+import android.net.ConnectivityManager;
+import android.net.InterfaceConfiguration;
+import android.net.LinkAddress;
+import android.os.IBinder;
+import android.os.INetworkManagementService;
+import android.os.ServiceManager;
+import android.util.Log;
+
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * This handles the PAN profile. All calls into this are made
+ * from Bluetooth Service.
+ */
+final class BluetoothPanProfileHandler {
+    private static final String TAG = "BluetoothPanProfileHandler";
+    private static final boolean DBG = true;
+
+    private ArrayList<String> mBluetoothIfaceAddresses;
+    private int mMaxPanDevices;
+
+    private static final String BLUETOOTH_IFACE_ADDR_START= "192.168.44.1";
+    private static final int BLUETOOTH_MAX_PAN_CONNECTIONS = 5;
+    private static final int BLUETOOTH_PREFIX_LENGTH        = 24;
+    public static BluetoothPanProfileHandler sInstance;
+    private final HashMap<BluetoothDevice, BluetoothPanDevice> mPanDevices;
+    private boolean mTetheringOn;
+    private Context mContext;
+    private BluetoothService mBluetoothService;
+
+    private BluetoothPanProfileHandler(Context context, BluetoothService service) {
+        mContext = context;
+        mPanDevices = new HashMap<BluetoothDevice, BluetoothPanDevice>();
+        mBluetoothService = service;
+        mTetheringOn = false;
+        mBluetoothIfaceAddresses = new ArrayList<String>();
+        try {
+            mMaxPanDevices = context.getResources().getInteger(
+                            com.android.internal.R.integer.config_max_pan_devices);
+        } catch (NotFoundException e) {
+            mMaxPanDevices = BLUETOOTH_MAX_PAN_CONNECTIONS;
+        }
+    }
+
+    static synchronized BluetoothPanProfileHandler getInstance(Context context,
+            BluetoothService service) {
+        if (sInstance == null) sInstance = new BluetoothPanProfileHandler(context, service);
+        return sInstance;
+    }
+
+    synchronized boolean isTetheringOn() {
+        return mTetheringOn;
+    }
+
+    synchronized boolean allowIncomingTethering() {
+        if (isTetheringOn() && getConnectedPanDevices().size() < mMaxPanDevices)
+            return true;
+        return false;
+    }
+
+    private BroadcastReceiver mTetheringReceiver = null;
+
+    synchronized void setBluetoothTethering(boolean value) {
+        if (!value) {
+            disconnectPanServerDevices();
+        }
+
+        if (mBluetoothService.getBluetoothState() != BluetoothAdapter.STATE_ON && value) {
+            IntentFilter filter = new IntentFilter();
+            filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
+            mTetheringReceiver = new BroadcastReceiver() {
+                @Override
+                public synchronized void onReceive(Context context, Intent intent) {
+                    if (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF)
+                            == BluetoothAdapter.STATE_ON) {
+                        mTetheringOn = true;
+                        mContext.unregisterReceiver(mTetheringReceiver);
+                    }
+                }
+            };
+            mContext.registerReceiver(mTetheringReceiver, filter);
+        } else {
+            mTetheringOn = value;
+        }
+    }
+
+    synchronized int getPanDeviceState(BluetoothDevice device) {
+        BluetoothPanDevice panDevice = mPanDevices.get(device);
+        if (panDevice == null) {
+            return BluetoothPan.STATE_DISCONNECTED;
+        }
+        return panDevice.mState;
+    }
+
+    synchronized boolean connectPanDevice(BluetoothDevice device) {
+        String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
+        if (DBG) Log.d(TAG, "connect PAN(" + objectPath + ")");
+        if (getPanDeviceState(device) != BluetoothPan.STATE_DISCONNECTED) {
+            errorLog(device + " already connected to PAN");
+        }
+
+        int connectedCount = 0;
+        for (BluetoothDevice panDevice: mPanDevices.keySet()) {
+            if (getPanDeviceState(panDevice) == BluetoothPan.STATE_CONNECTED) {
+                connectedCount ++;
+            }
+        }
+        if (connectedCount > 8) {
+            debugLog(device + " could not connect to PAN because 8 other devices are"
+                    + "already connected");
+            return false;
+        }
+
+        handlePanDeviceStateChange(device, BluetoothPan.STATE_CONNECTING,
+                                           BluetoothPan.LOCAL_PANU_ROLE);
+        if (mBluetoothService.connectPanDeviceNative(objectPath, "nap")) {
+            debugLog("connecting to PAN");
+            return true;
+        } else {
+            handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTED,
+                                                BluetoothPan.LOCAL_PANU_ROLE);
+            errorLog("could not connect to PAN");
+            return false;
+        }
+    }
+
+    private synchronized boolean disconnectPanServerDevices() {
+        debugLog("disconnect all PAN devices");
+
+        for (BluetoothDevice device: mPanDevices.keySet()) {
+            BluetoothPanDevice panDevice = mPanDevices.get(device);
+            int state = panDevice.mState;
+            if (state == BluetoothPan.STATE_CONNECTED &&
+                    panDevice.mLocalRole == BluetoothPan.LOCAL_NAP_ROLE) {
+                String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
+
+                handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTING,
+                        panDevice.mLocalRole);
+
+                if (!mBluetoothService.disconnectPanServerDeviceNative(objectPath,
+                        device.getAddress(),
+                        panDevice.mIfaceAddr)) {
+                    errorLog("could not disconnect Pan Server Device "+device.getAddress());
+
+                    // Restore prev state
+                    handlePanDeviceStateChange(device, state,
+                            panDevice.mLocalRole);
+
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    synchronized List<BluetoothDevice> getConnectedPanDevices() {
+        List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();
+
+        for (BluetoothDevice device: mPanDevices.keySet()) {
+            if (getPanDeviceState(device) == BluetoothPan.STATE_CONNECTED) {
+                devices.add(device);
+            }
+        }
+        return devices;
+    }
+
+    synchronized boolean disconnectPanDevice(BluetoothDevice device) {
+        String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
+        debugLog("disconnect PAN(" + objectPath + ")");
+
+        int state = getPanDeviceState(device);
+        if (state != BluetoothPan.STATE_CONNECTED) {
+            debugLog(device + " already disconnected from PAN");
+            return false;
+        }
+
+        BluetoothPanDevice panDevice = mPanDevices.get(device);
+
+        if (panDevice == null) {
+            errorLog("No record for this Pan device:" + device);
+            return false;
+        }
+
+        handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTING,
+                                    panDevice.mLocalRole);
+        if (panDevice.mLocalRole == BluetoothPan.LOCAL_NAP_ROLE) {
+            if (!mBluetoothService.disconnectPanServerDeviceNative(objectPath, device.getAddress(),
+                    panDevice.mIface)) {
+                // Restore prev state, this shouldn't happen
+                handlePanDeviceStateChange(device, state, panDevice.mLocalRole);
+                return false;
+            }
+        } else {
+            if (!mBluetoothService.disconnectPanDeviceNative(objectPath)) {
+                // Restore prev state, this shouldn't happen
+                handlePanDeviceStateChange(device, state, panDevice.mLocalRole);
+                return false;
+            }
+        }
+        return true;
+    }
+
+    synchronized void handlePanDeviceStateChange(BluetoothDevice device,
+                                                 String iface, int state, int role) {
+        int prevState;
+        String ifaceAddr = null;
+        BluetoothPanDevice panDevice = mPanDevices.get(device);
+
+        if (panDevice == null) {
+            prevState = BluetoothPan.STATE_DISCONNECTED;
+        } else {
+            prevState = panDevice.mState;
+            ifaceAddr = panDevice.mIfaceAddr;
+        }
+        if (prevState == state) return;
+
+        if (role == BluetoothPan.LOCAL_NAP_ROLE) {
+            if (state == BluetoothPan.STATE_CONNECTED) {
+                ifaceAddr = enableTethering(iface);
+                if (ifaceAddr == null) Log.e(TAG, "Error seting up tether interface");
+            } else if (state == BluetoothPan.STATE_DISCONNECTED) {
+                if (ifaceAddr != null) {
+                    mBluetoothIfaceAddresses.remove(ifaceAddr);
+                    ifaceAddr = null;
+                }
+            }
+        } else {
+            // PANU Role = reverse Tether
+            if (state == BluetoothPan.STATE_CONNECTED) {
+                BluetoothTetheringDataTracker.getInstance().startReverseTether(iface, device);
+            } else if (state == BluetoothPan.STATE_DISCONNECTED &&
+                  (prevState == BluetoothPan.STATE_CONNECTED ||
+                  prevState == BluetoothPan.STATE_DISCONNECTING)) {
+                BluetoothTetheringDataTracker.getInstance().stopReverseTether(panDevice.mIface);
+            }
+        }
+
+        if (panDevice == null) {
+            panDevice = new BluetoothPanDevice(state, ifaceAddr, iface, role);
+            mPanDevices.put(device, panDevice);
+        } else {
+            panDevice.mState = state;
+            panDevice.mIfaceAddr = ifaceAddr;
+            panDevice.mLocalRole = role;
+        }
+
+        if (state == BluetoothPan.STATE_DISCONNECTED) {
+            mPanDevices.remove(device);
+        }
+
+        Intent intent = new Intent(BluetoothPan.ACTION_PAN_STATE_CHANGED);
+        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
+        intent.putExtra(BluetoothPan.EXTRA_PREVIOUS_PAN_STATE, prevState);
+        intent.putExtra(BluetoothPan.EXTRA_PAN_STATE, state);
+        intent.putExtra(BluetoothPan.EXTRA_LOCAL_ROLE, role);
+        mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM);
+
+        debugLog("Pan Device state : device: " + device + " State:" + prevState + "->" + state);
+        mBluetoothService.sendConnectionStateChange(device, state, prevState);
+    }
+
+    synchronized void handlePanDeviceStateChange(BluetoothDevice device,
+                                                 int state, int role) {
+        handlePanDeviceStateChange(device, null, state, role);
+    }
+
+    private class BluetoothPanDevice {
+        private int mState;
+        private String mIfaceAddr;
+        private String mIface;
+        private int mLocalRole; // Which local role is this PAN device bound to
+
+        BluetoothPanDevice(int state, String ifaceAddr, String iface, int localRole) {
+            mState = state;
+            mIfaceAddr = ifaceAddr;
+            mIface = iface;
+            mLocalRole = localRole;
+        }
+    }
+
+    private String createNewTetheringAddressLocked() {
+        if (getConnectedPanDevices().size() == mMaxPanDevices) {
+            debugLog ("Max PAN device connections reached");
+            return null;
+        }
+        String address = BLUETOOTH_IFACE_ADDR_START;
+        while (true) {
+            if (mBluetoothIfaceAddresses.contains(address)) {
+                String[] addr = address.split("\\.");
+                Integer newIp = Integer.parseInt(addr[2]) + 1;
+                address = address.replace(addr[2], newIp.toString());
+            } else {
+                break;
+            }
+        }
+        mBluetoothIfaceAddresses.add(address);
+        return address;
+    }
+
+    // configured when we start tethering
+    private synchronized String enableTethering(String iface) {
+        debugLog("updateTetherState:" + iface);
+
+        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
+        INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
+        ConnectivityManager cm =
+            (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+        String[] bluetoothRegexs = cm.getTetherableBluetoothRegexs();
+
+        // bring toggle the interfaces
+        String[] currentIfaces = new String[0];
+        try {
+            currentIfaces = service.listInterfaces();
+        } catch (Exception e) {
+            Log.e(TAG, "Error listing Interfaces :" + e);
+            return null;
+        }
+
+        boolean found = false;
+        for (String currIface: currentIfaces) {
+            if (currIface.equals(iface)) {
+                found = true;
+                break;
+            }
+        }
+
+        if (!found) return null;
+
+        String address = createNewTetheringAddressLocked();
+        if (address == null) return null;
+
+        InterfaceConfiguration ifcg = null;
+        try {
+            ifcg = service.getInterfaceConfig(iface);
+            if (ifcg != null) {
+                InetAddress addr = null;
+                if (ifcg.addr == null || (addr = ifcg.addr.getAddress()) == null ||
+                        addr.equals(InetAddress.getByName("0.0.0.0")) ||
+                        addr.equals(InetAddress.getByName("::0"))) {
+                    addr = InetAddress.getByName(address);
+                }
+                ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up");
+                ifcg.addr = new LinkAddress(addr, BLUETOOTH_PREFIX_LENGTH);
+                ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running", "");
+                ifcg.interfaceFlags = ifcg.interfaceFlags.replace("  "," ");
+                service.setInterfaceConfig(iface, ifcg);
+                if (cm.tether(iface) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
+                    Log.e(TAG, "Error tethering "+iface);
+                }
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Error configuring interface " + iface + ", :" + e);
+            return null;
+        }
+        return address;
+    }
+
+    private static void debugLog(String msg) {
+        if (DBG) Log.d(TAG, msg);
+    }
+
+    private static void errorLog(String msg) {
+        Log.e(TAG, msg);
+    }
+}
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index df5097e..a295de5 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -24,17 +24,17 @@
 
 package android.server;
 
+import com.android.internal.app.IBatteryStats;
+
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothDeviceProfileState;
 import android.bluetooth.BluetoothHeadset;
-import android.bluetooth.BluetoothInputDevice;
 import android.bluetooth.BluetoothPan;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothProfileState;
 import android.bluetooth.BluetoothSocket;
-import android.bluetooth.BluetoothTetheringDataTracker;
 import android.bluetooth.BluetoothUuid;
 import android.bluetooth.IBluetooth;
 import android.bluetooth.IBluetoothCallback;
@@ -44,14 +44,9 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.SharedPreferences;
-import android.content.res.Resources.NotFoundException;
-import android.net.ConnectivityManager;
-import android.net.InterfaceConfiguration;
-import android.net.LinkAddress;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.INetworkManagementService;
 import android.os.Message;
 import android.os.ParcelUuid;
 import android.os.RemoteException;
@@ -60,8 +55,6 @@
 import android.util.Log;
 import android.util.Pair;
 
-import com.android.internal.app.IBatteryStats;
-
 import java.io.BufferedInputStream;
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
@@ -76,7 +69,6 @@
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
 import java.io.UnsupportedEncodingException;
-import java.net.InetAddress;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -96,7 +88,6 @@
     private int mBluetoothState;
     private boolean mRestart = false;  // need to call enable() after disable()
     private boolean mIsDiscovering;
-    private boolean mTetheringOn;
     private int[] mAdapterSdpHandles;
     private ParcelUuid[] mAdapterUuids;
 
@@ -106,7 +97,7 @@
     private final Context mContext;
 
     private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
-    private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
+    static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
 
     private static final String DOCK_ADDRESS_PATH = "/sys/class/switch/dock/bt_addr";
     private static final String DOCK_PIN_PATH = "/sys/class/switch/dock/bt_pin";
@@ -125,13 +116,6 @@
     private static final long INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 3000;
     private static final long MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 12000;
 
-    private ArrayList<String> mBluetoothIfaceAddresses;
-    private int mMaxPanDevices;
-
-    private static final String BLUETOOTH_IFACE_ADDR_START= "192.168.44.1";
-    private static final int BLUETOOTH_MAX_PAN_CONNECTIONS = 5;
-    private static final String BLUETOOTH_NETMASK        = "255.255.255.0";
-
     // The timeout used to sent the UUIDs Intent
     // This timeout should be greater than the page timeout
     private static final int UUID_INTENT_DELAY = 6000;
@@ -155,11 +139,8 @@
     private final HashMap<String, BluetoothDeviceProfileState> mDeviceProfileState;
     private final BluetoothProfileState mA2dpProfileState;
     private final BluetoothProfileState mHfpProfileState;
-    private final BluetoothProfileState mHidProfileState;
 
     private BluetoothA2dpService mA2dpService;
-    private final HashMap<BluetoothDevice, Integer> mInputDevices;
-    private final HashMap<BluetoothDevice, Pair<Integer, String>> mPanDevices;
     private final HashMap<String, Pair<byte[], byte[]>> mDeviceOobData;
 
     private int mProfilesConnected = 0, mProfilesConnecting = 0, mProfilesDisconnecting = 0;
@@ -167,9 +148,9 @@
     private static String mDockAddress;
     private String mDockPin;
 
-    private String mIface;
-
     private int mAdapterConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
+    private BluetoothPanProfileHandler mBluetoothPanProfileHandler;
+    private BluetoothInputProfileHandler mBluetoothInputProfileHandler;
 
     private static class RemoteService {
         public String address;
@@ -218,7 +199,7 @@
 
         mBluetoothState = BluetoothAdapter.STATE_OFF;
         mIsDiscovering = false;
-        mTetheringOn = false;
+
         mAdapterProperties = new HashMap<String, String>();
         mDeviceProperties = new HashMap<String, Map<String,String>>();
 
@@ -230,27 +211,17 @@
         mDeviceProfileState = new HashMap<String, BluetoothDeviceProfileState>();
         mA2dpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.A2DP);
         mHfpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.HFP);
-        mHidProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.HID);
-
-        mBluetoothIfaceAddresses = new ArrayList<String>();
-        try {
-            mMaxPanDevices = context.getResources().getInteger(
-                            com.android.internal.R.integer.config_max_pan_devices);
-        } catch (NotFoundException e) {
-            mMaxPanDevices = BLUETOOTH_MAX_PAN_CONNECTIONS;
-        }
 
         mHfpProfileState.start();
         mA2dpProfileState.start();
-        mHidProfileState.start();
 
         IntentFilter filter = new IntentFilter();
         registerForAirplaneMode(filter);
 
         filter.addAction(Intent.ACTION_DOCK_EVENT);
         mContext.registerReceiver(mReceiver, filter);
-        mInputDevices = new HashMap<BluetoothDevice, Integer>();
-        mPanDevices = new HashMap<BluetoothDevice, Pair<Integer, String>>();
+        mBluetoothInputProfileHandler = BluetoothInputProfileHandler.getInstance(mContext, this);
+        mBluetoothPanProfileHandler = BluetoothPanProfileHandler.getInstance(mContext, this);
     }
 
     public static synchronized String readDockBluetoothAddress() {
@@ -590,21 +561,16 @@
                     persistBluetoothOnSetting(true);
                 }
 
-                updateSdpRecords();
-
                 mIsDiscovering = false;
                 mBondState.readAutoPairingData();
                 mBondState.loadBondState();
                 initProfileState();
 
-                // Log bluetooth on to battery stats.
-                long ident = Binder.clearCallingIdentity();
-                try {
-                    mBatteryStats.noteBluetoothOn();
-                } catch (RemoteException e) {
-                } finally {
-                    Binder.restoreCallingIdentity(ident);
-                }
+                // This should be the last step of the the enable thread.
+                // Because this adds SDP records which asynchronously
+                // broadcasts the Bluetooth On State in updateBluetoothState.
+                // So we want all internal state setup before this.
+                updateSdpRecords();
             } else {
                 setBluetoothState(BluetoothAdapter.STATE_OFF);
             }
@@ -652,6 +618,11 @@
         }
     }
 
+    /**
+     * This function is called from Bluetooth Event Loop when onPropertyChanged
+     * for adapter comes in with UUID property.
+     * @param uuidsThe uuids of adapter as reported by Bluez.
+     */
     synchronized void updateBluetoothState(String uuids) {
         if (mBluetoothState == BluetoothAdapter.STATE_TURNING_ON) {
             ParcelUuid[] adapterUuids = convertStringToParcelUuid(uuids);
@@ -662,6 +633,15 @@
                 String[] propVal = {"Pairable", getProperty("Pairable")};
                 mEventLoop.onPropertyChanged(propVal);
 
+                // Log bluetooth on to battery stats.
+                long ident = Binder.clearCallingIdentity();
+                try {
+                    mBatteryStats.noteBluetoothOn();
+                } catch (RemoteException e) {
+                } finally {
+                    Binder.restoreCallingIdentity(ident);
+                }
+
                 if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) {
                     disable(false);
                 }
@@ -825,7 +805,8 @@
 
             // HID is handled by BluetoothService, other profiles
             // will be handled by their respective services.
-            setInitialInputDevicePriority(mAdapter.getRemoteDevice(address), state);
+            mBluetoothInputProfileHandler.setInitialInputDevicePriority(
+                    mAdapter.getRemoteDevice(address), state);
 
             if (DBG) log(address + " bond state " + oldState + " -> " + state + " (" +
                          reason + ")");
@@ -1472,425 +1453,6 @@
         return sp.contains(SHARED_PREFERENCE_DOCK_ADDRESS + address);
     }
 
-    public synchronized boolean isTetheringOn() {
-        return mTetheringOn;
-    }
-
-    /*package*/ synchronized boolean allowIncomingTethering() {
-        if (isTetheringOn() && getConnectedPanDevices().size() < mMaxPanDevices)
-            return true;
-        return false;
-    }
-
-    private BroadcastReceiver mTetheringReceiver = null;
-
-    public synchronized void setBluetoothTethering(boolean value) {
-        if (!value) {
-            disconnectPan();
-        }
-
-        if (getBluetoothState() != BluetoothAdapter.STATE_ON && value) {
-            IntentFilter filter = new IntentFilter();
-            filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
-            mTetheringReceiver = new BroadcastReceiver() {
-                @Override
-                public synchronized void onReceive(Context context, Intent intent) {
-                    if (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF)
-                            == BluetoothAdapter.STATE_ON) {
-                        mTetheringOn = true;
-                        mContext.unregisterReceiver(mTetheringReceiver);
-                    }
-                }
-            };
-            mContext.registerReceiver(mTetheringReceiver, filter);
-        } else {
-            mTetheringOn = value;
-        }
-    }
-
-    public synchronized int getPanDeviceState(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-
-        Pair<Integer, String> panDevice = mPanDevices.get(device);
-        if (panDevice == null) {
-            return BluetoothPan.STATE_DISCONNECTED;
-        }
-        return panDevice.first;
-    }
-
-    public synchronized boolean connectPanDevice(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-
-        String objectPath = getObjectPathFromAddress(device.getAddress());
-        if (DBG) log("connect PAN(" + objectPath + ")");
-        if (getPanDeviceState(device) != BluetoothPan.STATE_DISCONNECTED) {
-            log (device + " already connected to PAN");
-        }
-
-        int connectedCount = 0;
-        for (BluetoothDevice panDevice: mPanDevices.keySet()) {
-            if (getPanDeviceState(panDevice) == BluetoothPan.STATE_CONNECTED) {
-                connectedCount ++;
-            }
-        }
-        if (connectedCount > 8) {
-            log (device + " could not connect to PAN because 8 other devices are already connected");
-            return false;
-        }
-
-        handlePanDeviceStateChange(device, BluetoothPan.STATE_CONNECTING,
-                                           BluetoothPan.LOCAL_PANU_ROLE);
-        if (connectPanDeviceNative(objectPath, "nap")) {
-            log ("connecting to PAN");
-            return true;
-        } else {
-            handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTED,
-                                                BluetoothPan.LOCAL_PANU_ROLE);
-            log ("could not connect to PAN");
-            return false;
-        }
-    }
-
-    private synchronized boolean disconnectPan() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (DBG) log("disconnect all PAN devices");
-
-        for (BluetoothDevice device: mPanDevices.keySet()) {
-            if (getPanDeviceState(device) == BluetoothPan.STATE_CONNECTED) {
-                if (!disconnectPanDevice(device)) {
-                    log ("could not disconnect Pan Device "+device.getAddress());
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    public synchronized List<BluetoothDevice> getConnectedPanDevices() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-
-        List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();
-
-        for (BluetoothDevice device: mPanDevices.keySet()) {
-            if (getPanDeviceState(device) == BluetoothPan.STATE_CONNECTED) {
-                devices.add(device);
-            }
-        }
-        return devices;
-    }
-
-    public synchronized boolean disconnectPanDevice(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        String objectPath = getObjectPathFromAddress(device.getAddress());
-        if (DBG) log("disconnect PAN(" + objectPath + ")");
-        if (getPanDeviceState(device) != BluetoothPan.STATE_CONNECTED) {
-            log (device + " already disconnected from PAN");
-        }
-        handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTING,
-                                    BluetoothPan.LOCAL_PANU_ROLE);
-        return disconnectPanDeviceNative(objectPath);
-    }
-
-    /*package*/ synchronized void handlePanDeviceStateChange(BluetoothDevice device,
-                                                             String iface,
-                                                             int state,
-                                                             int role) {
-        int prevState;
-        String ifaceAddr = null;
-
-        if (mPanDevices.get(device) == null) {
-            prevState = BluetoothPan.STATE_DISCONNECTED;
-        } else {
-            prevState = mPanDevices.get(device).first;
-            ifaceAddr = mPanDevices.get(device).second;
-        }
-        if (prevState == state) return;
-
-        if (role == BluetoothPan.LOCAL_NAP_ROLE) {
-            if (state == BluetoothPan.STATE_CONNECTED) {
-                ifaceAddr = enableTethering(iface);
-                if (ifaceAddr == null) Log.e(TAG, "Error seting up tether interface");
-            } else if (state == BluetoothPan.STATE_DISCONNECTED) {
-                if (ifaceAddr != null) {
-                    mBluetoothIfaceAddresses.remove(ifaceAddr);
-                    ifaceAddr = null;
-                }
-            }
-        } else {
-            // PANU Role = reverse Tether
-            if (state == BluetoothPan.STATE_CONNECTED) {
-                mIface = iface;
-                BluetoothTetheringDataTracker.getInstance().startReverseTether(iface, device);
-            } else if (state == BluetoothPan.STATE_DISCONNECTED &&
-                  (prevState == BluetoothPan.STATE_CONNECTED ||
-                  prevState == BluetoothPan.STATE_DISCONNECTING)) {
-                BluetoothTetheringDataTracker.getInstance().stopReverseTether(mIface);
-            }
-        }
-
-        Pair<Integer, String> value = new Pair<Integer, String>(state, ifaceAddr);
-        mPanDevices.put(device, value);
-
-        Intent intent = new Intent(BluetoothPan.ACTION_PAN_STATE_CHANGED);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-        intent.putExtra(BluetoothPan.EXTRA_PREVIOUS_PAN_STATE, prevState);
-        intent.putExtra(BluetoothPan.EXTRA_PAN_STATE, state);
-        intent.putExtra(BluetoothPan.EXTRA_LOCAL_ROLE, role);
-        mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-
-        if (DBG) log("Pan Device state : device: " + device + " State:" + prevState + "->" + state);
-        sendConnectionStateChange(device, state, prevState);
-    }
-
-    /*package*/ synchronized void handlePanDeviceStateChange(BluetoothDevice device,
-                                                             int state, int role) {
-        handlePanDeviceStateChange(device, null, state, role);
-    }
-
-    private String createNewTetheringAddressLocked() {
-        if (getConnectedPanDevices().size() == mMaxPanDevices) {
-            log("Max PAN device connections reached");
-            return null;
-        }
-        String address = BLUETOOTH_IFACE_ADDR_START;
-        while (true) {
-            if (mBluetoothIfaceAddresses.contains(address)) {
-                String[] addr = address.split("\\.");
-                Integer newIp = Integer.parseInt(addr[2]) + 1;
-                address = address.replace(addr[2], newIp.toString());
-            } else {
-                break;
-            }
-        }
-        mBluetoothIfaceAddresses.add(address);
-        return address;
-    }
-
-    // configured when we start tethering
-    private synchronized String enableTethering(String iface) {
-        log("updateTetherState:" + iface);
-
-        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
-        INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
-        ConnectivityManager cm =
-            (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
-        String[] bluetoothRegexs = cm.getTetherableBluetoothRegexs();
-
-        // bring toggle the interfaces
-        String[] currentIfaces = new String[0];
-        try {
-            currentIfaces = service.listInterfaces();
-        } catch (Exception e) {
-            Log.e(TAG, "Error listing Interfaces :" + e);
-            return null;
-        }
-
-        boolean found = false;
-        for (String currIface: currentIfaces) {
-            if (currIface.equals(iface)) {
-                found = true;
-                break;
-            }
-        }
-
-        if (!found) return null;
-
-        String address = createNewTetheringAddressLocked();
-        if (address == null) return null;
-
-        InterfaceConfiguration ifcg = null;
-        try {
-            ifcg = service.getInterfaceConfig(iface);
-            if (ifcg != null) {
-                InetAddress mask = InetAddress.getByName(BLUETOOTH_NETMASK);
-                InetAddress addr = null;
-                if (ifcg.addr == null || (addr = ifcg.addr.getAddress()) == null ||
-                        addr.equals(InetAddress.getByName("0.0.0.0")) ||
-                        addr.equals(InetAddress.getByName("::0"))) {
-                    addr = InetAddress.getByName(address);
-                }
-                ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up");
-                ifcg.addr = new LinkAddress(addr, mask);
-                ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running", "");
-                ifcg.interfaceFlags = ifcg.interfaceFlags.replace("  "," ");
-                service.setInterfaceConfig(iface, ifcg);
-                if (cm.tether(iface) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
-                    Log.e(TAG, "Error tethering "+iface);
-                }
-            }
-        } catch (Exception e) {
-            Log.e(TAG, "Error configuring interface " + iface + ", :" + e);
-            return null;
-        }
-        return address;
-    }
-
-    public synchronized boolean connectInputDevice(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-
-        String objectPath = getObjectPathFromAddress(device.getAddress());
-        if (objectPath == null ||
-            getInputDeviceState(device) != BluetoothInputDevice.STATE_DISCONNECTED ||
-            getInputDevicePriority(device) == BluetoothInputDevice.PRIORITY_OFF) {
-            return false;
-        }
-        BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress());
-        if (state != null) {
-            Message msg = new Message();
-            msg.arg1 = BluetoothDeviceProfileState.CONNECT_HID_OUTGOING;
-            msg.obj = state;
-            mHidProfileState.sendMessage(msg);
-            return true;
-        }
-        return false;
-    }
-
-    public synchronized boolean connectInputDeviceInternal(BluetoothDevice device) {
-        String objectPath = getObjectPathFromAddress(device.getAddress());
-        handleInputDeviceStateChange(device, BluetoothInputDevice.STATE_CONNECTING);
-        if (!connectInputDeviceNative(objectPath)) {
-            handleInputDeviceStateChange(device, BluetoothInputDevice.STATE_DISCONNECTED);
-            return false;
-        }
-        return true;
-    }
-
-    public synchronized boolean disconnectInputDevice(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-
-        String objectPath = getObjectPathFromAddress(device.getAddress());
-        if (objectPath == null ||
-                getInputDeviceState(device) == BluetoothInputDevice.STATE_DISCONNECTED) {
-            return false;
-        }
-        BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress());
-        if (state != null) {
-            Message msg = new Message();
-            msg.arg1 = BluetoothDeviceProfileState.DISCONNECT_HID_OUTGOING;
-            msg.obj = state;
-            mHidProfileState.sendMessage(msg);
-            return true;
-        }
-        return false;
-    }
-
-    public synchronized boolean disconnectInputDeviceInternal(BluetoothDevice device) {
-        String objectPath = getObjectPathFromAddress(device.getAddress());
-        handleInputDeviceStateChange(device, BluetoothInputDevice.STATE_DISCONNECTING);
-        if (!disconnectInputDeviceNative(objectPath)) {
-            handleInputDeviceStateChange(device, BluetoothInputDevice.STATE_CONNECTED);
-            return false;
-        }
-        return true;
-    }
-
-    public synchronized int getInputDeviceState(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-
-        if (mInputDevices.get(device) == null) {
-            return BluetoothInputDevice.STATE_DISCONNECTED;
-        }
-        return mInputDevices.get(device);
-    }
-
-    public synchronized List<BluetoothDevice> getConnectedInputDevices() {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        List<BluetoothDevice> devices = lookupInputDevicesMatchingStates(
-            new int[] {BluetoothInputDevice.STATE_CONNECTED});
-        return devices;
-    }
-
-    public synchronized int getInputDevicePriority(BluetoothDevice device) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        return Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.getBluetoothInputDevicePriorityKey(device.getAddress()),
-                BluetoothInputDevice.PRIORITY_UNDEFINED);
-    }
-
-    public synchronized boolean setInputDevicePriority(BluetoothDevice device, int priority) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
-                                                "Need BLUETOOTH_ADMIN permission");
-        if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
-            return false;
-        }
-        return Settings.Secure.putInt(mContext.getContentResolver(),
-                Settings.Secure.getBluetoothInputDevicePriorityKey(device.getAddress()),
-                priority);
-    }
-
-    /*package*/synchronized List<BluetoothDevice> lookupInputDevicesMatchingStates(int[] states) {
-        List<BluetoothDevice> inputDevices = new ArrayList<BluetoothDevice>();
-
-        for (BluetoothDevice device: mInputDevices.keySet()) {
-            int inputDeviceState = getInputDeviceState(device);
-            for (int state : states) {
-                if (state == inputDeviceState) {
-                    inputDevices.add(device);
-                    break;
-                }
-            }
-        }
-        return inputDevices;
-    }
-
-    private synchronized void handleInputDeviceStateChange(BluetoothDevice device, int state) {
-        int prevState;
-        if (mInputDevices.get(device) == null) {
-            prevState = BluetoothInputDevice.STATE_DISCONNECTED;
-        } else {
-            prevState = mInputDevices.get(device);
-        }
-        if (prevState == state) return;
-
-        mInputDevices.put(device, state);
-
-        if (getInputDevicePriority(device) >
-              BluetoothInputDevice.PRIORITY_OFF &&
-            state == BluetoothInputDevice.STATE_CONNECTING ||
-            state == BluetoothInputDevice.STATE_CONNECTED) {
-            // We have connected or attempting to connect.
-            // Bump priority
-            setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_AUTO_CONNECT);
-        }
-
-        Intent intent = new Intent(BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED);
-        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-        intent.putExtra(BluetoothInputDevice.EXTRA_PREVIOUS_INPUT_DEVICE_STATE, prevState);
-        intent.putExtra(BluetoothInputDevice.EXTRA_INPUT_DEVICE_STATE, state);
-        mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-
-        if (DBG) log("InputDevice state : device: " + device + " State:" + prevState + "->" + state);
-        sendConnectionStateChange(device, state, prevState);
-    }
-
-    /*package*/ void handleInputDevicePropertyChange(String address, boolean connected) {
-        int state = connected ? BluetoothInputDevice.STATE_CONNECTED :
-            BluetoothInputDevice.STATE_DISCONNECTED;
-        BluetoothDevice device = mAdapter.getRemoteDevice(address);
-        handleInputDeviceStateChange(device, state);
-    }
-
-    private void setInitialInputDevicePriority(BluetoothDevice device, int state) {
-        switch (state) {
-            case BluetoothDevice.BOND_BONDED:
-                if (getInputDevicePriority(device) == BluetoothInputDevice.PRIORITY_UNDEFINED) {
-                    setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_ON);
-                }
-                break;
-            case BluetoothDevice.BOND_NONE:
-                setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_UNDEFINED);
-                break;
-        }
-    }
-
-    /*package*/ boolean isRemoteDeviceInCache(String address) {
-        return (mDeviceProperties.get(address) != null);
-    }
-
     /*package*/ String[] getRemoteDeviceProperties(String address) {
         if (!isEnabledInternal()) return null;
 
@@ -2675,6 +2237,114 @@
         if (!result) log("Set Link Timeout to:" + num_slots + " slots failed");
     }
 
+    /**** Handlers for PAN  Profile ****/
+
+    public synchronized boolean isTetheringOn() {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+        return mBluetoothPanProfileHandler.isTetheringOn();
+    }
+
+    /*package*/ synchronized boolean allowIncomingTethering() {
+        return mBluetoothPanProfileHandler.allowIncomingTethering();
+    }
+
+    public synchronized void setBluetoothTethering(boolean value) {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+        mBluetoothPanProfileHandler.setBluetoothTethering(value);
+    }
+
+    public synchronized int getPanDeviceState(BluetoothDevice device) {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+        return mBluetoothPanProfileHandler.getPanDeviceState(device);
+    }
+
+    public synchronized boolean connectPanDevice(BluetoothDevice device) {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+            "Need BLUETOOTH_ADMIN permission");
+        return mBluetoothPanProfileHandler.connectPanDevice(device);
+    }
+
+    public synchronized List<BluetoothDevice> getConnectedPanDevices() {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+        return mBluetoothPanProfileHandler.getConnectedPanDevices();
+    }
+
+    public synchronized boolean disconnectPanDevice(BluetoothDevice device) {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+            "Need BLUETOOTH_ADMIN permission");
+        return mBluetoothPanProfileHandler.disconnectPanDevice(device);
+    }
+
+    /*package*/ synchronized void handlePanDeviceStateChange(BluetoothDevice device,
+                                                             String iface,
+                                                             int state,
+                                                             int role) {
+        mBluetoothPanProfileHandler.handlePanDeviceStateChange(device, iface, state, role);
+    }
+
+    /*package*/ synchronized void handlePanDeviceStateChange(BluetoothDevice device,
+                                                             int state, int role) {
+        mBluetoothPanProfileHandler.handlePanDeviceStateChange(device, null, state, role);
+    }
+
+    /**** Handlers for Input Device Profile ****/
+
+    public synchronized boolean connectInputDevice(BluetoothDevice device) {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+                                                "Need BLUETOOTH_ADMIN permission");
+        BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress());
+        return mBluetoothInputProfileHandler.connectInputDevice(device, state);
+    }
+
+    public synchronized boolean connectInputDeviceInternal(BluetoothDevice device) {
+        return mBluetoothInputProfileHandler.connectInputDeviceInternal(device);
+    }
+
+    public synchronized boolean disconnectInputDevice(BluetoothDevice device) {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+                                                "Need BLUETOOTH_ADMIN permission");
+        BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress());
+        return mBluetoothInputProfileHandler.disconnectInputDevice(device, state);
+    }
+
+    public synchronized boolean disconnectInputDeviceInternal(BluetoothDevice device) {
+        return mBluetoothInputProfileHandler.disconnectInputDeviceInternal(device);
+    }
+
+    public synchronized int getInputDeviceState(BluetoothDevice device) {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+        return mBluetoothInputProfileHandler.getInputDeviceState(device);
+
+    }
+
+    public synchronized List<BluetoothDevice> getConnectedInputDevices() {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+        return mBluetoothInputProfileHandler.getConnectedInputDevices();
+    }
+
+    public synchronized int getInputDevicePriority(BluetoothDevice device) {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+        return mBluetoothInputProfileHandler.getInputDevicePriority(device);
+    }
+
+    public synchronized boolean setInputDevicePriority(BluetoothDevice device, int priority) {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+                                                "Need BLUETOOTH_ADMIN permission");
+        return mBluetoothInputProfileHandler.setInputDevicePriority(device, priority);
+    }
+
+    /*package*/synchronized List<BluetoothDevice> lookupInputDevicesMatchingStates(int[] states) {
+        return mBluetoothInputProfileHandler.lookupInputDevicesMatchingStates(states);
+    }
+
+    /*package*/ synchronized void handleInputDevicePropertyChange(String address, boolean connected) {
+        mBluetoothInputProfileHandler.handleInputDevicePropertyChange(address, connected);
+    }
+
+    /*package*/ boolean isRemoteDeviceInCache(String address) {
+        return (mDeviceProperties.get(address) != null);
+    }
+
     public boolean connectHeadset(String address) {
         if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false;
 
@@ -2928,12 +2598,14 @@
             short channel);
     private native boolean removeServiceRecordNative(int handle);
     private native boolean setLinkTimeoutNative(String path, int num_slots);
-    private native boolean connectInputDeviceNative(String path);
-    private native boolean disconnectInputDeviceNative(String path);
+    native boolean connectInputDeviceNative(String path);
+    native boolean disconnectInputDeviceNative(String path);
 
-    private native boolean setBluetoothTetheringNative(boolean value, String nap, String bridge);
-    private native boolean connectPanDeviceNative(String path, String dstRole);
-    private native boolean disconnectPanDeviceNative(String path);
+    native boolean setBluetoothTetheringNative(boolean value, String nap, String bridge);
+    native boolean connectPanDeviceNative(String path, String dstRole);
+    native boolean disconnectPanDeviceNative(String path);
+    native boolean disconnectPanServerDeviceNative(String path,
+            String address, String iface);
 
     private native int[] addReservedServiceRecordsNative(int[] uuuids);
     private native boolean removeReservedServiceRecordsNative(int[] handles);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 03a6aa5..378eb21 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1421,55 +1421,6 @@
     }
 
     /**
-     * Used by views that contain lists of items. This state indicates that
-     * the view is showing the last item.
-     * @hide
-     */
-    protected static final int[] LAST_STATE_SET = {R.attr.state_last};
-    /**
-     * Used by views that contain lists of items. This state indicates that
-     * the view is showing the first item.
-     * @hide
-     */
-    protected static final int[] FIRST_STATE_SET = {R.attr.state_first};
-    /**
-     * Used by views that contain lists of items. This state indicates that
-     * the view is showing the middle item.
-     * @hide
-     */
-    protected static final int[] MIDDLE_STATE_SET = {R.attr.state_middle};
-    /**
-     * Used by views that contain lists of items. This state indicates that
-     * the view is showing only one item.
-     * @hide
-     */
-    protected static final int[] SINGLE_STATE_SET = {R.attr.state_single};
-    /**
-     * Used by views that contain lists of items. This state indicates that
-     * the view is pressed and showing the last item.
-     * @hide
-     */
-    protected static final int[] PRESSED_LAST_STATE_SET = {R.attr.state_last, R.attr.state_pressed};
-    /**
-     * Used by views that contain lists of items. This state indicates that
-     * the view is pressed and showing the first item.
-     * @hide
-     */
-    protected static final int[] PRESSED_FIRST_STATE_SET = {R.attr.state_first, R.attr.state_pressed};
-    /**
-     * Used by views that contain lists of items. This state indicates that
-     * the view is pressed and showing the middle item.
-     * @hide
-     */
-    protected static final int[] PRESSED_MIDDLE_STATE_SET = {R.attr.state_middle, R.attr.state_pressed};
-    /**
-     * Used by views that contain lists of items. This state indicates that
-     * the view is pressed and showing only one item.
-     * @hide
-     */
-    protected static final int[] PRESSED_SINGLE_STATE_SET = {R.attr.state_single, R.attr.state_pressed};
-
-    /**
      * Temporary Rect currently for use in setBackground().  This will probably
      * be extended in the future to hold our own class with more than just
      * a Rect. :)
@@ -1497,14 +1448,14 @@
      * {@hide}
      */
     @ViewDebug.ExportedProperty(category = "measurement")
-    /*package*/ int mMeasuredWidth;
+    int mMeasuredWidth;
 
     /**
      * Height as measured during measure pass.
      * {@hide}
      */
     @ViewDebug.ExportedProperty(category = "measurement")
-    /*package*/ int mMeasuredHeight;
+    int mMeasuredHeight;
 
     /**
      * Flag to indicate that this view was marked INVALIDATED, or had its display list
@@ -3749,16 +3700,6 @@
     }
 
     /**
-     * Determine if this view has the FITS_SYSTEM_WINDOWS flag set.
-     * @return True if window has FITS_SYSTEM_WINDOWS set
-     *
-     * @hide
-     */
-    public boolean isFitsSystemWindowsFlagSet() {
-        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
-    }
-
-    /**
      * Returns the visibility status for this view.
      *
      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
@@ -8436,6 +8377,7 @@
      *
      * @hide
      */
+    @SuppressWarnings({"UnusedDeclaration"})
     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
         Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.DIRTY_MASK) +
                 ") DRAWN(" + (mPrivateFlags & DRAWN) + ")" + " CACHE_VALID(" +
@@ -8473,10 +8415,7 @@
      * @hide
      */
     public boolean canHaveDisplayList() {
-        if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
-            return false;
-        }
-        return true;
+        return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
     }
 
     /**
@@ -8719,12 +8658,14 @@
             if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
                 Bitmap.Config quality;
                 if (!opaque) {
+                    // Never pick ARGB_4444 because it looks awful
+                    // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
                     switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
                         case DRAWING_CACHE_QUALITY_AUTO:
                             quality = Bitmap.Config.ARGB_8888;
                             break;
                         case DRAWING_CACHE_QUALITY_LOW:
-                            quality = Bitmap.Config.ARGB_4444;
+                            quality = Bitmap.Config.ARGB_8888;
                             break;
                         case DRAWING_CACHE_QUALITY_HIGH:
                             quality = Bitmap.Config.ARGB_8888;
@@ -11324,6 +11265,7 @@
      * </p>
      */
     public boolean dispatchDragEvent(DragEvent event) {
+        //noinspection SimplifiableIfStatement
         if (mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
                 && mOnDragListener.onDrag(this, event)) {
             return true;
diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java
index ba425a6..0a9386d 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtype.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -16,10 +16,14 @@
 
 package android.view.inputmethod;
 
+import android.content.Context;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
 
 /**
  * This class is used to specify meta information of a subtype contained in an input method.
@@ -148,4 +152,35 @@
             String mode, String extraValue) {
         return Arrays.hashCode(new Object[] {nameResId, iconResId, locale, mode, extraValue});
     }
+
+    /**
+     * Sort the list of InputMethodSubtype
+     * @param context Context will be used for getting localized strings from IME
+     * @param flags Flags for the sort order
+     * @param imi InputMethodInfo of which subtypes are subject to be sorted
+     * @param subtypeList List of InputMethodSubtype which will be sorted
+     * @return Sorted list of subtypes
+     * @hide
+     */
+    public static List<InputMethodSubtype> sort(Context context, int flags, InputMethodInfo imi,
+            List<InputMethodSubtype> subtypeList) {
+        if (imi == null) return subtypeList;
+        final HashSet<InputMethodSubtype> inputSubtypesSet = new HashSet<InputMethodSubtype>(
+                subtypeList);
+        final ArrayList<InputMethodSubtype> sortedList = new ArrayList<InputMethodSubtype>();
+        int N = imi.getSubtypeCount();
+        for (int i = 0; i < N; ++i) {
+            InputMethodSubtype subtype = imi.getSubtypeAt(i);
+            if (inputSubtypesSet.contains(subtype)) {
+                sortedList.add(subtype);
+                inputSubtypesSet.remove(subtype);
+            }
+        }
+        // If subtypes in inputSubtypesSet remain, that means these subtypes are not
+        // contained in imi, so the remaining subtypes will be appended.
+        for (InputMethodSubtype subtype: inputSubtypesSet) {
+            sortedList.add(subtype);
+        }
+        return sortedList;
+    }
 }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index a7b12a0..874eac8 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1187,7 +1187,7 @@
         if (AccessibilityManager.getInstance(mContext).isEnabled()
                 && getSettings().getJavaScriptEnabled()) {
             // exposing the TTS for now ...
-            mTextToSpeech = new TextToSpeech(getContext(), null); 
+            mTextToSpeech = new TextToSpeech(getContext(), null);
             addJavascriptInterface(mTextToSpeech, ALIAS_ACCESSIBILITY_JS_INTERFACE);
         }
     }
@@ -2323,6 +2323,11 @@
     private View mTitleBar;
 
     /**
+     * the title bar rendering gravity
+     */
+    private int mTitleGravity;
+
+    /**
      * Add or remove a title bar to be embedded into the WebView, and scroll
      * along with it vertically, while remaining in view horizontally. Pass
      * null to remove the title bar from the WebView, and return to drawing
@@ -2343,6 +2348,16 @@
     }
 
     /**
+     * Set where to render the embedded title bar
+     * NO_GRAVITY at the top of the page
+     * TOP        at the top of the screen
+     * @hide
+     */
+    public void setTitleBarGravity(int gravity) {
+        mTitleGravity = gravity;
+    }
+
+    /**
      * Given a distance in view space, convert it to content space. Note: this
      * does not reflect translation, just scaling, so this should not be called
      * with coordinates, but should be called for dimensions like width or
@@ -3683,7 +3698,12 @@
             // When drawing the title bar, move it horizontally to always show
             // at the top of the WebView.
             mTitleBar.offsetLeftAndRight(mScrollX - mTitleBar.getLeft());
-            int newTop = Math.min(0, mScrollY);
+            int newTop = 0;
+            if (mTitleGravity == Gravity.NO_GRAVITY) {
+                newTop = Math.min(0, mScrollY);
+            } else if (mTitleGravity == Gravity.TOP) {
+                newTop = mScrollY;
+            }
             mTitleBar.setBottom(newTop + getTitleHeight());
             mTitleBar.setTop(newTop);
         }
@@ -3842,7 +3862,7 @@
         if (detector != null && detector.isInProgress()) {
             return false;
         }
-        
+
         if (mNativeClass != 0 && nativeCursorIsTextInput()) {
             // Send the click so that the textfield is in focus
             centerKeyPressOnTextField();
@@ -3894,18 +3914,14 @@
      * Select the word at the indicated content coordinates.
      */
     boolean selectText(int x, int y) {
-        if (!setUpSelect()) {
+        if (!setUpSelect(true, x, y)) {
             return false;
         }
-        if (mNativeClass != 0 && nativeWordSelection(x, y)) {
-            nativeSetExtendSelection();
-            mDrawSelectionPointer = false;
-            mSelectionStarted = true;
-            mTouchMode = TOUCH_DRAG_MODE;
-            return true;
-        }
-        selectionDone();
-        return false;
+        nativeSetExtendSelection();
+        mDrawSelectionPointer = false;
+        mSelectionStarted = true;
+        mTouchMode = TOUCH_DRAG_MODE;
+        return true;
     }
 
     private int mOrientation = Configuration.ORIENTATION_UNDEFINED;
@@ -4857,19 +4873,32 @@
     }
 
     /*
-     * Enter selecting text mode.  Returns true if the WebView is now in
+     * Enter selecting text mode, and see if CAB should be shown.
+     * Returns true if the WebView is now in
      * selecting text mode (including if it was already in that mode, and this
      * method did nothing).
      */
-    private boolean setUpSelect() {
+    private boolean setUpSelect(boolean selectWord, int x, int y) {
         if (0 == mNativeClass) return false; // client isn't initialized
         if (inFullScreenMode()) return false;
         if (mSelectingText) return true;
+        nativeResetSelection();
+        if (selectWord && !nativeWordSelection(x, y)) {
+            selectionDone();
+            return false;
+        }
+        mSelectCallback = new SelectActionModeCallback();
+        mSelectCallback.setWebView(this);
+        if (startActionMode(mSelectCallback) == null) {
+            // There is no ActionMode, so do not allow the user to modify a
+            // selection.
+            selectionDone();
+            return false;
+        }
         mExtendSelection = false;
         mSelectingText = mDrawSelectionPointer = true;
         // don't let the picture change during text selection
         WebViewCore.pauseUpdatePicture(mWebViewCore);
-        nativeResetSelection();
         if (nativeHasCursorNode()) {
             Rect rect = nativeCursorNodeBounds();
             mSelectX = contentToViewX(rect.left);
@@ -4882,14 +4911,6 @@
             mSelectY = mScrollY + getViewHeightWithTitle() / 2;
         }
         nativeHideCursor();
-        mSelectCallback = new SelectActionModeCallback();
-        mSelectCallback.setWebView(this);
-        if (startActionMode(mSelectCallback) == null) {
-            // There is no ActionMode, so do not allow the user to modify a
-            // selection.
-            selectionDone();
-            return false;
-        }
         mMinAutoScrollX = 0;
         mMaxAutoScrollX = getViewWidth();
         mMinAutoScrollY = 0;
@@ -4923,7 +4944,7 @@
      * Do not rely on this functionality; it will be deprecated in the future.
      */
     public void emulateShiftHeld() {
-        setUpSelect();
+        setUpSelect(false, 0, 0);
     }
 
     /**
diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java
index 190c0fc..072992e 100644
--- a/core/java/android/widget/AdapterViewAnimator.java
+++ b/core/java/android/widget/AdapterViewAnimator.java
@@ -279,6 +279,7 @@
      *
      * @param whichChild the index of the child view to display
      */
+    @android.view.RemotableViewMethod
     public void setDisplayedChild(int whichChild) {
         setDisplayedChild(whichChild, true);
     }
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 482ce56..c854fac 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1056,24 +1056,34 @@
     }
 
     /**
-     * Equivalent to calling {@link AdapterViewFlipper#showNext()}
+     * Equivalent to calling {@link AdapterViewAnimator#showNext()}
      *
-     * @param viewId The id of the view on which to call {@link AdapterViewFlipper#showNext()}
+     * @param viewId The id of the view on which to call {@link AdapterViewAnimator#showNext()}
      */
     public void showNext(int viewId) {
         addAction(new ReflectionActionWithoutParams(viewId, "showNext"));
     }
 
     /**
-     * Equivalent to calling {@link AdapterViewFlipper#showPrevious()}
+     * Equivalent to calling {@link AdapterViewAnimator#showPrevious()}
      *
-     * @param viewId The id of the view on which to call {@link AdapterViewFlipper#showPrevious()}
+     * @param viewId The id of the view on which to call {@link AdapterViewAnimator#showPrevious()}
      */
     public void showPrevious(int viewId) {
         addAction(new ReflectionActionWithoutParams(viewId, "showPrevious"));
     }
 
     /**
+     * Equivalent to calling {@link AdapterViewAnimator#setDisplayedChild(int)}
+     *
+     * @param viewId The id of the view on which to call
+     *               {@link AdapterViewAnimator#setDisplayedChild(int)}
+     */
+    public void setDisplayedChild(int viewId, int childIndex) {
+        setInt(viewId, "setDisplayedChild", childIndex);
+    }
+
+    /**
      * Equivalent to calling View.setVisibility
      * 
      * @param viewId The id of the view whose visibility should change
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index 0a48feb..13a911b 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -914,7 +914,9 @@
                 // view and queueing it to be loaded if it has not already been loaded.
                 Context context = parent.getContext();
                 RemoteViews rv = mCache.getRemoteViewsAt(position);
-                int typeId = mCache.getMetaDataAt(position).typeId;
+                RemoteViewsIndexMetaData indexMetaData = mCache.getMetaDataAt(position);
+                indexMetaData.isRequested = true;
+                int typeId = indexMetaData.typeId;
 
                 // Reuse the convert view where possible
                 if (layout != null) {
diff --git a/core/java/android/widget/ViewAnimator.java b/core/java/android/widget/ViewAnimator.java
index 7b66893..3c683d6 100644
--- a/core/java/android/widget/ViewAnimator.java
+++ b/core/java/android/widget/ViewAnimator.java
@@ -96,6 +96,7 @@
      *
      * @param whichChild the index of the child view to display
      */
+    @android.view.RemotableViewMethod
     public void setDisplayedChild(int whichChild) {
         mWhichChild = whichChild;
         if (whichChild >= getChildCount()) {
@@ -122,6 +123,7 @@
     /**
      * Manually shows the next child.
      */
+    @android.view.RemotableViewMethod
     public void showNext() {
         setDisplayedChild(mWhichChild + 1);
     }
@@ -129,6 +131,7 @@
     /**
      * Manually shows the previous child.
      */
+    @android.view.RemotableViewMethod
     public void showPrevious() {
         setDisplayedChild(mWhichChild - 1);
     }
diff --git a/core/jni/android_server_BluetoothService.cpp b/core/jni/android_server_BluetoothService.cpp
index 2c39871..bf0504f 100644
--- a/core/jni/android_server_BluetoothService.cpp
+++ b/core/jni/android_server_BluetoothService.cpp
@@ -1214,6 +1214,45 @@
     return JNI_FALSE;
 }
 
+static jboolean disconnectPanServerDeviceNative(JNIEnv *env, jobject object,
+                                                jstring path, jstring address,
+                                                jstring iface) {
+    LOGV(__FUNCTION__);
+#ifdef HAVE_BLUETOOTH
+    LOGE("disconnectPanServerDeviceNative");
+    native_data_t *nat = get_native_data(env, object);
+    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
+    struct event_loop_native_data_t *eventLoopNat =
+            get_EventLoop_native_data(env, eventLoop);
+
+    if (nat && eventLoopNat) {
+        const char *c_address = env->GetStringUTFChars(address, NULL);
+        const char *c_path = env->GetStringUTFChars(path, NULL);
+        const char *c_iface = env->GetStringUTFChars(iface, NULL);
+
+        int len = env->GetStringLength(path) + 1;
+        char *context_path = (char *)calloc(len, sizeof(char));
+        strlcpy(context_path, c_path, len);  // for callback
+
+        bool ret = dbus_func_args_async(env, nat->conn, -1,
+                                        onPanDeviceConnectionResult,
+                                        context_path, eventLoopNat,
+                                        get_adapter_path(env, object),
+                                        DBUS_NETWORKSERVER_IFACE,
+                                        "DisconnectDevice",
+                                        DBUS_TYPE_STRING, &c_address,
+                                        DBUS_TYPE_STRING, &c_iface,
+                                        DBUS_TYPE_INVALID);
+
+        env->ReleaseStringUTFChars(address, c_address);
+        env->ReleaseStringUTFChars(iface, c_iface);
+        env->ReleaseStringUTFChars(path, c_path);
+        return ret ? JNI_TRUE : JNI_FALSE;
+    }
+#endif
+    return JNI_FALSE;
+}
+
 static JNINativeMethod sMethods[] = {
      /* name, signature, funcPtr */
     {"classInitNative", "()V", (void*)classInitNative},
@@ -1274,6 +1313,8 @@
     {"connectPanDeviceNative", "(Ljava/lang/String;Ljava/lang/String;)Z",
               (void *)connectPanDeviceNative},
     {"disconnectPanDeviceNative", "(Ljava/lang/String;)Z", (void *)disconnectPanDeviceNative},
+    {"disconnectPanServerDeviceNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z",
+              (void *)disconnectPanServerDeviceNative},
 };
 
 
diff --git a/core/res/res/anim/wallpaper_intra_close_enter.xml b/core/res/res/anim/wallpaper_intra_close_enter.xml
index e05345d..a499a09 100644
--- a/core/res/res/anim/wallpaper_intra_close_enter.xml
+++ b/core/res/res/anim/wallpaper_intra_close_enter.xml
@@ -19,16 +19,16 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:detachWallpaper="true" android:shareInterpolator="false">
-    <scale android:fromXScale="1.0" android:toXScale="1.0"
-            android:fromYScale=".9" android:toYScale="1.0"
+    <scale android:fromXScale=".95" android:toXScale="1.0"
+            android:fromYScale=".95" android:toYScale="1.0"
             android:pivotX="50%p" android:pivotY="50%p"
             android:fillEnabled="true" android:fillBefore="true"
             android:interpolator="@interpolator/decelerate_quint"
-            android:startOffset="200"
+            android:startOffset="160"
             android:duration="300" />
     <alpha android:fromAlpha="0" android:toAlpha="1.0"
             android:fillEnabled="true" android:fillBefore="true"
-            android:interpolator="@interpolator/decelerate_quint"
-            android:startOffset="200"
+            android:interpolator="@interpolator/decelerate_cubic"
+            android:startOffset="160"
             android:duration="300"/>
-</set>
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/wallpaper_intra_close_exit.xml b/core/res/res/anim/wallpaper_intra_close_exit.xml
index df7acc9..12a8df5 100644
--- a/core/res/res/anim/wallpaper_intra_close_exit.xml
+++ b/core/res/res/anim/wallpaper_intra_close_exit.xml
@@ -19,14 +19,14 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:detachWallpaper="true" android:shareInterpolator="false">
-    <scale android:fromXScale="1.0" android:toXScale="0.9"
-            android:fromYScale="1.0" android:toYScale="0.9"
+    <scale android:fromXScale="1.0" android:toXScale="1.0"
+            android:fromYScale="1.0" android:toYScale="0.0"
             android:pivotX="50%p" android:pivotY="50%p"
             android:fillEnabled="true" android:fillAfter="true"
-            android:interpolator="@interpolator/decelerate_quint"
+            android:interpolator="@interpolator/linear"
             android:duration="300" />
     <alpha android:fromAlpha="1.0" android:toAlpha="0"
-            android:fillEnabled="true" android:fillAfter="true"
+        	android:fillEnabled="true" android:fillAfter="true"
             android:interpolator="@interpolator/decelerate_cubic"
-            android:duration="150"/>
-</set>
+            android:duration="120"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/wallpaper_intra_open_enter.xml b/core/res/res/anim/wallpaper_intra_open_enter.xml
index ff310a1..a499a09 100644
--- a/core/res/res/anim/wallpaper_intra_open_enter.xml
+++ b/core/res/res/anim/wallpaper_intra_open_enter.xml
@@ -19,14 +19,16 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:detachWallpaper="true" android:shareInterpolator="false">
-    <scale android:fromXScale="0.95" android:toXScale="1.0"
-            android:fromYScale="0.95" android:toYScale="1.0"
+    <scale android:fromXScale=".95" android:toXScale="1.0"
+            android:fromYScale=".95" android:toYScale="1.0"
             android:pivotX="50%p" android:pivotY="50%p"
+            android:fillEnabled="true" android:fillBefore="true"
             android:interpolator="@interpolator/decelerate_quint"
-            android:startOffset="200"
+            android:startOffset="160"
             android:duration="300" />
     <alpha android:fromAlpha="0" android:toAlpha="1.0"
+            android:fillEnabled="true" android:fillBefore="true"
             android:interpolator="@interpolator/decelerate_cubic"
-            android:startOffset="200"
+            android:startOffset="160"
             android:duration="300"/>
-</set>
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/wallpaper_intra_open_exit.xml b/core/res/res/anim/wallpaper_intra_open_exit.xml
index 47ea0b4..12a8df5 100644
--- a/core/res/res/anim/wallpaper_intra_open_exit.xml
+++ b/core/res/res/anim/wallpaper_intra_open_exit.xml
@@ -22,9 +22,11 @@
     <scale android:fromXScale="1.0" android:toXScale="1.0"
             android:fromYScale="1.0" android:toYScale="0.0"
             android:pivotX="50%p" android:pivotY="50%p"
+            android:fillEnabled="true" android:fillAfter="true"
             android:interpolator="@interpolator/linear"
             android:duration="300" />
     <alpha android:fromAlpha="1.0" android:toAlpha="0"
+        	android:fillEnabled="true" android:fillAfter="true"
             android:interpolator="@interpolator/decelerate_cubic"
-            android:duration="160"/>
-</set> 
+            android:duration="120"/>
+</set>
\ No newline at end of file
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
index 1ecf103..3667c7b 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
@@ -46,8 +46,8 @@
  * <accesspoint></accesspoint>. The supported configuration includes: ssid,
  * security, eap, phase2, identity, password, anonymousidentity, cacert, usercert,
  * in which each is included in the corresponding tags. Static IP setting is also supported.
- * Tags that can be used include: ip, gateway, netmask, dns1, dns2. All access points have to be
- * enclosed in tags of <resources></resources>.
+ * Tags that can be used include: ip, gateway, networkprefixlength, dns1, dns2. All access points
+ * have to be enclosed in tags of <resources></resources>.
  *
  * The following is a sample configuration file for an access point using EAP-PEAP with MSCHAP2.
  * <resources>
@@ -62,7 +62,8 @@
  * </resources>
  *
  * Note:ssid and security have to be the first two tags
- *      for static ip setting, tag "ip" should be listed before other fields: dns, gateway, netmask.
+ *      for static ip setting, tag "ip" should be listed before other fields: dns, gateway,
+ *      networkprefixlength.
  */
 public class AccessPointParserHelper {
     private static final String KEYSTORE_SPACE = "keystore://";
@@ -106,7 +107,6 @@
         boolean ip = false;
         boolean gateway = false;
         boolean networkprefix = false;
-        boolean netmask = false;
         boolean dns1 = false;
         boolean dns2 = false;
         boolean eap = false;
@@ -163,9 +163,6 @@
             if (tagName.equalsIgnoreCase("networkprefixlength")) {
                 networkprefix = true;
             }
-            if (tagName.equalsIgnoreCase("netmask")) {
-                netmask = true;
-            }
             if (tagName.equalsIgnoreCase("dns1")) {
                 dns1 = true;
             }
@@ -321,19 +318,6 @@
                 }
                 networkprefix = false;
             }
-            if (netmask) {
-                try {
-                    String netMaskStr = new String(ch, start, length);
-                    if (!InetAddress.isNumeric(netMaskStr)) {
-                        throw new SAXException();
-                    }
-                    InetAddress netMaskAddr = InetAddress.getByName(netMaskStr);
-                    mLinkProperties.addLinkAddress(new LinkAddress(mInetAddr, netMaskAddr));
-                } catch (UnknownHostException e) {
-                    throw new SAXException();
-                }
-                netmask = false;
-            }
             if (dns1) {
                 try {
                     String dnsAddr = new String(ch, start, length);
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
index ea79f8c..4457de9 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
@@ -108,6 +108,14 @@
                 fail("thread in sleep is interrupted");
             }
             assertTrue(mAct.mWifiManager.setWifiApEnabled(config, false));
+            // Wait for 30 seconds until Wi-Fi tethering is stopped
+            try {
+                Thread.sleep(30 * 1000);
+                Log.v(TAG, "wait for Wi-Fi tethering to be disabled.");
+            } catch (Exception e) {
+                fail("thread in sleep is interrupted");
+            }
+            assertFalse("Wi-Fi AP disable failed", mAct.mWifiManager.isWifiApEnabled());
         }
         if (i == iterations) {
             mLastIteration = iterations;
diff --git a/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java b/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java
index 242e578..aedfbad 100644
--- a/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java
+++ b/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java
@@ -56,6 +56,12 @@
     private static final int META_STATE_ALT_LEFT_ON = KeyEvent.META_ALT_ON
             | KeyEvent.META_ALT_LEFT_ON;
 
+    /** Prefix for the CSS style span appended by WebKit. */
+    private static final String APPLE_SPAN_PREFIX = "<span class=\"Apple-style-span\"";
+
+    /** Suffix for the CSS style span appended by WebKit. */
+    private static final String APPLE_SPAN_SUFFIX = "</span>";
+
     /** The value for not specified selection string since null is a valid value. */
     private static final String SELECTION_STRING_UNKNOWN = "Unknown";
 
@@ -1578,6 +1584,27 @@
     }
 
     /**
+     * Strips the apple span appended by WebKit while generating
+     * the selection markup.
+     *
+     * @param markup The markup.
+     * @return Stripped from apple spans markup.
+     */
+    private static String stripAppleSpanFromMarkup(String markup) {
+        StringBuilder stripped = new StringBuilder(markup);
+        int prefixBegIdx = stripped.indexOf(APPLE_SPAN_PREFIX);
+        while (prefixBegIdx >= 0) {
+            int prefixEndIdx = stripped.indexOf(">", prefixBegIdx) + 1;
+            stripped.replace(prefixBegIdx, prefixEndIdx, "");
+            int suffixBegIdx = stripped.lastIndexOf(APPLE_SPAN_SUFFIX);
+            int suffixEndIdx = suffixBegIdx + APPLE_SPAN_SUFFIX.length();
+            stripped.replace(suffixBegIdx, suffixEndIdx, "");
+            prefixBegIdx = stripped.indexOf(APPLE_SPAN_PREFIX);
+        }
+        return stripped.toString();
+    }
+
+    /**
      * Disables accessibility and the mock accessibility service.
      */
     private void disableAccessibilityAndMockAccessibilityService() {
@@ -1757,7 +1784,11 @@
             }
             if (!event.getText().isEmpty()) {
                 CharSequence text = event.getText().get(0);
-                sReceivedSelectionString = (text != null) ? text.toString() : null;
+                if (text != null) {
+                    sReceivedSelectionString = stripAppleSpanFromMarkup(text.toString());
+                } else {
+                    sReceivedSelectionString = null;
+                }
             }
             synchronized (sTestLock) {
                 sTestLock.notifyAll();
diff --git a/docs/html/guide/appendix/market-filters.jd b/docs/html/guide/appendix/market-filters.jd
index 6ca8acc..f826f43 100644
--- a/docs/html/guide/appendix/market-filters.jd
+++ b/docs/html/guide/appendix/market-filters.jd
@@ -5,23 +5,25 @@
 <div id="qv">
 
 <h2>Quickview</h2>
-<ul> <li>Android Market applies filters to that let you control whether your app is shown to a
-user who is browing or searching for apps.</li> 
-<li>Filtering is determined by elements in an app's manifest file,
-aspects of the device being used, and other factors.</li> </ul>
+<ul>
+<li>Android Market applies filters that control which Android-powered devices can access your
+application on Market.</li>
+<li>Filtering is determined by comparing device configurations that you declare in you app's
+manifest file to the configurations defined by the device, as well as other factors.</li> </ul>
 
 <h2>In this document</h2>
 
 <ol> <li><a href="#how-filters-work">How Filters Work in Android Market</a></li>
 <li><a href="#manifest-filters">Filtering based on Manifest File Elements</a></li>
 <li><a href="#other-filters">Other Filters</a></li> 
+<li><a href="#advanced-filters">Advanced Manifest Filters</a></li>
 </ol>
 
 <h2>See also</h2>
  <ol> 
 <li><a
-href="{@docRoot}guide/practices/compatibility.html">Compatibility</a></li>
-<li style="margin-top:2px;"><code><a
+href="{@docRoot}guide/practices/compatibility.html">Android Compatibility</a></li>
+<li><code><a
 href="{@docRoot}guide/topics/manifest/supports-screens-element.html">&lt;supports-screens&gt;</a></code></li>
 <li><code><a
 href="{@docRoot}guide/topics/manifest/uses-configuration-element.html">&lt;uses-configuration&gt;</a></code></li>
@@ -42,36 +44,40 @@
 href="http://market.android.com/publish">Go to Android Market &raquo;</a> </div>
 </div>
 
-</div> </div>
+</div>
+</div>
 
-<p>When a user searches or browses in Android Market, the results are filtered, and
-some applications might not be visible. For example, if an application requires a
+
+<p>When a user searches or browses in Android Market, the results are filtered based on which
+applications are compatible with the user's device. For example, if an application requires a
 trackball (as specified in the manifest file), then Android Market will not show
-the app on any device that does not have a trackball.</p> <p>The manifest file and
-the device's hardware and features are only part of how applications are filtered
-&#8212; filtering also depends on the country and carrier, the presence or absence
-of a SIM card, and other factors. </p>
+the app on any device that does not have a trackball.</p>
+
+<p>The manifest file and the device's hardware and features are only part of how applications are
+filtered&mdash;filtering might also depend on the country and carrier, the presence or absence of a
+SIM card, and other factors. </p>
 
 <p>Changes to the Android Market filters are independent of changes 
 to the Android platform itself. This document will be updated periodically to reflect 
-any changes that occur. </p>
+any changes that affect the way Android Market filters applications.</p>
+
 
 <h2 id="how-filters-work">How Filters Work in Android Market</h2>
 
 <p>Android Market uses the filter restrictions described below to determine
 whether to show your application to a user who is browsing or searching for
-applications on a given device. When determining whether to display your app,
+applications on an Android-powered device. When determining whether to display your app,
 Market checks the device's hardware and software capabilities, as well as it's
 carrier, location, and other characteristics. It then compares those against the
 restrictions and dependencies expressed by the application itself, in its
-manifest, <code>.apk</code>, and publishing details. If the application is
+manifest file and publishing details. If the application is
 compatible with the device according to the filter rules, Market displays the
 application to the user. Otherwise, Market hides your application from search
 results and category browsing. </p>
 
-<p> You can use the filters described below to control whether Market shows or
-hides your application to users. You can request any combination of the
-available filters for your app &#8212; for example, you could set a
+<p>You can use the filters described below to control whether Market shows or
+hides your application to users. You can use any combination of the
+available filters for your app&mdash;for example, you can set a
 <code>minSdkVersion</code> requirement of <code>"4"</code> and set
 <code>smallScreens="false"</code> in the app, then when uploading the app to
 Market you could target European countries (carriers) only. Android Market's
@@ -92,16 +98,18 @@
 available. </li>
 </ul>
 
+
+
 <h2 id="manifest-filters">Filtering based on Manifest Elements</h2>
 
 <p>Most Market filters are triggered by elements within an application's
 manifest file, <a
 href="{@docRoot}guide/topics/manifest/manifest-intro.html">AndroidManifest.xml</a>,
-although not everything in the manifest file can trigger filtering. The
-table below lists the manifest elements that you can use to trigger Android
-Market filtering, and explains how the filtering works.</p>
+although not everything in the manifest file can trigger filtering.
+Table 1 lists the manifest elements that you should use to trigger Android
+Market filtering, and explains how the filtering for each element works.</p>
 
-<p class="table-caption"><strong>Table 1.</strong> Manifest elements that
+<p id="table1" class="table-caption"><strong>Table 1.</strong> Manifest elements that
 trigger filtering on Market.</p>
 <table>
   <tr>
@@ -313,10 +321,13 @@
   </tr>
 </table>
 
+
 <h2 id="other-filters">Other Filters</h2>
+
 <p>Android Market uses other application characteristics to determine whether to show or hide an application for a particular user on a given device, as described in the table below. </p>
 
-<p class="table-caption"><strong>Table 2.</strong> Application and publishing characteristics that affect filtering on Market.</p>
+<p id="table2" class="table-caption"><strong>Table 2.</strong> Application and publishing
+characteristics that affect filtering on Market.</p>
 <table> <tr>
     <th>Filter Name</th> <th>How It Works</th> </tr>
 
@@ -351,3 +362,38 @@
 developer devices or unreleased devices.</p></td> </tr> </table>
 
 
+
+
+<h2 id="advanced-filters">Advanced Manifest Filters</h2>
+
+<p>In addition to the manifest elements in <a href="#table1">table 1</a>, Android Market can also
+filter applications based on the advanced manifest elements in table 3.</p>
+
+<p>These manifest elements and the filtering they trigger are for exceptional use-cases
+only. They are designed for some types of high-performance games and similar applications that
+require strict controls on application distribution. <strong>Most applications should never use
+these filters</strong>.</p>
+
+<p id="table3" class="table-caption"><strong>Table 3.</strong> Advanced manifest elements for
+Android Market filtering.</p>
+<table>
+  <tr><th>Manifest Element</th><th>Summary</th></tr>
+  <tr>
+    <td><nobr><a href="{@docRoot}guide/topics/manifest/compatible-screens-element.html">{@code
+&lt;compatible-screens&gt;}</a></nobr></td>
+    <td>
+      <p>Android Market filters the application if the device screen size and density does not match
+any of the screen configurations (declared by a {@code &lt;screen&gt;} element) in the {@code
+&lt;compatible-screens&gt;} element.</p>
+      <p class="caution"><strong>Caution:</strong> Normally, <strong>you should not use
+this manifest element</strong>. Using this element can dramatically
+reduce the potential user base for your application, by excluding all combinations of screen size
+and density that you have not listed. You should instead use the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> manifest element (described above in <a href="#table1">table
+1</a>) to enable screen compatibility mode for screen configurations you have not accounted for
+with alternative resources.</p>
+    </td>
+  </tr>
+</table>
+
diff --git a/docs/html/guide/developing/testing/index.jd b/docs/html/guide/developing/testing/index.jd
index 8ffaf58..8a08959 100644
--- a/docs/html/guide/developing/testing/index.jd
+++ b/docs/html/guide/developing/testing/index.jd
@@ -18,14 +18,14 @@
     which guides you through a more complex testing scenario.
 </p>
 <dl>
-  <dt><a href="testing_eclipse.html">Testing in Eclipse, with ADT</a></dt>
+  <dt><a href="testing_eclipse.html">Testing from Eclipse, with ADT</a></dt>
           <dd>
             The ADT plugin lets you quickly set up and manage test projects directly in
             the Eclipse UI. Once you have written your tests, you can build and run them and
             then see the results in the Eclipse JUnit view. You can also use the SDK command-line
             tools to execute your tests if needed.
           </dd>
-  <dt><a href="testing_otheride.html">Testing in Other IDEs</a></dt>
+  <dt><a href="testing_otheride.html">Testing from Other IDEs</a></dt>
     <dd>
         The SDK command-line tools provide the same capabilities as the ADT plugin. You can
         use them to set up and manage test projects, build your test application,
diff --git a/docs/html/guide/developing/tools/monkeyrunner_concepts.jd b/docs/html/guide/developing/tools/monkeyrunner_concepts.jd
index d648b93..658ff75 100644
--- a/docs/html/guide/developing/tools/monkeyrunner_concepts.jd
+++ b/docs/html/guide/developing/tools/monkeyrunner_concepts.jd
@@ -110,8 +110,17 @@
 # to see if the installation worked.
 device.installPackage('myproject/bin/MyApplication.apk')
 
-# Runs an activity in the application
-device.startActivity(component='com.example.android.myapplication.MainActivity')
+# sets a variable with the package's internal name
+package = 'com.example.android.myapplication'
+
+# sets a variable with the name of an Activity in the package
+activity = 'com.example.android.myapplication.MainActivity'
+
+# sets the name of the component to start
+runComponent = package + '/' + activity
+
+# Runs the component
+device.startActivity(component=runComponent)
 
 # Presses the Menu button
 device.press('KEYCODE_MENU','DOWN_AND_UP')
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index aafbe30..24ccfdb 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -65,6 +65,9 @@
           <li><a href="<?cs var:toroot ?>guide/topics/fundamentals/fragments.html">
             <span class="en">Fragments</span>
           </a> <span class="new">new!</span></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/providers/loaders.html">
+            <span class="en">Loaders</span>
+          </a><span class="new">new!</span></li>
           <li><a href="<?cs var:toroot ?>guide/topics/fundamentals/tasks-and-back-stack.html">
             <span class="en">Tasks and Back Stack</span>
           </a></li>
@@ -95,8 +98,9 @@
     <ul>
       <li class="toggle-list">
         <div><a href="<?cs var:toroot ?>guide/topics/ui/index.html">
-               <span class="en">User Interface</span>
-             </a></div>
+            <span class="en">User Interface</span>
+          </a>
+          <span class="new">more!</span></div>
         <ul>
           <li><a href="<?cs var:toroot ?>guide/topics/ui/declaring-layout.html">
                <span class="en">Declaring Layout</span>
@@ -125,7 +129,12 @@
                 <span class="en">Creating Status Bar Notifications</span>
               </a></li>
             </ul>
-          </li><!-- end of notifying the user -->
+          </li>
+          <li>
+              <a href="<?cs var:toroot ?>guide/topics/ui/drag-drop.html">
+                  Dragging and Dropping
+              </a><span class="new">new!</span>
+          </li>
           <li><a href="<?cs var:toroot ?>guide/topics/ui/themes.html">
                 <span class="en">Applying Styles and Themes</span>
               </a></li>
@@ -202,6 +211,7 @@
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a></li>
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/application-element.html">&lt;application&gt;</a></li>
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/category-element.html">&lt;category&gt;</a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/compatible-screens-element.html">&lt;compatible-screens&gt;</a></li>
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/data-element.html">&lt;data&gt;</a></li>
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/grant-uri-permission-element.html">&lt;grant-uri-permission&gt;</a></li>
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/instrumentation-element.html">&lt;instrumentation&gt;</a></li>
@@ -228,8 +238,9 @@
     <ul>
       <li class="toggle-list">
         <div><a href="<?cs var:toroot ?>guide/topics/graphics/index.html">
-               <span class="en">Graphics</span>
-             </a></div>
+            <span class="en">Graphics</span>
+          </a>
+          <span class="new">more!</span></div>
         <ul>
           <li><a href="<?cs var:toroot ?>guide/topics/graphics/2d-graphics.html">
                 <span class="en">2D Graphics</span>
@@ -251,6 +262,12 @@
       <li><a href="<?cs var:toroot ?>guide/topics/media/index.html">
             <span class="en">Audio and Video</span>
           </a></li>
+      <li>
+        <a href="<?cs var:toroot ?>guide/topics/clipboard/copy-paste.html">
+            <span class="en">Copy and Paste</span>
+        </a>
+        <span class="new">new!</span>
+      </li>
   <!--<li class="toggle-list">
         <div><a style="color:gray;">Sensors</a></div>
           <ul>
@@ -402,24 +419,24 @@
       <li class="toggle-list">
         <div>
            <a href="<?cs var:toroot ?>guide/developing/devices/index.html">
-        	     <span class="en">Managing Virtual Devices</span>
-         	 </a>
+                <span class="en">Creating and Managing Virtual Devices</span>
+            </a>
         </div>
         <ul>
           <li>
             <a href="<?cs var:toroot ?>guide/developing/devices/managing-avds.html">
               <span class="en">With AVD Manager</span>
-         	 </a>
+            </a>
           </li>
           <li>
             <a href="<?cs var:toroot ?>guide/developing/devices/managing-avds-cmdline.html">
-              <span class="en">From the Command Line</span>
-         	 </a>
+              <span class="en">On the Command Line</span>
+            </a>
           </li>
           <li>
            <a href="<?cs var:toroot ?>guide/developing/devices/emulator.html">
-        	     <span class="en">Using the Android Emulator</span>
-         	 </a>
+                <span class="en">Using the Android Emulator</span>
+            </a>
           </li>
         </ul>
       </li>
@@ -428,7 +445,7 @@
           <span class="en">Using Hardware Devices</span>
         </a>
       </li>
-      
+
       <li class="toggle-list">
         <div>
           <a href="<?cs var:toroot ?>guide/developing/projects/index.html">
@@ -443,7 +460,7 @@
           </li>
           <li>
             <a href="<?cs var:toroot ?>guide/developing/projects/projects-cmdline.html">
-        	    <span class="en">From the Command Line</span>
+                <span class="en">On the Command Line</span>
             </a>
           </li>
         </ul>
@@ -473,12 +490,12 @@
         <ul>
           <li>
             <a href="<?cs var:toroot ?>guide/developing/debugging/debugging-projects.html">
-         	    <span class="en">From Eclipse with ADT</span>
+                <span class="en">In Eclipse with ADT</span>
             </a>
           </li>
           <li>
             <a href="<?cs var:toroot ?>guide/developing/debugging/debugging-projects-cmdline.html">
-         	    <span class="en">From Other IDEs</span>
+                <span class="en">In Other IDEs</span>
             </a>
           </li>
           <li>
@@ -488,23 +505,23 @@
           </li>
           <li>
             <a href="<?cs var:toroot ?>guide/developing/debugging/debugging-log.html">
-         	    <span class="en">Reading and Writing Logs</span>
+                <span class="en">Reading and Writing Log Messages</span>
             </a>
           </li>
           <li>
             <a href="<?cs var:toroot ?>guide/developing/debugging/debugging-ui.html">
-         	    <span class="en">Debugging and Profiling UIs</span>
-          	</a>
+                <span class="en">Debugging and Profiling UIs</span>
+            </a>
           </li>
           <li>
             <a href="<?cs var:toroot ?>guide/developing/debugging/debugging-tracing.html">
-         	    <span class="en">Profiling with Traceview and dmtracedump</span>
-          	</a>
+                <span class="en">Profiling with Traceview and dmtracedump</span>
+            </a>
           </li>
           <li>
             <a href="<?cs var:toroot ?>guide/developing/debugging/debugging-devtools.html">
-         	    <span class="en">Using the Dev Tools App</span>
-          	</a>
+                <span class="en">Using the Dev Tools App</span>
+            </a>
           </li>
         </ul>
       </li>
diff --git a/docs/html/guide/topics/clipboard/copy-paste.jd b/docs/html/guide/topics/clipboard/copy-paste.jd
new file mode 100644
index 0000000..6c86f47
--- /dev/null
+++ b/docs/html/guide/topics/clipboard/copy-paste.jd
@@ -0,0 +1,1094 @@
+page.title=Copy and Paste
+@jd:body
+<div id="qv-wrapper">
+    <div id="qv">
+        <h2>Quickview</h2>
+            <ul>
+                <li>
+                    A clipboard-based framework for copying and pasting data.
+                </li>
+                <li>
+                    Supports both simple and complex data, including text strings, complex data
+                    structures, text and binary stream data, and application assets.
+                </li>
+                <li>
+                    Copies and pastes simple text directly to and from the clipboard.
+                </li>
+                <li>
+                    Copies and pastes complex data using a content provider.
+                </li>
+                <li>
+                    Requires API 11.
+                </li>
+            </ul>
+        <h2>In this document</h2>
+        <ol>
+            <li>
+                <a href="#Clipboard">The Clipboard Framework</a>
+            </li>
+            <li>
+                <a href="#ClipboardClasses">Clipboard Classes</a>
+                <ol>
+                    <li>
+                        <a href="#ClipboardManager">ClipboardManager</a>
+                    </li>
+                    <li>
+                        <a href="#ClipClasses">
+                            ClipData, ClipDescription, and ClipData.Item
+                        </a>
+                    </li>
+                    <li>
+                        <a href="#ClipDataMethods">ClipData convenience methods</a>
+                    </li>
+                    <li>
+                        <a href="#CoerceToText">Coercing the clipboard data to text</a>
+                    </li>
+                </ol>
+            </li>
+            <li>
+                <a href="#Copying">Copying to the Clipboard</a>
+            </li>
+            <li>
+                <a href="#Pasting">Pasting from the Clipboard</a>
+                <ol>
+                    <li>
+                        <a href="#PastePlainText">Pasting plain text</a>
+                    </li>
+                    <li>
+                        <a href="#PasteContentUri">Pasting data from a content URI</a>
+                    </li>
+                    <li>
+                        <a href="#PasteIntent">Pasting an Intent</a>
+                    </li>
+                </ol>
+            </li>
+            <li>
+                <a href="#Provider">Using Content Providers to Copy Complex Data</a>
+                <ol>
+                    <li>
+                        <a href="#Encoding">Encoding an identifier on the URI</a>
+                    </li>
+                    <li>
+                        <a href="#Records">Copying data structures</a>
+                    </li>
+                    <li>
+                        <a href="#Streams">Copying data streams</a>
+                    </li>
+                </ol>
+            </li>
+            <li>
+                <a href="#DataDesign">Designing Effective Copy/Paste Functionality</a>
+            </li>
+        </ol>
+        <h2>Key classes</h2>
+        <ol>
+            <li>
+                {@link android.content.ClipboardManager ClipboardManager}
+            </li>
+            <li>
+                {@link android.content.ClipData ClipData}
+            </li>
+            <li>
+                {@link android.content.ClipData.Item ClipData.Item}
+            </li>
+            <li>
+                {@link android.content.ClipDescription ClipDescription}
+            </li>
+            <li>
+                {@link android.net.Uri Uri}
+            </li>
+            <li>
+                {@link android.content.ContentProvider}
+            </li>
+            <li>
+                {@link android.content.Intent Intent}
+            </li>
+        </ol>
+        <h2>Related Samples</h2>
+        <ol>
+            <li>
+                <a href="{@docRoot}resources/samples/NotePad/index.html">
+                Note Pad sample application</a>
+            </li>
+        </ol>
+        <h2>See also</h2>
+        <ol>
+            <li>
+            <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
+            </li>
+        </ol>
+    </div>
+</div>
+<p>
+    Android provides a powerful clipboard-based framework for copying and pasting. It
+    supports both simple and complex data types, including text strings, complex data
+    structures, text and binary stream data, and even application assets. Simple text data is stored
+    directly in the clipboard, while complex data is stored as a reference that the pasting
+    application resolves with a content provider. Copying and pasting works both within an
+    application and between applications that implement the framework.
+</p>
+
+<p>
+    Since a part of the framework uses content providers, this topic assumes some
+    familiarity with the Android Content Provider API, which is described in the topic
+    <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>.
+</p>
+<h2 id="Clipboard">The Clipboard Framework</h2>
+<p>
+    When you use the clipboard framework, you put data into a clip object, and then
+    put the clip object on the system-wide clipboard. The clip object can take one of three forms:
+</p>
+    <dl>
+        <dt>Text</dt>
+        <dd>
+            A text string. You put the string directly into the clip object, which you then put onto
+            the clipboard. To paste the string, you get the clip object from the clipboard and copy
+            the string to into your application's storage.
+        </dd>
+        <dt>URI</dt>
+        <dd>
+            A {@link android.net.Uri} object representing any form of URI. This is primarily for
+            copying complex data from a content provider. To copy data, you put a
+            {@link android.net.Uri} object into a clip object and put the clip object onto
+            the clipboard. To paste the data, you get the clip object, get the
+            {@link android.net.Uri} object, resolve it to a data source such as a content provider,
+            and copy the data from the source into your application's storage.
+        </dd>
+        <dt>Intent</dt>
+        <dd>
+            An {@link android.content.Intent}. This supports copying application shortcuts. To copy
+            data, you create an Intent, put it into a clip object, and put the clip object onto the
+            clipboard. To paste the data, you get the clip object and then copy the Intent object
+            into your application's memory area.
+        </dd>
+    </dl>
+<p>
+    The clipboard holds only one clip object at a time. When an application puts a clip object on
+    the clipboard, the previous clip object disappears.
+</p>
+<p>
+    If you want to allow users to paste data into your application, you don't have to handle all
+    types of data. You can examine the data on the clipboard before you give users the option to
+    paste it. Besides having a certain data form, the clip object also contains metadata that tells
+    you what MIME type or types are available. This metadata helps you decide if your application
+    can do something useful with the clipboard data. For example, if you have an application that
+    primarily handles text you may want to ignore clip objects that contain a URI or Intent.
+</p>
+<p>
+    You may also want to allow users to paste text regardless of the form of data on the
+    clipboard. To do this, you can force the clipboard data into a text representation, and then
+    paste this text. This is described in the section <a href="#CoerceToText">Coercing the
+    clipboard to text</a>.
+</p>
+<h2 id="ClipboardClasses">Clipboard Classes</h2>
+<p>
+    This section describes the classes used by the clipboard framework.
+</p>
+<h3 id="ClipboardManager">ClipboardManager</h3>
+<p>
+    In the Android system, the system clipboard is represented by the global
+    {@link android.content.ClipboardManager} class. You do not instantiate this
+    class directly; instead, you get a reference to it by invoking
+    {@link android.content.Context#getSystemService(String) getSystemService(CLIPBOARD_SERVICE)}.
+</p>
+<h3 id="ClipClasses">ClipData, ClipData.Item, and ClipDescription</h3>
+<p>
+    To add data to the clipboard, you create a {@link android.content.ClipData} object that
+    contains both a description of the data and the data itself. The clipboard holds only one
+    {@link android.content.ClipData} at a time. A {@link android.content.ClipData} contains a
+    {@link android.content.ClipDescription} object and one or more
+    {@link android.content.ClipData.Item} objects.
+</p>
+<p>
+    A {@link android.content.ClipDescription} object contains metadata about the clip. In
+    particular, it contains an array of available MIME types for the clip's data. When you put a
+    clip on the clipboard, this array is available to pasting applications, which can examine it to
+    see if they can handle any of available the MIME types.
+</p>
+<p>
+    A {@link android.content.ClipData.Item} object contains the text, URI, or Intent data:
+</p>
+<dl>
+    <dt>Text</dt>
+    <dd>
+        A {@link java.lang.CharSequence}.
+    </dd>
+    <dt>URI</dt>
+    <dd>
+        A {@link android.net.Uri}. This usually contains a content provider URI, although any
+        URI is allowed. The application that provides the data puts the URI on the clipboard.
+        Applications that want to paste the data get the URI from the clipboard and use it to
+        access the content provider (or other data source) and retrieve the data.
+    </dd>
+    <dt>Intent</dt>
+    <dd>
+        An {@link android.content.Intent}. This data type allows you to copy an application shortcut
+        to the clipboard. Users can then paste the shortcut into their applications for later use.
+    </dd>
+</dl>
+<p>
+    You can add more than one {@link android.content.ClipData.Item} object to a clip. This allows
+    users to copy and paste multiple selections as a single clip. For example, if you have a list
+    widget that allows the user to select more than one item at a time, you can copy all the items
+    to the clipboard at once. To do this, you create a separate
+    {@link android.content.ClipData.Item} for each list item, and then you add the
+    {@link android.content.ClipData.Item} objects to the {@link android.content.ClipData} object.
+</p>
+<h3 id="ClipDataMethods">ClipData convenience methods</h3>
+<p>
+    The {@link android.content.ClipData} class provides static convenience methods for creating
+    a {@link android.content.ClipData} object with a single {@link android.content.ClipData.Item}
+    object and a simple {@link android.content.ClipDescription} object:
+</p>
+<dl>
+    <dt>
+{@link android.content.ClipData#newPlainText(CharSequence,CharSequence) newPlainText(label, text)}
+    </dt>
+    <dd>
+        Returns a {@link android.content.ClipData} object whose single
+        {@link android.content.ClipData.Item} object contains a text string. The
+        {@link android.content.ClipDescription} object's label is set to <code>label</code>.
+        The single MIME type in {@link android.content.ClipDescription} is
+        {@link android.content.ClipDescription#MIMETYPE_TEXT_PLAIN}.
+        <p>
+            Use
+{@link android.content.ClipData#newPlainText(CharSequence,CharSequence) newPlainText()}
+            to create a clip from a text string.
+    </dd>
+    <dt>
+{@link android.content.ClipData#newUri(ContentResolver, CharSequence, Uri) newUri(resolver, label, URI)}
+    </dt>
+    <dd>
+        Returns a {@link android.content.ClipData} object whose single
+        {@link android.content.ClipData.Item} object contains a URI. The
+        {@link android.content.ClipDescription} object's label is set to <code>label</code>.
+        If the URI is a content URI ({@link android.net.Uri#getScheme() Uri.getScheme()} returns
+        <code>content:</code>), the method uses the {@link android.content.ContentResolver} object
+        provided in <code>resolver</code> to retrieve the available MIME types from the
+        content provider and store them in {@link android.content.ClipDescription}. For a URI that
+        is not a <code>content:</code> URI, the method sets the MIME type to
+        {@link android.content.ClipDescription#MIMETYPE_TEXT_URILIST}.
+        <p>
+            Use
+{@link android.content.ClipData#newUri(ContentResolver, CharSequence, Uri) newUri()}
+            to create a clip from a URI, particularly a <code>content:</code> URI.
+        </p>
+    </dd>
+    <dt>
+        {@link android.content.ClipData#newIntent(CharSequence, Intent) newIntent(label, intent)}
+    </dt>
+    <dd>
+        Returns a {@link android.content.ClipData} object whose single
+        {@link android.content.ClipData.Item} object contains an {@link android.content.Intent}.
+        The {@link android.content.ClipDescription} object's label is set to <code>label</code>.
+        The MIME type is set to {@link android.content.ClipDescription#MIMETYPE_TEXT_INTENT}.
+        <p>
+            Use
+{@link android.content.ClipData#newIntent(CharSequence, Intent) newIntent()}
+            to create a clip from an Intent object.
+    </dd>
+</dl>
+<h3 id="CoerceToText">Coercing the clipboard data to text</h3>
+<p>
+    Even if your application only handles text, you can copy non-text data from the
+    clipboard by converting it with the method
+    {@link android.content.ClipData.Item#coerceToText(Context) ClipData.Item.coerceToText()}.
+</p>
+<p>
+    This method converts the data in {@link android.content.ClipData.Item} to text and
+    returns a {@link java.lang.CharSequence}. The value that
+    {@link android.content.ClipData.Item#coerceToText(Context) ClipData.Item.coerceToText()}
+    returns is based on the form of data in {@link android.content.ClipData.Item}:
+</p>
+<dl>
+    <dt><em>Text</em></dt>
+    <dd>
+        If {@link android.content.ClipData.Item} is text
+        ({@link android.content.ClipData.Item#getText()} is not null),
+        {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} returns the
+        text.
+    </dd>
+    <dt><em>URI</em></dt>
+    <dd>
+        If {@link android.content.ClipData.Item} is a URI
+        ({@link android.content.ClipData.Item#getUri()} is not null),
+        {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} tries to use
+        it as a content URI:
+    <ul>
+        <li>
+                If the URI is a content URI and the provider can return a text stream,
+                {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} returns
+                a text stream.
+            </li>
+            <li>
+                If the URI is a content URI but the provider does not offer a text stream,
+                {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} returns
+                a representation of the URI. The representation is the same as that returned by
+                {@link android.net.Uri#toString() Uri.toString()}.
+            </li>
+            <li>
+                If the URI is not a content URI,
+                {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} returns
+                a representation of the URI. The representation is the same as that returned by
+                {@link android.net.Uri#toString() Uri.toString()}.
+            </li>
+        </ul>
+    </dd>
+    <dt><em>Intent</em></dt>
+    <dd>
+        If {@link android.content.ClipData.Item} is an Intent
+        ({@link android.content.ClipData.Item#getIntent()} is not null),
+        {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} converts it to
+        an Intent URI and returns it. The representation is the same as that returned by
+        {@link android.content.Intent#toUri(int) Intent.toUri(URI_INTENT_SCHEME)}.
+    </dd>
+</dl>
+<p>
+    The clipboard framework is summarized in Figure 1. To copy data, an application puts a
+    {@link android.content.ClipData} object on the {@link android.content.ClipboardManager} global
+    clipboard. The {@link android.content.ClipData} contains one or more
+    {@link android.content.ClipData.Item} objects and one
+    {@link android.content.ClipDescription} object. To paste data, an application gets the
+    {@link android.content.ClipData}, gets its MIME type from the
+    {@link android.content.ClipDescription}, and gets the data either from
+    the {@link android.content.ClipData.Item} or from the content provider referred to by
+    {@link android.content.ClipData.Item}.
+</p>
+    <a name="framework"></a>
+    <img
+        src="{@docRoot}images/ui/clipboard/copy_paste_framework.png"
+        alt="A block diagram of the copy and paste framework" height="400px" id="figure1" />
+<p class="img-caption">
+    <strong>Figure 1.</strong> The Android clipboard framework
+</p>
+<h2 id="Copying">Copying to the Clipboard</h2>
+<p>
+    As described previously, to copy data to the clipboard you get a handle to the global
+    {@link android.content.ClipboardManager} object, create a {@link android.content.ClipData}
+    object, add a {@link android.content.ClipDescription} and one or more
+    {@link android.content.ClipData.Item} objects to it, and add the finished
+    {@link android.content.ClipData} object to the {@link android.content.ClipboardManager} object.
+    This is described in detail in the following procedure:
+</p>
+<ol>
+    <li>
+        If you are copying data using a content URI, set up a content
+        provider.
+        <p>
+            The <a href="{@docRoot}resources/samples/NotePad/index.html">
+            Note Pad</a> sample application is an example of using a content provider for
+            copying and pasting. The
+<a href="{@docRoot}resources/samples/NotePad/src/com/example/android/notepad/NotePadProvider.html">
+            NotePadProvider</a> class implements the content provider. The
+<a href="{@docRoot}resources/samples/NotePad/src/com/example/android/notepad/NotePad.html">
+            NotePad</a> class defines a contract between the provider and other applications,
+            including the supported MIME types.
+        </p>
+    </li>
+    <li>
+        Get the system clipboard:
+<pre>
+
+...
+
+// if the user selects copy
+case R.id.menu_copy:
+
+// Gets a handle to the clipboard service.
+ClipboardManager clipboard = (ClipboardManager)
+        getSystemService(Context.CLIPBOARD_SERVICE);
+</pre>
+    </li>
+    <li>
+        <p>
+            Copy the data to a new {@link android.content.ClipData} object:
+        </p>
+        <ul>
+            <li>
+                <h4>For text</h4>
+<pre>
+// Creates a new text clip to put on the clipboard
+ClipData clip = ClipData.newPlainText(&quot;simple text&quot;,&quot;Hello, World!&quot;);
+</pre>
+            </li>
+            <li>
+                <h4>For a URI</h4>
+                <p>
+                    This snippet constructs a URI by encoding a record ID onto the content URI
+                    for the provider. This technique is covered in more detail
+                    in the section <a href="#Encoding">Encoding an identifier on the URI</a>:
+                </p>
+<pre>
+// Creates a Uri based on a base Uri and a record ID based on the contact's last name
+// Declares the base URI string
+private static final String CONTACTS = &quot;content:&#47;&#47;com.example.contacts&quot;;
+
+// Declares a path string for URIs that you use to copy data
+private static final String COPY_PATH = &quot;/copy&quot;;
+
+// Declares the Uri to paste to the clipboard
+Uri copyUri = Uri.parse(CONTACTS + COPY_PATH + &quot;/&quot; + lastName);
+
+...
+
+// Creates a new URI clip object. The system uses the anonymous getContentResolver() object to
+// get MIME types from provider. The clip object's label is &quot;URI&quot;, and its data is
+// the Uri previously created.
+ClipData clip = ClipData.newUri(getContentResolver(),&quot;URI&quot;,copyUri);
+</pre>
+            </li>
+            <li>
+                <h4>For an Intent</h4>
+                <p>
+                    This snippet constructs an Intent for an application
+                    and then puts it in the clip object:
+                </p>
+<pre>
+// Creates the Intent
+Intent appIntent = new Intent(this, com.example.demo.myapplication.class);
+
+...
+
+// Creates a clip object with the Intent in it. Its label is &quot;Intent&quot; and its data is
+// the Intent object created previously
+ClipData clip = ClipData.newIntent(&quot;Intent&quot;,appIntent);
+</pre>
+            </li>
+        </ul>
+    </li>
+    <li>
+        Put the new clip object on the clipboard:
+<pre>
+// Set the clipboard's primary clip.
+clipboard.setPrimaryClip(clip);
+</pre>
+    </li>
+</ol>
+<h2 id="Pasting">Pasting from the Clipboard</h2>
+<p>
+    As described previously, you paste data from the clipboard by getting the global clipboard
+    object, getting the clip object, looking at its data, and if possible copying the data from
+    the clip object to your own storage. This section describes in detail how to do this for
+    the three forms of clipboard data.
+</p>
+<h3 id="PastePlainText">Pasting plain text</h3>
+<p>
+    To paste plain text, first get the global clipboard and verify that it can return plain text.
+    Then get the clip object and copy its text to your own storage using
+    {@link android.content.ClipData.Item#getText()}, as described in the following procedure:
+</p>
+<ol>
+    <li>
+        Get the global {@link android.content.ClipboardManager} object using
+ {@link android.content.Context#getSystemService(String) getSystemService(CLIPBOARD_SERVICE)}. Also
+        declare a global variable to contain the pasted text:
+<pre>
+ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
+
+String pasteData = &quot;&quot;;
+
+</pre>
+    </li>
+    <li>
+        Next, determine if you should enable or disable the &quot;paste&quot; option in the
+        current Activity. You should verify that the clipboard contains a clip and that you
+        can handle the type of data represented by the clip:
+<pre>
+// Gets the ID of the &quot;paste&quot; menu item
+MenuItem mPasteItem = menu.findItem(R.id.menu_paste);
+
+// If the clipboard doesn't contain data, disable the paste menu item.
+// If it does contain data, decide if you can handle the data.
+if (!(clipboard.hasPrimaryClip())) {
+
+    mPasteItem.setEnabled(false);
+
+    } else if (!(clipboard.getPrimaryClipDescription().hasMimeType(MIMETYPE_TEXT_PLAIN))) {
+
+        // This disables the paste menu item, since the clipboard has data but it is not plain text
+        mPasteItem.setEnabled(false);
+    } else {
+
+        // This enables the paste menu item, since the clipboard contains plain text.
+        mPasteItem.setEnabled(true);
+    }
+}
+</pre>
+    </li>
+    <li>
+        Copy the data from the clipboard. This point in the program is only reachable if the
+        &quot;paste&quot; menu item is enabled, so you can assume that the clipboard contains
+        plain text. You do not yet know if it contains a text string or a URI that points to plain
+        text. The following snippet tests this, but it only shows the code for handling plain text:
+<pre>
+// Responds to the user selecting &quot;paste&quot;
+case R.id.menu_paste:
+
+// Examines the item on the clipboard. If getText() does not return null, the clip item contains the
+// text. Assumes that this application can only handle one item at a time.
+ ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0);
+
+// Gets the clipboard as text.
+pasteData = item.getText();
+
+// If the string contains data, then the paste operation is done
+if (pasteData != null) {
+    return;
+
+// The clipboard does not contain text. If it contains a URI, attempts to get data from it
+} else {
+    Uri pasteUri = item.getUri();
+
+    // If the URI contains something, try to get text from it
+    if (pasteUri != null) {
+
+        // calls a routine to resolve the URI and get data from it. This routine is not
+        // presented here.
+        pasteData = resolveUri(Uri);
+        return;
+    } else {
+
+    // Something is wrong. The MIME type was plain text, but the clipboard does not contain either
+    // text or a Uri. Report an error.
+    Log.e(&quot;Clipboard contains an invalid data type&quot;);
+    return;
+    }
+}
+</pre>
+    </li>
+</ol>
+<h3 id="PasteContentUri">Pasting data from a content URI</h3>
+<p>
+    If the {@link android.content.ClipData.Item} object contains a content URI and you
+    have determined that you can handle one of its MIME types, create a
+    {@link android.content.ContentResolver} and then call the appropriate content provider
+    method to retrieve the data.
+</p>
+<p>
+    The following procedure describes how to get data from a content provider based on a
+    content URI on the clipboard. It checks that a MIME type that the application can use
+    is available from the provider:
+</p>
+<ol>
+    <li>
+        Declare a global variable to contain the MIME type:
+<pre>
+// Declares a MIME type constant to match against the MIME types offered by the provider
+public static final String MIME_TYPE_CONTACT = &quot;vnd.android.cursor.item/vnd.example.contact&quot;
+</pre>
+    </li>
+    <li>
+        Get the global clipboard. Also get a content resolver so you can access the content
+        provider:
+<pre>
+// Gets a handle to the Clipboard Manager
+ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
+
+// Gets a content resolver instance
+ContentResolver cr = getContentResolver();
+</pre>
+    </li>
+    <li>
+        Get the primary clip from the clipboard, and get its contents as a URI:
+<pre>
+// Gets the clipboard data from the clipboard
+ClipData clip = clipboard.getPrimaryClip();
+
+if (clip != null) {
+
+    // Gets the first item from the clipboard data
+    ClipData.Item item = clip.getItemAt(0);
+
+    // Tries to get the item's contents as a URI
+    Uri pasteUri = item.getUri();
+</pre>
+    </li>
+    <li>
+        Test to see if the URI is a content URI by calling
+        {@link android.content.ContentResolver#getType(Uri) getType(Uri)}. This method returns
+        null if <code>Uri</code> does not point to a valid content provider:
+<pre>
+    // If the clipboard contains a URI reference
+    if (pasteUri != null) {
+
+        // Is this a content URI?
+        String uriMimeType = cr.getType(pasteUri);
+</pre>
+    </li>
+    <li>
+        Test to see if the content provider supports a MIME type that the current application
+        understands. If it does, call
+        {@link android.content.ContentResolver#query(Uri, String[], String, String[], String)
+        ContentResolver.query()} to get the data. The return value is a
+        {@link android.database.Cursor}:
+<pre>
+        // If the return value is not null, the Uri is a content Uri
+        if (uriMimeType != null) {
+
+            // Does the content provider offer a MIME type that the current application can use?
+            if (uriMimeType.equals(MIME_TYPE_CONTACT)) {
+
+                // Get the data from the content provider.
+                Cursor pasteCursor = cr.query(uri, null, null, null, null);
+
+                // If the Cursor contains data, move to the first record
+                if (pasteCursor != null) {
+                    if (pasteCursor.moveToFirst()) {
+
+                    // get the data from the Cursor here. The code will vary according to the
+                    // format of the data model.
+                    }
+                }
+
+                // close the Cursor
+                pasteCursor.close();
+             }
+         }
+     }
+}
+</pre>
+    </li>
+</ol>
+<h3 id="PasteIntent">Pasting an Intent</h3>
+<p>
+    To paste an Intent, first get the global clipboard. Examine the
+    {@link android.content.ClipData.Item} object to see if it contains an Intent. Then call
+    {@link android.content.ClipData.Item#getIntent()} to copy the Intent to your own storage.
+    The following snippet demonstrates this:
+</p>
+<pre>
+// Gets a handle to the Clipboard Manager
+ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
+
+// Checks to see if the clip item contains an Intent, by testing to see if getIntent() returns null
+Intent pasteIntent = clipboard.getPrimaryClip().getItemAt(0).getIntent();
+
+if (pasteIntent != null) {
+
+    // handle the Intent
+
+} else {
+
+    // ignore the clipboard, or issue an error if your application was expecting an Intent to be
+    // on the clipboard
+}
+</pre>
+<h2 id="Provider">Using Content Providers to Copy Complex Data</h2>
+<p>
+    Content providers support copying complex data such as database records or file streams.
+    To copy the data, you put a content URI on the clipboard. Pasting applications then get this
+    URI from the clipboard and use it to retrieve database data or file stream descriptors.
+</p>
+<p>
+    Since the pasting application only has the content URI for your data, it needs to know which
+    piece of data to retrieve. You can provide this information by encoding an identifier for the
+    data on the URI itself, or you can provide a unique URI that will return the data you want to
+    copy. Which technique you choose depends on the organization of your data.
+</p>
+<p>
+    The following sections describe how to set up URIs, how to provide complex data, and how to
+    provide file streams. The descriptions assume that you are familiar with the general principles
+    of content provider design.
+</p>
+<h3 id="Encoding">Encoding an identifier on the URI</h3>
+<p>
+    A useful technique for copying data to the clipboard with a URI is to encode an identifier for
+    the data on the URI itself. Your content provider can then get the identifier from the URI and
+    use it to retrieve the data. The pasting application doesn't have to know that the identifier
+    exists; all it has to do is get your &quot;reference&quot; (the URI plus the identifier) from
+    the clipboard, give it your content provider, and get back the data.
+</p>
+<p>
+    You usually encode an identifier onto a content URI by concatenating it to the end of the URI.
+    For example, suppose you define your provider URI as the following string:
+</p>
+<pre>
+&quot;content://com.example.contacts&quot;
+</pre>
+<p>
+   If you want to encode a name onto this URI, you would use the following snippet:
+</p>
+<pre>
+String uriString = &quot;content:&#47;&#47;com.example.contacts&quot; + &quot;/&quot; + &quot;Smith&quot;
+
+// uriString now contains content://com.example.contacts/Smith.
+
+// Generates a uri object from the string representation
+Uri copyUri = Uri.parse(uriString);
+</pre>
+<p>
+    If you are already using a content provider, you may want to add a new URI path that indicates
+    the URI is for copying. For example, suppose you already have the following URI paths:
+</p>
+<pre>
+&quot;content://com.example.contacts&quot;/people
+&quot;content://com.example.contacts&quot;/people/detail
+&quot;content://com.example.contacts&quot;/people/images
+</pre>
+<p>
+   You could add another path that is specific to copy URIs:
+</p>
+<pre>
+&quot;content://com.example.contacts/copying&quot;
+</pre>
+<p>
+    You could then detect a &quot;copy&quot; URI by pattern-matching and handle it with code that
+    is specific for copying and pasting.
+</p>
+<p>
+    You normally use the encoding technique if you're already using a content provider, internal
+    database, or internal table to organize your data. In these cases, you have multiple pieces of
+    data you want to copy, and presumably a unique identifier for each piece. In response to a
+    query from the pasting application, you can look up the data by its identifier and return it.
+</p>
+<p>
+    If you don't have multiple pieces of data, then you probably don't need to encode an identifier.
+    You can simply use a URI that is unique to your provider. In response to a query, your provider
+    would return the data it currently contains.
+</p>
+<p>
+    Getting a single record by ID is used in the
+    <a href="{@docRoot}resources/samples/NotePad/index.html">Note Pad</a> sample application to
+    open a note from the notes list. The sample uses the <code>_id</code> field from an SQL
+    database, but you can have any numeric or character identifier you want.
+</p>
+<h3 id="Records">Copying data structures</h3>
+<p>
+    You set up a content provider for copying and pasting complex data as a subclass of the
+    {@link android.content.ContentProvider} component. You should also encode the URI you put on
+    the clipboard so that it points to the exact record you want to provide. In addition, you
+    have to consider the existing state of your application:
+</p>
+<ul>
+    <li>
+        If you already have a content provider, you can add to its functionality. You may only
+        need to modify its
+{@link android.content.ContentResolver#query(Uri, String[], String, String[], String) query()}
+        method to handle URIs coming from applications that want to paste data. You will
+        probably want to modify the method to handle a &quot;copy&quot; URI pattern.
+    </li>
+    <li>
+        If your application maintains an internal database, you may
+        want to move this database into a content provider to facilitate copying from it.
+    </li>
+    <li>
+        If you are not currently using a database, you can implement a simple content provider
+        whose sole purpose is to offer data to applications that are pasting from the
+        clipboard.
+    </li>
+</ul>
+<p>
+In the content provider, you will want to override at least the following methods:
+</p>
+<dl>
+    <dt>
+{@link android.content.ContentResolver#query(Uri, String[], String, String[], String) query()}
+    </dt>
+    <dd>
+        Pasting applications will assume that they can get your data by using this method with
+        the URI you put on the clipboard. To support copying, you should have this method
+        detect URIs that contain a special &quot;copy&quot; path. Your application can then
+        create a &quot;copy&quot; URI to put on the clipboard, containing the copy path and
+        a pointer to the exact record you want to copy.
+    </dd>
+    <dt>
+        {@link android.content.ContentProvider#getType(Uri) getType()}
+    </dt>
+    <dd>
+        This method should return the MIME type or types for the data you intend to copy. The method
+        {@link android.content.ClipData#newUri(ContentResolver, CharSequence, Uri) newUri()} calls
+        {@link android.content.ContentProvider#getType(Uri) getType()} in order to put the MIME
+        types into the new {@link android.content.ClipData} object.
+        <p>
+            MIME types for complex data are described in the topic
+            <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>.
+        </p>
+    </dd>
+</dl>
+<p>
+    Notice that you don't have to have any of the other content provider methods such as
+    {@link android.content.ContentProvider#insert(Uri, ContentValues) insert()} or
+    {@link android.content.ContentProvider#update(Uri, ContentValues, String, String[]) update()}.
+    A pasting application only needs to get your supported MIME types and copy data from your
+    provider. If you already have these methods, they won't interfere with copy operations.
+</p>
+<p>
+    The following snippets demonsrate how to set up your application to copy complex data:
+</p>
+<ol>
+    <li>
+        <p>
+            In the global constants for your application,
+            declare a base URI string and a path that identifies URI strings you are
+            using to copy data. Also declare a MIME type for the copied data:
+        </p>
+<pre>
+// Declares the base URI string
+private static final String CONTACTS = &quot;content:&#47;&#47;com.example.contacts&quot;;
+
+// Declares a path string for URIs that you use to copy data
+private static final String COPY_PATH = &quot;/copy&quot;;
+
+// Declares a MIME type for the copied data
+public static final String MIME_TYPE_CONTACT = &quot;vnd.android.cursor.item/vnd.example.contact&quot;
+</pre>
+    </li>
+    <li>
+        In the Activity from which users copy data,
+        set up the code to copy data to the clipboard. In response to a copy request, put
+        the URI on the clipboard:
+<pre>
+public class MyCopyActivity extends Activity {
+
+    ...
+
+// The user has selected a name and is requesting a copy.
+case R.id.menu_copy:
+
+    // Appends the last name to the base URI
+    // The name is stored in &quot;lastName&quot;
+    uriString = CONTACTS + COPY_PATH + &quot;/&quot; + lastName;
+
+    // Parses the string into a URI
+    Uri copyUri = Uri.parse(uriString);
+
+    // Gets a handle to the clipboard service.
+    ClipboardManager clipboard = (ClipboardManager)
+        getSystemService(Context.CLIPBOARD_SERVICE);
+
+    ClipData clip = ClipData.newUri(getContentResolver(), &quot;URI&quot;, copyUri);
+
+    // Set the clipboard's primary clip.
+    clipboard.setPrimaryClip(clip);
+</pre>
+    </li>
+
+    <li>
+    <p>
+        In the global scope of your content provider, create a URI matcher and add a URI
+        pattern that will match URIs you put on the clipboard:
+    </p>
+<pre>
+public class MyCopyProvider extends ContentProvider {
+
+    ...
+
+// A Uri Match object that simplifies matching content URIs to patterns.
+private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+
+// An integer to use in switching based on the incoming URI pattern
+private static final int GET_SINGLE_CONTACT = 0;
+
+...
+
+// Adds a matcher for the content URI. It matches
+// &quot;content://com.example.contacts/copy/*&quot;
+sUriMatcher.addURI(CONTACTS, "names/*", GET_SINGLE_CONTACT);
+</pre>
+    </li>
+    <li>
+    <p>
+        Set up the
+     {@link android.content.ContentProvider#query(Uri, String[], String, String[], String) query()}
+        method. This method can handle different URI patterns, depending on how you code it, but
+        only the pattern for the clipboard copying operation is shown:
+    </p>
+<pre>
+// Sets up your provider's query() method.
+public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+    String sortOrder) {
+
+    ...
+
+    // Switch based on the incoming content URI
+    switch (sUriMatcher.match(uri)) {
+
+    case GET_SINGLE_CONTACT:
+
+        // query and return the contact for the requested name. Here you would decode
+        // the incoming URI, query the data model based on the last name, and return the result
+        // as a Cursor.
+
+    ...
+
+}
+</pre>
+    </li>
+    <li>
+        <p>
+            Set up the {@link android.content.ContentProvider#getType(Uri) getType()} method to
+            return an appropriate MIME type for copied data:
+        </p>
+<pre>
+// Sets up your provider's getType() method.
+public String getType(Uri uri) {
+
+    ...
+
+    switch (sUriMatcher.match(uri)) {
+
+    case GET_SINGLE_CONTACT:
+
+            return (MIME_TYPE_CONTACT);
+</pre>
+    </li>
+</ol>
+<p>
+    The section <a href="#PasteContentUri">Pasting data from a content URI</a>
+    describes how to get a content URI from the clipboard and use it to get and paste data.
+</p>
+<h3 id="Streams">Copying data streams</h3>
+<p>
+    You can copy and paste large amounts of text and binary data as streams. The data can have
+    forms such as the following:
+</p>
+    <ul>
+        <li>
+            Files stored on the actual device.
+        </li>
+        <li>
+            Streams from sockets.
+        </li>
+        <li>
+            Large amounts of data stored in a provider's underlying database system.
+        </li>
+    </ul>
+<p>
+    A content provider for data streams provides access to its data with a file descriptor object
+    such as {@link android.content.res.AssetFileDescriptor} instead of a
+    {@link android.database.Cursor} object. The pasting application reads the data stream using
+    this file descriptor.
+</p>
+<p>
+    To set up your application to copy a data stream with a provider, follow these steps:
+</p>
+<ol>
+    <li>
+        Set up a content URI for the data stream you are putting on the clipboard. Options
+        for doing this include the following:
+        <ul>
+            <li>
+                Encode an identifier for the data stream onto the URI,
+                as described in the section
+                <a href="#Encoding">Encoding an identifier on the URI</a>, and then maintain a
+                table in your provider that contains identifiers and the corresponding stream name.
+            </li>
+            <li>
+                Encode the stream name directly on the URI.
+            </li>
+            <li>
+                Use a unique URI that always returns the current stream from the provider. If you
+                use this option, you have to remember to update your provider to point to a
+                different stream whenever you copy the stream to the clipboard via the URI.
+            </li>
+        </ul>
+    </li>
+    <li>
+        Provide a MIME type for each type of data stream you plan to offer. Pasting applications
+        need this information to determine if they can paste the data on the clipboard.
+    </li>
+    <li>
+        Implement one of the {@link android.content.ContentProvider} methods that returns
+        a file descriptor for a stream. If you encode identifiers on the content URI, use this
+        method to determine which stream to open.
+    </li>
+    <li>
+        To copy the data stream to the clipboard, construct the content URI and place it
+        on the clipboard.
+    </li>
+</ol>
+<p>
+    To paste a data stream, an application gets the clip from the clipboard, gets the URI, and
+    uses it in a call to a {@link android.content.ContentResolver} file descriptor method that
+    opens the stream. The {@link android.content.ContentResolver} method calls the corresponding
+    {@link android.content.ContentProvider} method, passing it the content URI. Your provider
+    returns the file descriptor to {@link android.content.ContentResolver} method. The pasting
+    application then has the responsibility to read the data from the stream.
+</p>
+<p>
+    The following list shows the most important file descriptor methods for a content provider.
+    Each of these has a corresponding {@link android.content.ContentResolver} method with the
+    string &quot;Descriptor&quot; appended to the method name; for example, the
+    {@link android.content.ContentResolver} analog of
+    {@link android.content.ContentProvider#openAssetFile(Uri, String) openAssetFile()} is
+{@link android.content.ContentResolver#openAssetFileDescriptor(Uri, String) openAssetFileDescriptor()}:
+</p>
+<dl>
+    <dt>
+{@link android.content.ContentProvider#openTypedAssetFile(Uri,String,Bundle) openTypedAssetFile()}
+    </dt>
+    <dd>
+        This method should return an asset file descriptor, but only if the provided MIME type is
+        supported by the provider. The caller (the application doing the pasting) provides a MIME
+        type pattern. The content provider (of the application that has copied a URI to the
+        clipboard) returns an {@link android.content.res.AssetFileDescriptor} file handle if it
+        can provide that MIME type, or throws an exception if it can not.
+        <p>
+            This method handles subsections of files. You can use it to read assets that the
+            content provider has copied to the clipboard.
+        </p>
+    </dd>
+    <dt>
+        {@link android.content.ContentProvider#openAssetFile(Uri, String) openAssetFile()}
+    </dt>
+    <dd>
+        This method is a more general form of
+{@link android.content.ContentProvider#openTypedAssetFile(Uri,String,Bundle) openTypedAssetFile()}.
+        It does not filter for allowed MIME types, but it can read subsections of files.
+    </dd>
+    <dt>
+        {@link android.content.ContentProvider#openFile(Uri, String) openFile()}
+    </dt>
+    <dd>
+        This is a more general form of
+        {@link android.content.ContentProvider#openAssetFile(Uri, String) openAssetFile()}. It can't
+        read subsections of files.
+    </dd>
+</dl>
+<p>
+    You can optionally use the
+{@link android.content.ContentProvider#openPipeHelper(Uri, String, Bundle, T, ContentProvider.PipeDataWriter) openPipeHelper()}
+    method with your file descriptor method. This allows the pasting application to read the
+    stream data in a background thread using a pipe. To use this method, you need to implement the
+    {@link android.content.ContentProvider.PipeDataWriter} interface. An example of doing this is
+    given in the <a href="{@docRoot}resources/samples/NotePad/index.html">Note Pad</a> sample
+    application, in the <code>openTypedAssetFile()</code> method of
+    <code>NotePadProvider.java</code>.
+</p>
+<h2 id="DataDesign">Designing Effective Copy/Paste Functionality</h2>
+<p>
+    To design effective copy and paste functionality for your application, remember these
+    points:
+</p>
+    <ul>
+        <li>
+            At any time, there is only one clip on the clipboard. A new copy operation by
+            any application in the system overwrites the previous clip. Since the user may
+            navigate away from your application and do a copy before returning, you can't assume
+            that the clipboard contains the clip that the user previously copied in <em>your</em>
+            application.
+        </li>
+        <li>
+            The intended purpose of multiple {@link android.content.ClipData.Item}
+            objects per clip is to support copying and pasting of multiple selections rather than
+            different forms of reference to a single selection. You usually want all of the
+           {@link android.content.ClipData.Item} objects in a clip to have the same form, that is,
+           they should all be simple text, content URI, or {@link android.content.Intent}, but not
+           a mixture.
+        </li>
+        <li>
+            When you provide data, you can offer different MIME representations. Add the MIME types
+            you support to the {@link android.content.ClipDescription}, and then
+            implement the MIME types in your content provider.
+        </li>
+        <li>
+            When you get data from the clipboard, your application is responsible for checking the
+            available MIME types and then deciding which one, if any, to use. Even if there is a
+            clip on the clipboard and the user requests a paste, your application is not required
+            to do the paste. You <em>should</em> do the paste if the MIME type is compatible. You
+            may choose to coerce the data on the clipboard to text using
+            {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} if you
+            choose. If your application supports more than one of the available MIME types, you can
+            allow the user to choose which one to use.
+        </li>
+    </ul>
diff --git a/docs/html/guide/topics/manifest/compatible-screens-element.jd b/docs/html/guide/topics/manifest/compatible-screens-element.jd
new file mode 100644
index 0000000..9fb0fd2
--- /dev/null
+++ b/docs/html/guide/topics/manifest/compatible-screens-element.jd
@@ -0,0 +1,108 @@
+page.title=&lt;compatible-screens&gt;
+@jd:body
+
+<dl class="xml">
+<dt>syntax:</dt>
+<dd>
+<pre>
+&lt;<a href="#compatible-screens">compatible-screens</a>&gt;
+    &lt;<a href="#screen">screen</a> android:<a href="#screenSize">screenSize</a>=["small" | "normal" | "large" | "xlarge"]
+            android:<a href="#screenDensity">screenDensity</a>=["ldpi" | "mdpi" | "hdpi" | "xhdpi"] /&gt;
+    ...
+&lt;/compatible-screens&gt;
+</pre>
+</dd>
+
+<dt>contained in:</dt>
+<dd><code><a
+href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code></dd>
+
+<dt>description:</dt>
+<dd>Specifies each screen configuration with which the application is compatible. Only one instance
+of the {@code &lt;compatible-screens&gt;} element is allowed in the manifest, but it can
+contain multiple <code>&lt;screen&gt;</code> elements. Each <code>&lt;screen&gt;</code> element
+specifies a specific screen size-density combination with which the application is compatible.
+
+  <p>The Android system <em>does not</em> read the {@code &lt;compatible-screens&gt;} manifest
+element (neither at install-time nor at runtime). This element is informational only and may be used
+by external services (such as Android Market) to better understand the application's compatibility
+with specific screen configurations and enable filtering for users. Any screen configuration that is
+<em>not</em> declared in this element is a screen with which the application is <em>not</em>
+compatible. Thus, external services (such as Android Market) should not provide the application to
+devices with such screens.</p>
+
+  <p class="caution"><strong>Caution:</strong> Normally, <strong>you should not use this manifest
+element</strong>. Using this element can dramatically reduce the potential user base for your
+application, by not allowing users to install your application if they have a device with a screen
+configuration that you have not listed. You should use it only as a last resort, when the
+application absolutely does not work with all screen configurations. Instead of using this element,
+you should follow the guide to <a href="{@docRoot}guide/practices/screens_support.html">Supporting
+Multiple Screens</a>, in order to provide complete support for multiple screens, by adding
+alternative resources for different screen sizes and densities.</p>
+
+  <p>If you want to set only a minimum screen <em>size</em> for your your application, then you
+should use the <a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> element. For example, if you want your application to be available
+only for <em>large</em> and <em>xlarge</em> screen devices, the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> element allows you to declare that your application does not
+support <em>small</em> and <em>normal</em> screen sizes. External services (such as Android
+Market) will filter your application accordingly. You can also use the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> element to declare whether the system should resize your
+application for different screen sizes.</p>
+
+  <p>Also see the <a href="{@docRoot}guide/appendix/market-filters.html">Market Filters</a>
+document for more information about how Android Market filters applications using this and
+other manifest elements.</p>
+
+</dd>
+
+<dt>child elements:</dt>
+<dd>
+  <dl class="tag-list">
+
+    <dt id="screen">{@code &lt;screen&gt;}</dt>
+    <dd>Specifies a single screen configuration with which the application is compatible.
+      <p>At least one instance of this element must be placed inside the {@code
+&lt;compatible-screens&gt;} element. This element <em>must include both</em> the {@code
+android:screenSize} and {@code android:screenDensity} attributes (if you do not declare both
+attributes, then the element is ignored).</p>
+
+      <p class="caps">attributes:</p>
+      <dl class="atn-list">
+        <dt id="screenSize"><code>android:screenSize</code></dt>
+        <dd><b>Required.</b> Specifies the screen size for this screen configuration.
+          <p>Accepted values:</p>
+          <ul>
+            <li>{@code small}</li>
+            <li>{@code normal}</li>
+            <li>{@code large}</li>
+            <li>{@code xlarge}</li>
+          </ul>
+          <p>For information about the different screen sizes, see <a
+href="{@docRoot}guide/practices/screens_support.html#range">Supporting Multiple Screens</a>.</p>
+        </dd>
+        <dt id="screenDensity"><code>android:screenDensity</code></dt>
+        <dd><b>Required.</b> Specifies the screen density for this screen configuration.
+          <p>Accepted values:</p>
+          <ul>
+            <li>{@code ldpi}</li>
+            <li>{@code mdpi}</li>
+            <li>{@code hdpi}</li>
+            <li>{@code xhdpi}</li>
+          </ul>
+          <p>For information about the different screen densities, see <a
+href="{@docRoot}guide/practices/screens_support.html#range">Supporting Multiple Screens</a>.</p>
+        </dd>
+      </dl>
+    </dd>
+  </dl>
+</dd>
+<dt>introduced in:</dt>
+<dd>API Level 9</dd>
+<dt>see also:</dt>
+<dd><a
+href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a></dd>
+<dd><a href="{@docRoot}guide/appendix/market-filters.html">Market Filters</a></dd>
+</dl>
diff --git a/docs/html/guide/topics/manifest/supports-screens-element.jd b/docs/html/guide/topics/manifest/supports-screens-element.jd
index 64a7a58..92c769e 100644
--- a/docs/html/guide/topics/manifest/supports-screens-element.jd
+++ b/docs/html/guide/topics/manifest/supports-screens-element.jd
@@ -6,7 +6,8 @@
 <dt>syntax:</dt>
 <dd>
 <pre class="stx">
-&lt;supports-screens android:<a href="#small">smallScreens</a>=["true" | "false"] 
+&lt;supports-screens android:<a href="#resizeable">resizeable</a>=["true" | "false"]
+                  android:<a href="#small">smallScreens</a>=["true" | "false"] 
                   android:<a href="#normal">normalScreens</a>=["true" | "false"] 
                   android:<a href="#large">largeScreens</a>=["true" | "false"] 
                   android:<a href="#xlarge">xlargeScreens</a>=["true" | "false"]
@@ -19,17 +20,33 @@
 
 <dt>description:</dt>
 <dd>Lets you specify the screen dimensions the
-application supports.  By default a modern application (using API Level 4 or higher) supports all
-screen sizes and must explicitly disable certain screen sizes here;
-older applications are assumed to support only the "normal"
-screen size.  Note that screen size is a separate axis from
-density. Screen size is determined as the available pixels to an application
-after density scaling has been applied. 
+application supports.  By default, a modern application (using API Level 4 or higher) supports all
+screen sizes; older applications are assumed to support only the "normal" screen size. Screen
+size is determined as the available pixels to an application after density scaling has been
+applied. (Note that screen size is a separate axis from screen density.)
 
-<p>Based on the target device screen density, the Android 
-framework will scale down assets by a factor of 0.75 (low dpi screens) 
-or scale them up by a factor of 1.5 (high dpi screens).
-The screen density is expressed as dots-per-inch (dpi).</p>
+<p>An application "supports" a given screen size if it fills the entire screen and works as
+expected. By default, the system will resize your application to fill the screen, if you have set
+either <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+minSdkVersion}</a> or <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+targetSdkVersion}</a> to {@code "4"} or higher. Resizing works well for most applications and
+you don't have to do any extra work to make your application work on larger screens.</p>
+
+<p>In addition to allowing the system to resize your application, you can add additional support
+for different screen sizes by providing <a
+href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">alternative
+layout resources</a> for different sizes. For instance, you might want to modify the layout
+of an activity when it is on a tablet or similar device that has an <em>xlarge</em> screen.</p>
+
+<p>If your application does not support <em>large</em> or <em>xlarge</em> screens, then you should
+declare that it is not resizeable by setting <a href="#resizeable">{@code android:resizeable}</a> to
+{@code "false"}, so that the system will not resize your application on larger screens.</p>
+
+<p>If your application does not support <em>small</em> screens, then
+there isn't much the system can do to make the application work well on a smaller screen, so
+external services (such as Android Market) should not allow users to install the application on such
+screens.</p>
+
 
 <p>For more information, see 
 <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>.</p>
@@ -38,16 +55,40 @@
 <dt>attributes:</dt>
 
 <dd>
-<dl class="attr"><dt><a name="small"></a>{@code android:smallScreens}</dt>
+<dl class="attr">
+  
+  <dt><a name="resizeable"></a>{@code android:resizeable}</dt>
+  <dd>Indicates whether the application is resizeable for different screen sizes. This attribute is
+true, by default, if you have set either <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> or <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> to
+{@code "4"} or higher. Otherwise, it is false by default. If set false, the system will not resize
+your application when run on <em>large</em> or <em>xlarge</em> screens. Instead, the
+application appears in a "postage stamp" that equals the <em>normal</em> screen size that your
+application does support. This is less than an ideal experience for users, because the
+application appears smaller than the available screen, but it might help your application run
+normally if it were designed only for the <em>normal</em> screen size and some behaviors do not work
+when resized.</p>
+  <p>To provide the best experience on all screen sizes, you should allow resizing and, if your
+application does not work well on larger screens, follow the guide to <a
+href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a> to enable
+additional screen support.</p>
+  </dd>
+  
+  
+  <dt><a name="small"></a>{@code android:smallScreens}</dt>
   <dd>Indicates whether the application supports smaller screen form-factors.
      A small screen is defined as one with a smaller aspect ratio than
      the "normal" (traditional HVGA) screen.  An application that does
      not support small screens <em>will not be available</em> for
-     small screen devices, because there is little the platform can do
-     to make such an application work on a smaller screen. If the application has set the <a
-href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code &lt;uses-sdk&gt;}</a> element's
-{@code android:minSdkVersion} or {@code android:targetSdkVersion} attribute to "4" or higher,
-the default value for this is "true", any value less than "4" results in this set to "false".
+     small screen devices from external services (such as Android Market), because there is little
+the platform can do
+     to make such an application work on a smaller screen. If the application has set either <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> or <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> to
+{@code "4"} or higher,
+the default value for this is {@code "true"}, any value less than {@code "4"} results in this set to
+{@code "false"}.
   </dd>
   
   <dt><a name="normal"></a>{@code android:normalScreens}</dt>
@@ -61,38 +102,44 @@
   <dt><a name="large"></a>{@code android:largeScreens}</dt>
   <dd>Indicates whether the application supports larger screen form-factors.
      A large screen is defined as a screen that is significantly larger
-     than a "normal" phone screen, and thus may require some special care
-     on the application's part to make good use of it. An application that 
-     does not support large screens (declares this "false")&mdash;but does support "normal" or
-"small" screens&mdash;will be placed as a "postage stamp" on 
-     a large screen, so that it retains the dimensions it was originally
-     designed for. If the application has set the <a
-href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code &lt;uses-sdk&gt;}</a> element's
-{@code android:minSdkVersion} or {@code android:targetSdkVersion} attribute to "4" or higher,
-the default value for this is "true", any value less than "4" results in this set to "false".
+     than a "normal" phone screen, and thus might require some special care
+     on the application's part to make good use of it, though it may rely on resizing by the
+system to fill the screen. If the application has set either <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> or <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> to
+{@code "4"} or higher,
+the default value for this is {@code "true"}, any value less than {@code "4"} results in this set to
+{@code "false"}.
   </dd>
-  
+
   <dt><a name="xlarge"></a>{@code android:xlargeScreens}</dt>
   <dd>Indicates whether the application supports extra large screen form-factors.
      An xlarge screen is defined as a screen that is significantly larger
      than a "large" screen, such as a tablet (or something larger) and may require special care
-     on the application's part to make good use of it. An application that 
-     does not support xlarge screens (declares this "false")&mdash;but does support "large",
-"normal", or "small" screens&mdash;will be placed as a "postage stamp" on 
-     an xlarge screen, so that it retains the dimensions it was originally
-     designed for. If the application has set the <a
-href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code &lt;uses-sdk&gt;}</a> element's
-{@code android:minSdkVersion} or {@code android:targetSdkVersion} attribute to "4" or higher,
-the default value for this is "true", any value less than "4" results in this set to "false".
+     on the application's part to make good use of it, though it may rely on resizing by the
+system to fill the screen. If the application has set either <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> or <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> to
+{@code "4"} or higher,
+the default value for this is {@code "true"}, any value less than {@code "4"} results in this set to
+{@code "false"}.
      <p>This attribute was introduced in API Level 9.</p>
   </dd>
   
   <dt><a name="any"></a>{@code android:anyDensity}</dt>
   <dd>Indicates whether the application includes resources to accommodate any screen
      density.  Older applications (before API Level 4) are assumed unable to
-     accomodate all densities and this is "false" by default. Applications using 
-     API Level 4 or higher are assumed able to and this is "true" by default. 
+     accomodate all densities and this is {@code "false"} by default. If the application has set
+either <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> or <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> to
+{@code "4"} or higher,
+the default value for this is {@code "true"}. Otherwise, it is {@code "false"}.
      You can explicitly supply your abilities here.
+     <p>Based on the "standard" device screen density (medium dpi), the Android framework will scale
+down application assets by a factor of 0.75 (low dpi screens) or scale them up by a factor of 1.5
+(high dpi screens), when you don't provide alternative resources for a specifc screen density. The
+screen density is expressed as dots-per-inch (dpi).</p>
   </dd>
   
 
diff --git a/docs/html/guide/topics/manifest/uses-feature-element.jd b/docs/html/guide/topics/manifest/uses-feature-element.jd
index 5242126..0828e8b 100644
--- a/docs/html/guide/topics/manifest/uses-feature-element.jd
+++ b/docs/html/guide/topics/manifest/uses-feature-element.jd
@@ -644,33 +644,46 @@
 </tr>
 
 <tr>
-  <td rowspan="4">Touchscreen</td>
+  <td rowspan="5">Touchscreen</td>
+  <td><code>android.hardware.faketouch</code></td>
+  <td>The application uses basic touch interaction events, such as "click down", "click
+up", and drag.</td>
+  <td>When declared, this indicates that the application is compatible with a device that offers an
+emulated touchscreen (or better). A device that offers an emulated touchscreen provides a user input
+system that can emulate a subset of touchscreen capabilities. An example of such an input system is
+a mouse or remote control that drives an on-screen cursor. If your application does not require
+complicated gestures and you want your application available to devices with an emulated
+touchscreen, you should declare this feature.</td>
+</tr>
+<tr>
   <td><code>android.hardware.touchscreen</code></td>
-  <td>The application uses touchscreen capabilities on the device.</td>
+  <td>The application uses touchscreen capabilities, for gestures more interactive
+than basic touches, such as a fling. This is a superset of the faketouch features.</td>
   <td></td>
 </tr>
 <tr>
   <td><code>android.hardware.touchscreen.multitouch</code></td>
-  <td>Subfeature. The application uses basic two-point multitouch capabilities on the device
-screen.</td>
+  <td>The application uses basic two-point multitouch capabilities on the device
+screen, such as for pinch gestures, but does not need to track touches independently. This
+is a superset of touchscreen features.</td>
   <td>If declared with the <code>"android:required="true"</code> attribute, this
-subfeature implicitly declares the <code>android.hardware.touchscreen</code>
+implicitly declares the <code>android.hardware.touchscreen</code>
 parent feature. </td>
 </tr>
 <tr>
   <td><code>android.hardware.touchscreen.multitouch.distinct</code></td>
   <td>Subfeature. The application uses advanced multipoint multitouch
 capabilities on the device screen, such as for tracking two or more points fully
-independently.</td>
+independently. This is a superset of multitouch features.</td>
   <td rowspan="2">If declared with the <code>"android:required="true"</code> attribute, this
-subfeature implicitly declares the
+implicitly declares the
 <code>android.hardware.touchscreen.multitouch</code> parent feature. </td>
 </tr>
 <tr>
   <td><code>android.hardware.touchscreen.multitouch.jazzhand</code></td>
-  <td>Subfeature. The application uses advanced multipoint multitouch
+  <td>The application uses advanced multipoint multitouch
 capabilities on the device screen, for tracking up to five points fully
-independently.</td>
+independently. This is a superset of distinct multitouch features.</td>
 </tr>
 
 <tr>
diff --git a/docs/html/guide/topics/providers/loaders.jd b/docs/html/guide/topics/providers/loaders.jd
new file mode 100644
index 0000000..c54656c
--- /dev/null
+++ b/docs/html/guide/topics/providers/loaders.jd
@@ -0,0 +1,492 @@
+page.title=Using Loaders
+@jd:body
+<div id="qv-wrapper">
+<div id="qv">
+    <h2>In this document</h2>
+    <ol>
+    <li><a href="#summary">Loader API Summary</a></li>
+    <li><a href="#app">Using Loaders in an Application</a>
+      <ol>
+        <li><a href="#requirements"></a></li>
+        <li><a href="#starting">Starting a Loader</a></li>
+        <li><a href="#restarting">Restarting a Loader</a></li>
+        <li><a href="#callback">Using the LoaderManager Callbacks</a></li>
+      </ol>
+    </li>
+    <li><a href="#example">Example</a>
+       <ol>
+         <li><a href="#more_examples">More Examples</a></li>
+        </ol>
+    </li>
+  </ol>
+    
+  <h2>Key classes</h2>
+    <ol>
+      <li>{@link android.app.LoaderManager}</li>
+      <li>{@link android.content.Loader}</li>
+
+    </ol>   
+    
+    <h2>Related samples</h2>
+   <ol>
+     <li> <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentCursorLoader.html"> FragmentCursorLoader</a></li>
+     <li> <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html"> LoaderThrottle</a></li>
+   </ol>
+  </div>
+</div>
+
+<p>Introduced in Android 3.0, loaders make it easy to asynchronously load data
+in an activity or fragment. Loaders have these characteristics:</p>
+  <ul>
+    <li>They are available to every {@link android.app.Activity} and {@link
+android.app.Fragment}.</li>
+    <li>They provide asynchronous loading of data.</li>
+    <li>They monitor the source of their data and deliver new results when the
+content changes.</li>
+    <li>They automatically reconnect to the last loader's cursor when being
+recreated after a configuration change. Thus, they don't need to re-query their
+data.</li>
+  </ul>
+ 
+<h2 id="summary">Loader API Summary</h2>
+
+<p>There are multiple classes and interfaces that may be involved in using
+loaders in an application. They are summarized in this table:</p>
+
+<table>
+  <tr>
+    <th>Class/Interface</th>
+    <th>Description</th>
+  </tr>
+  <tr>
+    <td>{@link android.app.LoaderManager}</td>
+    <td>An abstract class associated with an {@link android.app.Activity} or
+{@link android.app.Fragment} for managing one or more {@link
+android.content.Loader} instances. This helps an application manage
+longer-running operations in conjunction with the {@link android.app.Activity}
+or {@link android.app.Fragment} lifecycle; the most common use of this is with a
+{@link android.content.CursorLoader}, however applications are free to write
+their own loaders for loading other types of data.
+    <br />
+    <br />
+    There is only one {@link android.app.LoaderManager} per activity or fragment. But a {@link android.app.LoaderManager} can have
+multiple loaders.</td>
+  </tr>
+  <tr>
+    <td>{@link android.app.LoaderManager.LoaderCallbacks}</td>
+    <td>A callback interface for a client to interact with the {@link
+android.app.LoaderManager}. For example, you use the {@link
+android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}
+callback method to create a new loader.</td>
+  </tr>
+  <tr>
+    <td>{@link android.content.Loader}</td>
+    <td>An abstract class that performs asynchronous loading of data. This is
+the base class for a loader. You would typically use {@link
+android.content.CursorLoader}, but you can implement your own subclass. While
+loaders are active they should monitor the source of their data and deliver new
+results when the contents change. </td>
+  </tr>
+  <tr>
+    <td>{@link android.content.AsyncTaskLoader}</td>
+    <td>Abstract loader that provides an {@link android.os.AsyncTask} to do the work.</td>
+  </tr>
+  <tr>
+    <td>{@link android.content.CursorLoader}</td>
+    <td>A subclass of {@link android.content.AsyncTaskLoader} that queries the
+{@link android.content.ContentResolver} and returns a {@link
+android.database.Cursor}. This class implements the {@link
+android.content.Loader} protocol in a standard way for querying cursors,
+building on {@link android.content.AsyncTaskLoader} to perform the cursor query
+on a background thread so that it does not block the application's UI. Using
+this loader is the best way to asynchronously load data from a {@link
+android.content.ContentProvider}, instead of performing a managed query through
+the fragment or activity's APIs.</td>
+  </tr>
+</table>
+
+<p>The classes and interfaces in the above table are the essential components
+you'll use to implement a loader in your application. You won't need all of them
+for each loader you create, but you'll always need a reference to the {@link
+android.app.LoaderManager} in order to initialize a loader and an implementation
+of a {@link android.content.Loader} class such as {@link
+android.content.CursorLoader}. The following sections show you how to use these
+classes and interfaces in an application.</p>
+
+<h2 id ="app">Using Loaders in an Application</h2>
+<p>This section describes how to use loaders in an Android application. An
+application that uses loaders typically includes the following:</p>
+<ul>
+  <li>An {@link android.app.Activity} or {@link android.app.Fragment}.</li>
+  <li>An instance of the {@link android.app.LoaderManager}.</li>
+  <li>A {@link android.content.CursorLoader} to load data backed by a {@link
+android.content.ContentProvider}. Alternatively, you can implement your own subclass
+of {@link android.content.Loader} or {@link android.content.AsyncTaskLoader} to
+load data from some other source.</li>
+  <li>An implementation for {@link android.app.LoaderManager.LoaderCallbacks}.
+This is where you create new loaders and manage your references to existing
+loaders.</li> 
+<li>A way of displaying the loader's data, such as a {@link
+android.widget.SimpleCursorAdapter}.</li>
+  <li>A data source, such as a {@link android.content.ContentProvider}, when using a 
+{@link android.content.CursorLoader}.</li>
+</ul>
+<h3 id="starting">Starting a Loader</h3>
+
+<p>The {@link android.app.LoaderManager} manages one or more {@link
+android.content.Loader} instances within an {@link android.app.Activity} or
+{@link android.app.Fragment}. There is only one {@link
+android.app.LoaderManager} per activity or fragment.</p> 
+
+<p>You typically
+initialize a {@link android.content.Loader} within the activity's {@link
+android.app.Activity#onCreate onCreate()} method, or within the fragment's
+{@link android.app.Fragment#onActivityCreated onActivityCreated()} method. You
+do this as follows:</p>
+
+<pre>// Prepare the loader.  Either re-connect with an existing one,
+// or start a new one.
+getLoaderManager().initLoader(0, null, this);</pre>
+
+<p>The {@link android.app.LoaderManager#initLoader initLoader()} method takes
+the following parameters:</p>
+<ul>
+  <li>A unique ID that identifies the loader. In this example, the ID is 0.</li>
+<li>Optional arguments to supply to the loader at
+construction (<code>null</code> in this example).</li> 
+
+<li>A {@link android.app.LoaderManager.LoaderCallbacks} implementation, which
+the {@link android.app.LoaderManager} calls to report loader events. In this
+example, the local class implements the {@link
+android.app.LoaderManager.LoaderCallbacks} interface, so it passes a reference
+to itself, {@code this}.</li> 
+</ul>
+<p>The {@link android.app.LoaderManager#initLoader initLoader()} call ensures that a loader
+is initialized and active. It has two possible outcomes:</p>
+<ul>
+  <li>If the loader specified by the ID already exists, the last created loader
+is reused.</li>
+  <li>If the loader specified by the ID does <em>not</em> exist,
+{@link android.app.LoaderManager#initLoader initLoader()} triggers the
+{@link android.app.LoaderManager.LoaderCallbacks} method {@link android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}.
+This is where you  implement the code to instantiate and return a new loader.
+For more discussion, see the section <a
+href="#onCreateLoader">onCreateLoader</a>.</li>
+</ul>
+<p>In either case, the given {@link android.app.LoaderManager.LoaderCallbacks}
+implementation is associated with the loader, and  will be called when the
+loader state changes.  If at the point of this call  the caller is in its
+started state, and the requested loader already exists and has generated its
+data, then the system calls {@link
+android.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()}
+immediately (during {@link android.app.LoaderManager#initLoader initLoader()}),
+so you must be prepared for this to happen. See <a href="#onLoadFinished">
+onLoadFinished</a> for more discussion of this callback</p>
+
+<p>Note that the {@link android.app.LoaderManager#initLoader initLoader()}
+method returns the {@link android.content.Loader} that is created, but you don't
+need to capture a reference to it. The {@link android.app.LoaderManager} manages
+the life of the loader automatically. The {@link android.app.LoaderManager}
+starts and stops loading when necessary, and maintains the state of the loader
+and its associated content. As this implies, you rarely interact with loaders
+directly (though for an example of using loader methods to fine-tune a loader's
+behavior, see the <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html"> LoaderThrottle</a> sample). 
+You most commonly use the {@link
+android.app.LoaderManager.LoaderCallbacks} methods to intervene in the loading
+process when particular events occur. For more discussion of this topic, see <a
+href="#callback">Using the LoaderManager Callbacks</a>.</p>
+
+<h3 id="restarting">Restarting a Loader</h3>
+
+<p>When you use {@link android.app.LoaderManager#initLoader initLoader()}, as
+shown above, it uses an existing loader with the specified ID if there is one.
+If there isn't, it creates one. But sometimes you want to discard your old data
+and start over.</p>
+
+<p>To discard your old data, you use {@link
+android.app.LoaderManager#restartLoader restartLoader()}. For example, this
+implementation of {@link android.widget.SearchView.OnQueryTextListener} restarts
+the loader when the user's query changes. The loader needs to be restarted so
+that it can use the revised search filter to do a new query:</p>
+
+<pre>
+public boolean onQueryTextChanged(String newText) {
+    // Called when the action bar search text has changed.  Update
+    // the search filter, and restart the loader to do a new query
+    // with this filter.
+    mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
+    getLoaderManager().restartLoader(0, null, this);
+    return true;
+}</pre>
+
+<h3 id="callback">Using the LoaderManager Callbacks</h3>
+
+<p>{@link android.app.LoaderManager.LoaderCallbacks} is a callback interface
+that lets a client  interact with the {@link android.app.LoaderManager}. </p>
+<p>Loaders, in particular {@link android.content.CursorLoader}, are  expected to
+retain their  data after being stopped. This allows applications to keep their
+data across the activity or fragment's {@link android.app.Activity#onStop
+onStop()} and {@link android.app.Activity#onStart onStart()} methods, so that
+when users return to an application, they don't have to wait for the data to
+reload. You use the {@link android.app.LoaderManager.LoaderCallbacks} methods
+when to know when to create a new loader, and to tell the application when it is
+ time to  stop using a loader's data.</p>
+
+<p>{@link android.app.LoaderManager.LoaderCallbacks} includes these
+methods:</p>
+<ul>
+  <li>{@link android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}  &#8212;
+Instantiate and return a new {@link android.content.Loader} for the given ID.
+</li></ul>
+<ul>
+  <li> {@link android.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()}
+&#8212; Called when a previously created loader has finished its load.
+</li></ul>
+<ul>
+  <li>{@link android.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()}  
+    &#8212; Called when a previously created loader is being reset,  thus  making its
+data unavailable.
+</li>
+</ul>
+<p>These methods are described in more detail in the following sections.</p>
+
+<h4 id ="onCreateLoader">onCreateLoader</h4>
+
+<p>When you attempt to access a loader (for example, through {@link
+android.app.LoaderManager#initLoader initLoader()}), it checks to see whether
+the loader specified by the ID exists. If it doesn't, it triggers the {@link
+android.app.LoaderManager.LoaderCallbacks} method {@link
+android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}. This
+is where you  create a new loader. Typically this will be a {@link
+android.content.CursorLoader}, but you can implement your own {@link
+android.content.Loader} subclass. </p>
+
+<p>In this example, the {@link
+android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}
+callback method creates a {@link android.content.CursorLoader}. You must build
+the {@link android.content.CursorLoader} using its constructor method, which
+requires the complete set of information needed to perform a query to the {@link
+android.content.ContentProvider}. Specifically, it needs:</p>
+<ul>
+  <li><em>uri</em> &#8212; The URI for the content to retrieve. </li>
+  <li><em>projection</em> &#8212; A list of which columns to return. Passing
+<code>null</code> will return all columns, which is inefficient. </li>
+  <li><em>selection</em> &#8212; A filter declaring which rows to return,
+formatted as an SQL WHERE clause (excluding the WHERE itself). Passing
+<code>null</code> will return all rows for the given URI. </li>
+  <li><em>selectionArgs</em> &#8212; You may include ?s in the selection, which will
+be replaced by the values from <em>selectionArgs</em>, in the order that they appear in
+the selection. The values will be bound as Strings. </li>
+  <li><em>sortOrder</em> &#8212; How to order the rows, formatted as an SQL
+ORDER BY clause (excluding the ORDER BY itself). Passing <code>null</code> will
+use the default sort order, which may be unordered.</li>
+</ul>
+<p>For example:</p>
+<pre>
+ // If non-null, this is the current filter the user has provided.
+String mCurFilter;
+...
+public Loader&lt;Cursor&gt; onCreateLoader(int id, Bundle args) {
+    // This is called when a new Loader needs to be created.  This
+    // sample only has one Loader, so we don't care about the ID.
+    // First, pick the base URI to use depending on whether we are
+    // currently filtering.
+    Uri baseUri;
+    if (mCurFilter != null) {
+        baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
+                  Uri.encode(mCurFilter));
+    } else {
+        baseUri = Contacts.CONTENT_URI;
+    }
+
+    // Now create and return a CursorLoader that will take care of
+    // creating a Cursor for the data being displayed.
+    String select = &quot;((&quot; + Contacts.DISPLAY_NAME + &quot; NOTNULL) AND (&quot;
+            + Contacts.HAS_PHONE_NUMBER + &quot;=1) AND (&quot;
+            + Contacts.DISPLAY_NAME + &quot; != '' ))&quot;;
+    return new CursorLoader(getActivity(), baseUri,
+            CONTACTS_SUMMARY_PROJECTION, select, null,
+            Contacts.DISPLAY_NAME + &quot; COLLATE LOCALIZED ASC&quot;);
+}</pre>
+<h4 id="onLoadFinished">onLoadFinished</h4>
+
+<p>This method is called when a previously created loader has finished its load.
+This method is guaranteed to be called prior to the release of  the last data
+that was supplied for this loader.  At this point  you should remove all use of
+the old data (since it will be released  soon), but should not do your own
+release of the data since its loader  owns it and will take care of that.</p>
+
+
+<p>The loader will release the data once it knows the application  is no longer
+using it.  For example, if the data is  a cursor from a {@link
+android.content.CursorLoader},  you should not call {@link
+android.database.Cursor#close close()} on it yourself. If the cursor is being
+placed in a {@link android.widget.CursorAdapter}, you should use the {@link
+android.widget.SimpleCursorAdapter#swapCursor swapCursor()}  method so that the
+old {@link android.database.Cursor} is not closed. For example:</p>
+
+<pre>
+// This is the Adapter being used to display the list's data.<br
+/>SimpleCursorAdapter mAdapter;
+...
+
+public void onLoadFinished(Loader&lt;Cursor&gt; loader, Cursor data) {
+    // Swap the new cursor in.  (The framework will take care of closing the
+    // old cursor once we return.)
+    mAdapter.swapCursor(data);
+}</pre>
+
+<h4 id="onLoaderReset">onLoaderReset</h4>
+
+<p>This method is called when a previously created loader is being reset,  thus 
+making its data unavailable. This callback lets you find  out when the data is
+about to be released so you can remove your  reference to it.  </p>
+<p>This implementation calls 
+{@link android.widget.SimpleCursorAdapter#swapCursor swapCursor()}  
+with a value of <code>null</code>:</p>
+
+<pre>
+// This is the Adapter being used to display the list's data.
+SimpleCursorAdapter mAdapter;
+...
+
+public void onLoaderReset(Loader&lt;Cursor&gt; loader) {
+    // This is called when the last Cursor provided to onLoadFinished()
+    // above is about to be closed.  We need to make sure we are no
+    // longer using it.
+    mAdapter.swapCursor(null);
+}</pre>
+
+
+<h2 id="example">Example</h2>
+
+<p>As an example, here is the full implementation of a {@link
+android.app.Fragment} that displays a {@link android.widget.ListView} containing
+the results of a query against the contacts content provider. It uses a {@link
+android.content.CursorLoader} to manage the query on the provider.</p>
+ 
+<p>For an application to access a user's contacts, as shown in this example, its
+manifest must include the permission
+{@link android.Manifest.permission#READ_CONTACTS READ_CONTACTS}.</p>
+
+<pre>
+public static class CursorLoaderListFragment extends ListFragment
+        implements OnQueryTextListener, LoaderManager.LoaderCallbacks&lt;Cursor&gt; {
+
+    // This is the Adapter being used to display the list's data.
+    SimpleCursorAdapter mAdapter;
+
+    // If non-null, this is the current filter the user has provided.
+    String mCurFilter;
+
+    @Override public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+
+        // Give some text to display if there is no data.  In a real
+        // application this would come from a resource.
+        setEmptyText(&quot;No phone numbers&quot;);
+
+        // We have a menu item to show in action bar.
+        setHasOptionsMenu(true);
+
+        // Create an empty adapter we will use to display the loaded data.
+        mAdapter = new SimpleCursorAdapter(getActivity(),
+                android.R.layout.simple_list_item_2, null,
+                new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },
+                new int[] { android.R.id.text1, android.R.id.text2 }, 0);
+        setListAdapter(mAdapter);
+
+        // Prepare the loader.  Either re-connect with an existing one,
+        // or start a new one.
+        getLoaderManager().initLoader(0, null, this);
+    }
+
+    @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        // Place an action bar item for searching.
+        MenuItem item = menu.add(&quot;Search&quot;);
+        item.setIcon(android.R.drawable.ic_menu_search);
+        item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+        SearchView sv = new SearchView(getActivity());
+        sv.setOnQueryTextListener(this);
+        item.setActionView(sv);
+    }
+
+    public boolean onQueryTextChange(String newText) {
+        // Called when the action bar search text has changed.  Update
+        // the search filter, and restart the loader to do a new query
+        // with this filter.
+        mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
+        getLoaderManager().restartLoader(0, null, this);
+        return true;
+    }
+
+    @Override public boolean onQueryTextSubmit(String query) {
+        // Don't care about this.
+        return true;
+    }
+
+    @Override public void onListItemClick(ListView l, View v, int position, long id) {
+        // Insert desired behavior here.
+        Log.i(&quot;FragmentComplexList&quot;, &quot;Item clicked: &quot; + id);
+    }
+
+    // These are the Contacts rows that we will retrieve.
+    static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
+        Contacts._ID,
+        Contacts.DISPLAY_NAME,
+        Contacts.CONTACT_STATUS,
+        Contacts.CONTACT_PRESENCE,
+        Contacts.PHOTO_ID,
+        Contacts.LOOKUP_KEY,
+    };
+    public Loader&lt;Cursor&gt; onCreateLoader(int id, Bundle args) {
+        // This is called when a new Loader needs to be created.  This
+        // sample only has one Loader, so we don't care about the ID.
+        // First, pick the base URI to use depending on whether we are
+        // currently filtering.
+        Uri baseUri;
+        if (mCurFilter != null) {
+            baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
+                    Uri.encode(mCurFilter));
+        } else {
+            baseUri = Contacts.CONTENT_URI;
+        }
+
+        // Now create and return a CursorLoader that will take care of
+        // creating a Cursor for the data being displayed.
+        String select = &quot;((&quot; + Contacts.DISPLAY_NAME + &quot; NOTNULL) AND (&quot;
+                + Contacts.HAS_PHONE_NUMBER + &quot;=1) AND (&quot;
+                + Contacts.DISPLAY_NAME + &quot; != '' ))&quot;;
+        return new CursorLoader(getActivity(), baseUri,
+                CONTACTS_SUMMARY_PROJECTION, select, null,
+                Contacts.DISPLAY_NAME + &quot; COLLATE LOCALIZED ASC&quot;);
+    }
+
+    public void onLoadFinished(Loader&lt;Cursor&gt; loader, Cursor data) {
+        // Swap the new cursor in.  (The framework will take care of closing the
+        // old cursor once we return.)
+        mAdapter.swapCursor(data);
+    }
+
+    public void onLoaderReset(Loader&lt;Cursor&gt; loader) {
+        // This is called when the last Cursor provided to onLoadFinished()
+        // above is about to be closed.  We need to make sure we are no
+        // longer using it.
+        mAdapter.swapCursor(null);
+    }
+}</pre>
+<h3 id="more_examples">More Examples</h3>
+
+<p>There are a few different samples in <strong>ApiDemos</strong> that
+illustrate how to use loaders:</p>
+<ul>
+  <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentCursorLoader.html"> FragmentCursorLoader</a> &#8212; A complete version of the
+snippet shown above.</li>
+  <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html"> LoaderThrottle</a> &#8212; An example of how to use throttling to
+reduce the number of queries a content provider does then its data changes.</li>
+</ul>
+
+<p>For information on downloading and installing the SDK samples, see <a
+href="http://developer.android.com/resources/samples/get.html"> Getting the
+Samples</a>. </p>
+
diff --git a/docs/html/guide/topics/ui/drag-drop.jd b/docs/html/guide/topics/ui/drag-drop.jd
new file mode 100644
index 0000000..46ccdf8
--- /dev/null
+++ b/docs/html/guide/topics/ui/drag-drop.jd
@@ -0,0 +1,995 @@
+page.title=Dragging and Dropping
+@jd:body
+<div id="qv-wrapper">
+    <div id="qv">
+        <h2>Quickview</h2>
+            <ul>
+                <li>
+                    Allow users to move data within your Activity layout using graphical gestures.
+                </li>
+                <li>
+                    Supports operations besides data movement.
+                </li>
+                <li>
+                    Only works within a single application.
+                </li>
+                <li>
+                    Requires API 11.
+                </li>
+            </ul>
+        <h2>In this document</h2>
+        <ol>
+            <li>
+                <a href="#AboutDragging">Overview</a>
+                <ol>
+                    <li>
+                        <a href="#DragDropLifecycle">The drag/drop process</a>
+                    </li>
+                    <li>
+                        <a href="#AboutDragListeners">The drag event listener and callback method</a>
+                    </li>
+                    <li>
+                        <a href="#AboutDragEvent">Drag events</a>
+                    </li>
+                    <li>
+                        <a href="#AboutDragShadowBuilder">
+                        The drag shadow</a>
+                    </li>
+                </ol>
+            </li>
+            <li>
+                <a href="#DesignDragOperation">Designing a Drag and Drop Operation</a>
+                <ol>
+                    <li>
+                        <a href="#StartDrag">Starting a drag</a>
+                    </li>
+                    <li>
+                        <a href="#HandleStart">Responding to a drag start</a>
+                    </li>
+                    <li>
+                        <a href="#HandleDuring">Handling events during the drag</a>
+                    </li>
+                    <li>
+                        <a href="#HandleDrop">Responding to a drop</a>
+                    </li>
+                    <li>
+                        <a href="#HandleEnd">Responding to a drag end</a>
+                    </li>
+                    <li>
+                        <a href="#RespondEventSample">Responding to drag events: an example</a>
+                    </li>
+                </ol>
+            </li>
+        </ol>
+        <h2>Key classes</h2>
+        <ol>
+            <li>
+                {@link android.view.View View}
+            </li>
+            <li>
+                {@link android.view.View.OnLongClickListener OnLongClickListener}
+            </li>
+            <li>
+                {@link android.view.View.OnDragListener OnDragListener}
+            </li>
+            <li>
+                {@link android.view.DragEvent DragEvent}
+            </li>
+            <li>
+                {@link android.view.View.DragShadowBuilder DragShadowBuilder}
+            </li>
+            <li>
+                {@link android.content.ClipData ClipData}
+            </li>
+            <li>
+                {@link android.content.ClipDescription ClipDescription}
+            </li>
+        </ol>
+        <h2>Related Samples</h2>
+        <ol>
+            <li>
+                <a href="{@docRoot}resources/samples/HoneycombGallery/index.html">
+                Honeycomb Gallery</a>.
+            </li>
+            <li>
+                <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/DragAndDropDemo.html">
+DragAndDropDemo.java</a> and
+                <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/DraggableDot.html">
+DraggableDot.java</a> in <a href="{@docRoot}resources/samples/ApiDemos/index.html">Api Demos</a>.
+            </li>
+        </ol>
+        <h2>See also</h2>
+        <ol>
+            <li>
+            <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
+            </li>
+            <li>
+                <a href="{@docRoot}guide/topics/ui/ui-events.html">Handling UI Events</a>
+            </li>
+        </ol>
+    </div>
+</div>
+<p>
+    With the Android drag/drop framework, you can allow your users to move data
+    from one View to another View in the current layout using a graphical drag and drop gesture.
+    The framework includes a drag event class, drag listeners, and helper methods and classes.
+</p>
+<p>
+    Although the framework is primarily designed for data movement, you can use
+    it for other UI actions. For example, you could create an app that mixes colors when the user
+    drags a color icon over another icon. The rest of this topic, however, describes the
+    framework in terms of data movement.
+</p>
+<h2 id="AboutDragging">Overview</h2>
+<p>
+    A drag and drop operation starts when the user makes some gesture that you recognize as a
+    signal to start dragging data. In response, your application tells the system that the drag is
+    starting. The system calls back to your application to get a representation of the data
+    being dragged. As the user's finger moves this representation (a &quot;drag shadow&quot;)
+    over the current layout, the system sends drag events to the drag event listener objects and
+    drag event callback methods associated with the {@link android.view.View} objects in the layout.
+    Once the user releases the drag shadow, the system ends the drag operation.
+</p>
+<p>
+    You create a drag event listener object (&quot;listeners&quot;) from a class that implements
+    {@link android.view.View.OnDragListener}. You set the drag event listener object for a View
+    with the View object's
+    {@link android.view.View#setOnDragListener(View.OnDragListener) setOnDragListener()} method.
+    Each View object also has a {@link android.view.View#onDragEvent(DragEvent) onDragEvent()}
+    callback method. Both of these are described in more detail in the section
+    <a href="#AboutDragListeners">The drag event listener and callback method</a>.
+</p>
+<p class="note">
+    <strong>Note</strong>: For the sake of simplicity, the following sections refer to the routine
+    that receives drag events as the &quot;drag event listener&quot;, even though it may actually
+    be a callback method.
+</p>
+<p>
+    When you start a drag, you include both the data you are moving and metadata describing this
+    data as part of the call to the system. During the drag, the system sends drag events to the
+    drag event listeners or callback methods of each View in the layout. The listeners or callback
+    methods can use the metadata to decide if they want to accept the data when it is dropped.
+    If the user drops the data over a View object, and that View object's listener or callback
+    method has previously told the system that it wants to accept the drop, then the system sends
+    the data to the listener or callback method in a drag event.
+</p>
+<p>
+    Your application tells the system to start a drag by calling the
+    {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}
+    method. This tells the system to start sending drag events. The method also sends the data that
+    you are dragging.
+</p>
+<p>
+    You can call
+    {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}
+    for any attached View in the current layout. The system only uses the View object to get access
+    to global settings in your layout.
+</p>
+<p>
+    Once your application calls
+    {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()},
+    the rest of the process uses events that the system sends to the View objects in your current
+    layout.
+</p>
+<h3 id="DragDropLifecycle">The drag/drop process</h3>
+<p>
+    There are basically four steps or states in the drag and drop process:
+</p>
+<dl>
+    <dt>
+        <em>Started</em>
+    </dt>
+    <dd>
+        In response to the user's gesture to begin a drag, your application calls
+        {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}
+        to tell the system to start a drag. The arguments
+        {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}
+        provide the data to be dragged, metadata for this data, and a callback for drawing the
+        drag shadow.
+        <p>
+            The system first responds by calling back to your application to get a drag shadow. It
+            then displays the drag shadow on the device.
+        </p>
+        <p>
+            Next, the system sends a drag event with action type
+            {@link android.view.DragEvent#ACTION_DRAG_STARTED} to the drag event listeners for
+            all the View objects in the current layout. To continue to receive drag events,
+            including a possible drop event, a drag event listener must return <code>true</code>.
+            This registers the listener with the system. Only registered listeners continue to
+            receive drag events. At this point, listeners can also change the appearance of their
+            View object to show that the listener can accept a drop event.
+        </p>
+        <p>
+            If the drag event listener returns <code>false</code>, then it will not receive drag
+            events for the current operation until the system sends a drag event with action type
+            {@link android.view.DragEvent#ACTION_DRAG_ENDED}. By sending <code>false</code>, the
+            listener tells the system that it is not interested in the drag operation and
+            does not want to accept the dragged data.
+        </p>
+    </dd>
+    <dt>
+        <em>Continuing</em>
+    </dt>
+    <dd>
+        The user continues the drag. As the drag shadow intersects the bounding box of a View
+        object, the system sends one or more drag events to the View object's drag event
+        listener (if it is registered to receive events). The listener may choose to
+        alter its View object's appearance in response to the event. For example, if the event
+        indicates that the drag shadow has entered the bounding box of the View
+        (action type {@link android.view.DragEvent#ACTION_DRAG_ENTERED}), the listener
+        can react by highlighting its View.
+    </dd>
+    <dt>
+        <em>Dropped</em>
+    </dt>
+    <dd>
+        The user releases the drag shadow within the bounding box of a View that can accept the
+        data. The system sends the View object's listener a drag event with action type
+        {@link android.view.DragEvent#ACTION_DROP}. The drag event contains the data that was
+        passed to the system in the call to
+        {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}
+        that started the operation. The listener is expected to return boolean <code>true</code> to
+        the system if code for accepting the drop succeeds.
+        <p>
+            Note that this step only occurs if the user drops the drag shadow within the bounding
+            box of a View whose listener is registered to receive drag events. If the user releases
+            the drag shadow in any other situation, no {@link android.view.DragEvent#ACTION_DROP}
+            drag event is sent.
+        </p>
+    </dd>
+    <dt>
+        <em>Ended</em>
+    </dt>
+    <dd>
+        After the user releases the drag shadow, and after the system sends out (if necessary)
+        a drag event with action type {@link android.view.DragEvent#ACTION_DROP}, the system sends
+        out a drag event with action type {@link android.view.DragEvent#ACTION_DRAG_ENDED} to
+        indicate that the drag operation is over. This is done regardless of where the user released
+        the drag shadow. The event is sent to every listener that is registered to receive drag
+        events, even if the listener received the {@link android.view.DragEvent#ACTION_DROP} event.
+    </dd>
+</dl>
+<p>
+    Each of these four steps is described in more detail in the section
+    <a href="#DesignDragOperation">Designing a Drag and Drop Operation</a>.
+</p>
+<h3 id="AboutDragListeners">The drag event listener and callback method</h3>
+<p>
+    A View receives drag events with either a drag event listener that implements
+    {@link android.view.View.OnDragListener} or with its
+    {@link android.view.View#onDragEvent(DragEvent)} callback method.
+    When the system calls the method or listener, it passes to them
+    a {@link android.view.DragEvent} object.
+</p>
+<p>
+    You will probably want to use the listener in most cases. When you design UIs, you usually
+    don't subclass View classes, but using the callback method forces you to do this in order to
+    override the method. In comparison, you can implement one listener class and then use it with
+    several different View objects. You can also implement it as an anonymous inline class. To
+    set the listener for a View object, call
+{@link android.view.View#setOnDragListener(android.view.View.OnDragListener) setOnDragListener()}.
+</p>
+<p>
+    You can have both a listener and a callback method for View object. If this occurs,
+    the system first calls the listener. The system doesn't call the callback method unless the
+    listener returns <code>false</code>.
+</p>
+<p>
+    The combination of the {@link android.view.View#onDragEvent(DragEvent)} method and
+    {@link android.view.View.OnDragListener} is analogous to the combination
+    of the {@link android.view.View#onTouchEvent(MotionEvent) onTouchEvent()} and
+    {@link android.view.View.OnTouchListener} used with touch events.
+</p>
+<h3 id="AboutDragEvent">Drag events</h3>
+<p>
+    The system sends out a drag event in the form of a {@link android.view.DragEvent} object. The
+    object contains an action type that tells the listener what is happening in the drag/drop
+    process. The object contains other data, depending on the action type.
+</p>
+<p>
+    To get the action type, a listener calls {@link android.view.DragEvent#getAction()}. There
+    are six possible values, defined by constants in the {@link android.view.DragEvent} class. These
+    are listed in <a href="table1">table 1</a>.
+</p>
+<p>
+    The {@link android.view.DragEvent} object also contains the data that your application provided
+    to the system in the call to
+    {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}.
+    Some of the data is valid only for certain action types. The data that is valid for each action
+    type is summarized in <a href="table2">table 2</a>. It is also described in detail with
+    the event for which it is valid in the section
+    <a href="#DesignDragOperation">Designing a Drag and Drop Operation</a>.
+</p>
+<p class="table-caption" id="table1">
+  <strong>Table 1.</strong> DragEvent action types
+</p>
+<table>
+    <tr>
+        <th scope="col">getAction() value</th>
+        <th scope="col">Meaning</th>
+    </tr>
+    <tr>
+        <td>{@link android.view.DragEvent#ACTION_DRAG_STARTED}</td>
+        <td>
+            A View object's drag event listener receives this event action type just after the
+            application calls
+{@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()} and
+            gets a drag shadow.
+        </td>
+    </tr>
+    <tr>
+        <td>{@link android.view.DragEvent#ACTION_DRAG_ENTERED}</td>
+        <td>
+            A View object's drag event listener receives this event action type when the drag shadow
+            has just entered the bounding box of the View. This is the first event action type the
+            listener receives when the drag shadow enters the bounding box. If the listener wants to
+            continue receiving drag events for this operation, it must return boolean
+            <code>true</code> to the system.
+        </td>
+    </tr>
+    <tr>
+        <td>{@link android.view.DragEvent#ACTION_DRAG_LOCATION}</td>
+        <td>
+            A View object's drag event listener receives this event action type after it receives a
+            {@link android.view.DragEvent#ACTION_DRAG_ENTERED} event while the drag shadow is
+            still within the bounding box of the View.
+        </td>
+    </tr>
+    <tr>
+        <td>{@link android.view.DragEvent#ACTION_DRAG_EXITED}</td>
+        <td>
+            A View object's drag event listener receives this event action type after it receives a
+            {@link android.view.DragEvent#ACTION_DRAG_ENTERED} and at least one
+            {@link android.view.DragEvent#ACTION_DRAG_LOCATION} event, and after the user has moved
+            the drag shadow outside the bounding box of the View.
+        </td>
+    </tr>
+    <tr>
+        <td>{@link android.view.DragEvent#ACTION_DROP}</td>
+        <td>
+            A View object's drag event listener receives this event action type when the user
+            releases the drag shadow over the View object. This action type is only sent to a View
+            object's listener if the listener returned boolean <code>true</code> in response to the
+            {@link android.view.DragEvent#ACTION_DRAG_STARTED} drag event. This action type is not
+            sent if the user releases the drag shadow on a View whose listener is not registered,
+            or if the user releases the drag shadow on anything that is not part of the current
+            layout.
+            <p>
+                The listener is expected to return boolean <code>true</code> if it successfully
+                processes the drop. Otherwise, it should return <code>false</code>.
+            </p>
+        </td>
+    </tr>
+    <tr>
+        <td>{@link android.view.DragEvent#ACTION_DRAG_ENDED}</td>
+        <td>
+            A View object's drag event listener receives this event action type
+            when the system is ending the drag operation. This action type is not necessarily
+            preceded by an {@link android.view.DragEvent#ACTION_DROP} event. If the system sent
+            a {@link android.view.DragEvent#ACTION_DROP}, receiving the
+            {@link android.view.DragEvent#ACTION_DRAG_ENDED} action type does not imply that the
+            drop operation succeeded. The listener must call
+            {@link android.view.DragEvent#getResult()} to get the value that was
+            returned in response to {@link android.view.DragEvent#ACTION_DROP}. If an
+            {@link android.view.DragEvent#ACTION_DROP} event was not sent, then
+            {@link android.view.DragEvent#getResult()} returns <code>false</code>.
+        </td>
+    </tr>
+</table>
+<p class="table-caption" id="table2">
+  <strong>Table 2.</strong> Valid DragEvent data by action type</p>
+<table>
+    <tr>
+        <th scope="col">{@link android.view.DragEvent#getAction()} value</th>
+        <th scope="col">{@link android.view.DragEvent#getClipDescription()} value</th>
+        <th scope="col">{@link android.view.DragEvent#getLocalState()} value</th>
+        <th scope="col">{@link android.view.DragEvent#getX()} value</th>
+        <th scope="col">{@link android.view.DragEvent#getY()} value</th>
+        <th scope="col">{@link android.view.DragEvent#getClipData()} value</th>
+        <th scope="col">{@link android.view.DragEvent#getResult()} value</th>
+    </tr>
+    <tr>
+        <td>{@link android.view.DragEvent#ACTION_DRAG_STARTED}</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">&nbsp;</td>
+        <td style="text-align: center;">&nbsp;</td>
+        <td style="text-align: center;">&nbsp;</td>
+    </tr>
+    <tr>
+        <td>{@link android.view.DragEvent#ACTION_DRAG_ENTERED}</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">&nbsp;</td>
+        <td style="text-align: center;">&nbsp;</td>
+    </tr>
+    <tr>
+        <td>{@link android.view.DragEvent#ACTION_DRAG_LOCATION}</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">&nbsp;</td>
+        <td style="text-align: center;">&nbsp;</td>
+    </tr>
+    <tr>
+        <td>{@link android.view.DragEvent#ACTION_DRAG_EXITED}</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">&nbsp;</td>
+        <td style="text-align: center;">&nbsp;</td>
+        <td style="text-align: center;">&nbsp;</td>
+        <td style="text-align: center;">&nbsp;</td>
+    </tr>
+    <tr>
+        <td>{@link android.view.DragEvent#ACTION_DROP}</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">&nbsp;</td>
+    </tr>
+    <tr>
+        <td>{@link android.view.DragEvent#ACTION_DRAG_ENDED}</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">&nbsp;</td>
+        <td style="text-align: center;">&nbsp;</td>
+        <td style="text-align: center;">&nbsp;</td>
+        <td style="text-align: center;">X</td>
+    </tr>
+</table>
+<p>
+    The {@link android.view.DragEvent#getAction()},
+    {@link android.view.DragEvent#describeContents()},
+    {@link android.view.DragEvent#writeToParcel(Parcel,int) writeToParcel()}, and
+    {@link android.view.DragEvent#toString()} methods always return valid data.
+</p>
+<p>
+    If a method does not contain valid data for a particular action type, it returns either
+    <code>null</code> or 0, depending on its result type.
+</p>
+<h3 id="AboutDragShadowBuilder">
+    The drag shadow
+</h3>
+<p>
+    During a drag and drop operation, the system displays a image that the user drags.
+    For data movement, this image represents the data being dragged. For other operations, the
+    image represents some aspect of the drag operation.
+</p>
+<p>
+    The image is called a drag shadow. You create it with methods you declare for a
+    {@link android.view.View.DragShadowBuilder} object, and then pass it to the system when you
+    start a drag using
+    {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}.
+    As part of its response to
+    {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()},
+    the system invokes the callback methods you've defined in
+    {@link android.view.View.DragShadowBuilder} to obtain a drag shadow.
+</p>
+<p>
+    The {@link android.view.View.DragShadowBuilder} class has two constructors:
+</p>
+    <dl>
+    <dt>{@link android.view.View.DragShadowBuilder#View.DragShadowBuilder(View)}</dt>
+    <dd>
+        This constructor accepts any of your application's
+        {@link android.view.View} objects. The constructor stores the View object
+        in the {@link android.view.View.DragShadowBuilder} object, so during
+        the callback you can access it as you construct your drag shadow.
+        It doesn't have to be associated with the View (if any) that the user
+        selected to start the drag operation.
+        <p>
+            If you use this constructor, you don't have to extend
+            {@link android.view.View.DragShadowBuilder} or override its methods. By default,
+            you will get a drag shadow that has the same appearance as the View you pass as an
+            argument, centered under the location where the user is touching the screen.
+        </p>
+    </dd>
+    <dt>{@link android.view.View.DragShadowBuilder#View.DragShadowBuilder()}</dt>
+    <dd>
+        If you use this constructor, no View object is available in the
+        {@link android.view.View.DragShadowBuilder} object (the field is set to <code>null</code>).
+        If you use this constructor, and you don't extend
+        {@link android.view.View.DragShadowBuilder} or override its methods,
+        you will get an invisible drag shadow.
+        The system does <em>not</em> give an error.
+    </dd>
+</dl>
+<p>
+    The {@link android.view.View.DragShadowBuilder} class has two methods:
+</p>
+<dl>
+    <dt>
+{@link android.view.View.DragShadowBuilder#onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()}
+    </dt>
+    <dd>
+        The system calls this method immediately after you call
+{@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}. Use it
+        to send to the system the dimensions and touch point of the drag shadow. The method has two
+        arguments:
+        <dl>
+            <dt><em>dimensions</em></dt>
+            <dd>
+                A {@link android.graphics.Point} object. The drag shadow width goes in
+                {@link android.graphics.Point#x} and its height goes in
+                {@link android.graphics.Point#y}.
+            </dd>
+            <dt><em>touch_point</em></dt>
+            <dd>
+                A {@link android.graphics.Point} object. The touch point is the location within the
+                drag shadow that should be under the user's finger during the drag. Its X
+                position goes in {@link android.graphics.Point#x} and its Y position goes in
+                {@link android.graphics.Point#y}
+            </dd>
+        </dl>
+    </dd>
+    <dt>
+       {@link android.view.View.DragShadowBuilder#onDrawShadow(Canvas) onDrawShadow()}
+    </dt>
+    <dd>
+        Immediately after the call to
+{@link android.view.View.DragShadowBuilder#onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()}
+        the system calls
+        {@link android.view.View.DragShadowBuilder#onDrawShadow(Canvas) onDrawShadow()} to get the
+        drag shadow itself. The method has a single argument, a {@link android.graphics.Canvas}
+        object that the system constructs from the parameters you provide in
+{@link android.view.View.DragShadowBuilder#onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()}
+        Use it to draw the drag shadow in the provided {@link android.graphics.Canvas} object.
+    </dd>
+</dl>
+<p>
+    To improve performance, you should keep the size of the drag shadow small. For a single item,
+    you may want to use a icon. For a multiple selection, you may want to use icons in a stack
+    rather than full images spread out over the screen.
+</p>
+<h2 id="DesignDragOperation">Designing a Drag and Drop Operation</h2>
+<p>
+    This section shows step-by-step how to start a drag, how to respond to events during
+    the drag, how respond to a drop event, and how to end the drag and drop operation.
+</p>
+<h3 id="StartDrag">Starting a drag</h3>
+<p>
+    The user starts a drag with a drag gesture, usually a long press, on a View object.
+    In response, you should do the following:
+</p>
+<ol>
+     <li>
+        As necessary, create a {@link android.content.ClipData} and
+        {@link android.content.ClipData.Item} for the data being moved. As part of the
+        ClipData object, supply metadata that is stored in a {@link android.content.ClipDescription}
+        object within the ClipData. For a drag and drop operation that does not represent data
+        movement, you may want to use <code>null</code> instead of an actual object.
+        <p>
+            For example, this code snippet shows how to respond to a long press on a ImageView
+            by creating a ClipData object that contains the tag or label of an
+            ImageView. Following this snippet, the next snippet shows how to override the methods in
+            {@link android.view.View.DragShadowBuilder}:
+        </p>
+<pre>
+// Create a string for the ImageView label
+private static final String IMAGEVIEW_TAG = &quot;icon bitmap&quot;
+
+// Creates a new ImageView
+ImageView imageView = new ImageView(this);
+
+// Sets the bitmap for the ImageView from an icon bit map (defined elsewhere)
+imageView.setImageBitmap(mIconBitmap);
+
+// Sets the tag
+imageView.setTag(IMAGEVIEW_TAG);
+
+    ...
+
+// Sets a long click listener for the ImageView using an anonymous listener object that
+// implements the OnLongClickListener interface
+imageView.setOnLongClickListener(new View.OnLongClickListener() {
+
+    // Defines the one method for the interface, which is called when the View is long-clicked
+    public boolean onLongClick(View v) {
+
+    // Create a new ClipData.
+    // This is done in two steps to provide clarity. The convenience method
+    // ClipData.newPlainText() can create a plain text ClipData in one step.
+
+    // Create a new ClipData.Item from the ImageView object's tag
+    ClipData.Item item = new ClipData.Item(v.getTag());
+
+    // Create a new ClipData using the tag as a label, the plain text MIME type, and
+    // the already-created item. This will create a new ClipDescription object within the
+    // ClipData, and set its MIME type entry to &quot;text/plain&quot;
+    ClipData dragData = new ClipData(v.getTag(),ClipData.MIMETYPE_TEXT_PLAIN,item);
+
+    // Instantiates the drag shadow builder.
+    View.DrawShadowBuilder myShadow = new MyDragShadowBuilder(imageView);
+
+    // Starts the drag
+
+            v.startDrag(dragData,  // the data to be dragged
+                        myShadow,  // the drag shadow builder
+                        null,      // no need to use local data
+                        0          // flags (not currently used, set to 0)
+            );
+
+    }
+}
+</pre>
+    </li>
+    <li>
+        The following code snippet defines {@code myDragShadowBuilder}
+        It creates a drag shadow for dragging a TextView as a small gray rectangle:
+<pre>
+    private static class MyDragShadowBuilder extends View.DragShadowBuilder {
+
+    // The drag shadow image, defined as a drawable thing
+    private static Drawable shadow;
+
+        // Defines the constructor for myDragShadowBuilder
+        public MyDragShadowBuilder(View v) {
+
+            // Stores the View parameter passed to myDragShadowBuilder.
+            super(v);
+
+            // Creates a draggable image that will fill the Canvas provided by the system.
+            shadow = new ColorDrawable(Color.LTGRAY);
+        }
+
+        // Defines a callback that sends the drag shadow dimensions and touch point back to the
+        // system.
+        &#64;Override
+        public void onProvideShadowMetrics (Point size, Point touch)
+            // Defines local variables
+            private int width, height;
+
+            // Sets the width of the shadow to half the width of the original View
+            width = getView().getWidth() / 2;
+
+            // Sets the height of the shadow to half the height of the original View
+            height = getView().getHeight() / 2;
+
+            // The drag shadow is a ColorDrawable. This sets its dimensions to be the same as the
+            // Canvas that the system will provide. As a result, the drag shadow will fill the
+            // Canvas.
+            shadow.setBounds(0, 0, width, height);
+
+            // Sets the size parameter's width and height values. These get back to the system
+            // through the size parameter.
+            size.set(width, height);
+
+            // Sets the touch point's position to be in the middle of the drag shadow
+            touch.set(width / 2, height / 2);
+        }
+
+        // Defines a callback that draws the drag shadow in a Canvas that the system constructs
+        // from the dimensions passed in onProvideShadowMetrics().
+        &#64;Override
+        public void onDrawShadow(Canvas canvas) {
+
+            // Draws the ColorDrawable in the Canvas passed in from the system.
+            shadow.draw(canvas);
+        }
+    }
+</pre>
+        <p class="note">
+            <strong>Note:</strong> Remember that you don't have to extend
+            {@link android.view.View.DragShadowBuilder}. The constructor
+            {@link android.view.View.DragShadowBuilder#View.DragShadowBuilder(View)} creates a
+            default drag shadow that's the same size as the View argument passed to it, with the
+            touch point centered in the drag shadow.
+        </p>
+    </li>
+</ol>
+<h3 id="HandleStart">Responding to a drag start</h3>
+<p>
+    During the drag operation, the system dispatches drag events to the drag event listeners
+    of the View objects in the current layout. The listeners should react
+    by calling {@link android.view.DragEvent#getAction()} to get the action type.
+    At the start of a drag, this methods returns {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
+</p>
+<p>
+    In response to an event with the action type {@link android.view.DragEvent#ACTION_DRAG_STARTED},
+    a listener should do the following:
+</p>
+<ol>
+    <li>
+        Call {@link android.view.DragEvent#getClipDescription()} to get the
+        {@link android.content.ClipDescription}. Use the MIME type methods in
+        {@link android.content.ClipDescription} to see if the listener can accept the data being
+        dragged.
+        <p>
+            If the drag and drop operation does not represent data movement, this may not be
+            necessary.
+        </p>
+    </li>
+    <li>
+        If the listener can accept a drop, it should return <code>true</code>. This tells
+        the system to continue to send drag events to the listener.
+        If it can't accept a drop, it should return <code>false</code>, and the system
+        will stop sending drag events until it sends out
+        {@link android.view.DragEvent#ACTION_DRAG_ENDED}.
+    </li>
+</ol>
+<p>
+    Note that for an {@link android.view.DragEvent#ACTION_DRAG_STARTED} event, these
+    the following {@link android.view.DragEvent} methods are not valid:
+    {@link android.view.DragEvent#getClipData()}, {@link android.view.DragEvent#getX()},
+    {@link android.view.DragEvent#getY()}, and {@link android.view.DragEvent#getResult()}.
+</p>
+<h3 id="HandleDuring">Handling events during the drag</h3>
+<p>
+    During the drag, listeners that returned <code>true</code> in response to
+    the {@link android.view.DragEvent#ACTION_DRAG_STARTED} drag event continue to receive drag
+    events. The types of drag events a listener receives during the drag depend on the location of
+    the drag shadow and the visibility of the listener's View.
+</p>
+<p>
+    During the drag, listeners primarily use drag events to decide if they should change the
+    appearance of their View.
+</p>
+<p>
+    During the drag, {@link android.view.DragEvent#getAction()} returns one of three
+    values:
+</p>
+<ul>
+    <li>
+        {@link android.view.DragEvent#ACTION_DRAG_ENTERED}:
+        The listener receives this when the touch point
+        (the point on the screen underneath the user's finger) has entered the bounding box of the
+        listener's View.
+    </li>
+    <li>
+        {@link android.view.DragEvent#ACTION_DRAG_LOCATION}: Once the listener receives an
+        {@link android.view.DragEvent#ACTION_DRAG_ENTERED} event, and before it receives an
+        A{@link android.view.DragEvent#ACTION_DRAG_EXITED} event, it receives a new
+        {@link android.view.DragEvent#ACTION_DRAG_LOCATION} event every time the touch point moves.
+        The {@link android.view.DragEvent#getX()} and {@link android.view.DragEvent#getY()} methods
+        return the the X and Y coordinates of the touch point.
+    </li>
+    <li>
+        {@link android.view.DragEvent#ACTION_DRAG_EXITED}:  This event is sent to a listener that
+        previously received {@link android.view.DragEvent#ACTION_DRAG_ENTERED}, after
+        the drag shadow is no longer within the bounding box of the listener's View.
+    </li>
+</ul>
+<p>
+    The listener does not need to react to any of these action types. If the listener returns a
+    value to the system, it is ignored. Here are some guidelines for responding to each of
+    these action types:
+</p>
+<ul>
+    <li>
+        In response to {@link android.view.DragEvent#ACTION_DRAG_ENTERED} or
+        {@link android.view.DragEvent#ACTION_DRAG_LOCATION}, the listener can change the appearance
+        of the View to indicate that it is about to receive a drop.
+    </li>
+    <li>
+        An event with the action type {@link android.view.DragEvent#ACTION_DRAG_LOCATION} contains
+        valid data for {@link android.view.DragEvent#getX()} and
+        {@link android.view.DragEvent#getY()}, corresponding to the location of the touch point.
+        The listener may want to use this information to alter the appearance of that part of the
+        View that is at the touch point. The listener can also use this information
+        to determine the exact position where the user is going to drop the drag shadow.
+    </li>
+    <li>
+        In response to {@link android.view.DragEvent#ACTION_DRAG_EXITED}, the listener should reset
+        any appearance changes it applied in response to
+        {@link android.view.DragEvent#ACTION_DRAG_ENTERED} or
+        {@link android.view.DragEvent#ACTION_DRAG_LOCATION}. This indicates to the user that
+        the View is no longer an imminent drop target.
+    </li>
+</ul>
+<h3 id="HandleDrop">Responding to a drop</h3>
+<p>
+    When the user releases the drag shadow on a View in the application, and that View previously
+    reported that it could accept the content being dragged, the system dispatches a drag event
+    to that View with the action type {@link android.view.DragEvent#ACTION_DROP}. The listener
+    should do the following:
+</p>
+<ol>
+    <li>
+        Call {@link android.view.DragEvent#getClipData()} to get the
+        {@link android.content.ClipData} object that was originally supplied in the call
+        to
+{@link android.view.View#startDrag(ClipData, View.DragShadowBuilder, Object, int) startDrag()}
+        and store it. If the drag and drop operation does not represent data movement,
+        this may not be necessary.
+    </li>
+    <li>
+        Return boolean <code>true</code> to indicate that the drop was processed successfully, or
+        boolean <code>false</code> if it was not. The returned value becomes the value returned by
+        {@link android.view.DragEvent#getResult()} for an
+        {@link android.view.DragEvent#ACTION_DRAG_ENDED} event.
+        <p>
+            Note that if the system does not send out an {@link android.view.DragEvent#ACTION_DROP}
+            event, the value of {@link android.view.DragEvent#getResult()} for an
+            {@link android.view.DragEvent#ACTION_DRAG_ENDED} event is <code>false</code>.
+        </p>
+    </li>
+</ol>
+<p>
+    For an {@link android.view.DragEvent#ACTION_DROP} event,
+    {@link android.view.DragEvent#getX()} and {@link android.view.DragEvent#getY()}
+    return the X and Y position of the drag point at the moment of the drop, using the coordinate
+    system of the View that received the drop.
+</p>
+<p>
+    The system does allow the user to release the drag shadow on a View whose listener is not
+    receiving drag events. It will also allow the user to release the drag shadow
+    on empty regions of the application's UI, or on areas outside of your application.
+    In all of these cases, the system does not send an event with action type
+    {@link android.view.DragEvent#ACTION_DROP}, although it does send out an
+    {@link android.view.DragEvent#ACTION_DRAG_ENDED} event.
+</p>
+<h3 id="HandleEnd">Responding to a drag end</h3>
+<p>
+    Immediately after the user releases the drag shadow, the system sends a
+    drag event to all of the drag event listeners in your application, with an action type of
+    {@link android.view.DragEvent#ACTION_DRAG_ENDED}. This indicates that the drag operation is
+    over.
+</p>
+<p>
+    Each listener should do the following:
+</p>
+<ol>
+    <li>
+        If listener changed its View object's appearance during the operation, it should reset the
+        View to its default appearance. This is a visual indication to the user that the operation
+        is over.
+    </li>
+    <li>
+        The listener can optionally call {@link android.view.DragEvent#getResult()} to find out more
+        about the operation. If a listener returned <code>true</code> in response to an event of
+        action type {@link android.view.DragEvent#ACTION_DROP}, then
+        {@link android.view.DragEvent#getResult()} will return boolean <code>true</code>. In all
+        other cases, {@link android.view.DragEvent#getResult()} returns boolean <code>false</code>,
+        including any case in which the system did not send out a
+        {@link android.view.DragEvent#ACTION_DROP} event.
+    </li>
+    <li>
+        The listener should return boolean <code>true</code> to the system.
+    </li>
+</ol>
+<p>
+</p>
+<h3 id="RespondEventSample">Responding to drag events: an example</h3>
+<p>
+    All drag events are initially received by your drag event method or listener. The following
+    code snippet is a simple example of reacting to drag events in a listener:
+</p>
+<pre>
+// Creates a new drag event listener
+mDragListen = new myDragEventListener();
+
+View imageView = new ImageView(this);
+
+// Sets the drag event listener for the View
+imageView.setOnDragListener(mDragListen);
+
+...
+
+protected class myDragEventListener implements View.OnDragEventListener {
+
+    // This is the method that the system calls when it dispatches a drag event to the
+    // listener.
+    public boolean onDrag(View v, DragEvent event) {
+
+        // Defines a variable to store the action type for the incoming event
+        final int action = event.getAction();
+
+        // Handles each of the expected events
+        switch(action) {
+
+            case DragEvent.ACTION_DRAG_STARTED:
+
+                // Determines if this View can accept the dragged data
+                if (event.getClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) {
+
+                    // As an example of what your application might do,
+                    // applies a blue color tint to the View to indicate that it can accept
+                    // data.
+                    v.setColorFilter(Color.BLUE);
+
+                    // Invalidate the view to force a redraw in the new tint
+                    v.invalidate();
+
+                    // returns true to indicate that the View can accept the dragged data.
+                    return(true);
+
+                    } else {
+
+                    // Returns false. During the current drag and drop operation, this View will
+                    // not receive events again until ACTION_DRAG_ENDED is sent.
+                    return(false);
+
+                    }
+                break;
+
+            case DragEvent.ACTION_DRAG_ENTERED: {
+
+                // Applies a green tint to the View. Return true; the return value is ignored.
+
+                v.setColorFilter(Color.GREEN);
+
+                // Invalidate the view to force a redraw in the new tint
+                v.invalidate();
+
+                return(true);
+
+                break;
+
+                case DragEvent.ACTION_DRAG_LOCATION:
+
+                // Ignore the event
+                    return(true);
+
+                break;
+
+                case DragEvent.ACTION_DRAG_EXITED:
+
+                    // Re-sets the color tint to blue. Returns true; the return value is ignored.
+                    v.setColorFilter(Color.BLUE);
+
+                    // Invalidate the view to force a redraw in the new tint
+                    v.invalidate();
+
+                    return(true);
+
+                break;
+
+                case DragEvent.ACTION_DROP:
+
+                    // Gets the item containing the dragged data
+                    ClipData.Item item = event.getClipData().getItemAt(0);
+
+                    // Gets the text data from the item.
+                    dragData = item.getText();
+
+                    // Displays a message containing the dragged data.
+                    Toast.makeText(this, "Dragged data is " + dragData, Toast.LENGTH_LONG);
+
+                    // Turns off any color tints
+                    v.clearColorFilter();
+
+                    // Invalidates the view to force a redraw
+                    v.invalidate();
+
+                    // Returns true. DragEvent.getResult() will return true.
+                    return(true);
+
+                break;
+
+                case DragEvent.ACTION_DRAG_ENDED:
+
+                    // Turns off any color tinting
+                    v.clearColorFilter();
+
+                    // Invalidates the view to force a redraw
+                    v.invalidate();
+
+                    // Does a getResult(), and displays what happened.
+                    if (event.getResult()) {
+                        Toast.makeText(this, "The drop was handled.", Toast.LENGTH_LONG);
+
+                    } else {
+                        Toast.makeText(this, "The drop didn't work.", Toast.LENGTH_LONG);
+
+                    };
+
+                    // returns true; the value is ignored.
+                    return(true);
+
+                break;
+
+                // An unknown action type was received.
+                default:
+                    Log.e("DragDrop Example","Unknown action type received by OnDragListener.");
+
+                break;
+        };
+    };
+};
+</pre>
\ No newline at end of file
diff --git a/docs/html/images/ui/clipboard/copy_paste_framework.png b/docs/html/images/ui/clipboard/copy_paste_framework.png
new file mode 100755
index 0000000..57facaa
--- /dev/null
+++ b/docs/html/images/ui/clipboard/copy_paste_framework.png
Binary files differ
diff --git a/docs/html/sdk/android-2.3.3.jd b/docs/html/sdk/android-2.3.3.jd
index dbc48f4..6d60fcc 100644
--- a/docs/html/sdk/android-2.3.3.jd
+++ b/docs/html/sdk/android-2.3.3.jd
@@ -54,7 +54,7 @@
 first.</p>
 
 <p>For a high-level introduction to Android 2.3, see the <a
-href="http://developer.android.com/sdk/android-2.3-highlights.html">Platform Highlights</a>.</p>
+href="{@docRoot}sdk/android-2.3-highlights.html">Platform Highlights</a>.</p>
 
 
 <h2 id="relnotes">Revisions</h2>
diff --git a/docs/html/sdk/android-2.3.jd b/docs/html/sdk/android-2.3.jd
index 734d97b..e7aa0fa 100644
--- a/docs/html/sdk/android-2.3.jd
+++ b/docs/html/sdk/android-2.3.jd
@@ -51,7 +51,7 @@
 first.</p>
 
 <p>For a high-level introduction to Android {@sdkPlatformVersion}, see the <a
-href="http://developer.android.com/sdk/android-{@sdkPlatformVersion}-highlights.html">Platform Highlights</a>.</p>
+href="{@docRoot}sdk/android-{@sdkPlatformVersion}-highlights.html">Platform Highlights</a>.</p>
 
 
 <h2 id="relnotes">Revisions</h2>
diff --git a/docs/html/sdk/android-3.0.jd b/docs/html/sdk/android-3.0.jd
index 2c8a7f0..6842c82 100644
--- a/docs/html/sdk/android-3.0.jd
+++ b/docs/html/sdk/android-3.0.jd
@@ -1,4 +1,6 @@
 page.title=Android 3.0 Platform Preview
+sdk.platform.version=3.0
+sdk.platform.apiLevel=11
 @jd:body
 
 <div id="qv-wrapper">
@@ -6,6 +8,7 @@
 
 <h2>In this document</h2>
 <ol>
+  <li><a href="#relnotes">Revisions</a></li>
   <li><a href="#api">API Overview</a></li>
   <li><a href="#api-level">API Level</a></li>
   <li><a href="#apps">Built-in Applications</a></li>
@@ -16,7 +19,7 @@
 <h2>Reference</h2>
 <ol>
 <li><a
-href="{@docRoot}sdk/api_diff/honeycomb/changes.html">API
+href="{@docRoot}sdk/api_diff/11/changes.html">API
 Differences Report &raquo;</a> </li>
 </ol>
 
@@ -28,18 +31,51 @@
 </div>
 </div>
 
-<p><em>API Level:</em> <b>Honeycomb</b></p>
 
-<p>For developers, the Android 3.0 preview is available as a downloadable component for the
-Android SDK.</p>
+<p><em>API Level:</em>&nbsp;<strong>{@sdkPlatformApiLevel}</strong></p>
 
-<p class="note"><strong>Note:</strong> Read the <a
-href="{@docRoot}sdk/preview/start.html">Getting Started</a> guide for important information
-about setting up your development environment and limitiations of the Android 3.0 preview.</p>
+<p>For developers, the Android {@sdkPlatformVersion} platform is available as a downloadable
+component for the Android SDK. The downloadable platform includes an Android library and system
+image, as well as a set of emulator skins and more. The downloadable platform includes no external
+libraries.</p>
+
+<p>To get started developing or testing against Android {@sdkPlatformVersion}, use the Android SDK
+Manager to download the platform into your SDK. For more information, see <a
+href="{@docRoot}sdk/adding-components.html">Adding SDK Components</a>. If you are new to Android, <a
+href="{@docRoot}sdk/index.html">download the SDK Starter Package</a> first.</p>
+
+<p>For a high-level introduction to Android {@sdkPlatformVersion}, see the <a
+href="{@docRoot}sdk/android-{@sdkPlatformVersion}-highlights.html">Platform
+Highlights</a>.</p>
 
 
 
+<h2 id="relnotes">Revisions</h2>
 
+<p>To determine what revision of the Android {@sdkPlatformVersion} platform you have installed,
+refer to the "Installed Packages" listing in the Android SDK and AVD Manager.</p>
+
+
+<div class="toggle-content opened" style="padding-left:1em;">
+
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img" alt="" />
+    Android {@sdkPlatformVersion}, Revision 1</a> <em>(February 2011)</em>
+  </a></p>
+
+  <div class="toggle-content-toggleme" style="padding-left:2em;">
+    
+<dl>
+  
+<dt>Dependencies:</dt>
+<dd>
+<p>Requires <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r10</a> or higher.</p>
+</dd>
+
+</dl>
+
+  </div>
+</div>
 
 
 
@@ -49,6 +85,9 @@
 including new features and changes in the framework API since the previous version.</p>
 
 
+
+
+
 <h3>Fragments</h3>
 
 <p>A fragment is a new framework component that allows you to separate distinct elements of an
@@ -65,9 +104,9 @@
 <p>Additionally:</p>
 
 <ul>
-  <li>Fragments are self-contained and can be reused in multiple activities</li>
-  <li>Fragments can be added, removed, replaced and animated inside the activity</li>
-  <li>Fragment can be added to a back stack managed by the activity, preserving the state of
+  <li>Fragments are self-contained and you can reuse them in multiple activities</li>
+  <li>You can add, remove, replace and animate fragments inside the activity</li>
+  <li>You can add fragments to a back stack managed by the activity, preserving the state of
 fragments as they are changed and allowing the user to navigate backward through the different
 states</li>
   <li>By <a
@@ -80,8 +119,8 @@
 
 <p>To manage the fragments in your activity, you must use the {@link
 android.app.FragmentManager}, which provides several APIs for interacting with fragments, such
-as finding fragments in the activity and popping fragments off the back stack to restore them
-after they've been removed or hidden.</p>
+as finding fragments in the activity and popping fragments off the back stack to restore their
+previous state.</p>
 
 <p>To perform a transaction, such as add or remove a fragment, you must create a {@link
 android.app.FragmentTransaction}. You can then call methods such as {@link
@@ -92,7 +131,10 @@
 the activity.</p>
 
 <p>For more information about using fragments, read the <a
-href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a> developer guide.</p>
+href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a> documentation. Several
+samples are also available in the <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/index.html#Fragment">
+API Demos</a> application.</p>
 
 
 
@@ -101,49 +143,51 @@
 
 <p>The Action Bar is a replacement for the traditional title bar at the top of the activity window.
 It includes the application logo in the left corner and provides a new interface for items in the
-activity's Options Menu. Additionally, the Action Bar allows you to:</p>
+<a href="{@docRoot}guide/topics/ui/menus.html#options-menu">Options Menu</a>. Additionally, the
+Action Bar allows you to:</p>
 
 <ul>
-  <li>Include select menu items directly in the Action Bar&mdash;as "action
-items"&mdash;for quick access to global user actions.
-    <p>In your XML declaration for the menu item, include the attribute, {@code
-android:showAsAction} with a value of {@code "ifRoom"}. When there's enough room in the
-Action Bar, the menu item appears directly in the bar. Otherwise, the item is placed in the
-overflow menu, revealed by the icon on the right side of the Action Bar.</p></li>
+  <li>Add menu items directly in the Action Bar&mdash;as "action items."
+    <p>In your XML declaration for the menu item, include the {@code
+android:showAsAction} attribute with a value of {@code "ifRoom"}. When there's enough room, the menu
+item appears directly in the Action Bar. Otherwise, the item is placed in the
+overflow menu, revealed by the menu icon on the right side of the Action Bar.</p></li>
 
-  <li>Add interactive widgets to the Action Bar&mdash;as "action views"&mdash;such as a search box.
-    <p>In the XML for the menu item that should behave as an action view, include the {@code
-android:actionViewLayout} attribute with a layout
-resource for the action view or {@code android:actionViewClass} with the class name of the
-widget. Like action items, an action view appears only when there's room for it in the Action
-Bar. If there's not enough room, it is placed in the overflow menu and behaves like a regular
-menu item (for example, an item can provide a {@link android.widget.SearchView} as an action
-view, but when in the overflow menu, selecting the item activates the search dialog).</p></li>
+  <li>Replace an action item with a widget (such as a search box)&mdash;creating an
+"action view."
+    <p>In the XML declaration for the menu item, add the {@code android:actionViewLayout} attribute
+with a layout resource or the {@code android:actionViewClass} attribute with the class name of a
+widget. (You must also declare the {@code android:showAsAction} attribute so that the item appears
+in the Action Bar.) If there's not enough room in the Action Bar and the item appears in the
+overflow menu, it behaves like a regular menu item and does not show the widget.</p></li>
 
-  <li>Add an action to the application logo when tapped and replace it with a custom logo
+  <li>Add an action to the application logo and replace it with a custom logo
     <p>The application logo is automatically assigned the {@code android.R.id.home} ID,
-which the system deliveres to your activity's {@link android.app.Activity#onOptionsItemSelected
-onOptionsItemSelected()} callback when tapped. Simply respond to this ID in your callback
+which the system delivers to your activity's {@link android.app.Activity#onOptionsItemSelected
+onOptionsItemSelected()} callback when touched. Simply respond to this ID in your callback
 method to perform an action such as go to your application's "home" activity.</p>
-    <p>To replace the icon with a logo, </p></li>
+    <p>To replace the icon with a logo, specify your application logo in the manifest file with the
+<a href="{@docRoot}guide/topics/manifest/application-element.html#logo">{@code android:logo}</a>
+attribute, then call {@link android.app.ActionBar#setDisplayUseLogoEnabled
+setDisplayUseLogoEnabled(true)} in your activity.</p></li>
 
-  <li>Add breadcrumbs for navigating backward through fragments</li>
-  <li>Add built in tabs and a drop-down list for navigation</li>
-  <li>Customize the Action Bar themes and custom backgrounds</li>
+  <li>Add breadcrumbs to navigate backward through the back stack of fragments</li>
+  <li>Add tabs or a drop-down list to navigate through fragments</li>
+  <li>Customize the Action Bar with themes and backgrounds</li>
 </ul>
 
-<p>The Action Bar is standard for all applications that set either the <a
+<p>The Action Bar is standard for all applications that use the new holographic theme, which is
+also standard when you set either the <a
 href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
 android:minSdkVersion}</a> or <a
 href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
-android:targetSdkVersion}</a> to {@code "Honeycomb"}. (The "Honeycomb" API Level is provisional
-and effective only while using the preview SDK&mdash;you must change it to the official API
-Level when the final SDK becomes available&mdash;see <a
-href="{@docRoot}sdk/preview/start.html">Getting Started</a> for more information.)</p>
+android:targetSdkVersion}</a> to {@code "11"}.</p>
 
 <p>For more information about the Action Bar, read the <a
-href="{@docRoot}guide/topics/ui/actionbar.html">Action
-Bar</a> developer guide.</p>
+href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a> documentation. Several
+samples are also available in the <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/index.html#ActionBar">
+API Demos</a> application.</p>
 
 
 
@@ -153,97 +197,123 @@
 <p>Applications can now copy and paste data (beyond mere text) to and from the system-wide
 clipboard. Clipped data can be plain text, a URI, or an intent.</p>
 
-<p>By providing the system access to your data in a content provider, the user can copy complex
-content (such as an image or data structure) from your application and paste it into another
-application that supports that type of content.</p>
+<p>By providing the system access to the data you want the user to copy, through a content provider,
+the user can copy complex content (such as an image or data structure) from your application and
+paste it into another application that supports that type of content.</p>
 
 <p>To start using the clipboard, get the global {@link android.content.ClipboardManager} object
 by calling {@link android.content.Context#getSystemService getSystemService(CLIPBOARD_SERVICE)}.</p>
 
-<p>To create an item to attach to the clipboard ("copy"), you need to create a new {@link
+<p>To copy an item to the clipboard, you need to create a new {@link
 android.content.ClipData} object, which holds one or more {@link android.content.ClipData.Item}
-objects, each describing a single entity. To create a {@link android.content.ClipData} object with
-just one {@link android.content.ClipData.Item}, you can use one of the helper methods, such as
-{@link android.content.ClipData#newPlainText newPlainText()}, {@link
+objects, each describing a single entity. To create a {@link android.content.ClipData} object
+containing just one {@link android.content.ClipData.Item}, you can use one of the helper methods,
+such as {@link android.content.ClipData#newPlainText newPlainText()}, {@link
 android.content.ClipData#newUri newUri()}, and {@link android.content.ClipData#newIntent
 newIntent()}, which each return a {@link android.content.ClipData} object pre-loaded with the
-appropriate {@link android.content.ClipData.Item}.</p>
+{@link android.content.ClipData.Item} you provide.</p>
 
 <p>To add the {@link android.content.ClipData} to the clipboard, pass it to {@link
 android.content.ClipboardManager#setPrimaryClip setPrimaryClip()} for your instance of {@link
 android.content.ClipboardManager}.</p>
 
-<p>You can then acquire ("paste") a file from the clipboard by calling {@link
+<p>You can then read a file from the clipboard (in order to paste it) by calling {@link
 android.content.ClipboardManager#getPrimaryClip()} on the {@link
 android.content.ClipboardManager}. Handling the {@link android.content.ClipData} you receive can
-be more complicated and you need to be sure you can actually handle the data type.</p>
+be complicated and you need to be sure you can actually handle the data type in the clipboard
+before attempting to paste it.</p>
 
-<p>For more information, see the {@link android.content.ClipData} class reference. You can also see
-an example implementation of copy and paste in the <a
-href="{@docRoot}resources/samples/NotePad/index.html">NotePad</a> sample application.</p>
+<p>The clipboard holds only one piece of clipped data (a {@link android.content.ClipData}
+object) at a time, but one {@link android.content.ClipData} can contain multiple {@link
+android.content.ClipData.Item}s.</p>
+
+<p>For more information, read the <a href="{@docRoot}guide/topics/clipboard/copy-paste.html">Copy
+and Paste</a> documentation. You can also see a simple implementation of copy and paste in the <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/content/ClipboardSample.
+html">API Demos</a> and a more complete implementation in the <a
+href="{@docRoot}resources/samples/NotePad/index.html">Note Pad</a> application.</p>
 
 
 
 
 <h3>Drag and drop</h3>
 
-<p>New APIs facilitate the ability for your application to implement drag and drop
-functionality in the UI.</p>
+<p>New APIs simplify drag and drop operations in your application's user interface. A drag
+operation is the transfer of some kind of data&mdash;carried in a {@link android.content.ClipData}
+object&mdash;from one place to another. The start and end point for the drag operation is a {@link
+android.view.View}, so the APIs that directly handle the drag and drop operations are
+in the {@link android.view.View} class.</p>
+
+<p>A drag and drop operation has a lifecycle that's defined by several drag actions&mdash;each
+defined by a {@link android.view.DragEvent} object&mdash;such as {@link
+android.view.DragEvent#ACTION_DRAG_STARTED}, {@link android.view.DragEvent#ACTION_DRAG_ENTERED}, and
+{@link android.view.DragEvent#ACTION_DROP}. Each view that wants to participate in a drag
+operation can listen for these actions.</p>
 
 <p>To begin dragging content in your activity, call {@link android.view.View#startDrag startDrag()}
 on a {@link android.view.View}, providing a {@link android.content.ClipData} object that represents
-the information to drag, a {@link android.view.View.DragShadowBuilder} to facilitate the "shadow"
-that the user sees while dragging, and an {@link java.lang.Object} that can share information about
-the drag object with views that may receive the object.</p>
+the data to drag, a {@link android.view.View.DragShadowBuilder} to facilitate the "shadow"
+that users see under their fingers while dragging, and an {@link java.lang.Object} that can share
+information about the drag object with views that may receive the object.</p>
 
-<p>To accept a drag object (receive the "drop") in a
-{@link android.view.View}, register the view with an {@link android.view.View.OnDragListener
-OnDragListener} by
-calling {@link android.view.View#setOnDragListener setOnDragListener()}. When a drag event occurs on
-the view, the system calls {@link android.view.View.OnDragListener#onDrag onDrag()} for the  {@link
+<p>To accept a drag object in a {@link android.view.View} (receive the "drop"), register the view
+with an {@link android.view.View.OnDragListener OnDragListener} by calling {@link
+android.view.View#setOnDragListener setOnDragListener()}. When a drag event occurs on the view, the
+system calls {@link android.view.View.OnDragListener#onDrag onDrag()} for the  {@link
 android.view.View.OnDragListener OnDragListener}, which receives a {@link android.view.DragEvent}
-describing the
-type of event has occurred (such as "drag started", "drag ended", or "drop"). During a drag, the
-system repeatedly calls {@link
-android.view.View.OnDragListener#onDrag onDrag()} for the view underneath the drag, to
-deliver a stream of events. The receiving view can
-inquire the event type delivered to {@link android.view.View#onDragEvent onDragEvent()} by calling
-{@link android.view.DragEvent#getAction getAction()} on the {@link android.view.DragEvent}.</p>
+describing the type of drag action has occurred (such as {@link
+android.view.DragEvent#ACTION_DRAG_STARTED}, {@link android.view.DragEvent#ACTION_DRAG_ENTERED}, and
+{@link android.view.DragEvent#ACTION_DROP}). During a drag, the system repeatedly calls {@link
+android.view.View.OnDragListener#onDrag onDrag()} for the view underneath the drag, to deliver a
+stream of drag events. The receiving view can inquire the event type delivered to {@link
+android.view.View#onDragEvent onDragEvent()} by calling {@link android.view.DragEvent#getAction
+getAction()} on the {@link android.view.DragEvent}.</p>
 
-<p>Although a drag event may carry a {@link android.content.ClipData} object, this is not related
-to the system clipboard. The data being dragged is passed as a {@link
-android.content.ClipData} object to {@link android.view.View#startDrag startDrag()} and the system
-sends it to the receiving {@link android.view.View} in the {@link android.view.DragEvent} sent to
-{@link android.view.View.OnDragListener#onDrag onDrag()}. A drag and drop operation should never
-put the dragged data in the global system clipboard.</p>
+<p class="note"><strong>Note:</strong> Although a drag event may carry a {@link
+android.content.ClipData} object, this is not related to the system clipboard. A drag and drop
+operation should never put the dragged data in the system clipboard.</p>
+
+<p>For more information, read the <a href="{@docRoot}guide/topics/ui/drag-drop.html">Dragging and
+Dropping</a> documentation. You can also see an implementation of drag and drop in the <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/DragAndDropDemo.html">
+API Demos</a> application and the <a
+href="{@docRoot}resources/samples/HoneycombGallery/index.html">Honeycomb Gallery</a>
+application.</p>
 
 
 
 <h3>App widgets</h3>
 
-<p>Android 3.0 supports several new widget classes for more interactive app widgets, including:
-{@link
-android.widget.GridView}, {@link android.widget.ListView}, {@link android.widget.StackView}, {@link
-android.widget.ViewFlipper}, and {@link android.widget.AdapterViewFlipper}.</p>
+<p>Android 3.0 supports several new widget classes for more interactive app widgets on the users
+Home screen, including: {@link android.widget.GridView}, {@link android.widget.ListView}, {@link
+android.widget.StackView}, {@link android.widget.ViewFlipper}, and {@link
+android.widget.AdapterViewFlipper}.</p>
 
-<p>You can also use the new {@link android.widget.RemoteViewsService} to populate
-collection views such as ({@link android.widget.GridView}, {@link android.widget.ListView}, and
-{@link android.widget.StackView}).</p>
+<p>More importantly, you can use the new {@link android.widget.RemoteViewsService} to create app
+widgets with collections, using widgets such as {@link android.widget.GridView}, {@link
+android.widget.ListView}, and {@link android.widget.StackView} that are backed by remote data,
+such as from a content provider.</p>
 
-<p>{@link android.appwidget.AppWidgetProviderInfo} also supports two new fields: {@link
+<p>The {@link android.appwidget.AppWidgetProviderInfo} class (defined with an {@code
+&lt;appwidget-provider&gt; XML file) also supports two new fields: {@link
 android.appwidget.AppWidgetProviderInfo#autoAdvanceViewId} and {@link
 android.appwidget.AppWidgetProviderInfo#previewImage}. The {@link
 android.appwidget.AppWidgetProviderInfo#autoAdvanceViewId} field lets you specify the view ID of the
-app widget subview, which is auto-advanced by the app widget’s host. The
+app widget subview that should be auto-advanced by the app widget’s host. The
 {@link android.appwidget.AppWidgetProviderInfo#previewImage} field specifies a preview of what the
 app widget looks like and is shown to the user from the widget picker. If this field is not
 supplied, the app widget's icon is used for the preview.</p>
 
-<p>Android also provides a new widget preview tool ({@code WidgetPreview}), located in the SDK
-tools, to take a screenshot of your app widget, which you can use when specifying the {@link
-android.appwidget.AppWidgetProviderInfo#previewImage} field.</p>
+<p>To help create a preview image for your app widget (to specify in the {@link
+android.appwidget.AppWidgetProviderInfo#autoAdvanceViewId} field), the Android emulator includes an
+application called "Widget Preview." To create a preview image, launch this application, select the
+app widget for your application and set it up how you'd like your preview image to appear, then save
+it and place it in your application's drawable resources.</p>
 
-
+<p>You can see an implementation of the new app widget features in the <a
+href="{@docRoot}resources/samples/StackWidget/index.html">StackView App Widget</a> and <a
+href="{@docRoot}resources/samples/WeatherListWidget/index.html">Weather List Widget</a>
+applications.</p>
 
 
 
@@ -251,7 +321,7 @@
 
 <p>The {@link android.app.Notification} APIs have been extended to support more content-rich status
 bar notifications, plus a new {@link android.app.Notification.Builder} class allows you to easily
-control the notification properties.</p>
+create {@link android.app.Notification} objects.</p>
 <p>New features include:</p>
 <ul>
   <li>Support for a large icon in the notification, using {@link
@@ -261,22 +331,32 @@
   <li>Support for custom layouts in the status bar ticker, using {@link
 android.app.Notification.Builder#setTicker(CharSequence,RemoteViews) setTicker()}.</li>
   <li>Support for custom notification layouts to include buttons with {@link
-android.app.PendingIntent}s, for more interactive notification widgets
-(such as to control ongoing music in the background).</li>
+android.app.PendingIntent}s, for more interactive notification widgets. For example, a
+notification can control music playback without starting an activity.</li>
 </ul>
 
 
 
-
 <h3>Content loaders</h3>
 
 <p>New framework APIs facilitate asynchronous loading of data using the {@link
 android.content.Loader} class. You can use it in combination with UI components such as views and
 fragments to dynamically load data from worker threads. The {@link
-android.content.CursorLoader} subclass is specially designed to help do so for data queried from
-a {@link android.content.ContentResolver}.</p>
+android.content.CursorLoader} subclass is specially designed to help you do so for data backed by
+a {@link android.content.ContentProvider}.</p>
 
+<p>All you need to do is implement the {@link android.app.LoaderManager.LoaderCallbacks
+LoaderCallbacks} interface to receive callbacks when a new loader is requested or the data has
+changed, then call {@link android.app.LoaderManager#initLoader initLoader()} to initialize the
+loader for your activity or fragment.</p>
 
+<p>For more information, read the <a
+href="{@docRoot}guide/topics/providers/loaders.html">Loaders</a> documentation. You can also see
+example code using loaders in the <a
+href="{@docRoot}samples/ApiDemos/src/com/example/android/apis/app/FragmentListCursorLoader.html">
+FragmentListCursorLoader</a> and <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html">
+LoaderThrottle</a> samples.</p>
 
 
 
@@ -297,10 +377,10 @@
 
 
 
-<h3>Animation framework</h3>
+<h3 id="animation">Animation framework</h3>
 
 <p>An all new flexible animation framework allows you to animate arbitrary properties of any object
-(View, Drawable, Fragment, Object, or anything else). It allows you to define many aspects of an
+(View, Drawable, Fragment, Object, or anything else). It allows you to define several aspects of an
 animation, such as:</p>
 <ul>
   <li>Duration</li>
@@ -309,13 +389,14 @@
   <li>Animator sets to play animations together, sequentially, or after specified delays</li>
   <li>Frame refresh delay</li>
 </ul>
-  
- <p>You can define these animation aspects, and others, for an object's int, float, and hexadecimal
-color values, by default.  To animate any other type of value, you tell the system how to calculate
-the values for that given type, by implementing the {@link android.animation.TypeEvaluator}
-interface.</p>
 
-<p>There are two animators you can use to animate values of a property: {@link
+ <p>You can define these animation aspects, and others, for an object's int, float, and hexadecimal
+color values, by default. That is, when an object has a property field for one of these types, you
+can change its value over time to affect an animation. To animate any other type of value, you tell
+the system how to calculate the values for that given type, by implementing the {@link
+android.animation.TypeEvaluator} interface.</p>
+
+<p>There are two animators you can use to animate the values of a property: {@link
 android.animation.ValueAnimator} and {@link android.animation.ObjectAnimator}. The {@link
 android.animation.ValueAnimator} computes the animation values, but is not aware of the specific
 object or property that is animated as a result. It simply performs the calculations, and you must
@@ -324,7 +405,7 @@
 allows you to set the object and property to animate, and it handles all animation work.
 That is, you give the {@link android.animation.ObjectAnimator} the object to animate, the
 property of the object to change over time, and a set of values to apply to the property over
-time in order to animate it, then start the animation.</p>
+time, then start the animation.</p>
 
 <p>Additionally, the {@link android.animation.LayoutTransition} class enables automatic transition
 animations for changes you make to your activity layout. To enable transitions for part of the
@@ -338,7 +419,10 @@
 discussed above.</p>
 
 <p>For more information, see the <a
-href="{@docRoot}guide/topics/graphics/animation.html">Animation</a> developer guide.</p>
+href="{@docRoot}guide/topics/graphics/animation.html">Property Animation</a> documentation. You can
+also see several samples using the animation APIs in the <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/index.html">API
+Demos</a> application.</p>
 
 
 
@@ -350,8 +434,11 @@
   <li><b>Multiple-choice selection for ListView and GridView</b>
 
 <p>New {@link android.widget.AbsListView#CHOICE_MODE_MULTIPLE_MODAL} mode for {@link
-android.widget.AbsListView#setChoiceMode setChoiceMode()} allows for selecting multiple items
-from a {@link android.widget.ListView} and {@link android.widget.GridView}.</p>
+android.widget.AbsListView#setChoiceMode setChoiceMode()} allows users to select multiple items
+from a {@link android.widget.ListView} or {@link android.widget.GridView}. When used in
+conjunction with the Action Bar, users can select multiple items and then select the action to
+perform from a list of options in the Action Bar (which has transformed into a Multi-choice
+Action Mode).</p>
 
 <p>To enable multiple-choice selection, call {@link
 android.widget.AbsListView#setChoiceMode setChoiceMode(CHOICE_MODE_MULTIPLE_MODAL)} and register a
@@ -373,10 +460,11 @@
   
   <li><b>New APIs to transform views</b>
   
-    <p>New APIs allow you to easily apply 2D and 3D transformations to {@link
-android.view.View}s in your activity layout, using a set of object properties that define the view's
+    <p>New APIs allow you to easily apply 2D and 3D transformations to views in your activity
+layout. New transformations are made possible with a set of object properties that define the view's
 layout position, orientation, transparency and more.</p>
-    <p>New methods to set properties include: {@link android.view.View#setAlpha setAlpha()}, {@link
+    <p>New methods to set the view properties include: {@link android.view.View#setAlpha
+setAlpha()}, {@link
 android.view.View#setBottom setBottom()}, {@link android.view.View#setLeft setLeft()}, {@link
 android.view.View#setRight setRight()}, {@link android.view.View#setBottom setBottom()}, {@link
 android.view.View#setPivotX setPivotX()}, {@link android.view.View#setPivotY setPivotY()}, {@link
@@ -385,14 +473,16 @@
 setScaleY()}, {@link android.view.View#setAlpha setAlpha()}, and others.</p>
 
     <p>Some methods also have a corresponding XML attribute that you can specify in your layout
-file. Available attributes include: {@code translationX}, {@code translationY}, {@code rotation},
+file, to apply a default transformation. Available attributes include: {@code translationX}, {@code
+translationY}, {@code rotation},
 {@code rotationX}, {@code rotationY}, {@code scaleX}, {@code scaleY}, {@code transformPivotX},
 {@code transformPivotY}, and {@code alpha}.</p>
 
-    <p>Using some of these new properties in combination with the new animation framework (discussed
-previously), you can easily create some fancy animations to your views. For example, to rotate a
+    <p>Using some of these new view properties in combination with the new <a
+href="#animation">animation framework</a> (discussed
+above), you can easily apply some fancy animations to your views. For example, to rotate a
 view on its y-axis, supply {@link android.animation.ObjectAnimator} with the {@link
-android.view.View}, the "rotationY" property, and the values to use:</p>
+android.view.View}, the "rotationY" property, and the start and end values:</p>
 <pre>
 ObjectAnimator animator = ObjectAnimator.ofFloat(myView, "rotationY", 0, 360);
 animator.setDuration(2000);
@@ -403,16 +493,25 @@
   
   <li><b>New holographic themes</b>
 
-    <p>The standard system widgets and overall look have been redesigned for use on larger screens
-such as tablets and incorporate the new "holographic" UI theme. The system applies these styles
-using the standard <a href="{@docRoot}guide/topics/ui/themes.html">style and theme</a> system.
-Any application that targets the Android 3.0 platform inherits the holographic theme by default.
-However, if your application also applies its own styles, then it will override the holographic
-theme, unless you update your styles to inherit the holographic theme.</p>
+    <p>The standard system widgets and overall look have been redesigned and incorporate a new
+"holographic" user interface theme. The system applies the new theme
+using the standard <a href="{@docRoot}guide/topics/ui/themes.html">style and theme</a> system.</p>
+
+<p>Any application that targets the Android 3.0 platform&mdash;by setting either the <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code android:minSdkVersion}</a>
+or <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+android:targetSdkVersion}</a> value to {@code "11"}&mdash;inherits the holographic theme by default.
+However, if your application also applies its own theme, then your theme will override the
+holographic theme, unless you update your styles to inherit the holographic theme.</p>
 
 <p>To apply the holographic theme to individual activities or to inherit them in your own theme
 definitions, use one of several new {@link android.R.style#Theme_Holo Theme.Holo}
-themes.</p>
+themes. If your application is compatible with version of Android lower than 3.0 and applies
+custom themes, then you should <a
+href="{@docRoot}guide/topics/ui/themes.html#SelectATheme">select a theme based on platform
+version</a>.</p>
+
   </li>
   
   
@@ -430,38 +529,36 @@
     each child at a regular interval.</p></li>
     
     <li>{@link android.widget.CalendarView}
-    <p>Allows users to select dates from a calendar and you can configure the range of dates
-    available. A user can select a date by tapping on it and can scroll and fling
-    the calendar to a desired date.</p></li>
+    <p>Allows users to select dates from a calendar by touching the date and can scroll or fling the
+calendar to a desired date. You can configure the range of dates available in the widget.</p></li>
     
     <li>{@link android.widget.ListPopupWindow}
     <p>Anchors itself to a host view and displays a list of choices, such as for a list of
     suggestions when typing into an {@link android.widget.EditText} view.</p></li>
     
     <li>{@link android.widget.NumberPicker}
-    <p>Enables the user to select a number from a predefined range. The widget presents an
-    input field and up and down buttons for selecting a number. Touching the input field shows a
-    scroll wheel that allows the user to scroll through values or touch again to directly edit the
-    current value. It also allows you to map from positions to strings, so that
-    the corresponding string is displayed instead of the position index.</p></li>
+    <p>Enables the user to select a number from a predefined range. The widget presents an input
+field and up and down buttons for selecting a number. Touching the input field allows the user to
+scroll through values or touch again to directly edit the current value. It also allows you to map
+positions to strings, so that the corresponding string is displayed instead of the index
+position.</p></li>
     
     <li>{@link android.widget.PopupMenu}
     <p>Displays a {@link android.view.Menu} in a modal popup window that's anchored to a view. The
-  popup
-    appears below the anchor view if there is room, or above it if there is not. If the IME (soft
-    keyboard) is visible, the popup does not overlap it until it is touched.</p></li>
+popup appears below the anchor view if there is room, or above it if there is not. If the IME (soft
+keyboard) is visible, the popup does not overlap the IME it until the user touches the
+menu.</p></li>
     
     <li>{@link android.widget.SearchView}
-    <p>Provides a search box that works in conjunction with a search provider (in the same manner as
-    the traditional <a href="{@docRoot}guide/topics/search/search-dialog.html">search dialog</a>).
-It
-    also displays recent query suggestions or custom suggestions as configured by the search
-    provider. This widget is particularly useful for offering search in the Action Bar.</p></li>
+    <p>Provides a search box that works in conjunction with the Search Manager (in the same manner
+as the traditional <a href="{@docRoot}guide/topics/search/search-dialog.html">search dialog</a>). It
+can also display recent query suggestions or custom suggestions as configured by the search
+provider. This widget is particularly useful for offering search in the <a
+href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a>.</p></li>
     
     <li>{@link android.widget.StackView}
-    <p>A view that displays its children in a 3D stack and allows users to discretely swipe through
-  the
-    children.</p></li>
+    <p>A view that displays its children in a 3D stack and allows users to swipe through
+  views like a rolodex.</p></li>
     
     </ul>
   </li>
@@ -470,13 +567,6 @@
 
 
 
-
-<!--
-<h3>WebKit</h3>
-<h3>JSON (utilities)</h3>
-    -->
-
-
 <h3>Graphics</h3>
 
 <ul>
@@ -519,7 +609,10 @@
 <p>Renderscript is a runtime 3D framework that provides both an API for building 3D scenes as well
 as a special, platform-independent shader language for maximum performance. Using Renderscript, you
 can accelerate graphics operations and data processing. Renderscript is an ideal way to create
-high-performance 3D effects for applications, wallpapers, carousels, and more.</p></li>
+high-performance 3D effects for applications, wallpapers, carousels, and more.</p>
+<p>For more information, see the <a
+href="{@docRoot}guide/topics/graphics/renderscript.html">3D Rendering and Computation with
+Renderscript</a> documentation.</p></li>
 </ul>
 
 
@@ -548,7 +641,9 @@
     
 <p>Applications can now pass an M3U playlist URL to the media framework to begin an HTTP Live
 streaming session. The media framework supports most of the HTTP Live streaming specification,
-including adaptive bit rate.</p></li>
+including adaptive bit rate. See the <a
+href="{@docRoot}guide/appendix/media-formats.html">Supported Media Formats</a> document for
+more information.</p></li>
 
   <li><b>EXIF data</b>
     
@@ -599,6 +694,301 @@
 
 
 
+<h3>Keyboard support</h3>
+
+<ul>
+<li>Support for Control, Meta, Caps Lock, Num Lock and Scroll Lock modifiers. For more information,
+see {@link android.view.KeyEvent#META_CTRL_ON} and related fields.</li>
+
+<li>Support for full desktop-style keyboards, including support for keys such as Escape, Home, End,
+Delete and others. You can determine whether key events are coming from a full keyboard by
+querying {@link android.view.KeyCharacterMap#getKeyboardType()} and checking for {@link
+android.view.KeyCharacterMap#FULL KeyCharacterMap.FULL}</li>
+
+<li>{@link android.widget.TextView} now supports keyboard-based cut, copy, paste, and select-all,
+using the key combinations Ctrl+X, Ctrl+C, Ctrl+V, and Ctrl+A.  It also supports PageUp/PageDown,
+Home/End, and keyboard-based text selection.</li>
+
+<li>{@link android.view.KeyEvent} adds several new methods to make it easier to check the key
+modifier state correctly and consistently. See {@link android.view.KeyEvent#hasModifiers(int)},
+{@link android.view.KeyEvent#hasNoModifiers()},
+{@link android.view.KeyEvent#metaStateHasModifiers(int,int) metaStateHasModifiers()},
+{@link android.view.KeyEvent#metaStateHasNoModifiers(int) metaStateHasNoModifiers()}.</li>
+
+<li>Applications can implement custom keyboard shortcuts by subclassing {@link
+android.app.Activity}, {@link android.app.Dialog}, or {@link android.view.View} and implementing
+{@link android.app.Activity#onKeyShortcut onKeyShortcut()}.  The framework calls this method
+whenever a key is combined with Ctrl key.  When creating an <a
+href="{@docRoot}guide/topics/ui/menus.html#options-menu">Options Menu</a>, you can register keyboard
+shortcuts by setting either the {@code android:alphabeticShortcut} or {@code
+android:numericShortcut} attribute for each <a
+href="{@docRoot}guide/topics/resources/menu-resource.html#item-element">{@code &lt;item&gt;}</a>
+element (or with {@link android.view.MenuItem#setShortcut setShortcut()}).</li>
+
+<li>Android 3.0 includes a new "virtual keyboard" device with the id {@link
+android.view.KeyCharacterMap#VIRTUAL_KEYBOARD KeyCharacterMap.VIRTUAL_KEYBOARD}. The virtual
+keyboard has a desktop-style US key map which is useful for synthesizing key events for testing
+input.</li>
+
+</ul>
+
+
+
+
+<h3>Split touch events</h3>
+
+<p>Previously, only a single view could accept touch events at one time. Android 3.0
+adds support for splitting touch events across views and even windows, so different views can accept
+simultaneous touch events.</p>
+
+<p>Split touch events is enabled by default when an application targets
+Android 3.0. That is, when the application has set either the <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code android:minSdkVersion}</a>
+or <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+android:targetSdkVersion}</a> attribute's value to {@code "11"}.</p>
+
+<p>However, the following properties allow you to disable split touch events across views inside
+specific view groups and across windows.</p>
+
+<ul>
+<li>The {@link android.R.attr#splitMotionEvents android:splitMotionEvents} attribute for view groups
+allows you to disable split touch events that occur between child views in a layout. For example:
+<pre>
+&lt;LinearLayout android:splitMotionEvents="false" ... >
+    ...
+&lt;/LinearLayout>
+</pre>
+<p>This way, child views in the linear layout cannot split touch events&mdash;only one view can
+receive touch events at a time.</p>
+</li>
+
+<li>The {@link android.R.attr#windowEnableSplitTouch android:windowEnableSplitTouch} style property
+allows you to disable split touch events across windows, by applying it to a theme for the activity
+or entire application. For example:
+<pre>
+&lt;style name="NoSplitMotionEvents" parent="android:Theme.Holo">
+    &lt;item name="android:windowEnableSplitTouch">false&lt;/item>
+    ...
+&lt;/style>
+</pre>
+<p>When this theme is applied to an <a
+href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a> or <a
+href="{@docRoot}guide/topics/manifest/application-element.html">{@code &lt;application&gt;}</a>,
+only touch events within the current activity window are accepted. For example, by disabling split
+touch events across windows, the system bar cannot receive touch events at the same time as the
+activity. This does <em>not</em> affect whether views inside the activity can split touch
+events&mdash;by default, the activity can still split touch events across views.</p>
+
+<p>For more information about creating a theme, read <a
+href="{@docRoot}guide/topics/ui/themes.html">Applying Styles and Themes</a>.</p>
+</li>
+</ul>
+
+
+
+<h3>WebKit</h3>
+
+<ul>
+  <li>New {@link android.webkit.WebViewFragment} class to create a fragment composed of a
+{@link android.webkit.WebView}.</li>
+  <li>New {@link android.webkit.WebSettings} methods:
+    <ul>
+      <li>{@link
+android.webkit.WebSettings#setDisplayZoomControls setDisplayZoomControls()} allows you to hide
+the on-screen zoom controls while still allowing the user to zoom with finger gestures ({@link
+android.webkit.WebSettings#setBuiltInZoomControls setBuiltInZoomControls()} must be set
+{@code true}).</li>
+      <li>New {@link android.webkit.WebSettings} method, {@link
+android.webkit.WebSettings#setEnableSmoothTransition setEnableSmoothTransition()}, allows you
+to enable smooth transitions when panning and zooming. When enabled, WebView will choose a solution
+to maximize the performance (for example, the WebView's content may not update during the
+transition).</li>
+    </ul>
+  <li>New {@link android.webkit.WebView} methods:
+    <ul>
+      <li>{@link android.webkit.WebView#onPause onPause()} callback, to pause any processing
+associated with the WebView when it becomes hidden. This is useful to reduce unnecessary CPU or
+network traffic when the WebView is not in the foreground.</li>
+      <li>{@link android.webkit.WebView#onResume onResume()} callback, to resume processing
+associated with the WebView, which was paused during {@link android.webkit.WebView#onPause
+onPause()}.</li>
+      <li>{@link android.webkit.WebView#saveWebArchive saveWebArchive()} allows you to save the
+current view as a web archive on the device.</li>
+      <li>{@link android.webkit.WebView#showFindDialog showFindDialog()} initiates a text search in
+the current view.</li>
+    </ul>
+  </li>
+</ul>
+
+
+
+<h3>Browser</h3>
+
+<p>The Browser application adds the following features to support web applications:</p>
+
+<ul>
+  <li><b>Media capture</b>
+    <p>As defined by the <a href="http://dev.w3.org/2009/dap/camera/">HTML Media Capture</a>
+specification, the Browser allows web applications to access audio, image and video capture
+capabilities of the device. For example, the following HTML provides an input for the user to
+capture a photo to upload:</p>
+<pre>
+&lt;input type="file" accept="image/*;capture=camera" />
+</pre>
+<p>Or by excluding the {@code capture=camera} parameter, the user can choose to either capture a
+new image with the camera or select one from the device (such as from the Gallery application).</p>
+  </li>
+
+  <li><b>Device Orientation</b>
+    <p>As defined by the <a
+href="http://dev.w3.org/geo/api/spec-source-orientation.html">Device Orientation Event</a>
+specification, the Browser allows web applications to listen to DOM events that provide information
+about the physical orientation and motion of the device.</p>
+    <p>The device orientation is expressed with the x, y, and z axes, in degrees and motion is
+expressed with acceleration and rotation rate data. A web page can register for orientation
+events by calling {@code window.addEventListener} with event type {@code "deviceorientation"}
+and register for motion events by registering the {@code "devicemotion"} event type.</p>
+  </li>
+  
+  <li><b>CSS 3D Transforms</b>
+    <p>As defined by the <a href="http://www.w3.org/TR/css3-3d-transforms/">CSS 3D Transform
+Module</a> specification, the Browser allows elements rendered by CSS to be transformed in three
+dimensions.</p>
+  </li>
+</ul>
+
+
+
+<h3>JSON utilities</h3>
+
+<p>New classes, {@link android.util.JsonReader} and {@link android.util.JsonWriter}, help you
+read and write JSON streams. The new APIs compliment the {@link org.json} classes which manipulate a
+document in memory.</p>
+
+<p>You can create an instance of {@link android.util.JsonReader} by calling
+its constructor method and passing the {@link java.io.InputStreamReader} that feeds the JSON string.
+Then begin reading an object by calling {@link android.util.JsonReader#beginObject()}, read a
+key name with {@link android.util.JsonReader#nextName()}, read the value using methods
+respective to the type, such as {@link android.util.JsonReader#nextString()} and {@link
+android.util.JsonReader#nextInt()}, and continue doing so while {@link
+android.util.JsonReader#hasNext()} is true.</p>
+
+<p>You can create an instance of {@link android.util.JsonWriter} by calling its constructor and
+passing the appropriate {@link java.io.OutputStreamWriter}. Then write the JSON data in a manner
+similar to the reader, using {@link android.util.JsonWriter#name name()} to add a property name
+and an appropriate {@link android.util.JsonWriter#value value()} method to add the respective
+value.</p>
+
+<p>These classes are strict by default. The {@link android.util.JsonReader#setLenient setLenient()}
+method in each class configures them to be more liberal in what they accept. This lenient
+parse mode is also compatible with the {@link org.json}'s default parser.</p>
+
+
+
+
+<h3>New feature constants</h3>
+
+<p>The <a
+href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code &lt;uses-feature&gt;}</a> 
+manfest element should be used to inform external entities (such as Android Market) of the set of
+hardware and software features on which your application depends. In this release, Android adds the
+following new constants that applications can declare with this element:</p>
+
+<ul>
+  <li>{@link android.content.pm.PackageManager#FEATURE_FAKETOUCH "android.hardware.faketouch"}
+    <p>When declared, this indicates that the application is compatible with a device that offers an
+emulated touchscreen (or better). A device that offers an emulated touchscreen provides a user input
+system that can emulate a subset of touchscreen
+capabilities. An example of such an input system is a mouse or remote control that drives an
+on-screen cursor. Such input systems support basic touch events like click down, click up, and drag.
+However, more complicated input types (such as gestures, flings, etc.) may be more difficult or
+impossible on faketouch devices (and multitouch gestures are definitely not possible).</p>
+    <p>If your application does <em>not</em> require complicated gestures and you do
+<em>not</em> want your application filtered from devices with an emulated touchscreen, you
+should declare {@link
+android.content.pm.PackageManager#FEATURE_FAKETOUCH "android.hardware.faketouch"} with a <a
+href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code &lt;uses-feature&gt;}</a>
+element. This way, your application will be available to the greatest number of device types,
+including those that provide only an emulated touchscreen input.</p>
+    <p>All devices that include a touchscreen also support {@link
+android.content.pm.PackageManager#FEATURE_FAKETOUCH "android.hardware.faketouch"}, because
+touchscreen capabilities are a superset of faketouch capabilities. Thus, unless you actually require
+a touchscreen, you should add a <a
+href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code &lt;uses-feature&gt;}</a>
+element for faketouch.</p>
+  </li>
+</ul>
+
+
+
+
+<h3>New permissions</h3>
+
+<ul>
+  <li>{@link android.Manifest.permission#BIND_REMOTEVIEWS
+"android.permission.BIND_REMOTEVIEWS"}
+  <p>This must be declared as a required permission in the <a
+href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a> manifest
+element for an implementation of {@link android.widget.RemoteViewsService}. For example, when
+creating an App Widget that uses {@link android.widget.RemoteViewsService} to populate a
+collection view, the manifest entry may look like this:</p>
+<pre>
+&lt;service android:name=".widget.WidgetService"
+    android:exported="false"
+    android:permission="android.permission.BIND_REMOTEVIEWS" />
+</pre>
+</ul>
+
+
+
+<h3>New platform technologies</h3>
+
+<ul>
+<li><strong>Storage</strong>
+  <ul>
+  <li>ext4 file system support to enable onboard eMMC storage.</li>
+  <li>FUSE file system to support MTP devices.</li>
+  <li>USB host mode support to support keyboards and USB hubs.</li>
+  <li>Support for MTP/PTP </li>
+  </ul>
+</li>
+
+<li><strong>Linux Kernel</strong>
+  <ul>
+  <li>Upgraded to 2.6.36</li>
+  </ul>
+</li>
+
+<li><strong>Dalvik VM</strong>
+  <ul>
+  <li>New code to support and optimize for SMP</li>
+  <li>Various improvements to the JIT infrastructure</li>
+  <li>Garbage collector improvements:
+    <ul>
+    <li>Tuned for SMP</li>
+    <li>Support for larger heap sizes</li>
+    <li>Unified handling for bitmaps and byte buffers</li>
+    </ul>
+  </li>
+  </ul>
+</li>
+
+<li><strong>Dalvik Core Libraries</strong>
+  <ul>
+  <li>New, much faster implementation of NIO (modern I/O library)</li>
+  <li>Improved exception messages</li>
+  <li>Correctness and performance fixes throughout</li>
+  </ul>
+</li>
+</ul>
+
+
+
+<h3 id="api-diff">API differences report</h3>
+
+<p>For a detailed view of all API changes in Android {@sdkPlatformVersion} (API Level
+{@sdkPlatformApiLevel}), see the <a
+href="{@docRoot}sdk/api_diff/{@sdkPlatformApiLevel}/changes.html">API Differences Report</a>.</p>
 
 
 
@@ -606,21 +996,25 @@
 
 <h2 id="api-level">API Level</h2>
 
-<p>The Android 3.0 platform delivers an updated version of
-the framework API. Because this is a preview of the Android 3.0 API, it uses a provisional API
-level of "Honeycomb", instead of an integer identifier, which will be provided when the final SDK
-is made available and all APIs are final.</p>
+<p>The Android {@sdkPlatformVersion} platform delivers an updated version of
+the framework API. The Android {@sdkPlatformVersion} API
+is assigned an integer identifier &mdash;
+<strong>{@sdkPlatformApiLevel}</strong> &mdash; that is
+stored in the system itself. This identifier, called the "API Level", allows the
+system to correctly determine whether an application is compatible with
+the system, prior to installing the application. </p>
 
-<p>To use APIs introduced in Android 3.0 in your application, you need compile the application
-against the Android library that is provided in the Android 3.0 preview SDK platform and you must
-declare this API Level in your manifest as <code>android:minSdkVersion="Honeycomb"</code>, in the
-<code>&lt;uses-sdk&gt;</code> element in the application's manifest.</p>
+<p>To use APIs introduced in Android {@sdkPlatformVersion} in your application,
+you need compile the application against the Android library that is provided in
+the Android {@sdkPlatformVersion} SDK platform. Depending on your needs, you might 
+also need to add an <code>android:minSdkVersion="{@sdkPlatformApiLevel}"</code>
+attribute to the <code>&lt;uses-sdk&gt;</code> element in the application's
+manifest. If your application is designed to run only on Android 2.3 and higher,
+declaring the attribute prevents the application from being installed on earlier
+versions of the platform.</p>
 
-<p>For more information about using this provisional API Level and setting up your environment
-to use the preview SDK, please see the <a href="{@docRoot}sdk/preview/start.html">Getting
-Started</a> document.</p>
-
-
+<p>For more information about how to use API Level, see the <a
+href="{@docRoot}guide/appendix/api-levels.html">API Levels</a> document. </p>
 
 
 <h2 id="apps">Built-in Applications</h2>
@@ -632,6 +1026,7 @@
 <tr>
 <td style="border:0;padding-bottom:0;margin-bottom:0;">
 <ul>
+<li>API Demos</li>
 <li>Browser</li>
 <li>Calculator</li>
 <li>Camera</li>
@@ -646,11 +1041,14 @@
 <td style="border:0;padding-bottom:0;margin-bottom:0;padding-left:5em;">
 <ul>
 <li>Gallery</li>
+<li>Gestures Builder</li>
+<li>Messaging</li>
 <li>Music</li>
 <li>Search</li>
 <li>Settings</li>
-<li>Spare Parts (developer app)</li>
+<li>Spare Parts</li>
 <li>Speech Recorder</li>
+<li>Widget Preview</li>
 </ul>
 </td>
 </tr>
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index 499b31f..1b4a336 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -3,7 +3,7 @@
 
 sdk.win_installer=installer_r09-windows.exe
 sdk.win_installer_bytes=32828818
-sdk.win_installer_checksum=a0185701ac0d635a4fbf8169ac949a3c5b3d31e0 
+sdk.win_installer_checksum=ef92e643731f820360e036eb11658656
 
 sdk.win_download=android-sdk_r09-windows.zip
 sdk.win_bytes=32779808
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index 2ba8076..1b94b2c 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -40,25 +40,15 @@
   if:sdk.preview ?>
   <li><h2>Android 3.0 Preview SDK</h2>
     <ul>
-      <li><a href="<?cs var:toroot ?>sdk/preview/start.html">Getting Started</a> <span class="new">new!</span></li>
-      <li class="toggle-list">
-        <div><a href="<?cs var:toroot ?>sdk/android-3.0.html">
-        <span class="en">Android 3.0 Platform</span></a> <span class="new">new!</span></div>
-        <ul>
-          <li><a href="<?cs var:toroot ?>sdk/api_diff/honeycomb/changes.html">API Differences Report
-&raquo;</a></li>
-        </ul>
-      </li>
+      <li><a href="<?cs var:toroot ?>sdk/preview/start.html">Getting Started</a> <span
+class="new">new!</span></li>
     </ul>
   </li><?cs
   /if ?>
   <?cs
   if:sdk.preview ?>
-  <li><h2>Android 3.0 Preview</h2>
+  <li><h2>Android x.x Preview</h2>
     <ul>
-      <li><a href="<?cs var:toroot ?>sdk/android-3.0-highlights.html">Platform Highlights</a> <span
-class="new">new!</span></li>
-      <li><a href="<?cs var:toroot ?>sdk/preview/index.html">SDK</a> <span class="new">new!</span></li>
     </ul>
   </li><?cs
   /if ?>
@@ -87,18 +77,19 @@
     </ul>
     <ul>
       <li class="toggle-list">
-      <div><a href="<?cs var:toroot ?>sdk/android-2.3.3.html">
-      <span class="en">Android 2.3.3 Platform</span></a>  <span class="new">new!</span></div>
+        <div><a href="<?cs var:toroot ?>sdk/android-3.0.html">
+        <span class="en">Android 3.0 Platform</span></a> <span class="new">new!</span></div>
         <ul>
-          <li><a href="<?cs var:toroot ?>sdk/api_diff/10/changes.html">API Differences Report &raquo;</a></li> 
+          <li><a href="<?cs var:toroot ?>sdk/android-3.0-highlights.html">Platform Highlights</a></li> 
+          <li><a href="<?cs var:toroot ?>sdk/api_diff/11/changes.html">API Differences Report &raquo;</a></li>
         </ul>
       </li>
       <li class="toggle-list">
-      <div><a href="<?cs var:toroot ?>sdk/android-2.3.html">
-      <span class="en">Android 2.3 Platform</span></a></div>
+      <div><a href="<?cs var:toroot ?>sdk/android-2.3.3.html">
+      <span class="en">Android 2.3.3 Platform</span></a> <span class="new">new!</span></div>
         <ul>
           <li><a href="<?cs var:toroot ?>sdk/android-2.3-highlights.html">Platform Highlights</a></li> 
-          <li><a href="<?cs var:toroot ?>sdk/api_diff/9/changes.html">API Differences Report &raquo;</a></li> 
+          <li><a href="<?cs var:toroot ?>sdk/api_diff/10/changes.html">API Differences Report &raquo;</a></li> 
         </ul>
       </li>
       <li><a href="<?cs var:toroot ?>sdk/android-2.2.html">Android 2.2 Platform</a></li>
@@ -108,6 +99,13 @@
       <li class="toggle-list">
         <div><a href="#" onclick="toggle(this.parentNode.parentNode,true); return false;">Older Platforms</a></div>
         <ul>
+          <li class="toggle-list">
+          <div><a href="<?cs var:toroot ?>sdk/android-2.3.html">
+          <span class="en">Android 2.3 Platform</span></a></div>
+            <ul>
+              <li><a href="<?cs var:toroot ?>sdk/api_diff/9/changes.html">API Differences Report &raquo;</a></li> 
+            </ul>
+          </li>
           <li><a href="<?cs var:toroot ?>sdk/android-2.0.1.html">Android 2.0.1 Platform</a></li>
           <li><a href="<?cs var:toroot ?>sdk/android-2.0.html">Android 2.0 Platform</a></li>
           <li><a href="<?cs var:toroot ?>sdk/android-1.1.html">Android 1.1 Platform</a></li>
@@ -115,7 +113,7 @@
       </li>
     </ul>
     <ul>
-      <li><a href="<?cs var:toroot ?>sdk/tools-notes.html">SDK Tools, r9</a> <span class="new">new!</span></li>
+      <li><a href="<?cs var:toroot ?>sdk/tools-notes.html">SDK Tools, r10</a> <span class="new">new!</span></li>
       <li><a href="<?cs var:toroot ?>sdk/win-usb.html">Google USB Driver, r4</a></li>
     </ul>
   </li>
@@ -131,7 +129,7 @@
       <span style="display:none" class="zh-TW"></span>
       </h2>
     <ul>
-      <li><a href="<?cs var:toroot ?>sdk/eclipse-adt.html">ADT 9.0.0
+      <li><a href="<?cs var:toroot ?>sdk/eclipse-adt.html">ADT 10.0.0
       <span style="display:none" class="de"></span>
       <span style="display:none" class="es"></span>
       <span style="display:none" class="fr"></span>
@@ -153,7 +151,7 @@
       <span style="display:none" class="zh-TW"></span>
     </h2>
     <ul>
-      <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r5b</a>
+      <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r6</a>
         <span class="new">new!</span></li>
       <li><a href="<?cs var:toroot ?>sdk/ndk/overview.html">What is the NDK?</a></li>
     </ul>
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index bd903da..b2f4379 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -245,25 +245,80 @@
         }
     }
 
+    /**
+     * Possible bitmap configurations. A bitmap configuration describes
+     * how pixels are stored. This affects the quality (color depth) as
+     * well as the ability to display transparent/translucent colors.
+     */
     public enum Config {
         // these native values must match up with the enum in SkBitmap.h
+
+        /**
+         * Each pixel is stored as a single translucency (alpha) channel.
+         * This is very useful to efficiently store masks for instance.
+         * No color information is stored.
+         * With this configuration, each pixel requires 1 byte of memory.
+         */
         ALPHA_8     (2),
+
+        /**
+         * Each pixel is stored on 2 bytes and only the RGB channels are
+         * encoded: red is stored with 5 bits of precision (32 possible
+         * values), green is stored with 6 bits of precision (64 possible
+         * values) and blue is stored with 5 bits of precision.
+         * 
+         * This configuration can produce slight visual artifacts depending
+         * on the configuration of the source. For instance, without
+         * dithering, the result might show a greenish tint. To get better
+         * results dithering should be applied.
+         * 
+         * This configuration may be useful when using opaque bitmaps
+         * that do not require high color fidelity.
+         */
         RGB_565     (4),
+
+        /**
+         * Each pixel is stored on 2 bytes. The three RGB color channels
+         * and the alpha channel (translucency) are stored with a 4 bits
+         * precision (16 possible values.)
+         * 
+         * This configuration is mostly useful if the application needs
+         * to store translucency information but also needs to save
+         * memory.
+         * 
+         * It is recommended to use {@link #ARGB_8888} instead of this
+         * configuration.
+         * 
+         * @deprecated Because of the poor quality of this configuration,
+         *             it is advised to use {@link #ARGB_8888} instead.
+         */
+        @Deprecated
         ARGB_4444   (5),
+
+        /**
+         * Each pixel is stored on 4 bytes. Each channel (RGB and alpha
+         * for translucency) is stored with 8 bits of precision (256
+         * possible values.)
+         * 
+         * This configuration is very flexible and offers the best
+         * quality. It should be used whenever possible.
+         */
         ARGB_8888   (6);
 
-        Config(int ni) {
-            this.nativeInt = ni;
-        }
         final int nativeInt;
 
-        /* package */ static Config nativeToConfig(int ni) {
-            return sConfigs[ni];
-        }
-
+        @SuppressWarnings({"deprecation"})
         private static Config sConfigs[] = {
             null, null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888
         };
+        
+        Config(int ni) {
+            this.nativeInt = ni;
+        }
+
+        static Config nativeToConfig(int ni) {
+            return sConfigs[ni];
+        }
     }
 
     /**
@@ -473,6 +528,7 @@
                 case ALPHA_8:
                     newConfig = Config.ALPHA_8;
                     break;
+                //noinspection deprecation
                 case ARGB_4444:
                 case ARGB_8888:
                 default:
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index e368848..cb08023 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -399,6 +399,9 @@
         if (mConnectingDataSource != NULL) {
             LOGI("interrupting the connection process");
             mConnectingDataSource->disconnect();
+        } else if (mConnectingRTSPController != NULL) {
+            LOGI("interrupting the connection process");
+            mConnectingRTSPController->disconnect();
         }
 
         if (mFlags & PREPARING_CONNECTED) {
@@ -409,7 +412,7 @@
     }
 
     if (mFlags & PREPARING) {
-        LOGI("waiting until preparation is completes.");
+        LOGI("waiting until preparation is completed.");
     }
 
     while (mFlags & PREPARING) {
@@ -1633,7 +1636,13 @@
             mLooper->start();
         }
         mRTSPController = new ARTSPController(mLooper);
+        mConnectingRTSPController = mRTSPController;
+
+        mLock.unlock();
         status_t err = mRTSPController->connect(mUri.string());
+        mLock.lock();
+
+        mConnectingRTSPController.clear();
 
         LOGI("ARTSPController::connect returned %d", err);
 
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 797e5ca..98b8c05 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -205,6 +205,7 @@
 
     sp<ALooper> mLooper;
     sp<ARTSPController> mRTSPController;
+    sp<ARTSPController> mConnectingRTSPController;
 
     sp<LiveSession> mLiveSession;
 
diff --git a/media/libstagefright/rtsp/ARTSPController.cpp b/media/libstagefright/rtsp/ARTSPController.cpp
index a7563ff..1328d2e 100644
--- a/media/libstagefright/rtsp/ARTSPController.cpp
+++ b/media/libstagefright/rtsp/ARTSPController.cpp
@@ -69,7 +69,14 @@
 void ARTSPController::disconnect() {
     Mutex::Autolock autoLock(mLock);
 
-    if (mState != CONNECTED) {
+    if (mState == CONNECTING) {
+        mState = DISCONNECTED;
+        mConnectionResult = ERROR_IO;
+        mCondition.broadcast();
+
+        mHandler.clear();
+        return;
+    } else if (mState != CONNECTED) {
         return;
     }
 
diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp
index d3f2cb4..baf99e5 100644
--- a/media/mtp/MtpPacket.cpp
+++ b/media/mtp/MtpPacket.cpp
@@ -153,12 +153,13 @@
 
 #ifdef MTP_HOST
 int MtpPacket::transfer(struct usb_request* request) {
-    if (usb_request_queue(request)) {
-        LOGE("usb_endpoint_queue failed, errno: %d", errno);
-        return -1;
-    }
-    request = usb_request_wait(request->dev);
-    return (request ? request->actual_length : -1);
+    int result = usb_device_bulk_transfer(request->dev,
+                            request->endpoint,
+                            request->buffer,
+                            request->buffer_length,
+                            0);
+    request->actual_length = result;
+    return result;
 }
 #endif
 
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar.xml b/packages/SystemUI/res/layout-xlarge/status_bar.xml
index b97b9ca..6c173c9 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar.xml
@@ -91,15 +91,6 @@
         </RelativeLayout>
     </FrameLayout>
 
-    <view
-        class="com.android.systemui.statusbar.tablet.ShirtPocket$DropZone"
-        android:id="@+id/drop_target"
-        android:layout_width="512dp"
-        android:layout_height="@*android:dimen/status_bar_height"
-        android:background="@drawable/pocket_drag_bg"
-        android:layout_gravity="right"
-        />
-
     <FrameLayout
         android:id="@+id/bar_shadow_holder"
         android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_notification_area.xml b/packages/SystemUI/res/layout-xlarge/status_bar_notification_area.xml
index c25a51e..f53b29e 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_notification_area.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_notification_area.xml
@@ -42,14 +42,6 @@
             android:visibility="gone"
             />
         
-        <com.android.systemui.statusbar.tablet.ShirtPocket
-            android:id="@+id/shirt_pocket"
-            android:layout_width="@*android:dimen/status_bar_height"
-            android:layout_height="@*android:dimen/status_bar_height"
-            android:background="#FFFF0000"
-            android:visibility="gone"
-            />
-
         <com.android.systemui.statusbar.tablet.NotificationIconArea
             android:id="@+id/notificationIcons"
             android:layout_width="wrap_content"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index bb0d3e1..7a13fde 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -392,11 +392,6 @@
         // for redirecting errant bar taps to the IME
         mFakeSpaceBar = sb.findViewById(R.id.fake_space_bar);
 
-        // drag and drop pocket
-        ShirtPocket p = (ShirtPocket) sb.findViewById(R.id.shirt_pocket);
-        ShirtPocket.DropZone z = (ShirtPocket.DropZone) sb.findViewById(R.id.drop_target);
-        z.setPocket(p);
-
         // "shadows" of the status bar features, for lights-out mode
         mShadow = sb.findViewById(R.id.bar_shadow);
         mShadow.setOnTouchListener(
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index bc19683..d25b9c8 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -596,13 +596,12 @@
         if (imi == null && mCurMethodId != null) {
             imi = mMethodMap.get(mCurMethodId);
         }
-        final List<InputMethodSubtype> enabledSubtypes =
+        List<InputMethodSubtype> enabledSubtypes =
                 mSettings.getEnabledInputMethodSubtypeListLocked(imi);
-        if (!allowsImplicitlySelectedSubtypes || enabledSubtypes.size() > 0) {
-            return enabledSubtypes;
-        } else {
-            return getApplicableSubtypesLocked(mRes, getSubtypes(imi));
+        if (allowsImplicitlySelectedSubtypes && enabledSubtypes.isEmpty()) {
+            enabledSubtypes = getApplicableSubtypesLocked(mRes, getSubtypes(imi));
         }
+        return InputMethodSubtype.sort(mContext, 0, imi, enabledSubtypes);
     }
 
     public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(InputMethodInfo imi,
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index ff5f989..f24f96c 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -90,7 +90,7 @@
     private BroadcastReceiver mStateReceiver;
 
     private static final String USB_NEAR_IFACE_ADDR      = "192.168.42.129";
-    private static final String USB_NETMASK              = "255.255.255.0";
+    private static final int USB_PREFIX_LENGTH        = 24;
 
     // USB is  192.168.42.1 and 255.255.255.0
     // Wifi is 192.168.43.1 and 255.255.255.0
@@ -568,8 +568,7 @@
                     ifcg = service.getInterfaceConfig(iface);
                     if (ifcg != null) {
                         InetAddress addr = InetAddress.getByName(USB_NEAR_IFACE_ADDR);
-                        InetAddress mask = InetAddress.getByName(USB_NETMASK);
-                        ifcg.addr = new LinkAddress(addr, mask);
+                        ifcg.addr = new LinkAddress(addr, USB_PREFIX_LENGTH);
                         if (enabled) {
                             ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up");
                         } else {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
index ff2b91e..30da2ff 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
@@ -294,7 +294,8 @@
             return null;
         }
 
-        String value = mResourceData[index].getValue();
+        ResourceValue resValue = mResourceData[index];
+        String value = resValue.getValue();
 
         if (value == null) {
             return null;
@@ -308,11 +309,13 @@
                 parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
                 parser.setInput(new FileReader(f));
 
-                ColorStateList colorStateList = ColorStateList.createFromXml(
-                        mContext.getResources(),
-                        // FIXME: we need to know if this resource is platform or not
-                        new BridgeXmlBlockParser(parser, mContext, false));
-                return colorStateList;
+                BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
+                        parser, mContext, resValue.isFramework());
+                try {
+                    return ColorStateList.createFromXml(mContext.getResources(), blockParser);
+                } finally {
+                    blockParser.ensurePopped();
+                }
             } catch (XmlPullParserException e) {
                 Bridge.getLog().error(LayoutLog.TAG_BROKEN,
                         "Failed to configure parser for " + value, e, null /*data*/);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java
index 38800da..2f54ae6 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java
@@ -45,6 +45,8 @@
     private boolean mStarted = false;
     private int mEventType = START_DOCUMENT;
 
+    private boolean mPopped = true; // default to true in case it's not pushed.
+
     /**
      * Builds a {@link BridgeXmlBlockParser}.
      * @param parser The XmlPullParser to get the content from.
@@ -59,6 +61,7 @@
 
         if (mContext != null) {
             mContext.pushParser(this);
+            mPopped = false;
         }
     }
 
@@ -82,6 +85,13 @@
         return null;
     }
 
+    public void ensurePopped() {
+        if (mContext != null && mPopped == false) {
+            mContext.popParser();
+            mPopped = true;
+        }
+    }
+
     // ------- XmlResourceParser implementation
 
     public void setFeature(String name, boolean state)
@@ -249,9 +259,9 @@
         }
         int ev = mParser.next();
 
-        if (ev == END_TAG && mParser.getDepth() == 1 && mContext != null) {
+        if (ev == END_TAG && mParser.getDepth() == 1) {
             // done with parser remove it from the context stack.
-            mContext.popParser();
+            ensurePopped();
         }
         mEventType = ev;
         return ev;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
index 771d89a..0c4b0d3 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
@@ -76,9 +76,13 @@
                 "UTF8");
 
         BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser(
-                parser, (BridgeContext) context, false);
+                parser, (BridgeContext) context, false /*platformFile*/);
 
-        inflater.inflate(bridgeParser, this, true);
+        try {
+            inflater.inflate(bridgeParser, this, true);
+        } finally {
+            bridgeParser.ensurePopped();
+        }
     }
 
     private InputStream getIcon(String iconName, Density[] densityInOut, String[] pathOut,
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 136b205..fedd789f 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -182,8 +182,8 @@
         context.setBridgeInflater(mInflater);
         mInflater.setFactory2(context);
 
-        mBlockParser = new BridgeXmlBlockParser(params.getLayoutDescription(),
-                context, false /* platformResourceFlag */);
+        mBlockParser = new BridgeXmlBlockParser(
+                params.getLayoutDescription(), context, false /* platformResourceFlag */);
 
         return SUCCESS.createResult();
     }
@@ -562,13 +562,14 @@
         BridgeContext context = getContext();
 
         // create a block parser for the XML
-        BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(childXml, context,
-                false /* platformResourceFlag */);
+        BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
+                childXml, context, false /* platformResourceFlag */);
 
         // inflate the child without adding it to the root since we want to control where it'll
         // get added. We do pass the parentView however to ensure that the layoutParams will
         // be created correctly.
         final View child = mInflater.inflate(blockParser, parentView, false /*attachToRoot*/);
+        blockParser.ensurePopped();
 
         invalidateRenderingSize();
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
index 19392a7..69f46e6 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
@@ -126,8 +126,13 @@
                     parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
                     parser.setInput(new FileReader(f));
 
-                    return ColorStateList.createFromXml(context.getResources(),
-                            new BridgeXmlBlockParser(parser, context, resValue.isFramework()));
+                    BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
+                            parser, context, resValue.isFramework());
+                    try {
+                        return ColorStateList.createFromXml(context.getResources(), blockParser);
+                    } finally {
+                        blockParser.ensurePopped();
+                    }
                 } catch (XmlPullParserException e) {
                     Bridge.getLog().error(LayoutLog.TAG_BROKEN,
                             "Failed to configure parser for " + value, e, null /*data*/);
@@ -164,8 +169,6 @@
      * @param context the current context
      */
     public static Drawable getDrawable(ResourceValue value, BridgeContext context) {
-        Drawable d = null;
-
         String stringValue = value.getValue();
         if (RenderResources.REFERENCE_NULL.equals(stringValue)) {
             return null;
@@ -205,9 +208,13 @@
                     parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
                     parser.setInput(new FileReader(f));
 
-                    d = Drawable.createFromXml(context.getResources(),
-                            new BridgeXmlBlockParser(parser, context, value.isFramework()));
-                    return d;
+                    BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
+                            parser, context, value.isFramework());
+                    try {
+                        return Drawable.createFromXml(context.getResources(), blockParser);
+                    } finally {
+                        blockParser.ensurePopped();
+                    }
                 } catch (Exception e) {
                     // this is an error and not warning since the file existence is checked before
                     // attempting to parse it.