Merge "Make sure EventHub reports added/removed devices immediately." into gingerbread
diff --git a/Android.mk b/Android.mk
index 6dc39eb..ab30c6e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -116,6 +116,14 @@
 	core/java/android/net/IConnectivityManager.aidl \
 	core/java/android/net/INetworkManagementEventObserver.aidl \
 	core/java/android/net/IThrottleManager.aidl \
+	core/java/android/nfc/ILlcpConnectionlessSocket.aidl \
+	core/java/android/nfc/ILlcpServiceSocket.aidl \
+	core/java/android/nfc/ILlcpSocket.aidl \
+	core/java/android/nfc/INdefTag.aidl \
+	core/java/android/nfc/INfcAdapter.aidl \
+	core/java/android/nfc/INfcTag.aidl \
+	core/java/android/nfc/IP2pInitiator.aidl \
+	core/java/android/nfc/IP2pTarget.aidl \
 	core/java/android/os/IHardwareService.aidl \
 	core/java/android/os/IMessenger.aidl \
 	core/java/android/os/INetworkManagementService.aidl \
@@ -159,14 +167,6 @@
 	core/java/com/android/internal/view/IInputMethodClient.aidl \
 	core/java/com/android/internal/view/IInputMethodManager.aidl \
 	core/java/com/android/internal/view/IInputMethodSession.aidl \
-	core/java/com/trustedlogic/trustednfc/android/ILlcpConnectionlessSocket.aidl \
-	core/java/com/trustedlogic/trustednfc/android/ILlcpServiceSocket.aidl \
-	core/java/com/trustedlogic/trustednfc/android/ILlcpSocket.aidl \
-	core/java/com/trustedlogic/trustednfc/android/INdefTag.aidl \
-	core/java/com/trustedlogic/trustednfc/android/INfcManager.aidl \
-	core/java/com/trustedlogic/trustednfc/android/INfcTag.aidl \
-	core/java/com/trustedlogic/trustednfc/android/IP2pInitiator.aidl \
-	core/java/com/trustedlogic/trustednfc/android/IP2pTarget.aidl \
 	location/java/android/location/IGeocodeProvider.aidl \
 	location/java/android/location/IGpsStatusListener.aidl \
 	location/java/android/location/IGpsStatusProvider.aidl \
@@ -249,6 +249,10 @@
 	frameworks/base/core/java/android/content/res/Configuration.aidl \
 	frameworks/base/core/java/android/appwidget/AppWidgetProviderInfo.aidl \
 	frameworks/base/core/java/android/net/Uri.aidl \
+	frameworks/base/core/java/android/nfc/NdefMessage.aidl \
+	frameworks/base/core/java/android/nfc/NdefRecord.aidl \
+	frameworks/base/core/java/android/nfc/Tag.aidl \
+	frameworks/base/core/java/android/nfc/NdefTag.aidl \
 	frameworks/base/core/java/android/os/Bundle.aidl \
 	frameworks/base/core/java/android/os/DropBoxManager.aidl \
 	frameworks/base/core/java/android/os/ParcelFileDescriptor.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 5618eaa..da1d46f 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -68,6 +68,8 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libreverbtest_intermediates)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/soundfx/)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/os/storage/*)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/trustedlogic)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/src/com/trustedlogic)
 
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/api/current.xml b/api/current.xml
index 5fd7a1b..0efc466 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -24649,6 +24649,17 @@
  visibility="public"
 >
 </field>
+<field name="COLUMN_MEDIAPROVIDER_URI"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;mediaprovider_uri&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="COLUMN_MEDIA_TYPE"
  type="java.lang.String"
  transient="false"
@@ -102984,6 +102995,33 @@
 </package>
 <package name="android.nfc"
 >
+<class name="FormatException"
+ extends="java.lang.Exception"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="FormatException"
+ type="android.nfc.FormatException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="FormatException"
+ type="android.nfc.FormatException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
 <class name="NdefMessage"
  extends="java.lang.Object"
  abstract="false"
@@ -103323,6 +103361,632 @@
 >
 </field>
 </class>
+<class name="NdefTag"
+ extends="android.nfc.Tag"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<method name="getNdefMessages"
+ return="android.nfc.NdefMessage[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getNdefMessages"
+ return="android.nfc.NdefMessage[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="java.lang.String">
+</parameter>
+</method>
+<method name="getNdefTargets"
+ return="java.lang.String[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TARGET_MIFARE_CLASSIC"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;type_mifare_classic&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TARGET_OTHER"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;other&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TARGET_TYPE_1"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;type_1&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TARGET_TYPE_2"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;type_2&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TARGET_TYPE_3"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;type_3&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TARGET_TYPE_4"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;type_4&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="NdefTagConnection"
+ extends="android.nfc.RawTagConnection"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getModeHint"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="makeReadOnly"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="readNdefMessages"
+ return="android.nfc.NdefMessage[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="FormatException" type="android.nfc.FormatException">
+</exception>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="writeNdefMessage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="android.nfc.NdefMessage">
+</parameter>
+<exception name="FormatException" type="android.nfc.FormatException">
+</exception>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<field name="NDEF_MODE_READ_ONCE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NDEF_MODE_READ_ONLY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NDEF_MODE_UNKNOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NDEF_MODE_WRITE_MANY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NDEF_MODE_WRITE_ONCE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="NfcAdapter"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="createNdefTagConnection"
+ return="android.nfc.NdefTagConnection"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="android.nfc.NdefTag">
+</parameter>
+</method>
+<method name="createNdefTagConnection"
+ return="android.nfc.NdefTagConnection"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="android.nfc.NdefTag">
+</parameter>
+<parameter name="target" type="java.lang.String">
+</parameter>
+</method>
+<method name="createRawTagConnection"
+ return="android.nfc.RawTagConnection"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+</method>
+<method name="createRawTagConnection"
+ return="android.nfc.RawTagConnection"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+<parameter name="target" type="java.lang.String">
+</parameter>
+</method>
+<method name="getDefaultAdapter"
+ return="android.nfc.NfcAdapter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getLocalNdefMessage"
+ return="android.nfc.NdefMessage"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isTagDiscoveryEnabled"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setLocalNdefMessage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="android.nfc.NdefMessage">
+</parameter>
+</method>
+<field name="ACTION_NDEF_TAG_DISCOVERED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.nfc.action.NDEF_TAG_DISCOVERED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_TAG_DISCOVERED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.nfc.action.TAG_DISCOVERED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_TAG"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.nfc.extra.TAG&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="RawTagConnection"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="close"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="connect"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="getTag"
+ return="android.nfc.Tag"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTagTarget"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isConnected"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="transceive"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="byte[]">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+</class>
+<class name="Tag"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getId"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getRawTargets"
+ return="java.lang.String[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dest" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TARGET_ISO_14443_3A"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;iso14443_3a&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TARGET_ISO_14443_3B"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;iso14443_3b&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TARGET_ISO_14443_3B_PRIME"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;iso14443_3b&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TARGET_ISO_14443_4"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;iso14443_4&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TARGET_ISO_15693"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;iso15693&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TARGET_JIS_X_6319_4"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;jis_x_6319_4&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TARGET_OTHER"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;other&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TARGET_TOPAZ"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;topaz&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 </package>
 <package name="android.opengl"
 >
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index c08f1fc..fda08f6 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -102,9 +102,6 @@
 import android.accounts.AccountManager;
 import android.accounts.IAccountManager;
 import android.app.admin.DevicePolicyManager;
-import com.trustedlogic.trustednfc.android.NfcManager;
-import com.trustedlogic.trustednfc.android.INfcManager;
-
 import com.android.internal.os.IDropBoxManagerService;
 
 import java.io.File;
@@ -173,7 +170,6 @@
     private static ThrottleManager sThrottleManager;
     private static WifiManager sWifiManager;
     private static LocationManager sLocationManager;
-    private static NfcManager sNfcManager;
     private static final HashMap<String, SharedPreferencesImpl> sSharedPrefs =
             new HashMap<String, SharedPreferencesImpl>();
 
@@ -972,8 +968,6 @@
             return getClipboardManager();
         } else if (WALLPAPER_SERVICE.equals(name)) {
             return getWallpaperManager();
-        } else if (NFC_SERVICE.equals(name)) {
-            return getNfcManager();
         } else if (DROPBOX_SERVICE.equals(name)) {
             return getDropBoxManager();
         } else if (DEVICE_POLICY_SERVICE.equals(name)) {
@@ -1209,21 +1203,6 @@
         return mDownloadManager;
     }
 
-    private NfcManager getNfcManager()
-    {
-        synchronized (sSync) {
-            if (sNfcManager == null) {
-                IBinder b = ServiceManager.getService(NFC_SERVICE);
-                if (b == null) {
-                    return null;
-                }
-                INfcManager service = INfcManager.Stub.asInterface(b);
-                sNfcManager = new NfcManager(service, mMainThread.getHandler());
-            }
-        }
-        return sNfcManager;
-    }
-
     @Override
     public int checkPermission(String permission, int pid, int uid) {
         if (permission == null) {
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index 00d8ae3..a25aa6f 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -28,7 +28,6 @@
 import android.os.ParcelFileDescriptor;
 import android.provider.BaseColumns;
 import android.provider.Downloads;
-import android.util.Log;
 import android.util.Pair;
 
 import java.io.File;
@@ -136,6 +135,12 @@
      */
     public final static String COLUMN_LAST_MODIFIED_TIMESTAMP = "last_modified_timestamp";
 
+    /**
+     * The URI to the corresponding entry in MediaProvider for this downloaded entry. It is
+     * used to delete the entries from MediaProvider database when it is deleted from the
+     * downloaded list.
+     */
+    public static final String COLUMN_MEDIAPROVIDER_URI = "mediaprovider_uri";
 
     /**
      * Value of {@link #COLUMN_STATUS} when the download is waiting to start.
@@ -266,6 +271,7 @@
     // this array must contain all public columns
     private static final String[] COLUMNS = new String[] {
         COLUMN_ID,
+        COLUMN_MEDIAPROVIDER_URI,
         COLUMN_TITLE,
         COLUMN_DESCRIPTION,
         COLUMN_URI,
@@ -281,6 +287,7 @@
     // columns to request from DownloadProvider
     private static final String[] UNDERLYING_COLUMNS = new String[] {
         Downloads.Impl._ID,
+        Downloads.Impl.COLUMN_MEDIAPROVIDER_URI,
         Downloads.COLUMN_TITLE,
         Downloads.COLUMN_DESCRIPTION,
         Downloads.COLUMN_URI,
@@ -677,6 +684,9 @@
                 selectionParts.add(Downloads.Impl.COLUMN_IS_VISIBLE_IN_DOWNLOADS_UI + " != '0'");
             }
 
+            // only return rows which are not marked 'deleted = 1'
+            selectionParts.add(Downloads.Impl.COLUMN_DELETED + " != '1'");
+
             String selection = joinStrings(" AND ", selectionParts);
             String orderDirection = (mOrderDirection == ORDER_ASCENDING ? "ASC" : "DESC");
             String orderBy = mOrderByColumn + " " + orderDirection;
@@ -743,6 +753,26 @@
     }
 
     /**
+     * Marks the specified download as 'to be deleted'. This is done when a completed download
+     * is to be removed but the row was stored without enough info to delete the corresponding
+     * metadata from Mediaprovider database. Actual cleanup of this row is done in DownloadService.
+     *
+     * @param ids the IDs of the downloads to be marked 'deleted'
+     * @return the number of downloads actually updated
+     * @hide
+     */
+    public int markRowDeleted(long... ids) {
+        if (ids == null || ids.length == 0) {
+            // called with nothing to remove!
+            throw new IllegalArgumentException("input param 'ids' can't be null");
+        }
+        ContentValues values = new ContentValues();
+        values.put(Downloads.Impl.COLUMN_DELETED, 1);
+        return mResolver.update(mBaseUri, values, getWhereClauseForIds(ids),
+                getWhereArgsForIds(ids));
+    }
+
+    /**
      * Cancel downloads and remove them from the download manager.  Each download will be stopped if
      * it was running, and it will no longer be accessible through the download manager.  If a file
      * was already downloaded to external storage, it will not be deleted.
@@ -950,6 +980,9 @@
             if (column.equals(COLUMN_MEDIA_TYPE)) {
                 return getUnderlyingString(Downloads.COLUMN_MIME_TYPE);
             }
+            if (column.equals(COLUMN_MEDIAPROVIDER_URI)) {
+                return getUnderlyingString(Downloads.Impl.COLUMN_MEDIAPROVIDER_URI);
+            }
 
             assert column.equals(COLUMN_LOCAL_URI);
             return getLocalUri();
diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
index df1d960..71aefbc 100644
--- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java
+++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
@@ -56,7 +56,7 @@
  */
 public final class BluetoothDeviceProfileState extends HierarchicalStateMachine {
     private static final String TAG = "BluetoothDeviceProfileState";
-    private static final boolean DBG = true; //STOPSHIP - Change to false
+    private static final boolean DBG = false;
 
     public static final int CONNECT_HFP_OUTGOING = 1;
     public static final int CONNECT_HFP_INCOMING = 2;
@@ -136,6 +136,10 @@
                 Message msg = new Message();
                 msg.what = AUTO_CONNECT_PROFILES;
                 sendMessageDelayed(msg, AUTO_CONNECT_DELAY);
+            } else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
+                // This is technically not needed, but we can get stuck sometimes.
+                // For example, if incoming A2DP fails, we are not informed by Bluez
+                sendMessage(TRANSITION_TO_STABLE);
             }
       }
     };
@@ -175,6 +179,7 @@
         filter.addAction(BluetoothA2dp.ACTION_SINK_STATE_CHANGED);
         filter.addAction(BluetoothHeadset.ACTION_STATE_CHANGED);
         filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
+        filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
 
         mContext.registerReceiver(mBroadcastReceiver, filter);
 
@@ -217,7 +222,7 @@
     private class BondedDevice extends HierarchicalState {
         @Override
         protected void enter() {
-            log("Entering ACL Connected state with: " + getCurrentMessage().what);
+            Log.i(TAG, "Entering ACL Connected state with: " + getCurrentMessage().what);
             Message m = new Message();
             m.copyFrom(getCurrentMessage());
             sendMessageAtFrontOfQueue(m);
@@ -295,14 +300,18 @@
 
         @Override
         protected void enter() {
-            log("Entering OutgoingHandsfree state with: " + getCurrentMessage().what);
+            Log.i(TAG, "Entering OutgoingHandsfree state with: " + getCurrentMessage().what);
             mCommand = getCurrentMessage().what;
             if (mCommand != CONNECT_HFP_OUTGOING &&
                 mCommand != DISCONNECT_HFP_OUTGOING) {
                 Log.e(TAG, "Error: OutgoingHandsfree state with command:" + mCommand);
             }
             mStatus = processCommand(mCommand);
-            if (!mStatus) sendMessage(TRANSITION_TO_STABLE);
+            if (!mStatus) {
+                sendMessage(TRANSITION_TO_STABLE);
+                mService.sendProfileStateMessage(BluetoothProfileState.HFP,
+                                                 BluetoothProfileState.TRANSITION_TO_STABLE);
+            }
         }
 
         @Override
@@ -386,14 +395,18 @@
 
         @Override
         protected void enter() {
-            log("Entering IncomingHandsfree state with: " + getCurrentMessage().what);
+            Log.i(TAG, "Entering IncomingHandsfree state with: " + getCurrentMessage().what);
             mCommand = getCurrentMessage().what;
             if (mCommand != CONNECT_HFP_INCOMING &&
                 mCommand != DISCONNECT_HFP_INCOMING) {
                 Log.e(TAG, "Error: IncomingHandsfree state with command:" + mCommand);
             }
             mStatus = processCommand(mCommand);
-            if (!mStatus) sendMessage(TRANSITION_TO_STABLE);
+            if (!mStatus) {
+                sendMessage(TRANSITION_TO_STABLE);
+                mService.sendProfileStateMessage(BluetoothProfileState.HFP,
+                                                 BluetoothProfileState.TRANSITION_TO_STABLE);
+            }
         }
 
         @Override
@@ -454,14 +467,18 @@
 
         @Override
         protected void enter() {
-            log("Entering OutgoingA2dp state with: " + getCurrentMessage().what);
+            Log.i(TAG, "Entering OutgoingA2dp state with: " + getCurrentMessage().what);
             mCommand = getCurrentMessage().what;
             if (mCommand != CONNECT_A2DP_OUTGOING &&
                 mCommand != DISCONNECT_A2DP_OUTGOING) {
                 Log.e(TAG, "Error: OutgoingA2DP state with command:" + mCommand);
             }
             mStatus = processCommand(mCommand);
-            if (!mStatus) sendMessage(TRANSITION_TO_STABLE);
+            if (!mStatus) {
+                sendMessage(TRANSITION_TO_STABLE);
+                mService.sendProfileStateMessage(BluetoothProfileState.A2DP,
+                                                 BluetoothProfileState.TRANSITION_TO_STABLE);
+            }
         }
 
         @Override
@@ -516,7 +533,7 @@
                     }
                     break;
                 case DISCONNECT_A2DP_OUTGOING:
-                    processCommand(DISCONNECT_A2DP_OUTGOING);
+                    deferMessage(message);
                     break;
                 case DISCONNECT_A2DP_INCOMING:
                     // Ignore, will be handled by Bluez
@@ -542,14 +559,18 @@
 
         @Override
         protected void enter() {
-            log("Entering IncomingA2dp state with: " + getCurrentMessage().what);
+            Log.i(TAG, "Entering IncomingA2dp state with: " + getCurrentMessage().what);
             mCommand = getCurrentMessage().what;
             if (mCommand != CONNECT_A2DP_INCOMING &&
                 mCommand != DISCONNECT_A2DP_INCOMING) {
                 Log.e(TAG, "Error: IncomingA2DP state with command:" + mCommand);
             }
             mStatus = processCommand(mCommand);
-            if (!mStatus) sendMessage(TRANSITION_TO_STABLE);
+            if (!mStatus) {
+                sendMessage(TRANSITION_TO_STABLE);
+                mService.sendProfileStateMessage(BluetoothProfileState.A2DP,
+                                                 BluetoothProfileState.TRANSITION_TO_STABLE);
+            }
         }
 
         @Override
@@ -622,7 +643,7 @@
     }
 
     synchronized boolean processCommand(int command) {
-        log("Processing command:" + command);
+        Log.i(TAG, "Processing command:" + command);
         switch(command) {
             case  CONNECT_HFP_OUTGOING:
                 if (mHeadsetService != null) {
diff --git a/core/java/android/bluetooth/BluetoothProfileState.java b/core/java/android/bluetooth/BluetoothProfileState.java
index 946dcaa..686ff7c 100644
--- a/core/java/android/bluetooth/BluetoothProfileState.java
+++ b/core/java/android/bluetooth/BluetoothProfileState.java
@@ -40,13 +40,13 @@
  */
 
 public class BluetoothProfileState extends HierarchicalStateMachine {
-    private static final boolean DBG = true; // STOPSHIP - change to false.
+    private static final boolean DBG = true;
     private static final String TAG = "BluetoothProfileState";
 
-    public static int HFP = 0;
-    public static int A2DP = 1;
+    public static final int HFP = 0;
+    public static final int A2DP = 1;
 
-    private static int TRANSITION_TO_STABLE = 100;
+    static final int TRANSITION_TO_STABLE = 100;
 
     private int mProfile;
     private BluetoothDevice mPendingDevice;
@@ -57,7 +57,7 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
-
+            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
             if (action.equals(BluetoothHeadset.ACTION_STATE_CHANGED)) {
                 int newState = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, 0);
                 if (mProfile == HFP && (newState == BluetoothHeadset.STATE_CONNECTED ||
@@ -70,6 +70,10 @@
                     newState == BluetoothA2dp.STATE_DISCONNECTED)) {
                     sendMessage(TRANSITION_TO_STABLE);
                 }
+            } else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
+                if (device.equals(mPendingDevice)) {
+                    sendMessage(TRANSITION_TO_STABLE);
+                }
             }
         }
     };
@@ -84,6 +88,7 @@
         IntentFilter filter = new IntentFilter();
         filter.addAction(BluetoothA2dp.ACTION_SINK_STATE_CHANGED);
         filter.addAction(BluetoothHeadset.ACTION_STATE_CHANGED);
+        filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
         context.registerReceiver(mBroadcastReceiver, filter);
     }
 
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 7154aee..de8e3f4 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -5267,7 +5267,19 @@
                 b.append(' ');
             }
             first = false;
-            b.append("dat=").append(mData);
+            b.append("dat=");
+            String scheme = mData.getScheme();
+            if (scheme != null) {
+                if (scheme.equalsIgnoreCase("tel")) {
+                    b.append("tel:xxx-xxx-xxxx");
+                } else if (scheme.equalsIgnoreCase("smsto")) {
+                    b.append("smsto:xxx-xxx-xxxx");
+                } else {
+                    b.append(mData);
+                }
+            } else {
+                b.append(mData);
+            }
         }
         if (mType != null) {
             if (!first) {
diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
index f9a1637..e1a9dbb 100644
--- a/core/java/android/content/SyncStorageEngine.java
+++ b/core/java/android/content/SyncStorageEngine.java
@@ -411,7 +411,7 @@
     }
 
     public void setSyncAutomatically(Account account, String providerName, boolean sync) {
-        Log.d(TAG, "setSyncAutomatically: " + account + ", provider " + providerName
+        Log.d(TAG, "setSyncAutomatically: " + /*account +*/ ", provider " + providerName
                 + " -> " + sync);
         synchronized (mAuthorities) {
             AuthorityInfo authority = getOrCreateAuthorityLocked(account, providerName, -1, false);
diff --git a/core/java/android/content/res/ObbInfo.java b/core/java/android/content/res/ObbInfo.java
index 5d6ed44..b653f9f 100644
--- a/core/java/android/content/res/ObbInfo.java
+++ b/core/java/android/content/res/ObbInfo.java
@@ -48,6 +48,13 @@
      */
     public int flags;
 
+    /**
+     * The salt for the encryption algorithm.
+     * 
+     * @hide
+     */
+    public byte[] salt;
+
     // Only allow things in this package to instantiate.
     /* package */ ObbInfo() {
     }
@@ -75,6 +82,7 @@
         dest.writeString(packageName);
         dest.writeInt(version);
         dest.writeInt(flags);
+        dest.writeByteArray(salt);
     }
 
     public static final Parcelable.Creator<ObbInfo> CREATOR
@@ -93,5 +101,6 @@
         packageName = source.readString();
         version = source.readInt();
         flags = source.readInt();
+        salt = source.createByteArray();
     }
 }
diff --git a/core/java/com/trustedlogic/trustednfc/android/internal/ErrorCodes.java b/core/java/android/nfc/ErrorCodes.java
similarity index 83%
rename from core/java/com/trustedlogic/trustednfc/android/internal/ErrorCodes.java
rename to core/java/android/nfc/ErrorCodes.java
index ca3b7e0..5b76d84 100644
--- a/core/java/com/trustedlogic/trustednfc/android/internal/ErrorCodes.java
+++ b/core/java/android/nfc/ErrorCodes.java
@@ -1,11 +1,11 @@
 /*
- * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2010, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,19 +14,13 @@
  * limitations under the License.
  */
 
-/**
- * File            : ErrorCodes.java
- * Original-Author : Trusted Logic S.A. (Sylvain Fonteneau)
- * Created         : 26-02-2010
- */
-
-package com.trustedlogic.trustednfc.android.internal;
+package android.nfc;
 
 /**
  * This class defines all the error codes that can be returned by the service
  * and producing an exception on the application level. These are needed since
  * binders does not support exceptions.
- * 
+ *
  * @hide
  */
 public class ErrorCodes {
@@ -40,7 +34,7 @@
     }
 
     public static final int SUCCESS = 0;
-    
+
     public static final int ERROR_IO = -1;
 
     public static final int ERROR_CANCELLED = -2;
@@ -58,34 +52,29 @@
     public static final int ERROR_WRITE = -7;
 
     public static final int ERROR_INVALID_PARAM = -8;
-    
+
     public static final int ERROR_INSUFFICIENT_RESOURCES = -9;
-    
+
     public static final int ERROR_SOCKET_CREATION = -10;
-    
+
     public static final int ERROR_SOCKET_NOT_CONNECTED = -11;
-    
+
     public static final int ERROR_BUFFER_TO_SMALL = -12;
 
     public static final int ERROR_SAP_USED = -13;
-    
+
     public static final int ERROR_SERVICE_NAME_USED = -14;
-    
+
     public static final int ERROR_SOCKET_OPTIONS = -15;
-    
+
     public static final int ERROR_NFC_ON = -16;
-    
+
     public static final int ERROR_NOT_INITIALIZED = -17;
-    
+
     public static final int ERROR_SE_ALREADY_SELECTED = -18;
-    
+
     public static final int ERROR_SE_CONNECTED = -19;
-    
+
     public static final int ERROR_NO_SE_CONNECTED = -20;
-    
-    
-    
-    
-    
-    
-}
+
+}
\ No newline at end of file
diff --git a/core/java/android/nfc/FormatException.java b/core/java/android/nfc/FormatException.java
new file mode 100644
index 0000000..21a7c3b
--- /dev/null
+++ b/core/java/android/nfc/FormatException.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.nfc;
+
+//TODO(npelly) javadoc or consider alternatives
+public class FormatException extends Exception {
+    public FormatException() {
+        super();
+    }
+
+    public FormatException(String message) {
+        super(message);
+    }
+}
diff --git a/core/java/com/trustedlogic/trustednfc/android/IP2pInitiator.aidl b/core/java/android/nfc/ILlcpConnectionlessSocket.aidl
similarity index 69%
copy from core/java/com/trustedlogic/trustednfc/android/IP2pInitiator.aidl
copy to core/java/android/nfc/ILlcpConnectionlessSocket.aidl
index 96819ae..c6d84e5 100644
--- a/core/java/com/trustedlogic/trustednfc/android/IP2pInitiator.aidl
+++ b/core/java/android/nfc/ILlcpConnectionlessSocket.aidl
@@ -14,19 +14,17 @@
  * limitations under the License.
  */
 
-package com.trustedlogic.trustednfc.android;
+package android.nfc;
+
+import android.nfc.LlcpPacket;
 
 /**
- * TODO
- *
- * {@hide}
+ * @hide
  */
-interface IP2pInitiator
+interface ILlcpConnectionlessSocket
 {
-
-    byte[]   getGeneralBytes(int nativeHandle);
-    int      getMode(int nativeHandle);
-    byte[]   receive(int nativeHandle);
-    boolean  send(int nativeHandle, in byte[] data);
-
+    void close(int nativeHandle);
+    int getSap(int nativeHandle);
+    LlcpPacket receiveFrom(int nativeHandle);
+    int sendTo(int nativeHandle, in LlcpPacket packet);
 }
\ No newline at end of file
diff --git a/core/java/com/trustedlogic/trustednfc/android/ILlcpServiceSocket.aidl b/core/java/android/nfc/ILlcpServiceSocket.aidl
similarity index 73%
rename from core/java/com/trustedlogic/trustednfc/android/ILlcpServiceSocket.aidl
rename to core/java/android/nfc/ILlcpServiceSocket.aidl
index 5eb1f3c..c3108dc 100644
--- a/core/java/com/trustedlogic/trustednfc/android/ILlcpServiceSocket.aidl
+++ b/core/java/android/nfc/ILlcpServiceSocket.aidl
@@ -14,19 +14,15 @@
  * limitations under the License.
  */
 
-package com.trustedlogic.trustednfc.android;
+package android.nfc;
 
 /**
- * TODO
- *
  * {@hide}
  */
 interface ILlcpServiceSocket
 {
-
-    int     accept(int nativeHandle);
-    void    close(int nativeHandle);
-    int     getAcceptTimeout(int nativeHandle);
-    void    setAcceptTimeout(int nativeHandle, int timeout);
-    
-}
\ No newline at end of file
+    int accept(int nativeHandle);
+    void close(int nativeHandle);
+    int getAcceptTimeout(int nativeHandle);
+    void setAcceptTimeout(int nativeHandle, int timeout);
+}
diff --git a/core/java/android/nfc/ILlcpSocket.aidl b/core/java/android/nfc/ILlcpSocket.aidl
new file mode 100644
index 0000000..dda5628
--- /dev/null
+++ b/core/java/android/nfc/ILlcpSocket.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.nfc;
+
+/**
+ * @hide
+ */
+interface ILlcpSocket
+{
+    int close(int nativeHandle);
+    int connect(int nativeHandle, int sap);
+    int connectByName(int nativeHandle, String sn);
+    int getConnectTimeout(int nativeHandle);
+    int getLocalSap(int nativeHandle);
+    int getLocalSocketMiu(int nativeHandle);
+    int getLocalSocketRw(int nativeHandle);
+    int getRemoteSocketMiu(int nativeHandle);
+    int getRemoteSocketRw(int nativeHandle);
+    int receive(int nativeHandle, out byte[] receiveBuffer);
+    int send(int nativeHandle, in byte[] data);
+    void setConnectTimeout(int nativeHandle, int timeout);
+}
\ No newline at end of file
diff --git a/core/java/com/trustedlogic/trustednfc/android/INdefTag.aidl b/core/java/android/nfc/INdefTag.aidl
similarity index 78%
rename from core/java/com/trustedlogic/trustednfc/android/INdefTag.aidl
rename to core/java/android/nfc/INdefTag.aidl
index 1f8d1a4..d131ebe 100644
--- a/core/java/com/trustedlogic/trustednfc/android/INdefTag.aidl
+++ b/core/java/android/nfc/INdefTag.aidl
@@ -14,19 +14,15 @@
  * limitations under the License.
  */
 
-package com.trustedlogic.trustednfc.android;
+package android.nfc;
 
-import com.trustedlogic.trustednfc.android.NdefMessage;
+import android.nfc.NdefMessage;
 
 /**
- * TODO
- *
- * {@hide}
+ * @hide
  */
 interface INdefTag
 {
-
     NdefMessage read(int nativeHandle);
-    boolean     write(int nativeHandle, in NdefMessage msg);
-
+    boolean write(int nativeHandle, in NdefMessage msg);
 }
\ No newline at end of file
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
new file mode 100644
index 0000000..7743ceb
--- /dev/null
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.nfc;
+
+import android.nfc.NdefMessage;
+import android.nfc.Tag;
+import android.nfc.ILlcpSocket;
+import android.nfc.ILlcpServiceSocket;
+import android.nfc.ILlcpConnectionlessSocket;
+import android.nfc.INfcTag;
+import android.nfc.IP2pTarget;
+import android.nfc.IP2pInitiator;
+
+/**
+ * @hide
+ */
+interface INfcAdapter
+{
+    ILlcpSocket getLlcpInterface();
+    ILlcpConnectionlessSocket getLlcpConnectionlessInterface();
+    ILlcpServiceSocket getLlcpServiceInterface();
+    INfcTag getNfcTagInterface();
+    IP2pTarget getP2pTargetInterface();
+    IP2pInitiator getP2pInitiatorInterface();
+
+    // NfcAdapter-class related methods
+    boolean isEnabled();
+    NdefMessage localGet();
+    void localSet(in NdefMessage message);
+    void openTagConnection(in Tag tag);
+
+    // Non-public methods
+    // TODO: check and complete
+    int createLlcpConnectionlessSocket(int sap);
+    int createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength);
+    int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength);
+    int deselectSecureElement();
+    boolean disable();
+    boolean enable();
+    String getProperties(String param);
+    int[] getSecureElementList();
+    int getSelectedSecureElement();
+    int selectSecureElement(int seId);
+    int setProperties(String param, String value);
+}
\ No newline at end of file
diff --git a/core/java/com/trustedlogic/trustednfc/android/INfcTag.aidl b/core/java/android/nfc/INfcTag.aidl
similarity index 62%
rename from core/java/com/trustedlogic/trustednfc/android/INfcTag.aidl
rename to core/java/android/nfc/INfcTag.aidl
index 79543c4..2171434 100644
--- a/core/java/com/trustedlogic/trustednfc/android/INfcTag.aidl
+++ b/core/java/android/nfc/INfcTag.aidl
@@ -14,25 +14,26 @@
  * limitations under the License.
  */
 
-package com.trustedlogic.trustednfc.android;
+package android.nfc;
 
-import com.trustedlogic.trustednfc.android.NdefMessage;
+import android.nfc.NdefMessage;
 
 /**
- * TODO
- *
- * {@hide}
+ * @hide
  */
 interface INfcTag
 {
-
-    int     close(int nativeHandle);
-    int     connect(int nativeHandle);
-    String  getType(int nativeHandle);
-    byte[]  getUid(int nativeHandle);
+    int close(int nativeHandle);
+    int connect(int nativeHandle);
+    String getType(int nativeHandle);
+    byte[] getUid(int nativeHandle);
     boolean isNdef(int nativeHandle);
-    byte[]  transceive(int nativeHandle, in byte[] data);
-    
+    byte[] transceive(int nativeHandle, in byte[] data);
+
+    int getLastError(int nativeHandle);
+
     NdefMessage read(int nativeHandle);
-    boolean     write(int nativeHandle, in NdefMessage msg);
+    int write(int nativeHandle, in NdefMessage msg);
+    int makeReadOnly(int nativeHandle);
+    int getModeHint(int nativeHandle);
 }
\ No newline at end of file
diff --git a/core/java/com/trustedlogic/trustednfc/android/IP2pInitiator.aidl b/core/java/android/nfc/IP2pInitiator.aidl
similarity index 72%
rename from core/java/com/trustedlogic/trustednfc/android/IP2pInitiator.aidl
rename to core/java/android/nfc/IP2pInitiator.aidl
index 96819ae..931f1f8 100644
--- a/core/java/com/trustedlogic/trustednfc/android/IP2pInitiator.aidl
+++ b/core/java/android/nfc/IP2pInitiator.aidl
@@ -14,19 +14,15 @@
  * limitations under the License.
  */
 
-package com.trustedlogic.trustednfc.android;
+package android.nfc;
 
 /**
- * TODO
- *
- * {@hide}
+ * @hide
  */
 interface IP2pInitiator
 {
-
-    byte[]   getGeneralBytes(int nativeHandle);
-    int      getMode(int nativeHandle);
-    byte[]   receive(int nativeHandle);
-    boolean  send(int nativeHandle, in byte[] data);
-
+    byte[] getGeneralBytes(int nativeHandle);
+    int getMode(int nativeHandle);
+    byte[] receive(int nativeHandle);
+    boolean send(int nativeHandle, in byte[] data);
 }
\ No newline at end of file
diff --git a/core/java/com/trustedlogic/trustednfc/android/IP2pInitiator.aidl b/core/java/android/nfc/IP2pTarget.aidl
similarity index 69%
copy from core/java/com/trustedlogic/trustednfc/android/IP2pInitiator.aidl
copy to core/java/android/nfc/IP2pTarget.aidl
index 96819ae..ddaaed42 100644
--- a/core/java/com/trustedlogic/trustednfc/android/IP2pInitiator.aidl
+++ b/core/java/android/nfc/IP2pTarget.aidl
@@ -14,19 +14,16 @@
  * limitations under the License.
  */
 
-package com.trustedlogic.trustednfc.android;
+package android.nfc;
 
 /**
- * TODO
- *
- * {@hide}
+ * @hide
  */
-interface IP2pInitiator
+interface IP2pTarget
 {
-
-    byte[]   getGeneralBytes(int nativeHandle);
-    int      getMode(int nativeHandle);
-    byte[]   receive(int nativeHandle);
-    boolean  send(int nativeHandle, in byte[] data);
-
+    byte[] getGeneralBytes(int nativeHandle);
+    int getMode(int nativeHandle);
+    int connect(int nativeHandle);
+    boolean disconnect(int nativeHandle);
+    byte[] transceive(int nativeHandle, in byte[] data);
 }
\ No newline at end of file
diff --git a/core/java/com/trustedlogic/trustednfc/android/LlcpPacket.aidl b/core/java/android/nfc/LlcpPacket.aidl
similarity index 92%
rename from core/java/com/trustedlogic/trustednfc/android/LlcpPacket.aidl
rename to core/java/android/nfc/LlcpPacket.aidl
index 297a1fe..80f424d 100644
--- a/core/java/com/trustedlogic/trustednfc/android/LlcpPacket.aidl
+++ b/core/java/android/nfc/LlcpPacket.aidl
@@ -14,6 +14,9 @@
  * limitations under the License.
  */
 
-package com.trustedlogic.trustednfc.android;
+package android.nfc;
 
-parcelable LlcpPacket;
+/**
+ * @hide
+ */
+parcelable LlcpPacket;
\ No newline at end of file
diff --git a/core/java/com/trustedlogic/trustednfc/android/LlcpPacket.java b/core/java/android/nfc/LlcpPacket.java
similarity index 71%
rename from core/java/com/trustedlogic/trustednfc/android/LlcpPacket.java
rename to core/java/android/nfc/LlcpPacket.java
index af79023..9919dc4 100644
--- a/core/java/com/trustedlogic/trustednfc/android/LlcpPacket.java
+++ b/core/java/android/nfc/LlcpPacket.java
@@ -14,76 +14,35 @@
  * limitations under the License.
  */
 
-/**
- * File            : LLCPPacket.java
- * Original-Author : Trusted Logic S.A. (Daniel Tomas)
- * Created         : 25-02-2010
- */
-
-package com.trustedlogic.trustednfc.android;
+package android.nfc;
 
 import android.os.Parcel;
 import android.os.Parcelable;
 
 /**
  * Represents a LLCP packet received in a LLCP Connectionless communication;
- * 
- * @since AA02.01
  * @hide
  */
 public class LlcpPacket implements Parcelable {
 
-    private int mRemoteSap;
+    private final int mRemoteSap;
 
-    private byte[] mDataBuffer;
-
-    /**
-     * Creator class, needed when implementing from Parcelable
-     * {@hide}
-     */
-    public static final Parcelable.Creator<LlcpPacket> CREATOR = new Parcelable.Creator<LlcpPacket>() {
-        public LlcpPacket createFromParcel(Parcel in) {
-            // Remote SAP
-            short sap = (short)in.readInt();
-            
-            // Data Buffer
-            int dataLength = in.readInt();
-            byte[] data = new byte[dataLength];
-            in.readByteArray(data);
-            
-            return new LlcpPacket(sap, data);
-        }
-
-        public LlcpPacket[] newArray(int size) {
-            return new LlcpPacket[size];
-        }
-    };
-    
+    private final byte[] mDataBuffer;
 
     /**
      * Creates a LlcpPacket to be sent to a remote Service Access Point number
      * (SAP)
-     * 
+     *
      * @param sap Remote Service Access Point number
      * @param data Data buffer
-     * @since AA02.01
      */
     public LlcpPacket(int sap, byte[] data) {
-    	mRemoteSap = sap;
+        mRemoteSap = sap;
         mDataBuffer = data;
     }
-    
-    /**
-     * @hide
-     */
-    public LlcpPacket() {
-    }
 
     /**
      * Returns the remote Service Access Point number
-     * 
-     * @return remoteSap
-     * @since AA02.01
      */
     public int getRemoteSap() {
         return mRemoteSap;
@@ -91,29 +50,36 @@
 
     /**
      * Returns the data buffer
-     * 
-     * @return data
-     * @since AA02.01
      */
     public byte[] getDataBuffer() {
         return mDataBuffer;
     }
 
-    /**
-     * (Parcelable) Describe the parcel
-     * {@hide}
-     */
     public int describeContents() {
         return 0;
     }
 
-    /**
-     * (Parcelable) Convert current object to a Parcel
-     * {@hide}
-     */
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(mRemoteSap);
         dest.writeInt(mDataBuffer.length);
-        dest.writeByteArray(mDataBuffer);      
+        dest.writeByteArray(mDataBuffer);
     }
-}
+
+    public static final Parcelable.Creator<LlcpPacket> CREATOR = new Parcelable.Creator<LlcpPacket>() {
+        public LlcpPacket createFromParcel(Parcel in) {
+            // Remote SAP
+            short sap = (short)in.readInt();
+
+            // Data Buffer
+            int dataLength = in.readInt();
+            byte[] data = new byte[dataLength];
+            in.readByteArray(data);
+
+            return new LlcpPacket(sap, data);
+        }
+
+        public LlcpPacket[] newArray(int size) {
+            return new LlcpPacket[size];
+        }
+    };
+}
\ No newline at end of file
diff --git a/core/java/com/trustedlogic/trustednfc/android/NdefMessage.aidl b/core/java/android/nfc/NdefMessage.aidl
similarity index 92%
rename from core/java/com/trustedlogic/trustednfc/android/NdefMessage.aidl
rename to core/java/android/nfc/NdefMessage.aidl
index e60f4e8..378b9d0 100644
--- a/core/java/com/trustedlogic/trustednfc/android/NdefMessage.aidl
+++ b/core/java/android/nfc/NdefMessage.aidl
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
-package com.trustedlogic.trustednfc.android;
+
+package android.nfc;
 
 parcelable NdefMessage;
diff --git a/core/java/android/nfc/NdefMessage.java b/core/java/android/nfc/NdefMessage.java
index 557f651..fcff2c9 100644
--- a/core/java/android/nfc/NdefMessage.java
+++ b/core/java/android/nfc/NdefMessage.java
@@ -20,8 +20,6 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import java.lang.UnsupportedOperationException;
-
 /**
  * NDEF Message data.
  * <p>
@@ -29,23 +27,34 @@
  * records.
  */
 public class NdefMessage implements Parcelable {
+    private static final byte FLAG_MB = (byte) 0x80;
+    private static final byte FLAG_ME = (byte) 0x40;
+
+    private final NdefRecord[] mRecords;
+
+    //TODO(npelly) FormatException
     /**
      * Create an NDEF message from raw bytes.
      * <p>
      * Validation is performed to make sure the Record format headers are valid,
      * and the ID + TYPE + PAYLOAD fields are of the correct size.
+     * @throws FormatException
      *
      * @hide
      */
-    public NdefMessage(byte[] data) {
-        throw new UnsupportedOperationException();
+    public NdefMessage(byte[] data) throws FormatException {
+        mRecords = null;  // stop compiler complaints about final field
+        if (parseNdefMessage(data) == -1) {
+            throw new FormatException("Error while parsing NDEF message");
+        }
     }
 
     /**
      * Create an NDEF message from NDEF records.
      */
     public NdefMessage(NdefRecord[] records) {
-        throw new UnsupportedOperationException();
+        mRecords = new NdefRecord[records.length];
+        System.arraycopy(records, 0, mRecords, 0, records.length);
     }
 
     /**
@@ -54,7 +63,7 @@
      * @return array of zero or more NDEF records.
      */
     public NdefRecord[] getRecords() {
-        throw new UnsupportedOperationException();
+        return mRecords.clone();
     }
 
     /**
@@ -64,26 +73,62 @@
      * @hide
      */
     public byte[] toByteArray() {
-        throw new UnsupportedOperationException();
+        //TODO(nxp): do not return null
+        //TODO(nxp): allocate the byte array once, copy each record once
+        //TODO(nxp): process MB and ME flags outside loop
+        if ((mRecords == null) || (mRecords.length == 0))
+            return null;
+
+        byte[] msg = {};
+
+        for (int i = 0; i < mRecords.length; i++) {
+            byte[] record = mRecords[i].toByteArray();
+            byte[] tmp = new byte[msg.length + record.length];
+
+            /* Make sure the Message Begin flag is set only for the first record */
+            if (i == 0) {
+                record[0] |= FLAG_MB;
+            } else {
+                record[0] &= ~FLAG_MB;
+            }
+
+            /* Make sure the Message End flag is set only for the last record */
+            if (i == (mRecords.length - 1)) {
+                record[0] |= FLAG_ME;
+            } else {
+                record[0] &= ~FLAG_ME;
+            }
+
+            System.arraycopy(msg, 0, tmp, 0, msg.length);
+            System.arraycopy(record, 0, tmp, msg.length, record.length);
+
+            msg = tmp;
+        }
+
+        return msg;
     }
 
-    @Override
     public int describeContents() {
         return 0;
     }
 
-    @Override
     public void writeToParcel(Parcel dest, int flags) {
-        throw new UnsupportedOperationException();
+        dest.writeInt(mRecords.length);
+        dest.writeTypedArray(mRecords, flags);
     }
 
     public static final Parcelable.Creator<NdefMessage> CREATOR =
             new Parcelable.Creator<NdefMessage>() {
         public NdefMessage createFromParcel(Parcel in) {
-            throw new UnsupportedOperationException();
+            int recordsLength = in.readInt();
+            NdefRecord[] records = new NdefRecord[recordsLength];
+            in.readTypedArray(records, NdefRecord.CREATOR);
+            return new NdefMessage(records);
         }
         public NdefMessage[] newArray(int size) {
-            throw new UnsupportedOperationException();
+            return new NdefMessage[size];
         }
     };
+
+    private native int parseNdefMessage(byte[] data);
 }
\ No newline at end of file
diff --git a/core/java/com/trustedlogic/trustednfc/android/NdefRecord.aidl b/core/java/android/nfc/NdefRecord.aidl
similarity index 92%
rename from core/java/com/trustedlogic/trustednfc/android/NdefRecord.aidl
rename to core/java/android/nfc/NdefRecord.aidl
index 9d95174..10f89d0 100644
--- a/core/java/com/trustedlogic/trustednfc/android/NdefRecord.aidl
+++ b/core/java/android/nfc/NdefRecord.aidl
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package com.trustedlogic.trustednfc.android;
+package android.nfc;
 
-parcelable NdefRecord;
+parcelable NdefRecord;
\ No newline at end of file
diff --git a/core/java/android/nfc/NdefRecord.java b/core/java/android/nfc/NdefRecord.java
index 54cbbeb..c08f2ed 100644
--- a/core/java/android/nfc/NdefRecord.java
+++ b/core/java/android/nfc/NdefRecord.java
@@ -138,6 +138,18 @@
      */
     public static final byte[] RTD_HANDOVER_SELECT = {0x48, 0x73}; // "Hs"
 
+    private static final byte FLAG_MB = (byte) 0x80;
+    private static final byte FLAG_ME = (byte) 0x40;
+    private static final byte FLAG_CF = (byte) 0x20;
+    private static final byte FLAG_SR = (byte) 0x10;
+    private static final byte FLAG_IL = (byte) 0x08;
+
+    private final byte mFlags;
+    private final short mTnf;
+    private final byte[] mType;
+    private final byte[] mId;
+    private final byte[] mPayload;
+
     /**
      * Construct an NDEF Record.
      * <p>
@@ -153,7 +165,29 @@
      *                must not be null
      */
     public NdefRecord(short tnf, byte[] type, byte[] id, byte[] payload) {
-        throw new UnsupportedOperationException();
+        /* check arguments */
+        if ((type == null) || (id == null) || (payload == null)) {
+            throw new IllegalArgumentException("Illegal null argument");
+        }
+
+        /* generate flag */
+        byte flags = FLAG_MB | FLAG_ME;
+
+        /* Determine if it is a short record */
+        if(payload.length < 0xFF) {
+            flags |= FLAG_SR;
+        }
+
+        /* Determine if an id is present */
+        if(id.length != 0) {
+            flags |= FLAG_IL;
+        }
+
+        mFlags = flags;
+        mTnf = tnf;
+        mType = type.clone();
+        mId = id.clone();
+        mPayload = payload.clone();
     }
 
     /**
@@ -174,7 +208,7 @@
      * TNF is the top-level type.
      */
     public short getTnf() {
-        throw new UnsupportedOperationException();
+        return mTnf;
     }
 
     /**
@@ -184,21 +218,21 @@
      * payload format.
      */
     public byte[] getType() {
-        throw new UnsupportedOperationException();
+        return mType.clone();
     }
 
     /**
      * Returns the variable length ID.
      */
     public byte[] getId() {
-        throw new UnsupportedOperationException();
+        return mId.clone();
     }
 
     /**
      * Returns the variable length payload.
      */
     public byte[] getPayload() {
-        throw new UnsupportedOperationException();
+        return mPayload.clone();
     }
 
     /**
@@ -206,26 +240,43 @@
      * @hide
      */
     public byte[] toByteArray() {
-        throw new UnsupportedOperationException();
+        return generate(mFlags, mTnf, mType, mId, mPayload);
     }
 
-    @Override
     public int describeContents() {
         return 0;
     }
 
-    @Override
     public void writeToParcel(Parcel dest, int flags) {
-        throw new UnsupportedOperationException();
+        dest.writeInt(mTnf);
+        dest.writeInt(mType.length);
+        dest.writeByteArray(mType);
+        dest.writeInt(mId.length);
+        dest.writeByteArray(mId);
+        dest.writeInt(mPayload.length);
+        dest.writeByteArray(mPayload);
     }
 
     public static final Parcelable.Creator<NdefRecord> CREATOR =
             new Parcelable.Creator<NdefRecord>() {
         public NdefRecord createFromParcel(Parcel in) {
-            throw new UnsupportedOperationException();
+            short tnf = (short)in.readInt();
+            int typeLength = in.readInt();
+            byte[] type = new byte[typeLength];
+            in.readByteArray(type);
+            int idLength = in.readInt();
+            byte[] id = new byte[idLength];
+            in.readByteArray(id);
+            int payloadLength = in.readInt();
+            byte[] payload = new byte[payloadLength];
+            in.readByteArray(payload);
+
+            return new NdefRecord(tnf, type, id, payload);
         }
         public NdefRecord[] newArray(int size) {
-            throw new UnsupportedOperationException();
+            return new NdefRecord[size];
         }
     };
+
+    private native byte[] generate(short flags, short tnf, byte[] type, byte[] id, byte[] data);
 }
\ No newline at end of file
diff --git a/core/java/com/trustedlogic/trustednfc/android/NdefMessage.aidl b/core/java/android/nfc/NdefTag.aidl
similarity index 89%
copy from core/java/com/trustedlogic/trustednfc/android/NdefMessage.aidl
copy to core/java/android/nfc/NdefTag.aidl
index e60f4e8..288f667 100644
--- a/core/java/com/trustedlogic/trustednfc/android/NdefMessage.aidl
+++ b/core/java/android/nfc/NdefTag.aidl
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
-package com.trustedlogic.trustednfc.android;
 
-parcelable NdefMessage;
+package android.nfc;
+
+parcelable NdefTag;
\ No newline at end of file
diff --git a/core/java/android/nfc/NdefTag.java b/core/java/android/nfc/NdefTag.java
new file mode 100644
index 0000000..25303c3
--- /dev/null
+++ b/core/java/android/nfc/NdefTag.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.nfc;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * NdefTag is a Tag that has NDEF messages or can store NDEF messages.
+ * <p>
+ * NDEF Tag's contain zero or more NDEF Messages in addition to the basic
+ * Tag properties of UID and Type.
+ * <p>
+ * NDEF Tag's that have been initialized will usually contain a single NDEF
+ * Message (and that Message can contain multiple NDEF Records). However it
+ * is possible for NDEF Tag's to contain multiple NDEF Messages.
+ * <p>
+ * This class is a immutable data class that contains the contents of the NDEF
+ * Message(s) as read at Tag discovery time.
+ * <p>
+ * NfcAdapter.createNdefTagConnection() can be used to modify the contents of
+ * some NDEF Tag's.
+ */
+public class NdefTag extends Tag implements Parcelable {
+    private final NdefMessage[] mMessages;
+
+    /**
+     * Hidden constructor to be used by NFC service when a
+     * tag is discovered and by Parcelable methods.
+     * @hide
+     */
+    public NdefTag(int type, byte[] uid, int nativeHandle, NdefMessage[] messages) {
+        super(type, true, uid, nativeHandle);
+        mMessages = messages.clone();
+    }
+
+    /**
+     * Get all NDEF Messages.
+     * <p>
+     * This retrieves the NDEF Messages that were found on the Tag at discovery
+     * time. It does not cause any further RF activity, and does not block.
+     * <p>
+     * Most tags only contain a single NDEF message.
+     *
+     * @return NDEF Messages found at Tag discovery
+     */
+    public NdefMessage[] getNdefMessages() {
+        return mMessages.clone();
+    }
+
+    /**
+     * Get only the NDEF Messages from a single NDEF target on a tag.
+     */
+    public NdefMessage[] getNdefMessages(String target) {
+        //TODO(nxp): new api method
+        throw new UnsupportedOperationException();
+    }
+
+    /** TODO(npelly):
+     * - check that any single tag can only have one of each NDEF type
+     * - ok to include mifare_classic?
+     */
+    public static final String TARGET_TYPE_1 = "type_1";
+    public static final String TARGET_TYPE_2 = "type_2";
+    public static final String TARGET_TYPE_3 = "type_3";
+    public static final String TARGET_TYPE_4 = "type_4";
+    public static final String TARGET_MIFARE_CLASSIC = "type_mifare_classic";
+    public static final String TARGET_OTHER = "other";
+
+    /**
+     * Return the
+     *
+     * @return
+     */
+    public String[] getNdefTargets() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        super.writeToParcel(dest, flags);
+        dest.writeInt(mMessages.length);
+        dest.writeTypedArray(mMessages, flags);
+    }
+
+    public static final Parcelable.Creator<NdefTag> CREATOR =
+            new Parcelable.Creator<NdefTag>() {
+        public NdefTag createFromParcel(Parcel in) {
+            Tag tag = Tag.CREATOR.createFromParcel(in);
+            int messagesLength = in.readInt();
+            NdefMessage[] messages = new NdefMessage[messagesLength];
+            in.readTypedArray(messages, NdefMessage.CREATOR);
+            return new NdefTag(tag.mType, tag.mUid, tag.mNativeHandle, messages);
+        }
+        public NdefTag[] newArray(int size) {
+            return new NdefTag[size];
+        }
+    };
+}
\ No newline at end of file
diff --git a/core/java/android/nfc/NdefTagConnection.java b/core/java/android/nfc/NdefTagConnection.java
new file mode 100644
index 0000000..0696b37
--- /dev/null
+++ b/core/java/android/nfc/NdefTagConnection.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.nfc;
+
+import java.io.IOException;
+
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * NdefTagConnection is a connection to an NDEF target on an NDEF tag.
+ */
+public class NdefTagConnection extends RawTagConnection {
+    public static final int NDEF_MODE_READ_ONCE = 1;
+    public static final int NDEF_MODE_READ_ONLY = 2;
+    public static final int NDEF_MODE_WRITE_ONCE = 3;
+    public static final int NDEF_MODE_WRITE_MANY = 4;
+    public static final int NDEF_MODE_UNKNOWN = 5;
+
+    private static final String TAG = "NFC";
+
+    /**
+     * Internal constructor, to be used by NfcAdapter
+     * @hide
+     */
+    NdefTagConnection(INfcAdapter service, NdefTag tag) throws RemoteException {
+        super(service, tag);
+    }
+
+    /**
+     * Read NDEF message(s).
+     * This will always return the most up to date payload, and can block.
+     * It can be canceled with close().
+     * Most NDEF tags will contain just one NDEF message.
+     * <p>
+     * @throws FormatException if the tag is not NDEF formatted
+     * @throws IOException if the target is lost or connection closed
+     * @throws FormatException
+     */
+    public NdefMessage[] readNdefMessages() throws IOException, FormatException {
+        //TODO(nxp): do not use getLastError(), it is racy
+        try {
+            NdefMessage[] msgArray = new NdefMessage[1];
+            NdefMessage msg = mTagService.read(mTag.mNativeHandle);
+            if (msg == null) {
+                int errorCode = mTagService.getLastError(mTag.mNativeHandle);
+                switch (errorCode) {
+                    case ErrorCodes.ERROR_IO:
+                        throw new IOException();
+                    case ErrorCodes.ERROR_INVALID_PARAM:
+                        throw new FormatException();
+                    default:
+                        // Should not happen
+                        throw new IOException();
+                }
+            }
+            msgArray[0] = msg;
+            return msgArray;
+        } catch (RemoteException e) {
+            Log.e(TAG, "NFC service died");
+            return null;
+        }
+    }
+
+    /**
+     * Attempt to write an NDEF message to a tag.
+     * This method will block until the data is written. It can be canceled
+     * with close().
+     * Many tags are write-once, so use this method carefully.
+     * Specification allows for multiple NDEF messages per NDEF tag, but it is
+     * encourage to only write one message, this so API only takes a single
+     * message. Use NdefRecord to write several records to a single tag.
+     * For write-many tags, use makeReadOnly() after this method to attempt
+     * to prevent further modification. For write-once tags this is not
+     * neccesary.
+     * Requires NFC_WRITE permission.
+     * @throws FormatException if the tag is not suitable for NDEF messages
+     * @throws IOException if the target is lost or connection closed or the
+     *                     write failed
+     */
+    public void writeNdefMessage(NdefMessage message) throws IOException, FormatException {
+        try {
+            int errorCode = mTagService.write(mTag.mNativeHandle, message);
+            switch (errorCode) {
+                case ErrorCodes.SUCCESS:
+                    break;
+                case ErrorCodes.ERROR_IO:
+                    throw new IOException();
+                case ErrorCodes.ERROR_INVALID_PARAM:
+                    throw new FormatException();
+                default:
+                    // Should not happen
+                    throw new IOException();
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "NFC service died");
+        }
+    }
+
+    /**
+     * Attempts to make the NDEF data in this tag read-only.
+     * This method will block until the action is complete. It can be canceled
+     * with close().
+     * Requires NFC_WRITE permission.
+     * @return true if the tag is now read-only
+     * @throws IOException if the target is lost, or connection closed
+     */
+    public boolean makeReadOnly() throws IOException {
+        try {
+            int errorCode = mTagService.makeReadOnly(mTag.mNativeHandle);
+            switch (errorCode) {
+                case ErrorCodes.SUCCESS:
+                    return true;
+                case ErrorCodes.ERROR_IO:
+                    throw new IOException();
+                case ErrorCodes.ERROR_INVALID_PARAM:
+                    return false;
+                default:
+                    // Should not happen
+                    throw new IOException();
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "NFC service died");
+            return false;
+        }
+    }
+
+    /**
+     * Read/Write mode hint.
+     * Provides a hint if further reads or writes are likely to suceed.
+     * @return one of NDEF_MODE
+     * @throws IOException if the target is lost or connection closed
+     */
+    public int getModeHint() throws IOException {
+        try {
+            int result = mTagService.getModeHint(mTag.mNativeHandle);
+            if (ErrorCodes.isError(result)) {
+                switch (result) {
+                    case ErrorCodes.ERROR_IO:
+                        throw new IOException();
+                    default:
+                        // Should not happen
+                        throw new IOException();
+                }
+            }
+            return result;
+
+        } catch (RemoteException e) {
+            Log.e(TAG, "NFC service died");
+            return NDEF_MODE_UNKNOWN;
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
new file mode 100644
index 0000000..02b9fb71
--- /dev/null
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project Licensed under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
+ * or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES 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.nfc;
+
+import java.lang.UnsupportedOperationException;
+
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.content.Context;
+import android.nfc.INfcAdapter;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+//TODO(npelly) permission {@link android.Manifest.permission#NFC_MODIFY}
+/**
+ * Represents a local NFC Adapter.
+ * <p>
+ * Use the static {@link #getDefaultAdapter} method to get the default NFC
+ * Adapter for this Android device. Most Android devices will have only one NFC
+ * Adapter, and {@link #getDefaultAdapter} returns the singleton object.
+ * <p>
+ * {@link NfcAdapter} can be used to create {@link RawTagConnection} or
+ * {@link NdefTagConnection} connections to modify or perform low level access
+ * to NFC Tags.
+ * <p class="note">
+ * <strong>Note:</strong> Some methods require the
+ * TODO permission.
+ */
+public final class NfcAdapter {
+    /**
+     * Intent to start an activity when a non-NDEF tag is discovered.
+     * TODO(npelly) finalize decision on using CATEGORY or DATA URI to provide a
+     * hint for applications to filter the tag type.
+     * TODO(npelly) probably combine these two intents since tags aren't that simple
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED";
+
+    /**
+     * Intent to start an activity when a NDEF tag is discovered. TODO(npelly)
+     * finalize decision on using CATEGORY or DATA URI to provide a hint for
+     * applications to filter the tag type.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_NDEF_TAG_DISCOVERED =
+            "android.nfc.action.NDEF_TAG_DISCOVERED";
+
+    /**
+     * Mandatory Tag extra for the ACTION_TAG and ACTION_NDEF_TAG intents.
+     */
+    public static final String EXTRA_TAG = "android.nfc.extra.TAG";
+
+    /**
+     * Broadcast Action: a transaction with a secure element has been detected.
+     * <p>
+     * Always contains the extra field
+     * {@link android.nfc.NfcAdapter#EXTRA_AID}
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_TRANSACTION_DETECTED =
+            "android.nfc.action.TRANSACTION_DETECTED";
+
+    /**
+     * Mandatory byte array extra field in
+     * {@link android.nfc.NfcAdapter#ACTION_TRANSACTION_DETECTED}.
+     * <p>
+     * Contains the AID of the applet involved in the transaction.
+     * @hide
+     */
+    public static final String EXTRA_AID = "android.nfc.extra.AID";
+
+    /**
+     * LLCP link status: The LLCP link is activated.
+     * @hide
+     */
+    public static final int LLCP_LINK_STATE_ACTIVATED = 0;
+
+    /**
+     * LLCP link status: The LLCP link is deactivated.
+     * @hide
+     */
+    public static final int LLCP_LINK_STATE_DEACTIVATED = 1;
+
+    /**
+     * Broadcast Action: the LLCP link state changed.
+     * <p>
+     * Always contains the extra field
+     * {@link android.nfc.NfcAdapter#EXTRA_LLCP_LINK_STATE_CHANGED}.
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_LLCP_LINK_STATE_CHANGED =
+            "android.nfc.action.LLCP_LINK_STATE_CHANGED";
+
+    /**
+     * Used as int extra field in
+     * {@link android.nfc.NfcAdapter#ACTION_LLCP_LINK_STATE_CHANGED}.
+     * <p>
+     * It contains the new state of the LLCP link.
+     * @hide
+     */
+    public static final String EXTRA_LLCP_LINK_STATE_CHANGED = "android.nfc.extra.LLCP_LINK_STATE";
+
+    /**
+     * Tag Reader Discovery mode
+     * @hide
+     */
+    private static final int DISCOVERY_MODE_TAG_READER = 0;
+
+    /**
+     * NFC-IP1 Peer-to-Peer mode Enables the manager to act as a peer in an
+     * NFC-IP1 communication. Implementations should not assume that the
+     * controller will end up behaving as an NFC-IP1 target or initiator and
+     * should handle both cases, depending on the type of the remote peer type.
+     * @hide
+     */
+    private static final int DISCOVERY_MODE_NFCIP1 = 1;
+
+    /**
+     * Card Emulation mode Enables the manager to act as an NFC tag. Provided
+     * that a Secure Element (an UICC for instance) is connected to the NFC
+     * controller through its SWP interface, it can be exposed to the outside
+     * NFC world and be addressed by external readers the same way they would
+     * with a tag.
+     * <p>
+     * Which Secure Element is exposed is implementation-dependent.
+     *
+     * @hide
+     */
+    private static final int DISCOVERY_MODE_CARD_EMULATION = 2;
+
+    private static final String TAG = "NFC";
+
+    private static boolean sIsInitialized = false;
+    private static NfcAdapter sAdapter;
+
+    private final INfcAdapter mService;
+
+    private NfcAdapter(INfcAdapter service) {
+        mService = service;
+    }
+
+    /**
+     * Get a handle to the default NFC Adapter on this Android device.
+     * <p>
+     * Most Android devices will only have one NFC Adapter (NFC Controller).
+     *
+     * @return the default NFC adapter, or null if no NFC adapter exists
+     */
+    public static NfcAdapter getDefaultAdapter() {
+        synchronized (NfcAdapter.class) {
+            if (sIsInitialized) {
+                return sAdapter;
+            }
+            sIsInitialized = true;
+
+            // TODO(npelly): check which method to use here to get the service
+            IBinder b = ServiceManager.getService(Context.NFC_SERVICE);
+            if (b == null) {
+                return null;  // This device does not have NFC
+            }
+
+            sAdapter = new NfcAdapter(INfcAdapter.Stub.asInterface(b));
+            return sAdapter;
+        }
+    }
+
+    /**
+     * Return true if this NFC Adapter is enabled to discover new tags.
+     * <p>
+     * If this method returns false, then applications should request the user
+     * turn on NFC tag discovery in Settings.
+     *
+     * @return true if this NFC Adapter is enabled to discover new tags
+     */
+    public boolean isTagDiscoveryEnabled() {
+        try {
+            return mService.isEnabled();
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in isEnabled()", e);
+            return false;
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public boolean enableTagDiscovery() {
+        try {
+            return mService.enable();
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in enable()", e);
+            return false;
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public boolean disableTagDiscovery() {
+        try {
+            return mService.disable();
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in disable()", e);
+            return false;
+        }
+    }
+
+    /**
+     * Set the NDEF Message that this NFC adapter should appear as to Tag
+     * readers.
+     * <p>
+     * Any Tag reader can read the contents of the local tag when it is in
+     * proximity, without any further user confirmation.
+     * <p>
+     * The implementation of this method must either
+     * <ul>
+     * <li>act as a passive tag containing this NDEF message
+     * <li>provide the NDEF message on over LLCP to peer NFC adapters
+     * </ul>
+     * The NDEF message is preserved across reboot.
+     * <p>
+     * Requires NFC_WRITE permission
+     *
+     * @param message NDEF message to make public
+     */
+    public void setLocalNdefMessage(NdefMessage message) {
+        try {
+            mService.localSet(message);
+        } catch (RemoteException e) {
+            Log.e(TAG, "NFC service died", e);
+        }
+    }
+
+    /**
+     * Get the NDEF Message that this adapter appears as to Tag readers.
+     * <p>
+     * Requires NFC_WRITE permission
+     *
+     * @return NDEF Message that is publicly readable
+     */
+    public NdefMessage getLocalNdefMessage() {
+        try {
+            return mService.localGet();
+        } catch (RemoteException e) {
+            Log.e(TAG, "NFC service died", e);
+            return null;
+        }
+    }
+
+    /**
+     * Create a raw tag connection to the default Target
+     */
+    public RawTagConnection createRawTagConnection(Tag tag) {
+        try {
+            return new RawTagConnection(mService, tag);
+        } catch (RemoteException e) {
+            Log.e(TAG, "NFC service died", e);
+            return null;
+        }
+    }
+
+    /**
+     * Create a raw tag connection to the specified Target
+     */
+    public RawTagConnection createRawTagConnection(Tag tag, String target) {
+        //TODO
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Create an NDEF tag connection to the default Target
+     */
+    public NdefTagConnection createNdefTagConnection(NdefTag tag) {
+        try {
+            return new NdefTagConnection(mService, tag);
+        } catch (RemoteException e) {
+            Log.e(TAG, "NFC service died", e);
+            return null;
+        }
+    }
+
+    /**
+     * Create an NDEF tag connection to the specified Target
+     */
+    public NdefTagConnection createNdefTagConnection(NdefTag tag, String target) {
+        //TODO
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/core/java/android/nfc/RawTagConnection.java b/core/java/android/nfc/RawTagConnection.java
new file mode 100644
index 0000000..67a836f
--- /dev/null
+++ b/core/java/android/nfc/RawTagConnection.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.nfc;
+
+import java.io.IOException;
+
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * RawTagConnection is a low-level connection to a Tag.
+ * <p>
+ * The only data transfer method that TagConnection offers is transceive().
+ * Applications must implement there own protocol stack on top of transceive().
+ * <p>
+ * Use NfcAdapter.createRawTagConnection() to create a RawTagConnection object.
+ *
+ * * <p class="note"><strong>Note:</strong>
+ * Most methods require the {@link android.Manifest.permission#BLUETOOTH}
+ * permission and some also require the
+ * {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+
+ */
+public class RawTagConnection {
+
+    /*package*/ final INfcAdapter mService;
+    /*package*/ final INfcTag mTagService;
+    /*package*/ final Tag mTag;
+    /*package*/ boolean mIsConnected;
+
+    private static final String TAG = "NFC";
+
+    /* package private */ RawTagConnection(INfcAdapter service, Tag tag) throws RemoteException {
+        mService = service;
+        mTagService = service.getNfcTagInterface();
+        mService.openTagConnection(tag);  // TODO(nxp): don't connect until connect()
+        mTag = tag;
+    }
+
+    /**
+     * Get the Tag this connection is associated with.
+     */
+    public Tag getTag() {
+        return mTag;
+    }
+
+    public String getTagTarget() {
+        //TODO
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Helper to indicate if transceive() calls might succeed.
+     * <p>
+     * Does not cause RF activity, and does not block.
+     * <p>
+     * Returns true if connect() has completed successfully, and the Tag is not
+     * yet known to be out of range. Applications must still handle IOException
+     * while using transceive().
+     */
+    public boolean isConnected() {
+        // TODO(nxp): update mIsConnected when tag goes out of range -
+        //            but do not do an active prescence check in
+        //            isConnected()
+        return mIsConnected;
+    }
+
+    /**
+     * Connect to tag.
+     * <p>
+     * This method blocks until the connection is established.
+     * <p>
+     * close() can be called from another thread to cancel this connection
+     * attempt.
+     *
+     * @throws IOException if the target is lost, or connect canceled
+     */
+    public void connect() throws IOException {
+        //TODO(nxp): enforce exclusivity
+        mIsConnected = true;
+    }
+
+    /**
+     * Close tag connection.
+     * <p>
+     * Causes blocking operations such as transceive() or connect() to
+     * be canceled and immediately throw IOException.
+     * <p>
+     * This object cannot be re-used after calling close(). Further calls
+     * to transceive() or connect() will fail.
+     */
+    public void close() {
+        mIsConnected = false;
+        try {
+            mTagService.close(mTag.mNativeHandle);
+        } catch (RemoteException e) {
+            Log.e(TAG, "NFC service died", e);
+        }
+    }
+
+    /**
+     * Send data to a tag, and return the response.
+     * <p>
+     * This method will block until the response is received. It can be canceled
+     * with close().
+     * <p>
+     * Requires NFC_WRITE permission.
+     *
+     * @param data bytes to send
+     * @return bytes received in response
+     * @throws IOException if the target is lost or connection closed
+     */
+    public byte[] transceive(byte[] data) throws IOException {
+        try {
+            byte[] response = mTagService.transceive(mTag.mNativeHandle, data);
+            if (response == null) {
+                throw new IOException("transcieve failed");
+            }
+            return response;
+        } catch (RemoteException e) {
+            Log.e(TAG, "NFC service died", e);
+            throw new IOException("NFC service died");
+        }
+    }
+}
diff --git a/core/java/com/trustedlogic/trustednfc/android/NdefMessage.aidl b/core/java/android/nfc/Tag.aidl
similarity index 89%
copy from core/java/com/trustedlogic/trustednfc/android/NdefMessage.aidl
copy to core/java/android/nfc/Tag.aidl
index e60f4e8..312261e 100644
--- a/core/java/com/trustedlogic/trustednfc/android/NdefMessage.aidl
+++ b/core/java/android/nfc/Tag.aidl
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
-package com.trustedlogic.trustednfc.android;
 
-parcelable NdefMessage;
+package android.nfc;
+
+parcelable Tag;
\ No newline at end of file
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
new file mode 100644
index 0000000..8f731e7
--- /dev/null
+++ b/core/java/android/nfc/Tag.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.nfc;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Immutable data class, represents a discovered tag.
+ * <p>
+ * A tag is a passive NFC element, such as NFC Forum Tag's, Mifare class Tags,
+ * Sony Felica Tags.
+ * <p>
+ * Tag's have a type and usually have a UID.
+ * <p>
+ * Tag objects are passed to applications via the NfcAdapter.EXTRA_TAG extra
+ * in NfcAdapter.ACTION_TAG_DISCOVERED intents. The Tag object is immutable
+ * and represents the state of the Tag at the time of discovery. It can be
+ * directly queried for its UID and Type, or used to create a TagConnection
+ * (NfcAdapter.createTagConnection()).
+ * <p>
+ * This Tag object can only be used to create a TagConnection while it is in
+ * range. If it is removed and then returned to range then the most recent
+ * Tag object (in ACTION_TAG_DISCOVERED) should be used to create a
+ * TagConnection.
+ */
+public class Tag implements Parcelable {
+
+    /**
+     * @hide
+     */
+    public static final int NFC_TAG_ISO14443_A = 1; /* phNfc_eISO14443_A_PICC */
+
+    /**
+     * @hide
+     */
+    public static final int NFC_TAG_ISO14443_4A = 2; /* phNfc_eISO14443_4A_PICC */
+
+    /**
+     * @hide
+     */
+    public static final int NFC_TAG_ISO14443_3A = 3; /* phNfc_eISO14443_3A_PICC */
+
+    /**
+     * @hide
+     */
+    public static final int NFC_TAG_MIFARE = 4; /* phNfc_eMifare_PICC */
+
+    /**
+     * @hide
+     */
+    public static final int NFC_TAG_ISO14443_B = 5; /* phNfc_eISO14443_B_PICC */
+
+    /**
+     * @hide
+     */
+    public static final int NFC_TAG_ISO14443_4B = 6; /* phNfc_eISO14443_4B_PICC */
+
+    /**
+     * @hide
+     */
+    public static final int NFC_TAG_ISO14443_B_PRIME = 7; /* phNfc_eISO14443_BPrime_PICC */
+
+    /**
+     * @hide
+     */
+    public static final int NFC_TAG_FELICA = 8; /* phNfc_eFelica_PICC */
+
+    /**
+     * @hide
+     */
+    public static final int NFC_TAG_JEWEL = 9; /* phNfc_eJewel_PICC */
+
+    /**
+     * @hide
+     */
+    public static final int NFC_TAG_ISO15693 = 10; /* phNfc_eISO15693_PICC */
+
+    /**
+     * @hide
+     */
+    public static final int NFC_TAG_OTHER = 11; /* phNfc_ePICC_DevType */
+
+
+    public static final String TARGET_ISO_14443_3A = "iso14443_3a";
+
+    public static final String TARGET_ISO_14443_3B = "iso14443_3b";
+
+    public static final String TARGET_ISO_14443_3B_PRIME = "iso14443_3b";
+
+    public static final String TARGET_ISO_14443_4 = "iso14443_4";
+
+    public static final String TARGET_ISO_15693 = "iso15693";
+
+    public static final String TARGET_JIS_X_6319_4 = "jis_x_6319_4";
+
+    public static final String TARGET_TOPAZ = "topaz";
+
+    public static final String TARGET_OTHER = "other";
+
+    /*package*/ final int mType;
+    /*package*/ final boolean mIsNdef;
+    /*package*/ final byte[] mUid;
+    /*package*/ final int mNativeHandle;
+
+    /**
+     * Hidden constructor to be used by NFC service only.
+     * @hide
+     */
+    public Tag(int type, boolean isNdef, byte[] uid, int nativeHandle) {
+        mType = type;
+        mIsNdef = isNdef;
+        mUid = uid.clone();
+        mNativeHandle = nativeHandle;
+    }
+
+    /**
+     * For use by NfcService only.
+     * @hide
+     */
+    public int getHandle() {
+        return mNativeHandle;
+    }
+
+    /**
+     * Return the available targets that this NFC adapter can use to create
+     * a RawTagConnection.
+     *
+     * @return
+     */
+    public String[] getRawTargets() {
+        //TODO
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Get the Tag type.
+     * <p>
+     * The Tag type is one of the NFC_TAG constants. It is read at discovery
+     * time and this method does not cause any further RF activity and does not
+     * block.
+     *
+     * @return a NFC_TAG constant
+     * @hide
+     */
+    public int getType() {
+        return mType;
+    }
+
+    /**
+     * Get the Tag Identifier (if it has one).
+     * <p>
+     * Tag ID is usually a serial number for the tag.
+     * <p>
+     * The Tag ID is read at discovery time and this method does not cause any
+     * further RF activity and does not block.
+     *
+     * @return ID, or null if it does not exist
+     */
+    public byte[] getId() {
+        if (mUid.length > 0) {
+            return mUid.clone();
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        boolean[] booleans = new boolean[] {mIsNdef};
+        dest.writeInt(mType);
+        dest.writeBooleanArray(booleans);
+        dest.writeInt(mUid.length);
+        dest.writeByteArray(mUid);
+        dest.writeInt(mNativeHandle);
+    }
+
+    public static final Parcelable.Creator<Tag> CREATOR =
+            new Parcelable.Creator<Tag>() {
+        public Tag createFromParcel(Parcel in) {
+            boolean[] booleans = new boolean[1];
+            int type = in.readInt();
+            in.readBooleanArray(booleans);
+            boolean isNdef = booleans[0];
+            int uidLength = in.readInt();
+            byte[] uid = new byte[uidLength];
+            in.readByteArray(uid);
+            int nativeHandle = in.readInt();
+
+            return new Tag(type, isNdef, uid, nativeHandle);
+        }
+        public Tag[] newArray(int size) {
+            return new Tag[size];
+        }
+    };
+}
\ No newline at end of file
diff --git a/core/java/android/os/storage/OnObbStateChangeListener.java b/core/java/android/os/storage/OnObbStateChangeListener.java
index 950195b..1fb1782 100644
--- a/core/java/android/os/storage/OnObbStateChangeListener.java
+++ b/core/java/android/os/storage/OnObbStateChangeListener.java
@@ -67,9 +67,9 @@
     public static final int ERROR_ALREADY_MOUNTED = 24;
 
     /**
-     * The current application does not have permission to use this OBB because
-     * the OBB indicates it's owned by a different package or the key used to
-     * open it is incorrect. Returned in status messages from calls made via
+     * The current application does not have permission to use this OBB. This
+     * could be because the OBB indicates it's owned by a different package or
+     * some other error. Returned in status messages from calls made via
      * {@link StorageManager}
      */
     public static final int ERROR_PERMISSION_DENIED = 25;
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index 8fd0e0a..72bf6b0 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -300,6 +300,15 @@
      */
     public static final String COLUMN_DESCRIPTION = "description";
 
+    /**
+     * Set to true if this download is deleted. It is completely removed from the database
+     * when MediaProvider database also deletes the metadata asociated with this downloaded file.
+     * <P>Type: BOOLEAN</P>
+     * <P>Owner can Read</P>
+     * @hide
+     */
+    public static final String COLUMN_DELETED = "deleted";
+
     /*
      * Lists the destinations that an application can specify for a download.
      */
@@ -881,6 +890,23 @@
         public static final String COLUMN_BYPASS_RECOMMENDED_SIZE_LIMIT =
             "bypass_recommended_size_limit";
 
+        /**
+         * Set to true if this download is deleted. It is completely removed from the database
+         * when MediaProvider database also deletes the metadata asociated with this downloaded file.
+         * <P>Type: BOOLEAN</P>
+         * <P>Owner can Read</P>
+         */
+        public static final String COLUMN_DELETED = "deleted";
+
+        /**
+         * The URI to the corresponding entry in MediaProvider for this downloaded entry. It is
+         * used to delete the entries from MediaProvider database when it is deleted from the
+         * downloaded list.
+         * <P>Type: TEXT</P>
+         * <P>Owner can Read</P>
+         */
+        public static final String COLUMN_MEDIAPROVIDER_URI = "mediaprovider_uri";
+
         /*
          * Lists the destinations that an application can specify for a download.
          */
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index bf9e854..6d8bd9b 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -1205,9 +1205,8 @@
             }
 
             Uri uri = uriBuilder.build();
-            if (DEBUG) {
-                Log.v(TAG, "getOrCreateThreadId uri: " + uri);
-            }
+            //if (DEBUG) Log.v(TAG, "getOrCreateThreadId uri: " + uri);
+
             Cursor cursor = SqliteWrapper.query(context, context.getContentResolver(),
                     uri, ID_PROJECTION, null, null, null);
             if (DEBUG) {
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
index a52a221..5cbfe74 100644
--- a/core/java/android/server/BluetoothA2dpService.java
+++ b/core/java/android/server/BluetoothA2dpService.java
@@ -71,7 +71,6 @@
     private final BluetoothService mBluetoothService;
     private final BluetoothAdapter mAdapter;
     private int   mTargetA2dpState;
-    private boolean mAdjustedPriority = false;
 
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
@@ -326,7 +325,10 @@
 
         String path = mBluetoothService.getObjectPathFromAddress(device.getAddress());
 
-        // State is DISCONNECTED
+        // State is DISCONNECTED and we are connecting.
+        if (getSinkPriority(device) < BluetoothA2dp.PRIORITY_AUTO_CONNECT) {
+            setSinkPriority(device, BluetoothA2dp.PRIORITY_AUTO_CONNECT);
+        }
         handleSinkStateChange(device, state, BluetoothA2dp.STATE_CONNECTING);
 
         if (!connectSinkNative(path)) {
@@ -491,14 +493,10 @@
             mTargetA2dpState = -1;
 
             if (getSinkPriority(device) > BluetoothA2dp.PRIORITY_OFF &&
-                    state == BluetoothA2dp.STATE_CONNECTING ||
                     state == BluetoothA2dp.STATE_CONNECTED) {
                 // We have connected or attempting to connect.
                 // Bump priority
                 setSinkPriority(device, BluetoothA2dp.PRIORITY_AUTO_CONNECT);
-            }
-
-            if (state == BluetoothA2dp.STATE_CONNECTED) {
                 // We will only have 1 device with AUTO_CONNECT priority
                 // To be backward compatible set everyone else to have PRIORITY_ON
                 adjustOtherSinkPriorities(device);
@@ -515,14 +513,11 @@
     }
 
     private void adjustOtherSinkPriorities(BluetoothDevice connectedDevice) {
-        if (!mAdjustedPriority) {
-            for (BluetoothDevice device : mAdapter.getBondedDevices()) {
-                if (getSinkPriority(device) >= BluetoothA2dp.PRIORITY_AUTO_CONNECT &&
-                    !device.equals(connectedDevice)) {
-                    setSinkPriority(device, BluetoothA2dp.PRIORITY_ON);
-                }
+        for (BluetoothDevice device : mAdapter.getBondedDevices()) {
+            if (getSinkPriority(device) >= BluetoothA2dp.PRIORITY_AUTO_CONNECT &&
+                !device.equals(connectedDevice)) {
+                setSinkPriority(device, BluetoothA2dp.PRIORITY_ON);
             }
-            mAdjustedPriority = true;
         }
     }
 
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index 94f80cc..c877c5c 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -512,7 +512,14 @@
             authorized = a2dp.getSinkPriority(device) > BluetoothA2dp.PRIORITY_OFF;
             if (authorized) {
                 Log.i(TAG, "Allowing incoming A2DP / AVRCP connection from " + address);
-                mBluetoothService.notifyIncomingA2dpConnection(address);
+                // Some headsets try to connect AVCTP before AVDTP - against the recommendation
+                // If AVCTP connection fails, we get stuck in IncomingA2DP state in the state
+                // machine.  We don't handle AVCTP signals currently. We only send
+                // intents for AVDTP state changes. We need to handle both of them in
+                // some cases. For now, just don't move to incoming state in this case.
+                if (!BluetoothUuid.isAvrcpTarget(uuid)) {
+                    mBluetoothService.notifyIncomingA2dpConnection(address);
+                }
             } else {
                 Log.i(TAG, "Rejecting incoming A2DP / AVRCP connection from " + address);
             }
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 71b4ee2..4d4d309 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -2227,6 +2227,16 @@
         mA2dpService = a2dpService;
     }
 
+    public void sendProfileStateMessage(int profile, int cmd) {
+        Message msg = new Message();
+        msg.what = cmd;
+        if (profile == BluetoothProfileState.HFP) {
+            mHfpProfileState.sendMessage(msg);
+        } else if (profile == BluetoothProfileState.A2DP) {
+            mA2dpProfileState.sendMessage(msg);
+        }
+    }
+
     private static void log(String msg) {
         Log.d(TAG, msg);
     }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 6df5445..040bf15 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -784,6 +784,11 @@
     private EdgeGlow mEdgeGlowBottom;
     private EdgeGlow mEdgeGlowLeft;
     private EdgeGlow mEdgeGlowRight;
+    /*
+     * These manage the delta the user has pulled beyond the edges.
+     */
+    private int mOverscrollDeltaX;
+    private int mOverscrollDeltaY;
 
     // Used to match key downs and key ups
     private boolean mGotKeyDown;
@@ -2569,17 +2574,59 @@
             boolean clampedY) {
         mInOverScrollMode = false;
         int maxX = computeMaxScrollX();
+        int maxY = computeMaxScrollY();
         if (maxX == 0) {
             // do not over scroll x if the page just fits the screen
             scrollX = pinLocX(scrollX);
         } else if (scrollX < 0 || scrollX > maxX) {
             mInOverScrollMode = true;
         }
-        if (scrollY < 0 || scrollY > computeMaxScrollY()) {
+        if (scrollY < 0 || scrollY > maxY) {
             mInOverScrollMode = true;
         }
 
+        int oldX = mScrollX;
+        int oldY = mScrollY;
+
         super.scrollTo(scrollX, scrollY);
+
+        // Only show overscroll bars if there was no movement in any direction
+        // as a result of scrolling.
+        if (mEdgeGlowTop != null && oldY == mScrollY && oldX == mScrollX) {
+            // Don't show left/right glows if we fit the whole content.
+            // Also don't show if there was vertical movement.
+            if (maxX > 0) {
+                final int pulledToX = oldX + mOverscrollDeltaX;
+                if (pulledToX < 0) {
+                    mEdgeGlowLeft.onPull((float) mOverscrollDeltaX / getWidth());
+                    if (!mEdgeGlowRight.isFinished()) {
+                        mEdgeGlowRight.onRelease();
+                    }
+                } else if (pulledToX > maxX) {
+                    mEdgeGlowRight.onPull((float) mOverscrollDeltaX / getWidth());
+                    if (!mEdgeGlowLeft.isFinished()) {
+                        mEdgeGlowLeft.onRelease();
+                    }
+                }
+                mOverscrollDeltaX = 0;
+            }
+
+            if (maxY > 0 || getOverScrollMode() == OVER_SCROLL_ALWAYS) {
+                final int pulledToY = oldY + mOverscrollDeltaY;
+                if (pulledToY < 0) {
+                    mEdgeGlowTop.onPull((float) mOverscrollDeltaY / getHeight());
+                    if (!mEdgeGlowBottom.isFinished()) {
+                        mEdgeGlowBottom.onRelease();
+                    }
+                } else if (pulledToY > maxY) {
+                    mEdgeGlowBottom.onPull((float) mOverscrollDeltaY / getHeight());
+                    if (!mEdgeGlowTop.isFinished()) {
+                        mEdgeGlowTop.onRelease();
+                    }
+                }
+                mOverscrollDeltaY = 0;
+            }
+        }
     }
 
     /**
@@ -3947,6 +3994,16 @@
             // requestFormData, and it needs to have the correct nodePointer.
             mWebTextView.setNodePointer(nodePointer);
             mWebTextView.setType(nativeFocusCandidateType());
+            Rect paddingRect = nativeFocusCandidatePaddingRect();
+            if (paddingRect != null) {
+                // Use contentToViewDimension since these are the dimensions of
+                // the padding.
+                mWebTextView.setPadding(
+                        contentToViewDimension(paddingRect.left),
+                        contentToViewDimension(paddingRect.top),
+                        contentToViewDimension(paddingRect.right),
+                        contentToViewDimension(paddingRect.bottom));
+            }
             if (null == text) {
                 if (DebugFlags.WEB_VIEW) {
                     Log.v(LOGTAG, "rebuildWebTextView null == text");
@@ -5039,6 +5096,8 @@
                     if (!mAllowPanAndScale) {
                         return true;
                     }
+                    mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
+                    mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
                 }
                 x = mScaleDetector.getFocusX();
                 y = mScaleDetector.getFocusY();
@@ -5550,42 +5609,16 @@
             final int oldY = mScrollY;
             final int rangeX = computeMaxScrollX();
             final int rangeY = computeMaxScrollY();
+
+            if (mEdgeGlowTop != null) {
+                // Save the deltas for overscroll glow.
+                mOverscrollDeltaX = deltaX;
+                mOverscrollDeltaY = deltaY;
+            }
+
             overScrollBy(deltaX, deltaY, oldX, oldY,
                     rangeX, rangeY,
                     mOverscrollDistance, mOverscrollDistance, true);
-
-            if (mEdgeGlowTop != null) {
-                // Don't show left/right glows if we fit the whole content.
-                if (rangeX > 0) {
-                    final int pulledToX = oldX + deltaX;
-                    if (pulledToX < 0) {
-                        mEdgeGlowLeft.onPull((float) deltaX / getWidth());
-                        if (!mEdgeGlowRight.isFinished()) {
-                            mEdgeGlowRight.onRelease();
-                        }
-                    } else if (pulledToX > rangeX) {
-                        mEdgeGlowRight.onPull((float) deltaX / getWidth());
-                        if (!mEdgeGlowLeft.isFinished()) {
-                            mEdgeGlowLeft.onRelease();
-                        }
-                    }
-                }
-
-                if (rangeY > 0 || getOverScrollMode() == OVER_SCROLL_ALWAYS) {
-                    final int pulledToY = oldY + deltaY;
-                    if (pulledToY < 0) {
-                        mEdgeGlowTop.onPull((float) deltaY / getHeight());
-                        if (!mEdgeGlowBottom.isFinished()) {
-                            mEdgeGlowBottom.onRelease();
-                        }
-                    } else if (pulledToY > rangeY) {
-                        mEdgeGlowBottom.onPull((float) deltaY / getHeight());
-                        if (!mEdgeGlowTop.isFinished()) {
-                            mEdgeGlowTop.onRelease();
-                        }
-                    }
-                }
-            }
         }
         if (!getSettings().getBuiltInZoomControls()) {
             boolean showPlusMinus = mMinZoomScale < mMaxZoomScale;
@@ -7839,6 +7872,13 @@
     /* package */ native int      nativeFocusCandidateMaxLength();
     /* package */ native String   nativeFocusCandidateName();
     private native Rect     nativeFocusCandidateNodeBounds();
+    /**
+     * @return A Rect with left, top, right, bottom set to the corresponding
+     * padding values in the focus candidate, if it is a textfield/textarea with
+     * a style.  Otherwise return null.  This is not actually a rectangle; Rect
+     * is being used to pass four integers.
+     */
+    private native Rect     nativeFocusCandidatePaddingRect();
     /* package */ native int      nativeFocusCandidatePointer();
     private native String   nativeFocusCandidateText();
     private native int      nativeFocusCandidateTextSize();
diff --git a/core/java/android/widget/EdgeGlow.java b/core/java/android/widget/EdgeGlow.java
index c1a389a..416be86 100644
--- a/core/java/android/widget/EdgeGlow.java
+++ b/core/java/android/widget/EdgeGlow.java
@@ -33,10 +33,10 @@
     private static final int RECEDE_TIME = 1000;
 
     // Time it will take before a pulled glow begins receding
-    private static final int PULL_TIME = 250;
+    private static final int PULL_TIME = 167;
 
     // Time it will take for a pulled glow to decay to partial strength before release
-    private static final int PULL_DECAY_TIME = 10000;
+    private static final int PULL_DECAY_TIME = 1000;
 
     private static final float MAX_ALPHA = 0.8f;
     private static final float HELD_EDGE_ALPHA = 0.7f;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5be52c4..9080f96 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -92,6 +92,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewDebug;
+import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 import android.view.ViewParent;
 import android.view.ViewRoot;
@@ -4446,6 +4447,7 @@
         }
 
         hideControllers();
+        stopTextSelectionMode();
 
         switch (keyCode) {
             case KeyEvent.KEYCODE_DPAD_CENTER:
@@ -6852,8 +6854,17 @@
     }
 
     private void prepareCursorControllers() {
+        boolean windowSupportsHandles = false;
+
+        ViewGroup.LayoutParams params = getRootView().getLayoutParams();
+        if (params instanceof WindowManager.LayoutParams) {
+            WindowManager.LayoutParams windowParams = (WindowManager.LayoutParams) params;
+            windowSupportsHandles = windowParams.type < WindowManager.LayoutParams.FIRST_SUB_WINDOW
+                    || windowParams.type > WindowManager.LayoutParams.LAST_SUB_WINDOW;
+        }
+
         // TODO Add an extra android:cursorController flag to disable the controller?
-        if (mCursorVisible && mLayout != null) {
+        if (windowSupportsHandles && mCursorVisible && mLayout != null) {
             if (mInsertionPointCursorController == null) {
                 mInsertionPointCursorController = new InsertionPointCursorController();
             }
@@ -6861,7 +6872,7 @@
             mInsertionPointCursorController = null;
         }
 
-        if (textCanBeSelected() && mLayout != null) {
+        if (windowSupportsHandles && textCanBeSelected() && mLayout != null) {
             if (mSelectionModifierCursorController == null) {
                 mSelectionModifierCursorController = new SelectionModifierCursorController();
             }
diff --git a/core/java/com/android/internal/app/ShutdownThread.java b/core/java/com/android/internal/app/ShutdownThread.java
index d1aff2a..714b259 100644
--- a/core/java/com/android/internal/app/ShutdownThread.java
+++ b/core/java/com/android/internal/app/ShutdownThread.java
@@ -33,6 +33,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.os.Vibrator;
 import android.os.storage.IMountService;
 import android.os.storage.IMountShutdownObserver;
@@ -60,6 +61,9 @@
     private static boolean mReboot;
     private static String mRebootReason;
 
+    // Provides shutdown assurance in case the system_server is killed
+    public static final String SHUTDOWN_ACTION_PROPERTY = "sys.shutdown.requested";
+
     // static instance of this thread
     private static final ShutdownThread sInstance = new ShutdownThread();
     
@@ -195,7 +199,17 @@
                 actionDone();
             }
         };
-        
+
+        /*
+         * Write a system property in case the system_server reboots before we
+         * get to the actual hardware restart. If that happens, we'll retry at
+         * the beginning of the SystemServer startup.
+         */
+        {
+            String reason = (mReboot ? "1" : "0") + (mRebootReason != null ? mRebootReason : "");
+            SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason);
+        }
+
         Log.i(TAG, "Sending shutdown broadcast...");
         
         // First send the high-level shut down broadcast.
@@ -325,10 +339,21 @@
             }
         }
 
-        if (mReboot) {
-            Log.i(TAG, "Rebooting, reason: " + mRebootReason);
+        rebootOrShutdown(mReboot, mRebootReason);
+    }
+
+    /**
+     * Do not call this directly. Use {@link #reboot(Context, String, boolean)}
+     * or {@link #shutdown(Context, boolean)} instead.
+     *
+     * @param reboot true to reboot or false to shutdown
+     * @param reason reason for reboot
+     */
+    public static void rebootOrShutdown(boolean reboot, String reason) {
+        if (reboot) {
+            Log.i(TAG, "Rebooting, reason: " + reason);
             try {
-                Power.reboot(mRebootReason);
+                Power.reboot(reason);
             } catch (Exception e) {
                 Log.e(TAG, "Reboot failed, will attempt shutdown instead", e);
             }
diff --git a/core/java/com/trustedlogic/trustednfc/android/ILlcpConnectionlessSocket.aidl b/core/java/com/trustedlogic/trustednfc/android/ILlcpConnectionlessSocket.aidl
deleted file mode 100644
index 35746ad..0000000
--- a/core/java/com/trustedlogic/trustednfc/android/ILlcpConnectionlessSocket.aidl
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.trustedlogic.trustednfc.android;
-
-import com.trustedlogic.trustednfc.android.LlcpPacket;
-
-/**
- * TODO
- *
- * {@hide}
- */
-interface ILlcpConnectionlessSocket
-{
-
-    void        close(int nativeHandle);
-    int         getSap(int nativeHandle);
-    LlcpPacket  receiveFrom(int nativeHandle);
-    int        sendTo(int nativeHandle, in LlcpPacket packet);
-    
-}
\ No newline at end of file
diff --git a/core/java/com/trustedlogic/trustednfc/android/ILlcpSocket.aidl b/core/java/com/trustedlogic/trustednfc/android/ILlcpSocket.aidl
deleted file mode 100644
index e9169d8..0000000
--- a/core/java/com/trustedlogic/trustednfc/android/ILlcpSocket.aidl
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.trustedlogic.trustednfc.android;
-
-/**
- * TODO
- *
- * {@hide}
- */
-interface ILlcpSocket
-{
- 
-    int     close(int nativeHandle);
-    int     connect(int nativeHandle, int sap);
-    int     connectByName(int nativeHandle, String sn);
-    int     getConnectTimeout(int nativeHandle);
-    int     getLocalSap(int nativeHandle);
-    int     getLocalSocketMiu(int nativeHandle);
-    int     getLocalSocketRw(int nativeHandle);
-    int     getRemoteSocketMiu(int nativeHandle);
-    int     getRemoteSocketRw(int nativeHandle);
-    int     receive(int nativeHandle, out byte[] receiveBuffer);
-    int     send(int nativeHandle, in byte[] data);
-    void    setConnectTimeout(int nativeHandle, int timeout);
-    
-}
-
diff --git a/core/java/com/trustedlogic/trustednfc/android/INfcManager.aidl b/core/java/com/trustedlogic/trustednfc/android/INfcManager.aidl
deleted file mode 100644
index ce36ab2..0000000
--- a/core/java/com/trustedlogic/trustednfc/android/INfcManager.aidl
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.trustedlogic.trustednfc.android;
-
-import com.trustedlogic.trustednfc.android.ILlcpSocket;
-import com.trustedlogic.trustednfc.android.ILlcpServiceSocket;
-import com.trustedlogic.trustednfc.android.ILlcpConnectionlessSocket;
-import com.trustedlogic.trustednfc.android.INfcTag;
-import com.trustedlogic.trustednfc.android.IP2pTarget;
-import com.trustedlogic.trustednfc.android.IP2pInitiator;
-
-
-/**
- * Interface that allows controlling NFC activity.
- *
- * {@hide}
- */
-interface INfcManager
-{
-
-    ILlcpSocket                 getLlcpInterface();
-    ILlcpConnectionlessSocket   getLlcpConnectionlessInterface();
-    ILlcpServiceSocket          getLlcpServiceInterface();
-    INfcTag                     getNfcTagInterface();
-    IP2pTarget                  getP2pTargetInterface();
-    IP2pInitiator               getP2pInitiatorInterface();
-    
-    void    cancel();
-    int     createLlcpConnectionlessSocket(int sap);
-    int     createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength);
-    int     createLlcpSocket(int sap, int miu, int rw, int linearBufferLength);
-    int     deselectSecureElement();
-    boolean disable();
-    boolean enable();
-    int     getOpenTimeout();
-    String  getProperties(String param);
-    int[]   getSecureElementList();
-    int     getSelectedSecureElement();
-    boolean isEnabled();
-    int     openP2pConnection();
-    int     openTagConnection();
-    int     selectSecureElement(int seId);
-    void    setOpenTimeout(int timeout);
-    int     setProperties(String param, String value);
-
-}
-
diff --git a/core/java/com/trustedlogic/trustednfc/android/IP2pTarget.aidl b/core/java/com/trustedlogic/trustednfc/android/IP2pTarget.aidl
deleted file mode 100644
index 8dcdf18..0000000
--- a/core/java/com/trustedlogic/trustednfc/android/IP2pTarget.aidl
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.trustedlogic.trustednfc.android;
-
-/**
- * TODO
- *
- * {@hide}
- */
-interface IP2pTarget
-{
-
-    byte[]     getGeneralBytes(int nativeHandle);
-    int        getMode(int nativeHandle);
-    int    	   connect(int nativeHandle);
-    boolean    disconnect(int nativeHandle);
-    byte[]     transceive(int nativeHandle, in byte[] data);
- 
-}
\ No newline at end of file
diff --git a/core/java/com/trustedlogic/trustednfc/android/LlcpConnectionlessSocket.java b/core/java/com/trustedlogic/trustednfc/android/LlcpConnectionlessSocket.java
index 0270626..eccdeb13 100644
--- a/core/java/com/trustedlogic/trustednfc/android/LlcpConnectionlessSocket.java
+++ b/core/java/com/trustedlogic/trustednfc/android/LlcpConnectionlessSocket.java
@@ -24,7 +24,9 @@
 
 import java.io.IOException;
 
-import com.trustedlogic.trustednfc.android.internal.ErrorCodes;
+import android.nfc.ErrorCodes;
+import android.nfc.ILlcpConnectionlessSocket;
+import android.nfc.LlcpPacket;
 
 import android.os.RemoteException;
 import android.util.Log;
@@ -32,19 +34,19 @@
 /**
  * LlcpConnectionlessSocket represents a LLCP Connectionless object to be used
  * in a connectionless communication
- * 
+ *
  * @since AA02.01
  * @hide
  */
 public class LlcpConnectionlessSocket {
-	
-	
+
+
     private static final String TAG = "LlcpConnectionlessSocket";
 
     /**
      * The handle returned by the NFC service and used to identify the LLCP connectionless socket in
      * every call of this class.
-     * 
+     *
      * @hide
      */
     protected int mHandle;
@@ -52,15 +54,15 @@
 
     /**
      * The entry point for LLCP Connectionless socket operations.
-     * 
+     *
      * @hide
      */
     protected ILlcpConnectionlessSocket mService;
-	
-	
+
+
     /**
      * Internal constructor for the LlcpConnectionlessSocket class.
-     * 
+     *
      * @param service The entry point to the Nfc Service for  LLCP Connectionless socket  class.
      * @param handle The handle returned by the NFC service and used to identify
      *            the socket in subsequent calls.
@@ -73,7 +75,7 @@
 
     /**
      * Send data to a specific LLCP Connectionless client
-     * 
+     *
      * @param packet Service Access Point number related to a LLCP
      *            Connectionless client and a data buffer to send
      * @throws IOException if the LLCP link has been lost or deactivated.
@@ -93,7 +95,7 @@
 
     /**
      * Receive data from a LLCP Connectionless client
-     * 
+     *
      * @return data data received from a specific LLCP Connectionless client
      * @throws IOException if the LLCP link has been lost or deactivated.
      * @see LlcpPacket
@@ -106,7 +108,7 @@
 				return packet;
 			}else{
 				// Handle potential errors
-				throw new IOException();			
+				throw new IOException();
 			}
 		} catch (RemoteException e) {
 			Log.e(TAG, "RemoteException in receiveFrom(): ", e);
@@ -116,7 +118,7 @@
 
     /**
      * Close the created Connectionless socket.
-     * 
+     *
      * @since AA02.01
      */
     public void close() {
@@ -129,13 +131,13 @@
 
     /**
      * Returns the local Service Access Point number of the socket
-     * 
+     *
      * @return sap
      * @since AA02.01
      */
     public int getSap() {
     	int sap = 0;
-    	
+
     	try {
 			sap = mService.getSap(mHandle);
 
diff --git a/core/java/com/trustedlogic/trustednfc/android/LlcpServiceSocket.java b/core/java/com/trustedlogic/trustednfc/android/LlcpServiceSocket.java
index a152ecb1..1bdf72f 100644
--- a/core/java/com/trustedlogic/trustednfc/android/LlcpServiceSocket.java
+++ b/core/java/com/trustedlogic/trustednfc/android/LlcpServiceSocket.java
@@ -24,7 +24,9 @@
 
 import java.io.IOException;
 
-import com.trustedlogic.trustednfc.android.internal.ErrorCodes;
+import android.nfc.ErrorCodes;
+import android.nfc.ILlcpSocket;
+import android.nfc.ILlcpServiceSocket;
 
 import android.os.RemoteException;
 import android.util.Log;
@@ -32,7 +34,7 @@
 /**
  * LlcpServiceSocket represents a LLCP Service to be used in a
  * Connection-oriented communication
- * 
+ *
  * @since AA02.01
  * @hide
  */
@@ -43,19 +45,19 @@
 	/**
 	 * The handle returned by the NFC service and used to identify the LLCP
 	 * Service socket in every call of this class.
-	 * 
+	 *
 	 * @hide
 	 */
 	protected int mHandle;
 
 	/**
 	 * The entry point for LLCP Service socket operations.
-	 * 
+	 *
 	 * @hide
 	 */
 	protected ILlcpServiceSocket mService;
-	
-    private ILlcpSocket mLlcpSocketService;
+
+    private final ILlcpSocket mLlcpSocketService;
 
 	static LlcpException convertErrorToLlcpException(int errorCode) {
 		return convertErrorToLlcpException(errorCode, null);
@@ -83,7 +85,7 @@
 
 	/**
 	 * Internal constructor for the LlcpServiceSocket class.
-	 * 
+	 *
 	 * @param service
 	 *            The entry point to the Nfc Service for LlcpServiceSocket
 	 *            class.
@@ -101,14 +103,14 @@
 	/**
 	 * Wait for incomming connection request from a LLCP client and accept this
 	 * request
-	 * 
+	 *
 	 * @return socket object to be used to communicate with a LLCP client
-	 * 
+	 *
 	 * @throws IOException
 	 *             if the llcp link is lost or deactivated
 	 * @throws LlcpException
 	 *             if not enough ressources are available
-	 * 
+	 *
 	 * @see LlcpSocket
 	 * @since AA02.01
 	 */
@@ -124,7 +126,7 @@
 					throw convertErrorToLlcpException(handle);
 				}
 			}
-	        
+
 			// Build the public LlcpSocket object
 			return new LlcpSocket(mLlcpSocketService, handle);
 		} catch (RemoteException e) {
@@ -136,7 +138,7 @@
 
 	/**
 	 * Set the timeout for the accept request
-	 * 
+	 *
 	 * @param timeout
 	 *            value of the timeout for the accept request
 	 * @since AA02.01
@@ -151,7 +153,7 @@
 
 	/**
 	 * Get the timeout value of the accept request
-	 * 
+	 *
 	 * @return mTimeout
 	 * @since AA02.01
 	 */
@@ -166,7 +168,7 @@
 
 	/**
 	 * Close the created Llcp Service socket
-	 * 
+	 *
 	 * @since AA02.01
 	 */
 	public void close() {
diff --git a/core/java/com/trustedlogic/trustednfc/android/LlcpSocket.java b/core/java/com/trustedlogic/trustednfc/android/LlcpSocket.java
index e47160c..ebde3e1 100644
--- a/core/java/com/trustedlogic/trustednfc/android/LlcpSocket.java
+++ b/core/java/com/trustedlogic/trustednfc/android/LlcpSocket.java
@@ -24,7 +24,8 @@
 
 import java.io.IOException;
 
-import com.trustedlogic.trustednfc.android.internal.ErrorCodes;
+import android.nfc.ErrorCodes;
+import android.nfc.ILlcpSocket;
 
 import android.os.RemoteException;
 import android.util.Log;
@@ -32,7 +33,7 @@
 /**
  * LlcpClientSocket represents a LLCP Connection-Oriented client to be used in a
  * connection-oriented communication
- * 
+ *
  * @since AA02.01
  * @hide
  */
@@ -43,14 +44,14 @@
 	/**
 	 * The handle returned by the NFC service and used to identify the LLCP
 	 * socket in every call of this class.
-	 * 
+	 *
 	 * @hide
 	 */
 	protected int mHandle;
 
 	/**
 	 * The entry point for LLCP socket operations.
-	 * 
+	 *
 	 * @hide
 	 */
 	protected ILlcpSocket mService;
@@ -84,7 +85,7 @@
 
 	/**
 	 * Internal constructor for the LlcpSocket class.
-	 * 
+	 *
 	 * @param service
 	 *            The entry point to the Nfc Service for LlcpServiceSocket
 	 *            class.
@@ -100,7 +101,7 @@
 
 	/**
 	 * Connect request to a specific LLCP Service by its SAP.
-	 * 
+	 *
 	 * @param sap
 	 *            Service Access Point number of the LLCP Service
 	 * @throws IOException
@@ -128,7 +129,7 @@
 
 	/**
 	 * Connect request to a specific LLCP Service by its Service Name.
-	 * 
+	 *
 	 * @param sn
 	 *            Service Name of the LLCP Service
 	 * @throws IOException
@@ -156,7 +157,7 @@
 
 	/**
 	 * Set the timeout for the connect request
-	 * 
+	 *
 	 * @param timeout
 	 *            timeout value for the connect request
 	 * @since AA02.01
@@ -171,7 +172,7 @@
 
 	/**
 	 * Get the timeout value of the connect request
-	 * 
+	 *
 	 * @return mTimeout
 	 * @since AA02.01
 	 */
@@ -187,7 +188,7 @@
 	/**
 	 * Disconnect request to the connected LLCP socket and close the created
 	 * socket.
-	 * 
+	 *
 	 * @throws IOException
 	 *             if the LLCP has been lost or deactivated.
 	 * @since AA02.01
@@ -206,7 +207,7 @@
 
 	/**
 	 * Send data to the connected LLCP Socket.
-	 * 
+	 *
 	 * @throws IOException
 	 *             if the LLCP has been lost or deactivated.
 	 * @since AA02.01
@@ -220,12 +221,12 @@
 			}
 		} catch (RemoteException e) {
 			Log.e(TAG, "RemoteException in send(): ", e);
-		}		
+		}
 	}
 
 	/**
 	 * Receive data from the connected LLCP socket
-	 * 
+	 *
 	 * @param receiveBuffer
 	 *            a buffer for the received data
 	 * @return length length of the data received
@@ -242,14 +243,14 @@
 			}
 		} catch (RemoteException e) {
 			Log.e(TAG, "RemoteException in send(): ", e);
-		}	
-		
+		}
+
 		return receivedLength;
 	}
-	
+
 	/**
 	 * Returns the local Service Access Point number of the socket
-	 * 
+	 *
 	 * @return localSap
 	 * @since AA02.01
 	 */
@@ -264,7 +265,7 @@
 
 	/**
 	 * Returns the local Maximum Information Unit(MIU) of the socket
-	 * 
+	 *
 	 * @return miu
 	 * @since AA02.01
 	 */
@@ -279,7 +280,7 @@
 
 	/**
 	 * Returns the local Receive Window(RW) of the socket
-	 * 
+	 *
 	 * @return rw
 	 * @since AA02.01
 	 */
@@ -296,7 +297,7 @@
 	 * Returns the remote Maximum Information Unit(MIU) of the socket.
 	 * <p>
 	 * This method must be called when the socket is in CONNECTED_STATE
-	 * 
+	 *
 	 * @return remoteMiu
 	 * @throws LlcpException
 	 *             if the LlcpClientSocket is not in a CONNECTED_STATE
@@ -320,7 +321,7 @@
 	 * Returns the remote Receive Window(RW) of the connected remote socket.
 	 * <p>
 	 * This method must be called when the socket is in CONNECTED_STATE
-	 * 
+	 *
 	 * @return rw
 	 * @throws LlcpException
 	 *             if the LlcpClientSocket is not in a CONNECTED_STATE
diff --git a/core/java/com/trustedlogic/trustednfc/android/NdefMessage.java b/core/java/com/trustedlogic/trustednfc/android/NdefMessage.java
deleted file mode 100644
index f03b604..0000000
--- a/core/java/com/trustedlogic/trustednfc/android/NdefMessage.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * File            : NDEFMessage.java
- * Original-Author : Trusted Logic S.A. (Jeremie Corbier)
- * Created         : 05-10-2009
- */
-
-package com.trustedlogic.trustednfc.android;
-
-import java.util.LinkedList;
-import java.util.ListIterator;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Represents an NDEF message as specified by the <a
- * href="http://www.nfc-forum.org/">NFC Forum</a>.
- * 
- * @see NdefRecord
- * 
- * @since AA01.04
- * @hide
- */
-public class NdefMessage implements Parcelable {
-	/* Flag values */
-	private static final int FLAG_MB = 0x80;
-	private static final int FLAG_ME = 0x40;
-	private static final int FLAG_CF = 0x20;
-	private static final int FLAG_SR = 0x10;
-	private static final int FLAG_IL = 0x08;
-
-	/**
-	 * Array of {@link NdefRecord} composing this message.
-	 */
-	private NdefRecord[] mRecords;
-
-	/**
-	 * Builds an NDEF message.
-	 * 
-	 * @param data raw NDEF message data
-	 * 
-	 * @throws NFCException
-	 */
-	public NdefMessage(byte[] data) throws NfcException {
-		if (parseNdefMessage(data) == -1)
-			throw new NfcException("Error while parsing NDEF message");
-	}
-
-	/**
-	 * Builds an NDEF message.
-	 * 
-	 * @param records
-	 *            an array of already created NDEF records
-	 */
-	public NdefMessage(NdefRecord[] records) {
-		mRecords = new NdefRecord[records.length];
-
-		System.arraycopy(records, 0, mRecords, 0, records.length);
-	}
-
-	/**
-	 * Returns the NDEF message as a byte array.
-	 * 
-	 * @return the message as a byte array
-	 */
-	public byte[] toByteArray() {
-		if ((mRecords == null) || (mRecords.length == 0))
-			return null;
-
-		byte[] msg = {};
-
-		for (int i = 0; i < mRecords.length; i++) {
-			byte[] record = mRecords[i].toByteArray();
-			byte[] tmp = new byte[msg.length + record.length];
-
-			/* Make sure the Message Begin flag is set only for the first record */
-			if (i == 0)
-				record[0] |= FLAG_MB;
-			else
-				record[0] &= ~FLAG_MB;
-
-			/* Make sure the Message End flag is set only for the last record */
-			if (i == (mRecords.length - 1))
-				record[0] |= FLAG_ME;
-			else
-				record[0] &= ~FLAG_ME;
-
-			System.arraycopy(msg, 0, tmp, 0, msg.length);
-			System.arraycopy(record, 0, tmp, msg.length, record.length);
-
-			msg = tmp;
-		}
-
-		return msg;
-	}
-	
-	/**
-	* Returns an array of {@link NdefRecord} composing this message.
-	*
-	* @return mRecords
-	* 
-	* @since AA02.01
-	*/
-	public NdefRecord[] getRecords(){
-		return mRecords;
-	}
-	
-	private native int parseNdefMessage(byte[] data);
-
-    /**
-     * (Parcelable) Describe the parcel
-     * {@hide}
-     */
-    public int describeContents() {
-        return 0;
-    }
-
-    /**
-     * (Parcelable) Convert current object to a Parcel
-     * {@hide}
-     */
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mRecords.length);
-        dest.writeTypedArray(mRecords, 0);
-    }
-
-    /**
-     * Creator class, needed when implementing from Parcelable
-     * {@hide}
-     */
-    public static final Parcelable.Creator<NdefMessage> CREATOR = new Parcelable.Creator<NdefMessage>() {
-        public NdefMessage createFromParcel(Parcel in) {
-            int recordsLength = in.readInt();
-            NdefRecord[] records = new NdefRecord[recordsLength];
-            in.readTypedArray(records, NdefRecord.CREATOR);
-            return new NdefMessage(records);
-        }
-
-        public NdefMessage[] newArray(int size) {
-            return new NdefMessage[size];
-        }
-    };
-    
-}
diff --git a/core/java/com/trustedlogic/trustednfc/android/NdefRecord.java b/core/java/com/trustedlogic/trustednfc/android/NdefRecord.java
deleted file mode 100644
index a0257fe..0000000
--- a/core/java/com/trustedlogic/trustednfc/android/NdefRecord.java
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * File            : NdefRecord.java
- * Original-Author : Trusted Logic S.A. (Jeremie Corbier)
- * Created         : 05-10-2009
- */
-
-package com.trustedlogic.trustednfc.android;
-
-import android.location.Location;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * An NDEF record as specified by the <a href="http://www.nfc-forum.org/">NFC
- * Forum</a>.
- * 
- * @see NdefMessage
- * 
- * @since AA01.04
- * @hide
- */
-public class NdefRecord implements Parcelable {
-
-	/**
-	 * Type Name Format - Empty record
-	 */
-	public static final short TNF_EMPTY = 0x0;
-
-	/**
-	 * Type Name Format - NFC Forum-defined type
-	 */
-	public static final short TNF_WELL_KNOWN_TYPE = 0x1;
-
-	/**
-	 * Type Name Format - RFC2045 MIME type
-	 */
-	public static final short TNF_MIME_MEDIA_TYPE = 0x2;
-
-	/**
-	 * Type Name Format - Absolute URI
-	 */
-	public static final short TNF_ABSOLUTE_URI = 0x3;
-
-	/**
-	 * Type Name Format - User-defined type
-	 */
-	public static final short TNF_EXTERNAL_TYPE = 0x4;
-
-	/**
-	 * Type Name Format - Unknown type
-	 */
-	public static final short TNF_UNKNOWN = 0x5;
-
-	/**
-	 * Type Name Format - Unchanged. This TNF is used for chunked records, so
-	 * that middle records inherits from the first record's type.
-	 */
-	public static final short TNF_UNCHANGED = 0x6;
-
-	/**
-	 * NFC Forum-defined Type - Smart Poster
-	 */
-	public static final byte[] TYPE_SMART_POSTER = { 0x53, 0x70 };
-
-	/**
-	 * NFC Forum-defined Type - Text
-	 */
-	public static final byte[] TYPE_TEXT = { 0x54 };
-
-	/**
-	 * NFC Forum-defined Type - URI
-	 */
-	public static final byte[] TYPE_URI = { 0x55 };
-
-	/**
-	 * NFC Forum-defined Global Type - Connection Handover Request
-	 */
-	public static final byte[] TYPE_HANDOVER_REQUEST = { 0x48, 0x72 };
-
-	/**
-	 * NFC Forum-defined Global Type - Connection Handover Select
-	 */
-	public static final byte[] TYPE_HANDOVER_SELECT = { 0x48, 0x73 };
-
-	/**
-	 * NFC Forum-defined Global Type - Connection Handover Carrier
-	 */
-	public static final byte[] TYPE_HANDOVER_CARRIER = { 0x48, 0x63 };
-
-	/**
-	 * NFC Forum-defined Local Type - Alternative Carrier
-	 */
-	public static final byte[] TYPE_ALTERNATIVE_CARRIER = { 0x61, 0x63 };
-
-	/* Flag values */
-	private static final int FLAG_MB = 0x80;
-	private static final int FLAG_ME = 0x40;
-	private static final int FLAG_CF = 0x20;
-	private static final int FLAG_SR = 0x10;
-	private static final int FLAG_IL = 0x08;
-
-	/**
-	 * Record Flags
-	 */
-	private short mFlags = 0;
-
-	/**
-	 * Record Type Name Format
-	 */
-	private short mTnf = 0;
-
-	/**
-	 * Record Type
-	 */
-	private byte[] mType = null;
-
-	/**
-	 * Record Identifier
-	 */
-	private byte[] mId = null;
-
-	/**
-	 * Record Payload
-	 */
-	private byte[] mPayload = null;
-
-	/**
-	 * Creates an NdefRecord given its Type Name Format, its type, its id and
-	 * its.
-	 * 
-	 * @param tnf
-	 *            Type Name Format
-	 * @param type
-	 *            record type
-	 * @param id
-	 *            record id (optional, can be null)
-	 * @param data
-	 *            record payload
-	 */
-	public NdefRecord(short tnf, byte[] type, byte[] id, byte[] data) {
-		
-		/* generate flag */
-		mFlags = FLAG_MB | FLAG_ME;
-		
-		/* Determine if it is a short record */
-		if(data.length < 0xFF)
-		{
-			mFlags |= FLAG_SR;
-		}
-		
-		/* Determine if an id is present */
-		if(id.length != 0)
-		{
-			mFlags |= FLAG_IL;
-		}
-		
-		mTnf = tnf;
-		mType = (byte[]) type.clone();
-		mId = (byte[]) id.clone();
-		mPayload = (byte[]) data.clone();
-	}
-
-	/**
-	 * Appends data to the record's payload.
-	 * 
-	 * @param data
-	 *            Data to be added to the record.
-	 */
-	public void appendPayload(byte[] data) {
-		byte[] newPayload = new byte[mPayload.length + data.length];
-
-		System.arraycopy(mPayload, 0, newPayload, 0, mPayload.length);
-		System.arraycopy(data, 0, newPayload, mPayload.length, data.length);
-
-		mPayload = newPayload;
-	}
-
-	/**
-	 * Returns record as a byte array.
-	 * 
-	 * @return record as a byte array.
-	 */
-	public byte[] toByteArray() {
-		return generate(mFlags, mTnf, mType, mId, mPayload);
-	}
-
-	private native byte[] generate(short flags, short tnf, byte[] type,
-			byte[] id, byte[] data);
-
-    /**
-     * (Parcelable) Describe the parcel
-     * {@hide}
-     */
-    public int describeContents() {
-        return 0;
-    }
-
-    /**
-     * (Parcelable) Convert current object to a Parcel
-     * {@hide}
-     */
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mTnf);
-        dest.writeInt(mType.length);
-        dest.writeByteArray(mType);
-        dest.writeInt(mId.length);
-        dest.writeByteArray(mId);
-        dest.writeInt(mPayload.length);
-        dest.writeByteArray(mPayload);
-    }
-
-    /**
-     * Creator class, needed when implementing from Parcelable
-     * {@hide}
-     */
-    public static final Parcelable.Creator<NdefRecord> CREATOR = new Parcelable.Creator<NdefRecord>() {
-        public NdefRecord createFromParcel(Parcel in) {
-            // TNF
-            short tnf = (short)in.readInt();
-            // Type
-            int typeLength = in.readInt();
-            byte[] type = new byte[typeLength];
-            in.readByteArray(type);
-            // ID
-            int idLength = in.readInt();
-            byte[] id = new byte[idLength];
-            in.readByteArray(id);
-            // Payload
-            int payloadLength = in.readInt();
-            byte[] payload = new byte[payloadLength];
-            in.readByteArray(payload);
-            
-            return new NdefRecord(tnf, type, id, payload);
-        }
-
-        public NdefRecord[] newArray(int size) {
-            return new NdefRecord[size];
-        }
-    };
-    
-    /**
-     * Returns record TNF
-     * 
-     * @return mTnf
-     */
-    public int getTnf(){
-    	return mTnf;
-    }
-    
-    /**
-     * Returns record TYPE
-     * 
-     * @return mType
-     */
-    public byte[] getType(){
-    	return mType;
-    }
-   
-    /**
-     * Returns record ID
-     * 
-     * @return mId
-     */
-    public byte[] getId(){
-    	return mId;
-    }
-    
-    /**
-     * Returns record Payload
-     * 
-     * @return mPayload
-     */
-    public byte[] getPayload(){
-    	return mPayload;
-    }
-    
-}
diff --git a/core/java/com/trustedlogic/trustednfc/android/NdefTag.java b/core/java/com/trustedlogic/trustednfc/android/NdefTag.java
deleted file mode 100644
index 1d99241..0000000
--- a/core/java/com/trustedlogic/trustednfc/android/NdefTag.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * File            : NDEFTag.java
- * Original-Author : Trusted Logic S.A. (Jeremie Corbier)
- * Created         : 04-12-2009
- */
-
-package com.trustedlogic.trustednfc.android;
-
-import java.io.IOException;
-
-import android.os.RemoteException;
-import android.util.Log;
-
-/**
- * NdefTag represents tags complying with the NFC Forum's NFC Data Exchange
- * Format.
- * 
- * @since AA01.04
- * @hide
- */
-public class NdefTag extends NfcTag {
-
-    private static final String TAG = "NdefTag";
-
-
-    public NdefTag(NfcTag tag){
-		super(tag.mService,tag.mHandle);
-		this.isConnected = tag.isConnected; 
-		this.isClosed = tag.isClosed;
-		tag.isClosed = false;
-    }
-    
-    /**
-     * Internal constructor for the NfcNdefTag class.
-     * 
-     * @param service The entry point to the Nfc Service for NfcNdefTag class.
-     * @param handle The handle returned by the NFC service and used to identify
-     *            the tag in subsequent calls.
-     * @hide
-     */
-    NdefTag(INfcTag service, int handle) {
-        super(service, handle);
-    }
-
-    /**
-     * Read NDEF data from an NDEF tag.
-     * 
-     * @return the NDEF message read from the tag.
-     * @throws NfcException if the tag is not NDEF-formatted.
-     * @throws IOException if the target has been lost or the connection has
-     *             been closed.
-     * @see NdefMessage
-     */
-    public NdefMessage read() throws NfcException, IOException {
-        // Check state
-        checkState();
-        
-        //Check if the tag is Ndef compliant
-        if(isNdef != true){
-            isNdef = isNdef();
-            if(isNdef != true) {
-                throw new NfcException("Tag is not NDEF compliant");
-            }
-        }
-
-        // Perform transceive
-        try {
-            NdefMessage msg = mService.read(mHandle);
-            if (msg == null) {
-                throw new IOException("NDEF read failed");
-            }
-            return msg;
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in read(): ", e);
-            return null;
-        }
-    }
-
-    /**
-     * Write NDEF data to an NDEF-compliant tag.
-     * 
-     * @param msg NDEF message to be written to the tag.
-     * @throws NfcException if the tag is not NDEF formatted.
-     * @throws IOException if the target has been lost or the connection has
-     *             been closed.
-     * @see NdefMessage
-     */
-    public void write(NdefMessage msg) throws NfcException, IOException {
-        // Check state
-        checkState();
-        
-        //Check if the tag is Ndef compliant
-        if(isNdef != true){
-            isNdef = isNdef();
-            if(isNdef != true) {
-                throw new NfcException("Tag is not NDEF compliant");
-            }
-        }
-
-        // Perform transceive
-        try {
-            boolean isSuccess = mService.write(mHandle, msg);
-            if (!isSuccess) {
-                throw new IOException("NDEF write failed");
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in write(): ", e);
-        }
-    }
-}
diff --git a/core/java/com/trustedlogic/trustednfc/android/NfcManager.java b/core/java/com/trustedlogic/trustednfc/android/NfcManager.java
deleted file mode 100644
index 98ab5bf..0000000
--- a/core/java/com/trustedlogic/trustednfc/android/NfcManager.java
+++ /dev/null
@@ -1,656 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * File            : NfcManager.java
- * Original-Author : Trusted Logic S.A. (Jeremie Corbier)
- * Created         : 26-08-2009
- */
-
-package com.trustedlogic.trustednfc.android;
-
-import java.io.IOException;
-
-import com.trustedlogic.trustednfc.android.internal.ErrorCodes;
-
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.media.MiniThumbFile;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.util.Log;
-
-//import android.util.Log;
-
-/**
- * This class provides the primary API for managing all aspects of NFC. Get an
- * instance of this class by calling
- * Context.getSystemService(Context.NFC_SERVICE).
- * @hide
- */
-public final class NfcManager {
-    /**
-     * Tag Reader Discovery mode
-     */
-    private static final int DISCOVERY_MODE_TAG_READER = 0;
-
-    /**
-     * NFC-IP1 Peer-to-Peer mode Enables the manager to act as a peer in an
-     * NFC-IP1 communication. Implementations should not assume that the
-     * controller will end up behaving as an NFC-IP1 target or initiator and
-     * should handle both cases, depending on the type of the remote peer type.
-     */
-    private static final int DISCOVERY_MODE_NFCIP1 = 1;
-
-    /**
-     * Card Emulation mode Enables the manager to act as an NFC tag. Provided
-     * that a Secure Element (an UICC for instance) is connected to the NFC
-     * controller through its SWP interface, it can be exposed to the outside
-     * NFC world and be addressed by external readers the same way they would
-     * with a tag.
-     * <p>
-     * Which Secure Element is exposed is implementation-dependent.
-     * 
-     * @since AA01.04
-     */
-    private static final int DISCOVERY_MODE_CARD_EMULATION = 2;
-
-    /**
-     * Used as Parcelable extra field in
-     * {@link com.trustedlogic.trustednfc.android.NfcManager#NDEF_TAG_DISCOVERED_ACTION}
-     * . It contains the NDEF message read from the NDEF tag discovered.
-     */
-    public static final String NDEF_MESSAGE_EXTRA = "com.trustedlogic.trustednfc.android.extra.NDEF_MESSAGE";
-
-    /**
-     * Broadcast Action: a NDEF tag has been discovered.
-     * <p>
-     * Always contains the extra field
-     * {@link com.trustedlogic.trustednfc.android.NfcManager#NDEF_MESSAGE_EXTRA}.
-     * <p class="note">
-     * <strong>Note:</strong> Requires the NFC_NOTIFY permission.
-     */
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String NDEF_TAG_DISCOVERED_ACTION = "com.trustedlogic.trustednfc.android.action.NDEF_TAG_DISCOVERED";
-
-    /**
-     * Used as byte array extra field in
-     * {@link com.trustedlogic.trustednfc.android.NfcManager#TRANSACTION_DETECTED_ACTION}
-     * . It contains the AID of the applet concerned by the transaction.
-     */
-    public static final String AID_EXTRA = "com.trustedlogic.trustednfc.android.extra.AID";
-
-    /**
-     * Broadcast Action: a transaction with a secure element has been detected.
-     * <p>
-     * Always contains the extra field
-     * {@link com.trustedlogic.trustednfc.android.NfcManager#AID_EXTRA}
-     * <p class="note">
-     * <strong>Note:</strong> Requires the NFC_NOTIFY permission
-     */
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String TRANSACTION_DETECTED_ACTION = "com.trustedlogic.trustednfc.android.action.TRANSACTION_DETECTED";
-
-    /**
-     * LLCP link status: The LLCP link is activated.
-     * 
-     * @since AA02.01
-     */
-    public static final int LLCP_LINK_STATE_ACTIVATED = 0;
-
-    /**
-     * LLCP link status: The LLCP link is deactivated.
-     * 
-     * @since AA02.01
-     */
-    public static final int LLCP_LINK_STATE_DEACTIVATED = 1;
-
-    /**
-     * Used as int extra field in
-     * {@link com.trustedlogic.trustednfc.android.NfcManager#LLCP_LINK_STATE_CHANGED_ACTION}
-     * . It contains the new state of the LLCP link.
-     */
-    public static final String LLCP_LINK_STATE_CHANGED_EXTRA = "com.trustedlogic.trustednfc.android.extra.LLCP_LINK_STATE";
-
-    /**
-     * Broadcast Action: the LLCP link state changed.
-     * <p>
-     * Always contains the extra field
-     * {@link com.trustedlogic.trustednfc.android.NfcManager#LLCP_LINK_STATE_CHANGED_EXTRA}.
-     * <p class="note">
-     * <strong>Note:</strong> Requires the NFC_LLCP permission.
-     */
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String LLCP_LINK_STATE_CHANGED_ACTION = "com.trustedlogic.trustednfc.android.action.LLCP_LINK_STATE_CHANGED";
-
-    private static final String TAG = "NfcManager";
-
-    private Handler mHandler;
-
-    private INfcManager mService;
-
-    private INfcTag mNfcTagService;
-
-    private IP2pTarget mP2pTargetService;
-
-    private IP2pInitiator mP2pInitiatorService;
-
-    private ILlcpSocket mLlcpSocketService;
-
-    private ILlcpConnectionlessSocket mLlcpConnectionlessSocketService;
-
-    private ILlcpServiceSocket mLlcpServiceSocketService;
-
-    static NfcException convertErrorToNfcException(int errorCode) {
-        return convertErrorToNfcException(errorCode, null);
-    }
-
-    static NfcException convertErrorToNfcException(int errorCode, String message) {
-        if (message == null) {
-            message = "";
-        } else {
-            message = " (" + message + ")";
-        }
-
-        switch (errorCode) {
-            case ErrorCodes.ERROR_BUSY:
-                return new NfcException("Another operation is already pending" + message);
-            case ErrorCodes.ERROR_CANCELLED:
-                return new NfcException("Operation cancelled" + message);
-            case ErrorCodes.ERROR_TIMEOUT:
-                return new NfcException("Operation timed out" + message);
-            case ErrorCodes.ERROR_SOCKET_CREATION:
-                return new NfcException("Error during the creation of an Llcp socket:" + message);
-            case ErrorCodes.ERROR_SAP_USED:
-                return new NfcException("Error SAP already used:" + message);
-            case ErrorCodes.ERROR_SERVICE_NAME_USED:
-                return new NfcException("Error Service Name already used:" + message);
-            case ErrorCodes.ERROR_SOCKET_OPTIONS:
-                return new NfcException("Error Socket options:" + message);
-            case ErrorCodes.ERROR_INVALID_PARAM:
-                return new NfcException("Error Set Properties: invalid param" + message);
-            case ErrorCodes.ERROR_NFC_ON:
-                return new NfcException("Error Set Properties : NFC is ON" + message);
-            case ErrorCodes.ERROR_NOT_INITIALIZED:
-                return new NfcException("NFC is not running " + message);
-            case ErrorCodes.ERROR_SE_ALREADY_SELECTED:
-                return new NfcException("Secure Element already connected" + message);
-            case ErrorCodes.ERROR_NO_SE_CONNECTED:
-                return new NfcException("No Secure Element connected" + message);
-            case ErrorCodes.ERROR_SE_CONNECTED:
-                return new NfcException("A secure Element is already connected" + message);
-            default:
-                return new NfcException("Unkown error code " + errorCode + message);
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public NfcManager(INfcManager service, Handler handler) {
-        mService = service;
-        mHandler = handler;
-        try {
-            mNfcTagService = mService.getNfcTagInterface();
-            mP2pInitiatorService = mService.getP2pInitiatorInterface();
-            mP2pTargetService = mService.getP2pTargetInterface();
-            mLlcpServiceSocketService = mService.getLlcpServiceInterface();
-            mLlcpConnectionlessSocketService = mService.getLlcpConnectionlessInterface();
-            mLlcpSocketService = mService.getLlcpInterface();
-        } catch (RemoteException e) {
-            mLlcpSocketService = null;
-            mNfcTagService = null;
-            mP2pInitiatorService = null;
-            mP2pTargetService = null;
-            mLlcpConnectionlessSocketService = null;
-            mLlcpServiceSocketService = null;
-        }
-    }
-
-    /**
-     * Return the status of the NFC feature
-     * 
-     * @return mIsNfcEnabled
-     * @since AA02.01
-     */
-    public boolean isEnabled() {
-        try {
-            return mService.isEnabled();
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in isEnabled(): ", e);
-            return false;
-        }
-    }
-
-    /**
-     * Enable the NFC Feature
-     * <p class="note">
-     * <strong>Note:</strong> Requires the NFC_ADMIN permission
-     * 
-     * @throws NfcException if the enable failed
-     * @since AA02.01
-     */
-    public void enable() throws NfcException {
-        try {
-            boolean isSuccess = mService.enable();
-            if (isSuccess == false) {
-                throw new NfcException("NFC Service failed to enable");
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in enable(): ", e);
-        }
-    }
-
-    /**
-     * Disable the NFC feature
-     * <p class="note">
-     * <strong>Note:</strong> Requires the NFC_ADMIN permission
-     * 
-     * @throws NfcException if the disable failed
-     * @since AA02.01
-     */
-    public void disable() throws NfcException {
-        try {
-            boolean isSuccess = mService.disable();
-            if (isSuccess == false) {
-                throw new NfcException("NFC Service failed to disable");
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in disable(): ", e);
-        }
-    }
-
-    /**
-     * Get the list of the identifiers of the Secure Elements detected
-     * by the NFC controller.
-     * 
-     * @return list a list of Secure Element identifiers.
-     * @see #getSelectedSecureElement
-     * @see #selectSecureElement(int)
-     * @see #deselectSecureElement
-     * @since AA02.01
-     */
-    public int[] getSecureElementList() {
-        try {
-            return mService.getSecureElementList();
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in getSecureElementList(): ", e);
-            return null;
-        }
-    }
-
-    /**
-     * Get the identifier of the currently selected secure element.
-     * 
-     * @return id identifier of the currently selected Secure Element. 0 if none.
-     * @see #getSecureElementList
-     * @see #selectSecureElement(int)
-     * @see #deselectSecureElement
-     * @since AA02.01
-     */
-    public int getSelectedSecureElement() {
-        try {
-            return mService.getSelectedSecureElement();
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in getSelectedSecureElement(): ", e);
-            return -1;
-        }
-    }
-
-    /**
-     * Select a specific Secure Element by its identifier.
-     * <p class="note">
-     * <strong>Note:</strong> Requires the NFC_ADMIN permission
-     * 
-     * @throws NfcException if a or this secure element is already selected
-     * @see #getSecureElementList
-     * @see #getSelectedSecureElement
-     * @see #deselectSecureElement
-     * @since AA02.01
-     */
-    public void selectSecureElement(int seId) throws NfcException  {
-        try {
-           int status = mService.selectSecureElement(seId);
-           if(status != ErrorCodes.SUCCESS){
-               throw convertErrorToNfcException(status);
-           }
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in selectSecureElement(): ", e);
-        }
-    }
-
-    /**
-     * Deselect the currently selected Secure Element
-     * <p class="note">
-     * <strong>Note:</strong> Requires the NFC_ADMIN permission
-     * 
-     * @throws NfcException if no secure Element is selected
-     * @see #getSecureElementList
-     * @see #getSelectedSecureElement
-     * @see #selectSecureElement(int)
-     * @since AA02.01
-     */
-    public void deselectSecureElement() throws NfcException {
-        try {
-            int status = mService.deselectSecureElement();
-            if(status != ErrorCodes.SUCCESS){
-                throw convertErrorToNfcException(status);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in deselectSecureElement(): ", e);
-        }
-    }
-
-    /**
-     * Open a connection with a remote NFC peer
-     * 
-     * This method does not return while no remote NFC peer enters the field.
-     * <p class="note">
-     * <strong>Note:</strong> Requires the NFC_RAW permission
-     * 
-     * @return P2pDevice object to be used to communicate with the detected
-     *         peer.
-     * @throws IOException if the target has been lost or the connection has
-     *             been closed.
-     * @throws NfcException if an open is already started
-     * @see P2pDevice
-     * @see #getOpenTimeout
-     * @see #setOpenTimeout(int)
-     * @see #cancel
-     * @since AA02.01
-     */
-    public P2pDevice openP2pConnection() throws IOException, NfcException {
-        try {
-            int handle = mService.openP2pConnection();
-            // Handle potential errors
-            if (ErrorCodes.isError(handle)) {
-                if (handle == ErrorCodes.ERROR_IO) {
-                    throw new IOException();
-                } else {
-                    throw convertErrorToNfcException(handle);
-                }
-            }
-            // Build the public NfcTag object, depending on its type
-            if (mP2pTargetService.getMode(handle) == P2pDevice.MODE_P2P_TARGET) {
-                return new P2pTarget(mP2pTargetService, handle);
-            } else {
-                return new P2pInitiator(mP2pInitiatorService, handle);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in openTagConnection(): ", e);
-            return null;
-        }
-    }
-
-    /**
-     * Open a connection with a tag
-     *
-     * This method does not return while no tag enters the field.
-     * <p class="note">
-     * <strong>Note:</strong> Requires the NFC_RAW permission
-     * 
-     * @return tag object to be use to communicate with the detected NfcTag.
-     * @throws IOException if the target has been lost or the connection has
-     *             been closed.
-     * @throws NfcException if an open is already started
-     * @see NfcTag
-     * @see #getOpenTimeout
-     * @see #setOpenTimeout(int)
-     * @see #cancel
-     * @since AA02.01
-     */
-    public NfcTag openTagConnection() throws IOException, NfcException {
-        try {
-            int handle = mService.openTagConnection();
-            // Handle potential errors
-            if (ErrorCodes.isError(handle)) {
-                if (handle == ErrorCodes.ERROR_IO) {
-                    throw new IOException();
-                } else {
-                    throw convertErrorToNfcException(handle);
-                }
-            }
-            // Build the public NfcTag object
-            return new NfcTag(mNfcTagService, handle);
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in openTagConnection(): ", e);
-            return null;
-        }
-    }
-
-    /**
-     * Set the timeout for open requests
-     * <p class="note">
-     * <strong>Note:</strong> Requires the NFC_RAW permission
-     * 
-     * @param timeout value of the timeout for open request
-     * @see #openP2pConnection
-     * @see #openTagConnection
-     * @see #getOpenTimeout
-     * @since AA02.01
-     */
-    public void setOpenTimeout(int timeout) {
-        try {
-            mService.setOpenTimeout(timeout);
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in setOpenTimeout(): ", e);
-        }
-    }
-
-    /**
-     * Get the timeout value of open requests
-     * 
-     * @return mTimeout
-     * @see #setOpenTimeout(int)
-     * @since AA02.01
-     */
-    public int getOpenTimeout() {
-        try {
-            return mService.getOpenTimeout();
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in getOpenTimeout(): ", e);
-            return 0;
-        }
-    }
-
-    /**
-     * Cancel an openTagConnection or an openP2pConnection started
-     * <p class="note">
-     * <strong>Note:</strong> Requires the NFC_RAW permission
-     * 
-     * @see #openP2pConnection
-     * @see #openTagConnection
-     * @since AA02.01
-     */
-    public void cancel() {
-        try {
-            mService.cancel();
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in cancel(): ", e);
-        }
-    }
-
-    /**
-     * Creates a connectionless socket for a LLCP link and set its Service
-     * Access Point number (SAP)
-     * <p class="note">
-     * <strong>Note:</strong> Requires the NFC_LLCP permission
-     * 
-     * @param sap Service Access Point number related to the created
-     *            Connectionless socket.
-     * @return LlcpConnectionlessSocket object to be used in a LLCP
-     *         Connectionless communication.
-     * @throws IOException if the socket creation failed
-     * @throws NfcException if socket ressources are insufficicent
-     * @see LlcpConnectionlessSocket
-     * @since AA02.01
-     */
-    public LlcpConnectionlessSocket createLlcpConnectionlessSocket(int sap) throws IOException,
-            NfcException {
-
-        try {
-            int handle = mService.createLlcpConnectionlessSocket(sap);
-            // Handle potential errors
-            if (ErrorCodes.isError(handle)) {
-                if (handle == ErrorCodes.ERROR_IO) {
-                    throw new IOException();
-                } else {
-                    throw convertErrorToNfcException(handle);
-                }
-            }
-
-            // Build the public LlcpConnectionLess object
-            return new LlcpConnectionlessSocket(mLlcpConnectionlessSocketService, handle);
-
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in createLlcpConnectionlessSocket(): ", e);
-            return null;
-        }
-    }
-
-    /**
-     * Creates a LlcpServiceSocket for a LLCP link, set its Service Access Point
-     * number (SAP).
-     * <p>
-     * During a LLCP communication, the LlcpServiceSocket will create LlcpSocket
-     * to communicate with incoming LLCP clients. For that, a server socket need
-     * to have some informations as a working buffer length in order to handle
-     * incoming data and some options to define the LLCP communication.
-     * <p class="note">
-     * <strong>Note:</strong> Requires the NFC_LLCP permission
-     * 
-     * @param sap
-     * @param sn Service Name of the LlcpServiceSocket
-     * @param miu Maximum Information Unit (MIU) for a LlcpSocket created by the
-     *            LlcpServiceSocket
-     * @param rw Receive Window (RW) for a LlcpSocket created by the
-     *            LlcpServiceSocket
-     * @param linearBufferLength size of the memory space needed to handle
-     *            incoming data for every LlcpSocket created.
-     * @return LlcpServiceSocket object to be used as a LLCP Service in a
-     *         connection oriented communication.
-     * @throws IOException if the socket creation failed
-     * @throws NfcException if socket ressources are insufficicent
-     * @see LlcpServiceSocket
-     * @since AA02.01
-     */
-    public LlcpServiceSocket createLlcpServiceSocket(int sap, String sn, int miu, int rw,
-            int linearBufferLength) throws IOException, NfcException {
-        try {
-            int handle = mService.createLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
-            // Handle potential errors
-            if (ErrorCodes.isError(handle)) {
-                if (handle == ErrorCodes.ERROR_IO) {
-                    throw new IOException();
-                } else {
-                    throw convertErrorToNfcException(handle);
-                }
-            }
-
-            // Build the public LlcpServiceSocket object
-            return new LlcpServiceSocket(mLlcpServiceSocketService, mLlcpSocketService, handle);
-
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in createLlcpServiceSocket(): ", e);
-            return null;
-        }
-    }
-
-    /**
-     * Creates a LlcpSocket for a LLCP link with a specific Service Access Point
-     * number (SAP)
-     * <p>
-     * A LlcpSocket need to have a linear buffer in order to handle incoming
-     * data. This linear buffer will be used to store incoming data as a stream.
-     * Data will be readable later.
-     * <p class="note">
-     * <strong>Note:</strong> Requires the NFC_LLCP permission
-     * 
-     * @param sap Service Access Point number for the created socket
-     * @param miu Maximum Information Unit (MIU) of the communication socket
-     * @param rw Receive Window (RW) of the communication socket
-     * @param linearBufferLength size of the memory space needed to handle
-     *            incoming data with this socket
-     * @throws IOException if the socket creation failed
-     * @throws NfcException if socket ressources are insufficicent
-     * @see LlcpSocket
-     * @since AA02.01
-     */
-    public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)
-            throws IOException, NfcException {
-        try {
-            int handle = mService.createLlcpSocket(sap, miu, rw, linearBufferLength);
-            // Handle potential errors
-            if (ErrorCodes.isError(handle)) {
-                if (handle == ErrorCodes.ERROR_IO) {
-                    throw new IOException();
-                } else {
-                    throw convertErrorToNfcException(handle);
-                }
-            }
-            // Build the public LlcpSocket object
-            return new LlcpSocket(mLlcpSocketService, handle);
-
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in createLlcpSocket(): ", e);
-            return null;
-        }
-    }
-
-    /**
-     * Set different parameters like the NCIP General bytes, the LLCP link
-     * parameters and all tag discovery parameters.
-     * <p class="note">
-     * <strong>Note:</strong> Requires the NFC_ADMIN permission
-     * 
-     * @param param parameter to be updated with a new value
-     * @param value new value of the parameter
-     * @throws NfcException if incorrect parameters of NFC is ON
-     * @since AA02.01
-     */
-    public void setProperties(String param, String value) throws NfcException {
-        try {
-            int result = mService.setProperties(param, value);
-            // Handle potential errors
-            if (ErrorCodes.isError(result)) {
-                throw convertErrorToNfcException(result);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in setProperties(): ", e);
-        }
-    }
-
-    /**
-     * Get the value of different parameters like the NCFIP General bytes, the
-     * LLCP link parameters and all tag discovery parameters.
-     * 
-     * @param param parameter to be updated
-     * @return String value of the requested parameter
-     * @throws RemoteException
-     * @since AA02.01
-     */
-    public String getProperties(String param) {
-        String value;
-        try {
-            value = mService.getProperties(param);
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in getProperties(): ", e);
-            return null;
-        }
-        return value;
-    }
-
-}
diff --git a/core/java/com/trustedlogic/trustednfc/android/NfcTag.java b/core/java/com/trustedlogic/trustednfc/android/NfcTag.java
deleted file mode 100644
index 798c7e4..0000000
--- a/core/java/com/trustedlogic/trustednfc/android/NfcTag.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * File            : NFCTag.java
- * Original-Author : Trusted Logic S.A. (Daniel Tomas)
- * Created         : 26-02-2010
- */
-
-package com.trustedlogic.trustednfc.android;
-
-import java.io.IOException;
-
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.trustedlogic.trustednfc.android.internal.ErrorCodes;
-
-/**
- * This class represents tags with no known formatting. One can use the method
- * {@link #isNdef()} to determine if the tag can store NDEF-formatted messages.
- * <p>
- * 
- * <pre class="prettyprint">
- * if (tag.isNdef()) {
- *     NdefTag ndefTag = (NdefTag) tag;
- *     NdefMessage msg = ndefTag.read();
- * }
- * </pre>
- * 
- * @since AA01.04
- * @see NdefMessage
- * @hide
- */
-public class NfcTag {
-
-    private static final String TAG = "NfcTag";
-
-    /**
-     * The handle returned by the NFC service and used to identify the tag in
-     * every call of this class.
-     * 
-     * @hide
-     */
-    protected int mHandle;
-
-    /**
-     * The entry point for tag operations.
-     * 
-     * @hide
-     */
-    protected INfcTag mService;
-
-    /**
-     * Flag set when the object is closed and thus not usable any more.
-     * 
-     * @hide
-     */
-    protected boolean isClosed = false;
-
-    /**
-     * Flag set when the tag is connected.
-     * 
-     * @hide
-     */
-    protected boolean isConnected = false;
-    
-    /**
-     * Flag set when a check NDEF is performed.
-     * 
-     * @hide
-     */
-    protected boolean isNdef = false;
-
-    /**
-     * Check if tag is still opened.
-     * 
-     * @return data sent by the P2pInitiator.
-     * @throws NfcException if accessing a closed target.
-     * 
-     * @hide               
-     */
-    public void checkState() throws NfcException {
-        if (isClosed) {
-            throw new NfcException("Tag has been closed.");
-        }
-        if (!isConnected) {
-            throw new NfcException("Tag is not connected.");
-        }
-    }
-
-    /**
-     * Internal constructor for the NfcTag class.
-     * 
-     * @param service The entry point to the Nfc Service for NfcTag class.
-     * @param handle The handle returned by the NFC service and used to identify
-     *            the tag in subsequent calls.
-     * @hide
-     */
-    NfcTag(INfcTag service, int handle) {
-        this.mService = service;
-        this.mHandle = handle;
-    }
-
-    /**
-     * Connects to the tag. This shall be called prior to any other operation on
-     * the tag.
-     * 
-     * @throws IOException if the tag has been lost or the connection has been
-     *             closed.
-     * @throws nfcException if the tag is already in connected state.
-     */
-    public void connect() throws NfcException, IOException {
-        // Check state
-        if (isClosed) {
-            throw new NfcException("Tag has been closed.");
-        }
-        if (isConnected) {
-            throw new NfcException("Already connected");
-        }
-
-        // Perform connect
-        try {
-            int result = mService.connect(mHandle);
-            if (ErrorCodes.isError(result)) {
-                if (result == ErrorCodes.ERROR_IO) {
-                    throw new IOException("Failed to connect");
-                }
-                else {
-                    throw NfcManager.convertErrorToNfcException(result);
-                }
-            }
-            isConnected = true;
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in connect(): ", e);
-        }
-    }
-
-    /**
-     * Disconnects from the tag. This must be called so that other targets can
-     * be discovered. It restarts the NFC discovery loop.
-     * 
-     * @throws NfcException if the tag is already in disconnected state or not connected
-     */
-    public void close() throws NfcException {
-        // Check state
-        checkState();
-
-        try {
-            mService.close(mHandle);
-            isClosed = true;
-            isConnected = false;
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in close(): ", e);
-        }
-    }
-
-    /**
-     * Exchanges raw data with the tag, whatever the tag type.
-     * 
-     * To exchange APDUs with a ISO14443-4-compliant tag, the data parameter
-     * must be filled with the C-APDU (CLA, INS, P1, P2 [, ...]). The returned
-     * data consists of the R-APDU ([...,] SW1, SW2).
-     * 
-     * @param data data to be sent to the tag
-     * @return data sent in response by the tag
-     * @throws IOException if the tag has been lost or the connection has been
-     *             closed.
-     * @throws NfcException in case of failure within the stack
-     */
-    public byte[] transceive(byte[] data) throws IOException, NfcException {
-        // Check state
-        checkState();
-
-        // Perform transceive
-        try {
-            byte[] response = mService.transceive(mHandle, data);
-            if (response == null) {
-                throw new IOException("Transceive failed");
-            }
-            return response;
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in transceive(): ", e);
-            return null;
-        }
-    }
-
-    /**
-     * Checks whether tag is NDEF-compliant or not.
-     * 
-     * @return true if the tag is NDEF-compliant, false otherwise
-     * @throws NfcException in case an error occurred when trying to determine
-     *             whether the tag is NDEF-compliant
-     */
-    public boolean isNdef() throws NfcException {
-        // Check state
-        checkState();
-
-        // Perform Check Ndef
-        try {
-            isNdef = mService.isNdef(mHandle);
-            return isNdef;
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in isNdef(): ", e);
-            return false;
-        }
-    }
-
-    /**
-     * Returns target type. constants.
-     * 
-     * @return tag type.
-     */
-    public String getType() {
-        try {
-            return mService.getType(mHandle);
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in getType(): ", e);
-            return null;
-        }
-    }
-    
-    /**
-     * Returns target UID.
-     * 
-     * @return tag UID.
-     */
-    public byte[] getUid() {
-        try {
-            return mService.getUid(mHandle);
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in getType(): ", e);
-            return null;
-        }
-    }
-
-}
diff --git a/core/java/com/trustedlogic/trustednfc/android/P2pInitiator.java b/core/java/com/trustedlogic/trustednfc/android/P2pInitiator.java
index 0f28ae0..6b93bce 100644
--- a/core/java/com/trustedlogic/trustednfc/android/P2pInitiator.java
+++ b/core/java/com/trustedlogic/trustednfc/android/P2pInitiator.java
@@ -23,15 +23,14 @@
 
 import java.io.IOException;
 
-import com.trustedlogic.trustednfc.android.internal.ErrorCodes;
-
+import android.nfc.IP2pInitiator;
 import android.os.RemoteException;
 import android.util.Log;
 
 /**
  * P2pInitiator represents the initiator in an NFC-IP1 peer-to-peer
  * communication.
- * 
+ *
  * @see P2pTarget
  * @since AA02.01
  * @hide
@@ -44,24 +43,24 @@
      * The entry point for P2P tag operations.
      * @hide
      */
-	private IP2pInitiator mService;
-	
+	private final IP2pInitiator mService;
+
     /**
      * Internal constructor for the P2pInitiator class.
-     * 
+     *
      * @param handle The handle returned by the NFC service and used to identify
      * 				 the tag in subsequent calls.
-     * 
+     *
      * @hide
      */
     P2pInitiator(IP2pInitiator service, int handle) {
         this.mService = service;
         this.mHandle = handle;
-    }	
+    }
 
     /**
      * Receives data from a P2pInitiator.
-     * 
+     *
      * @return data sent by the P2pInitiator.
      * @throws IOException if the target has been lost or if the connection has
      *             been closed.
@@ -81,7 +80,7 @@
 
     /**
      * Sends data to a P2pInitiator.
-     * 
+     *
      * @param data data to be sent to the P2pInitiator.
      * @throws IOException if the target has been lost or if the connection has
      *             been closed.
diff --git a/core/java/com/trustedlogic/trustednfc/android/P2pTarget.java b/core/java/com/trustedlogic/trustednfc/android/P2pTarget.java
index b5e00db..aa9e94f 100644
--- a/core/java/com/trustedlogic/trustednfc/android/P2pTarget.java
+++ b/core/java/com/trustedlogic/trustednfc/android/P2pTarget.java
@@ -23,14 +23,14 @@
 
 import java.io.IOException;
 
-import com.trustedlogic.trustednfc.android.internal.ErrorCodes;
-
+import android.nfc.ErrorCodes;
+import android.nfc.IP2pTarget;
 import android.os.RemoteException;
 import android.util.Log;
 
 /**
  * P2pTarget represents the target in an NFC-IP1 peer-to-peer communication.
- * 
+ *
  * @see P2pInitiator
  * @since AA02.01
  * @hide
@@ -43,27 +43,27 @@
      * The entry point for P2P tag operations.
      * @hide
      */
-	private IP2pTarget mService;
-	
+	private final IP2pTarget mService;
+
     /**
      * Flag set when the object is closed and thus not usable any more.
      * @hide
      */
-	private boolean isClosed = false;
-	
+	private final boolean isClosed = false;
+
     /**
      * Flag set when the tag is connected.
      * @hide
      */
 	private boolean isConnected = false;
-	
+
     /**
      * Check if tag is still opened.
-     * 
+     *
      * @return data sent by the P2pInitiator.
      * @throws NfcException if accessing a closed target.
-     * 
-     * @hide          
+     *
+     * @hide
      */
     public void checkState() throws NfcException {
     	if(isClosed) {
@@ -73,21 +73,21 @@
 
     /**
      * Internal constructor for the P2pTarget class.
-     * 
+     *
      * @param handle The handle returned by the NFC service and used to identify
      * 				 the tag in subsequent calls.
-     * 
+     *
      * @hide
      */
     P2pTarget(IP2pTarget service, int handle) {
         this.mService = service;
         this.mHandle = handle;
-    }	
+    }
 
     /**
      * Connects to the P2pTarget. This shall be called prior to any other
      * operation on the P2pTarget.
-     * 
+     *
      * @throws NfcException
      */
     public void connect() throws NfcException {
@@ -96,7 +96,7 @@
     	if (isConnected) {
     		throw new NfcException("Already connected");
     	}
-    	
+
     	// Perform connect
         try {
             int result = mService.connect(mHandle);
@@ -105,7 +105,8 @@
                     throw new NfcException("Failed to connect");
                 }
                 else {
-                    throw NfcManager.convertErrorToNfcException(result);
+      //              TODO(nxp)
+     //               throw NfcAdapter.convertErrorToNfcException(result);
                 }
             }
             isConnected = true;
@@ -117,7 +118,7 @@
     /**
      * Disconnects from the P2p Target. This must be called so that other
      * targets can be discovered. It restarts the NFC discovery loop.
-     * 
+     *
      * @throws NFCException
      */
     public void disconnect() throws NfcException {
@@ -132,7 +133,7 @@
 
     /**
      * Exchanges raw data with the P2pTarget.
-     * 
+     *
      * @param data data to be sent to the P2pTarget
      * @return data sent in response by the P2pTarget
      * @throws IOException if the target has been lost or the connection has
@@ -158,10 +159,11 @@
 
     /**
      * Get the General bytes of the connected P2P Target
-     * 
+     *
      * @return general bytes of the connected P2P Target
      * @throws IOException if the target in not in connected state
      */
+    @Override
     public byte[] getGeneralBytes() throws IOException {
         try {
             if(isConnected){
diff --git a/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpConnectionlessSocket.java b/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpConnectionlessSocket.java
index ccfbeb4..eff01b6 100644
--- a/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpConnectionlessSocket.java
+++ b/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpConnectionlessSocket.java
@@ -22,47 +22,47 @@
 
 package com.trustedlogic.trustednfc.android.internal;
 
-import com.trustedlogic.trustednfc.android.LlcpPacket;
+import android.nfc.LlcpPacket;
 
 /**
  * LlcpConnectionlessSocket represents a LLCP Connectionless object to be used
  * in a connectionless communication
- * 
+ *
  * @since AA02.01
- * {@hide}
+ * @hide
  */
 
 public class NativeLlcpConnectionlessSocket {
-	
-	private int mHandle;
-	
-	private int mSap;
-	
-	private int mLinkMiu;
-	
-	public NativeLlcpConnectionlessSocket(){;
-	}
-	
-	public NativeLlcpConnectionlessSocket(int sap){
-		mSap = sap;
-	}
-	
+
+    private int mHandle;
+
+    private int mSap;
+
+    private int mLinkMiu;
+
+    public NativeLlcpConnectionlessSocket(){;
+    }
+
+    public NativeLlcpConnectionlessSocket(int sap){
+        mSap = sap;
+    }
+
     public native boolean doSendTo(int sap, byte[] data);
 
     public native LlcpPacket doReceiveFrom(int linkMiu);
 
     public native boolean doClose();
-    
+
     public int getLinkMiu(){
-    	return mLinkMiu;
+        return mLinkMiu;
     }
-    
+
     public int getSap(){
-    	return mSap;
+        return mSap;
     }
-    
+
     public int getHandle(){
-    	return mHandle;
+        return mHandle;
     }
 
 }
diff --git a/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpServiceSocket.java b/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpServiceSocket.java
index a01f135..079d69b 100644
--- a/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpServiceSocket.java
+++ b/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpServiceSocket.java
@@ -30,53 +30,53 @@
 
 public class NativeLlcpServiceSocket {
 
-	private int mHandle;
-	
-	private int mLocalMiu;
-	
-	private int mLocalRw;
-	
-	private int mLocalLinearBufferLength;
-	
-	private int mSap;
-	
-	private int mTimeout;
-	
-	private String mServiceName;
-	
-	public NativeLlcpServiceSocket(){
-		
-	}
-	
-	public NativeLlcpServiceSocket(String serviceName){
-		mServiceName = serviceName;
-	}
-	
+    private int mHandle;
+
+    private int mLocalMiu;
+
+    private int mLocalRw;
+
+    private int mLocalLinearBufferLength;
+
+    private int mSap;
+
+    private int mTimeout;
+
+    private String mServiceName;
+
+    public NativeLlcpServiceSocket(){
+
+    }
+
+    public NativeLlcpServiceSocket(String serviceName){
+        mServiceName = serviceName;
+    }
+
     public native NativeLlcpSocket doAccept(int timeout, int miu, int rw, int linearBufferLength);
 
     public native boolean doClose();
-    
+
     public int getHandle(){
-    	return mHandle;
+        return mHandle;
     }
-    
+
     public void setAcceptTimeout(int timeout){
-    	mTimeout = timeout; 
+        mTimeout = timeout;
     }
-    
+
     public int getAcceptTimeout(){
-    	return mTimeout;
+        return mTimeout;
     }
-    
+
     public int getRw(){
-    	return mLocalRw;
+        return mLocalRw;
     }
-    
+
     public int getMiu(){
-    	return mLocalMiu;
+        return mLocalMiu;
     }
-    
+
     public int getLinearBufferLength(){
-    	return mLocalLinearBufferLength;
+        return mLocalLinearBufferLength;
     }
 }
diff --git a/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpSocket.java b/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpSocket.java
index 077c5e0..818cfaa 100644
--- a/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpSocket.java
+++ b/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpSocket.java
@@ -25,29 +25,29 @@
 /**
  * LlcpClientSocket represents a LLCP Connection-Oriented client to be used in a
  * connection-oriented communication
- * {@hide}
+ * @hide
  */
 
 public class NativeLlcpSocket {
-	
-	private int mHandle;
-	
-	private int mSap;
-	
-	private int mLocalMiu;
-	
-	private int mLocalRw;
-	
+
+    private int mHandle;
+
+    private int mSap;
+
+    private int mLocalMiu;
+
+    private int mLocalRw;
+
     private int mTimeout;
-    
+
     public NativeLlcpSocket(){
-    	
+
     }
-    
+
     public NativeLlcpSocket(int sap, int miu, int rw){
-    	mSap = sap;
-    	mLocalMiu = miu;
-    	mLocalRw = rw;
+        mSap = sap;
+        mLocalMiu = miu;
+        mLocalRw = rw;
     }
 
     public native boolean doConnect(int nSap, int timeout);
@@ -59,35 +59,35 @@
     public native boolean doSend(byte[] data);
 
     public native int doReceive(byte[] recvBuff);
-    
+
     public native int doGetRemoteSocketMiu();
-    
+
     public native int doGetRemoteSocketRw();
-    
-    
-    
+
+
+
     public void setConnectTimeout(int timeout){
-    	mTimeout = timeout;
+        mTimeout = timeout;
     }
-    
+
     public int getConnectTimeout(){
-    	return mTimeout;
+        return mTimeout;
     }
-    
+
     public int getSap(){
-    	return mSap;
+        return mSap;
     }
-    
+
     public int getMiu(){
-    	return mLocalMiu;
+        return mLocalMiu;
     }
-    
+
     public int getRw(){
-    	return mLocalRw;
+        return mLocalRw;
     }
-    
+
     public int getHandle(){
-    	return mHandle;
+        return mHandle;
     }
 
 }
diff --git a/core/java/com/trustedlogic/trustednfc/android/internal/NativeNdefTag.java b/core/java/com/trustedlogic/trustednfc/android/internal/NativeNdefTag.java
index d1e64a6..819b0395 100644
--- a/core/java/com/trustedlogic/trustednfc/android/internal/NativeNdefTag.java
+++ b/core/java/com/trustedlogic/trustednfc/android/internal/NativeNdefTag.java
@@ -25,7 +25,7 @@
 /**
  * Native interface to the NDEF tag functions
  *
- * {@hide}
+ * @hide
  */
 public class NativeNdefTag {
     private int mHandle;
diff --git a/core/java/com/trustedlogic/trustednfc/android/internal/NativeNfcManager.java b/core/java/com/trustedlogic/trustednfc/android/internal/NativeNfcManager.java
index 2f5a0f0..5ff348a 100644
--- a/core/java/com/trustedlogic/trustednfc/android/internal/NativeNfcManager.java
+++ b/core/java/com/trustedlogic/trustednfc/android/internal/NativeNfcManager.java
@@ -24,36 +24,40 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Handler;
 import android.os.Message;
 import android.util.Log;
 
-import com.trustedlogic.trustednfc.android.NfcManager;
-import com.trustedlogic.trustednfc.android.NdefMessage;
-import com.trustedlogic.trustednfc.android.NfcTag;
+import android.nfc.FormatException;
+import android.nfc.NdefTag;
+import android.nfc.NfcAdapter;
+import android.nfc.NdefMessage;
+import android.nfc.Tag;
 
 /**
- * Native interface to the NFC Manager functions {@hide}
+ * Native interface to the NFC Manager functions
+ * @hide
  */
 public class NativeNfcManager {
-    
+
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String INTERNAL_LLCP_LINK_STATE_CHANGED_EXTRA = "com.trustedlogic.trustednfc.android.extra.INTERNAL_LLCP_LINK_STATE";
 
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String INTERNAL_LLCP_LINK_STATE_CHANGED_ACTION = "com.trustedlogic.trustednfc.android.action.INTERNAL_LLCP_LINK_STATE_CHANGED";
-    
+
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String INTERNAL_TARGET_DESELECTED_ACTION = "com.trustedlogic.trustednfc.android.action.INTERNAL_TARGET_DESELECTED";
 
     /* Native structure */
     private int mNative;
 
-    private Context mContext;
+    private final Context mContext;
 
-    private Handler mNfcHandler;
+    private final Handler mNfcHandler;
 
     private static final String TAG = "NativeNfcManager";
 
@@ -92,10 +96,14 @@
      */
     public native void enableDiscovery(int mode);
 
+    public native void disableDiscovery();
+
+    public native void readerDiscovery();
+
     /**
      * Disables an NFCManager mode of operation. Allows to disable tag reader,
      * peer to peer initiator or target modes.
-     * 
+     *
      * @param mode discovery mode to enable. Must be one of the provided
      *            NFCManager.DISCOVERY_MODE_* constants.
      */
@@ -130,45 +138,81 @@
     public native boolean doActivateLlcp();
 
     private class NfcHandler extends Handler {
+
+        private int convertType(String typeName) {
+            if (typeName.equals("Iso14443")) {
+                return Tag.NFC_TAG_ISO14443_4B;
+            } else if (typeName.equals("MifareUL")) {
+                return Tag.NFC_TAG_MIFARE;
+            } else if (typeName.equals("Mifare1K")) {
+                return Tag.NFC_TAG_MIFARE;
+            } else if (typeName.equals("Mifare4K")) {
+                return Tag.NFC_TAG_MIFARE;
+            } else if (typeName.equals("MifareDESFIRE")) {
+                return Tag.NFC_TAG_MIFARE;
+            } else if (typeName.equals("Unknown Mifare")) {
+                return Tag.NFC_TAG_MIFARE;
+            } else if (typeName.equals("Felica")) {
+                return Tag.NFC_TAG_FELICA;
+            } else if (typeName.equals("Jewel")) {
+                return Tag.NFC_TAG_JEWEL;
+            } else {
+                return Tag.NFC_TAG_OTHER;
+            }
+        }
+
         @Override
         public void handleMessage(Message msg) {
 
             try {
                 switch (msg.what) {
                     case MSG_NDEF_TAG:
-                        Log.d(TAG, "Checking for NDEF tag message");
-                        NativeNfcTag tag = (NativeNfcTag) msg.obj;
-                        if (tag.doConnect()) {
-                            if (tag.checkNDEF()) {
-                                byte[] buff = tag.doRead();
+                        Log.d(TAG, "Tag detected, notifying applications");
+                        NativeNfcTag nativeTag = (NativeNfcTag) msg.obj;
+                        if (nativeTag.doConnect()) {
+                            if (nativeTag.checkNDEF()) {
+                                byte[] buff = nativeTag.doRead();
                                 if (buff != null) {
-                                    NdefMessage msgNdef = new NdefMessage(buff);
-                                    if (msgNdef != null) {
-                                        /* Send broadcast ordered */
-                                        Intent NdefMessageIntent = new Intent();
-                                        NdefMessageIntent
-                                                .setAction(NfcManager.NDEF_TAG_DISCOVERED_ACTION);
-                                        NdefMessageIntent.putExtra(NfcManager.NDEF_MESSAGE_EXTRA,
-                                                msgNdef);
-                                        Log.d(TAG, "NDEF message found, broadcasting to applications");
-                                        mContext.sendOrderedBroadcast(NdefMessageIntent,
-                                                android.Manifest.permission.NFC_NOTIFY);
-                                        /* Disconnect tag */
-                                        tag.doAsyncDisconnect();
+                                    NdefMessage[] msgNdef = new NdefMessage[1];
+                                    try {
+                                        msgNdef[0] = new NdefMessage(buff);
+                                        NdefTag tag = new NdefTag(convertType(nativeTag.getType()), nativeTag.getUid(), nativeTag.getHandle(), msgNdef);
+                                        Intent intent = new Intent();
+                                        intent.setAction(NfcAdapter.ACTION_NDEF_TAG_DISCOVERED);
+                                        intent.putExtra(NfcAdapter.EXTRA_TAG, tag);
+                                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                                        Log.d(TAG, "NDEF tag found, starting corresponding activity");
+                                        try {
+                                            mContext.startActivity(intent);
+                                        } catch (ActivityNotFoundException e) {
+                                            Log.w(TAG, "No activity found, disconnecting");
+                                            nativeTag.doAsyncDisconnect();
+                                        }
+                                    } catch (FormatException e) {
+                                        Log.w(TAG, "Unable to create NDEF message object (tag empty or not well formated)");
+                                        nativeTag.doAsyncDisconnect();
                                     }
                                 } else {
-                                   Log.w(TAG, "Unable to read NDEF message (tag empty or not well formated)");
-                                    /* Disconnect tag */
-                                    tag.doAsyncDisconnect();
+                                    Log.w(TAG, "Unable to read NDEF message (tag empty or not well formated)");
+                                    nativeTag.doAsyncDisconnect();
                                 }
                             } else {
-                                Log.d(TAG, "Tag is *not* NDEF compliant");
-                                /* Disconnect tag */
-                                tag.doAsyncDisconnect();
+                                Intent intent = new Intent();
+                                Tag tag = new Tag(convertType(nativeTag.getType()), false, nativeTag.getUid(), nativeTag.getHandle());
+                                intent.setAction(NfcAdapter.ACTION_TAG_DISCOVERED);
+                                intent.putExtra(NfcAdapter.EXTRA_TAG, tag);
+                                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                                Log.d(TAG, "Non-NDEF tag found, starting corresponding activity");
+                                try {
+                                    mContext.startActivity(intent);
+                                } catch (ActivityNotFoundException e) {
+                                    Log.w(TAG, "No activity found, disconnecting");
+                                    nativeTag.doAsyncDisconnect();
+                                }
                             }
                         } else {
-                            /* Disconnect tag */
-                            tag.doAsyncDisconnect();
+                            Log.w(TAG, "Failed to connect to tag");
+                            nativeTag.doAsyncDisconnect();
                         }
                         break;
                     case MSG_CARD_EMULATION:
@@ -176,8 +220,8 @@
                         byte[] aid = (byte[]) msg.obj;
                         /* Send broadcast ordered */
                         Intent TransactionIntent = new Intent();
-                        TransactionIntent.setAction(NfcManager.TRANSACTION_DETECTED_ACTION);
-                        TransactionIntent.putExtra(NfcManager.AID_EXTRA, aid);
+                        TransactionIntent.setAction(NfcAdapter.ACTION_TRANSACTION_DETECTED);
+                        TransactionIntent.putExtra(NfcAdapter.EXTRA_AID, aid);
                         Log.d(TAG, "Broadcasting Card Emulation event");
                         mContext.sendOrderedBroadcast(TransactionIntent,
                                 android.Manifest.permission.NFC_NOTIFY);
@@ -201,7 +245,7 @@
                                                 .setAction(INTERNAL_LLCP_LINK_STATE_CHANGED_ACTION);
                                         LlcpLinkIntent.putExtra(
                                                 INTERNAL_LLCP_LINK_STATE_CHANGED_EXTRA,
-                                                NfcManager.LLCP_LINK_STATE_ACTIVATED);
+                                                NfcAdapter.LLCP_LINK_STATE_ACTIVATED);
                                         Log.d(TAG, "Broadcasting internal LLCP activation");
                                         mContext.sendBroadcast(LlcpLinkIntent);
                                     }
@@ -223,7 +267,7 @@
                                     LlcpLinkIntent
                                             .setAction(INTERNAL_LLCP_LINK_STATE_CHANGED_ACTION);
                                     LlcpLinkIntent.putExtra(INTERNAL_LLCP_LINK_STATE_CHANGED_EXTRA,
-                                            NfcManager.LLCP_LINK_STATE_ACTIVATED);
+                                            NfcAdapter.LLCP_LINK_STATE_ACTIVATED);
                                     Log.d(TAG, "Broadcasting internal LLCP activation");
                                     mContext.sendBroadcast(LlcpLinkIntent);
                                 }
@@ -235,9 +279,9 @@
                         /* Broadcast Intent Link LLCP activated */
                         Log.d(TAG, "LLCP Link Deactivated message");
                         Intent LlcpLinkIntent = new Intent();
-                        LlcpLinkIntent.setAction(NfcManager.LLCP_LINK_STATE_CHANGED_ACTION);
-                        LlcpLinkIntent.putExtra(NfcManager.LLCP_LINK_STATE_CHANGED_EXTRA,
-                                NfcManager.LLCP_LINK_STATE_DEACTIVATED);
+                        LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
+                        LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
+                                NfcAdapter.LLCP_LINK_STATE_DEACTIVATED);
                         Log.d(TAG, "Broadcasting LLCP deactivation");
                         mContext.sendOrderedBroadcast(LlcpLinkIntent,
                                 android.Manifest.permission.NFC_LLCP);
diff --git a/core/java/com/trustedlogic/trustednfc/android/internal/NativeNfcTag.java b/core/java/com/trustedlogic/trustednfc/android/internal/NativeNfcTag.java
index b92783d..47cf45b 100644
--- a/core/java/com/trustedlogic/trustednfc/android/internal/NativeNfcTag.java
+++ b/core/java/com/trustedlogic/trustednfc/android/internal/NativeNfcTag.java
@@ -24,39 +24,48 @@
 
 /**
  * Native interface to the NFC tag functions
- * 
- * {@hide}
+ *
+ * @hide
  */
 public class NativeNfcTag {
-	private int mHandle;
+    private int mHandle;
 
-	private String mType;
-	
-	private byte[] mUid;
+    private String mType;
 
-	public native boolean doConnect();
+    private byte[] mUid;
 
-	public native boolean doDisconnect();
-	
-	public native void doAsyncDisconnect();
+    public native boolean doConnect();
 
-	public native byte[] doTransceive(byte[] data);
+    public native boolean doDisconnect();
 
-	public native boolean checkNDEF();
-	
+    public native void doAsyncDisconnect();
+
+    public native byte[] doTransceive(byte[] data);
+
+    public native boolean checkNDEF();
+
     public native byte[] doRead();
 
     public native boolean doWrite(byte[] buf);
 
-	public int getHandle() {
-		return mHandle;
-	}
-	
-	public String getType() {
-		return mType;
-	}
-	
-	public byte[] getUid() {
-		return mUid;
-	}
+    private NativeNfcTag() {
+    }
+
+    public NativeNfcTag(int handle, String type, byte[] uid) {
+        mHandle = handle;
+        mType = type;
+        mUid = uid.clone();
+    }
+
+    public int getHandle() {
+        return mHandle;
+    }
+
+    public String getType() {
+        return mType;
+    }
+
+    public byte[] getUid() {
+        return mUid;
+    }
 }
diff --git a/core/java/com/trustedlogic/trustednfc/android/internal/NativeP2pDevice.java b/core/java/com/trustedlogic/trustednfc/android/internal/NativeP2pDevice.java
index 75d25ba..c674309 100644
--- a/core/java/com/trustedlogic/trustednfc/android/internal/NativeP2pDevice.java
+++ b/core/java/com/trustedlogic/trustednfc/android/internal/NativeP2pDevice.java
@@ -24,52 +24,52 @@
 
 /**
  * Native interface to the P2P Initiator functions
- * 
- * {@hide}
+ *
+ * @hide
  */
 public class NativeP2pDevice {
-	
-	/**
-	* Peer-to-Peer Target.
-	*/
-	public static final short MODE_P2P_TARGET          = 0x00;
 
-	/**
-	* Peer-to-Peer Initiator.
-	*/
-	public static final short MODE_P2P_INITIATOR       = 0x01;
+    /**
+    * Peer-to-Peer Target.
+    */
+    public static final short MODE_P2P_TARGET          = 0x00;
 
-	/**
-	* Invalid target type.
-	*/
-	public static final short MODE_INVALID			   = 0xff;
+    /**
+    * Peer-to-Peer Initiator.
+    */
+    public static final short MODE_P2P_INITIATOR       = 0x01;
 
-	private int mHandle;
+    /**
+    * Invalid target type.
+    */
+    public static final short MODE_INVALID             = 0xff;
 
-	private int mMode;
+    private int mHandle;
 
-	private byte[] mGeneralBytes;
+    private int mMode;
 
-	public native byte[] doReceive();
+    private byte[] mGeneralBytes;
 
-	public native boolean doSend(byte[] data);
+    public native byte[] doReceive();
 
-	public native boolean doConnect();
+    public native boolean doSend(byte[] data);
 
-	public native boolean doDisconnect();
+    public native boolean doConnect();
 
-	public native byte[] doTransceive(byte[] data);
-	
-	public int getHandle() {
-		return mHandle;
-	}
+    public native boolean doDisconnect();
 
-	public int getMode() {
-		return mMode;
-	}
+    public native byte[] doTransceive(byte[] data);
 
-	public byte[] getGeneralBytes() {
-		return mGeneralBytes;
-	}
+    public int getHandle() {
+        return mHandle;
+    }
+
+    public int getMode() {
+        return mMode;
+    }
+
+    public byte[] getGeneralBytes() {
+        return mGeneralBytes;
+    }
 
 }
diff --git a/core/jni/android_content_res_ObbScanner.cpp b/core/jni/android_content_res_ObbScanner.cpp
index 2a9eacf..3fd7985 100644
--- a/core/jni/android_content_res_ObbScanner.cpp
+++ b/core/jni/android_content_res_ObbScanner.cpp
@@ -32,6 +32,7 @@
     jfieldID packageName;
     jfieldID version;
     jfieldID flags;
+    jfieldID salt;
 } gObbInfoClassInfo;
 
 static void doThrow(JNIEnv* env, const char* exc, const char* msg = NULL)
@@ -69,6 +70,14 @@
     env->SetObjectField(obbInfo, gObbInfoClassInfo.packageName, packageName);
     env->SetIntField(obbInfo, gObbInfoClassInfo.version, obb->getVersion());
     env->SetIntField(obbInfo, gObbInfoClassInfo.flags, obb->getFlags());
+
+    size_t saltLen;
+    const unsigned char* salt = obb->getSalt(&saltLen);
+    if (saltLen > 0) {
+        jbyteArray saltArray = env->NewByteArray(saltLen);
+        env->SetByteArrayRegion(saltArray, 0, saltLen, (jbyte*)salt);
+        env->SetObjectField(obbInfo, gObbInfoClassInfo.salt, saltArray);
+    }
 }
 
 /*
@@ -99,6 +108,8 @@
             "version", "I");
     GET_FIELD_ID(gObbInfoClassInfo.flags, gObbInfoClassInfo.clazz,
             "flags", "I");
+    GET_FIELD_ID(gObbInfoClassInfo.salt, gObbInfoClassInfo.clazz,
+            "salt", "[B");
 
     return AndroidRuntime::registerNativeMethods(env, "android/content/res/ObbScanner", gMethods,
             NELEM(gMethods));
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 43eeda8..ff079e4 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -86,9 +86,10 @@
     <protected-broadcast android:name="android.hardware.action.USB_DISCONNECTED" />
     <protected-broadcast android:name="android.hardware.action.USB_STATE" />
 
-    <protected-broadcast android:name="com.trustedlogic.trustednfc.android.action.NDEF_TAG_DISCOVERED" />
-    <protected-broadcast android:name="com.trustedlogic.trustednfc.android.action.TRANSACTION_DETECTED" />
-    <protected-broadcast android:name="com.trustedlogic.trustednfc.android.action.LLCP_LINK_STATE_CHANGED" />
+    <protected-broadcast android:name="android.nfc.action.NDEF_TAG_DISCOVERED" />
+    <protected-broadcast android:name="android.nfc.action.TAG_DISCOVERED" />
+    <protected-broadcast android:name="android.nfc.action.LLCP_LINK_STATE_CHANGED" />
+    <protected-broadcast android:name="android.nfc.action.TRANSACTION_DETECTED" />
 
     <!-- ====================================== -->
     <!-- Permissions for things that cost money -->
diff --git a/core/res/res/drawable-hdpi/ic_media_ff.png b/core/res/res/drawable-hdpi/ic_media_ff.png
index b0dc05b..0d9ecd0 100644
--- a/core/res/res/drawable-hdpi/ic_media_ff.png
+++ b/core/res/res/drawable-hdpi/ic_media_ff.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_next.png b/core/res/res/drawable-hdpi/ic_media_next.png
index 2552f4e..5ee97b6 100644
--- a/core/res/res/drawable-hdpi/ic_media_next.png
+++ b/core/res/res/drawable-hdpi/ic_media_next.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_pause.png b/core/res/res/drawable-hdpi/ic_media_pause.png
index d4670c2..a223f9a 100644
--- a/core/res/res/drawable-hdpi/ic_media_pause.png
+++ b/core/res/res/drawable-hdpi/ic_media_pause.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_play.png b/core/res/res/drawable-hdpi/ic_media_play.png
index e67ec80..746d3d2 100644
--- a/core/res/res/drawable-hdpi/ic_media_play.png
+++ b/core/res/res/drawable-hdpi/ic_media_play.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_previous.png b/core/res/res/drawable-hdpi/ic_media_previous.png
index 05eba71..b581a11 100644
--- a/core/res/res/drawable-hdpi/ic_media_previous.png
+++ b/core/res/res/drawable-hdpi/ic_media_previous.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_rew.png b/core/res/res/drawable-hdpi/ic_media_rew.png
index 88eed2e..4dd8739 100644
--- a/core/res/res/drawable-hdpi/ic_media_rew.png
+++ b/core/res/res/drawable-hdpi/ic_media_rew.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_green.png b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_green.png
index 4f95d50..b9fd0a4 100644
--- a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_green.png
+++ b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_green.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_red.png b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_red.png
index 10a37b7..94e947d 100644
--- a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_red.png
+++ b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_red.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_background.9.png b/core/res/res/drawable-hdpi/menu_background.9.png
index 1b43435..f4c9e08 100644
--- a/core/res/res/drawable-hdpi/menu_background.9.png
+++ b/core/res/res/drawable-hdpi/menu_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_background_fill_parent_width.9.png b/core/res/res/drawable-hdpi/menu_background_fill_parent_width.9.png
index ec974d6..a3cec11 100644
--- a/core/res/res/drawable-hdpi/menu_background_fill_parent_width.9.png
+++ b/core/res/res/drawable-hdpi/menu_background_fill_parent_width.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_bottom_dark.9.png b/core/res/res/drawable-hdpi/popup_bottom_dark.9.png
index 8b5d3d5..442105c 100755
--- a/core/res/res/drawable-hdpi/popup_bottom_dark.9.png
+++ b/core/res/res/drawable-hdpi/popup_bottom_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_center_medium.9.png b/core/res/res/drawable-hdpi/popup_center_medium.9.png
index 1ce2a6d..5129dbd 100755
--- a/core/res/res/drawable-hdpi/popup_center_medium.9.png
+++ b/core/res/res/drawable-hdpi/popup_center_medium.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_full_dark.9.png b/core/res/res/drawable-hdpi/popup_full_dark.9.png
index 8f2fdf0..c28465b 100755
--- a/core/res/res/drawable-hdpi/popup_full_dark.9.png
+++ b/core/res/res/drawable-hdpi/popup_full_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_top_dark.9.png b/core/res/res/drawable-hdpi/popup_top_dark.9.png
index 1108909..31f5f3b 100755
--- a/core/res/res/drawable-hdpi/popup_top_dark.9.png
+++ b/core/res/res/drawable-hdpi/popup_top_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_gps_on.png b/core/res/res/drawable-hdpi/stat_sys_gps_on.png
index 1e1ab32..150c9fc 100644
--- a/core/res/res/drawable-hdpi/stat_sys_gps_on.png
+++ b/core/res/res/drawable-hdpi/stat_sys_gps_on.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle.png b/core/res/res/drawable-hdpi/text_select_handle.png
deleted file mode 100644
index 80d48ab..0000000
--- a/core/res/res/drawable-hdpi/text_select_handle.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_ff.png b/core/res/res/drawable-mdpi/ic_media_ff.png
old mode 100755
new mode 100644
index ce7e195..d99779d
--- a/core/res/res/drawable-mdpi/ic_media_ff.png
+++ b/core/res/res/drawable-mdpi/ic_media_ff.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_next.png b/core/res/res/drawable-mdpi/ic_media_next.png
old mode 100755
new mode 100644
index 84f38e8..cee4930
--- a/core/res/res/drawable-mdpi/ic_media_next.png
+++ b/core/res/res/drawable-mdpi/ic_media_next.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_pause.png b/core/res/res/drawable-mdpi/ic_media_pause.png
old mode 100755
new mode 100644
index 688118e..c3dfcbd
--- a/core/res/res/drawable-mdpi/ic_media_pause.png
+++ b/core/res/res/drawable-mdpi/ic_media_pause.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_play.png b/core/res/res/drawable-mdpi/ic_media_play.png
old mode 100755
new mode 100644
index 7aa7af8..688e01d
--- a/core/res/res/drawable-mdpi/ic_media_play.png
+++ b/core/res/res/drawable-mdpi/ic_media_play.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_previous.png b/core/res/res/drawable-mdpi/ic_media_previous.png
old mode 100755
new mode 100644
index 1bba544..1be95b4
--- a/core/res/res/drawable-mdpi/ic_media_previous.png
+++ b/core/res/res/drawable-mdpi/ic_media_previous.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_rew.png b/core/res/res/drawable-mdpi/ic_media_rew.png
old mode 100755
new mode 100644
index 132df7f..8311508
--- a/core/res/res/drawable-mdpi/ic_media_rew.png
+++ b/core/res/res/drawable-mdpi/ic_media_rew.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_bottom_dark.9.png b/core/res/res/drawable-mdpi/popup_bottom_dark.9.png
index 76a2a7f..c21f982 100644
--- a/core/res/res/drawable-mdpi/popup_bottom_dark.9.png
+++ b/core/res/res/drawable-mdpi/popup_bottom_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_bottom_medium.9.png b/core/res/res/drawable-mdpi/popup_bottom_medium.9.png
index dee6d6b..0992135 100755
--- a/core/res/res/drawable-mdpi/popup_bottom_medium.9.png
+++ b/core/res/res/drawable-mdpi/popup_bottom_medium.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_full_dark.9.png b/core/res/res/drawable-mdpi/popup_full_dark.9.png
index 2305be4..84ba5ca0 100644
--- a/core/res/res/drawable-mdpi/popup_full_dark.9.png
+++ b/core/res/res/drawable-mdpi/popup_full_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_top_dark.9.png b/core/res/res/drawable-mdpi/popup_top_dark.9.png
index af511f2..2f847ad 100644
--- a/core/res/res/drawable-mdpi/popup_top_dark.9.png
+++ b/core/res/res/drawable-mdpi/popup_top_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_gps_on.png b/core/res/res/drawable-mdpi/stat_sys_gps_on.png
old mode 100755
new mode 100644
index a2c677d..70354b4
--- a/core/res/res/drawable-mdpi/stat_sys_gps_on.png
+++ b/core/res/res/drawable-mdpi/stat_sys_gps_on.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle.png b/core/res/res/drawable-mdpi/text_select_handle.png
deleted file mode 100644
index 93a5a15..0000000
--- a/core/res/res/drawable-mdpi/text_select_handle.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_left.png b/core/res/res/drawable-mdpi/text_select_handle_left.png
new file mode 100644
index 0000000..40e6ac0
--- /dev/null
+++ b/core/res/res/drawable-mdpi/text_select_handle_left.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_middle.png b/core/res/res/drawable-mdpi/text_select_handle_middle.png
index 201e7f9..9421759d 100644
--- a/core/res/res/drawable-mdpi/text_select_handle_middle.png
+++ b/core/res/res/drawable-mdpi/text_select_handle_middle.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_right.png b/core/res/res/drawable-mdpi/text_select_handle_right.png
new file mode 100644
index 0000000..9d2d08a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/text_select_handle_right.png
Binary files differ
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index a33851c..e799527 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -63,6 +63,9 @@
         <item>@drawable/scrollbar_handle_horizontal</item>
         <item>@drawable/scrollbar_handle_vertical</item>
         <item>@drawable/spinner_dropdown_background</item>
+        <item>@drawable/text_select_handle_left</item>
+        <item>@drawable/text_select_handle_middle</item>
+        <item>@drawable/text_select_handle_right</item>
         <item>@drawable/title_bar</item>
         <item>@drawable/title_bar_shadow</item>
         <!-- Visual lock screen -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 849c564..99fc5c2 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -149,9 +149,15 @@
          Software implementation will be used if config_hardware_auto_brightness_available is not set -->
     <bool name="config_automatic_brightness_available">false</bool>
 
+    <!-- Don't name config resources like this.  It should look like config_annoyDianne -->
+    <bool name="config_annoy_dianne">true</bool>
+
     <!-- If this is true, the screen will come on when you unplug usb/power/whatever. -->
     <bool name="config_unplugTurnsOnScreen">false</bool>
     
+    <!-- If this is true, the screen will fade off. -->
+    <bool name="config_animateScreenLights">true</bool>
+    
     <!-- XXXXXX END OF RESOURCES USING WRONG NAMING CONVENTION -->
 
     <!-- The number of degrees to rotate the display when the keyboard is open. -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5c60fd5..037a362 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -382,7 +382,7 @@
     <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgrouplab_storage">Storage</string>
     <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this.   [CHAR LIMIT=30] -->
-    <string name="permgroupdesc_storage" product="nosdcard">Access the shared storage.</string>
+    <string name="permgroupdesc_storage" product="nosdcard">Access the USB storage.</string>
     <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgroupdesc_storage" product="default">Access the SD card.</string>
 
@@ -890,29 +890,29 @@
     <string name="permdesc_mount_format_filesystems">Allows the application to format removable storage.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permlab_asec_access">get information on secure storage</string>
+    <string name="permlab_asec_access">get information on internal storage</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permdesc_asec_access">Allows the application to get information on secure storage.</string>
+    <string name="permdesc_asec_access">Allows the application to get information on internal storage.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permlab_asec_create">create secure storage</string>
+    <string name="permlab_asec_create">create internal storage</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permdesc_asec_create">Allows the application to create secure storage.</string>
+    <string name="permdesc_asec_create">Allows the application to create internal storage.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permlab_asec_destroy">destroy secure storage</string>
+    <string name="permlab_asec_destroy">destroy internal storage</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permdesc_asec_destroy">Allows the application to destroy secure storage.</string>
+    <string name="permdesc_asec_destroy">Allows the application to destroy internal storage.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permlab_asec_mount_unmount">mount / unmount secure storage</string>
+    <string name="permlab_asec_mount_unmount">mount / unmount internal storage</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permdesc_asec_mount_unmount">Allows the application to mount / unmount secure storage.</string>
+    <string name="permdesc_asec_mount_unmount">Allows the application to mount / unmount internal storage.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permlab_asec_rename">rename secure storage</string>
+    <string name="permlab_asec_rename">rename internal storage</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permdesc_asec_rename">Allows the application to rename secure storage.</string>
+    <string name="permdesc_asec_rename">Allows the application to rename internal storage.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_vibrate">control vibrator</string>
@@ -1227,11 +1227,11 @@
       user dictionary.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] -->
-    <string name="permlab_sdcardWrite" product="nosdcard">modify/delete shared storage contents</string>
+    <string name="permlab_sdcardWrite" product="nosdcard">modify/delete USB storage contents</string>
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_sdcardWrite" product="default">modify/delete SD card contents</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] -->
-    <string name="permdesc_sdcardWrite" product="nosdcard">Allows an application to write to the shared storage.</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard">Allows an application to write to the USB storage.</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_sdcardWrite" product="default">Allows an application to write to the SD card.</string>
 
@@ -2091,15 +2091,15 @@
     <!-- See USB_STORAGE.  USB_STORAGE_DIALOG:  After the user selects the notification, a dialog is shown asking if he wants to mount.  This is the title. -->
     <string name="usb_storage_title">USB connected</string>
     <!-- See USB_STORAGE.    This is the message. [CHAR LIMIT=NONE] -->
-    <string name="usb_storage_message" product="nosdcard">You have connected your phone to your computer via USB. Select the button below if you want to copy files between your computer and your Android\u2018s shared storage.</string>
+    <string name="usb_storage_message" product="nosdcard">You have connected your phone to your computer via USB. Select the button below if you want to copy files between your computer and your Android\u2018s USB storage.</string>
     <!-- See USB_STORAGE.    This is the message. -->
     <string name="usb_storage_message" product="default">You have connected your phone to your computer via USB. Select the button below if you want to copy files between your computer and your Android\u2018s SD card.</string>
     <!-- See USB_STORAGE.    This is the button text to mount the phone on the computer. -->
     <string name="usb_storage_button_mount">Turn on USB storage</string>
     <!-- See USB_STORAGE_DIALOG.  If there was an error mounting, this is the text. [CHAR LIMIT=NONE] -->
-    <string name="usb_storage_error_message" product="nosdcard">There is a problem using your shared storage for USB storage.</string>
+    <string name="usb_storage_error_message" product="nosdcard">There is a problem using your USB storage for USB mass storage.</string>
     <!-- See USB_STORAGE_DIALOG.  If there was an error mounting, this is the text. -->
-    <string name="usb_storage_error_message" product="default">There is a problem using your SD card for USB storage.</string>
+    <string name="usb_storage_error_message" product="default">There is a problem using your SD card for USB mass storage.</string>
     <!-- USB_STORAGE: When the user connects the phone to a computer via USB, we show a notification asking if he wants to share files across.  This is the title -->
     <string name="usb_storage_notification_title">USB connected</string>
     <!-- See USB_STORAGE. This is the message. -->
@@ -2115,7 +2115,7 @@
     <!-- See USB_STORAGE_STOP.  USB_STORAGE_STOP_DIALOG:  After the user selects the notification, a dialog is shown asking if he wants to stop usb storage.  This is the title. -->
     <string name="usb_storage_stop_title">USB storage in use</string>
     <!-- See USB_STORAGE_STOP.    This is the message. [CHAR LIMIT=NONE] -->
-    <string name="usb_storage_stop_message" product="nosdcard">Before turning off USB storage, make sure you have unmounted (\u201cejected\u201d) your Android\u2018s shared storage from your computer.</string>
+    <string name="usb_storage_stop_message" product="nosdcard">Before turning off USB storage, make sure you have unmounted (\u201cejected\u201d) your Android\u2018s USB storage from your computer.</string>
     <!-- See USB_STORAGE_STOP.    This is the message. -->
     <string name="usb_storage_stop_message" product="default">Before turning off USB storage, make sure you have unmounted (\u201cejected\u201d) your Android\u2018s SD card from your computer.</string>
     <!-- See USB_STORAGE_STOP.    This is the button text to stop usb storage. -->
@@ -2135,11 +2135,11 @@
     <!-- External media format dialog strings -->
     <!-- This is the label for the activity, and should never be visible to the user. -->
     <!-- See EXTMEDIA_FORMAT.  EXTMEDIA_FORMAT_DIALOG:  After the user selects the notification, a dialog is shown asking if he wants to format the SD card.  This is the title. [CHAR LIMIT=20] -->
-    <string name="extmedia_format_title" product="nosdcard">Format shared storage</string>
+    <string name="extmedia_format_title" product="nosdcard">Format USB storage</string>
     <!-- See EXTMEDIA_FORMAT.  EXTMEDIA_FORMAT_DIALOG:  After the user selects the notification, a dialog is shown asking if he wants to format the SD card.  This is the title. -->
     <string name="extmedia_format_title" product="default">Format SD card</string>
     <!-- See EXTMEDIA_FORMAT.   This is the message. [CHAR LIMIT=NONE] -->
-    <string name="extmedia_format_message" product="nosdcard">Format shared storage, erasing all files stored there?  Action cannot be reversed!</string>
+    <string name="extmedia_format_message" product="nosdcard">Format USB storage, erasing all files stored there?  Action cannot be reversed!</string>
     <!-- See EXTMEDIA_FORMAT.   This is the message. -->
     <string name="extmedia_format_message" product="default">Are you sure you want to format the SD card? All data on your card will be lost.</string>
     <!-- See EXTMEDIA_FORMAT.    This is the button text to format the sd card. -->
@@ -2167,49 +2167,49 @@
 
     <!-- External media notification strings -->
     <!-- Shown when external media is being checked [CHAR LIMIT=30] -->
-    <string name="ext_media_checking_notification_title" product="nosdcard">Preparing shared storage</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard">Preparing USB storage</string>
     <!-- Shown when external media is being checked -->
     <string name="ext_media_checking_notification_title" product="default">Preparing SD card</string>
     <string name="ext_media_checking_notification_message">Checking for errors.</string>
 
     <!-- Shown when external media is blank (or unsupported filesystem) [CHAR LIMIT=30] -->
-    <string name="ext_media_nofs_notification_title" product="nosdcard">Blank shared storage</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard">Blank USB storage</string>
     <!-- Shown when external media is blank (or unsupported filesystem) -->
     <string name="ext_media_nofs_notification_title" product="default">Blank SD card</string>
-    <!-- Shown when shared storage cannot be read.  [CHAR LIMIT=NONE] -->
-    <string name="ext_media_nofs_notification_message" product="nosdcard">Shared storage blank or has unsupported filesystem.</string>
+    <!-- Shown when USB storage cannot be read.  [CHAR LIMIT=NONE] -->
+    <string name="ext_media_nofs_notification_message" product="nosdcard">USB storage blank or has unsupported filesystem.</string>
     <string name="ext_media_nofs_notification_message" product="default">SD card blank or has unsupported filesystem.</string>
 
     <!-- Shown when external media is unmountable (corrupt)) [CHAR LIMIT=30] -->
-    <string name="ext_media_unmountable_notification_title" product="nosdcard">Damaged shared storage</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard">Damaged USB storage</string>
     <!-- Shown when external media is unmountable (corrupt)) -->
     <string name="ext_media_unmountable_notification_title" product="default">Damaged SD card</string>
-    <!-- Shown when shared storage cannot be read.  [CHAR LIMIT=NONE] -->
-    <string name="ext_media_unmountable_notification_message" product="nosdcard">Shared storage damaged. You may have to reformat it.</string>
+    <!-- Shown when USB storage cannot be read.  [CHAR LIMIT=NONE] -->
+    <string name="ext_media_unmountable_notification_message" product="nosdcard">USB storage damaged. You may have to reformat it.</string>
     <string name="ext_media_unmountable_notification_message" product="default">SD card damaged. You may have to reformat it.</string>
 
     <!-- Shown when external media is unsafely removed [CHAR LIMIT=30] -->
-    <string name="ext_media_badremoval_notification_title" product="nosdcard">Shared storage unexpectedly removed</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard">USB storage unexpectedly removed</string>
     <!-- Shown when external media is unsafely removed -->
     <string name="ext_media_badremoval_notification_title" product="default">SD card unexpectedly removed</string>
     <!-- Shown when external media is unsafely removed.  [CHAR LIMIT=NONE] -->
-    <string name="ext_media_badremoval_notification_message" product="nosdcard">Unmount shared storage before removing to avoid data loss.</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard">Unmount USB storage before removing to avoid data loss.</string>
     <string name="ext_media_badremoval_notification_message" product="default">Unmount SD card before removing to avoid data loss.</string>
 
     <!-- Shown when external media has been safely removed [CHAR LIMIT=30] -->
-    <string name="ext_media_safe_unmount_notification_title" product="nosdcard">Shared storage safe to remove</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard">USB storage safe to remove</string>
     <!-- Shown when external media has been safely removed -->
     <string name="ext_media_safe_unmount_notification_title" product="default">SD card safe to remove</string>
     <!-- Shown when external media has been safely removed.  [CHAR LIMIT=NONE] -->
-    <string name="ext_media_safe_unmount_notification_message" product="nosdcard">You can safely remove shared storage.</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard">You can safely remove USB storage.</string>
     <string name="ext_media_safe_unmount_notification_message" product="default">You can safely remove SD card.</string>
 
     <!-- Shown when external media is missing [CHAR LIMIT=30] -->
-    <string name="ext_media_nomedia_notification_title" product="nosdcard">Removed shared storage</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard">Removed USB storage</string>
     <!-- Shown when external media is missing -->
     <string name="ext_media_nomedia_notification_title" product="default">Removed SD card</string>
     <!-- Shown when external media is missing.  [CHAR LIMIT=NONE] -->
-    <string name="ext_media_nomedia_notification_message" product="nosdcard">Shared storage removed. Insert new media.</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard">USB storage removed. Insert new media.</string>
     <string name="ext_media_nomedia_notification_message" product="default">SD card removed. Insert a new one.</string>
 
     <!-- Shown in LauncherActivity when the requested target Intent didn't return any matching Activities, leaving the list empty. -->
diff --git a/core/tests/coretests/res/raw/test1.obb b/core/tests/coretests/res/raw/test1.obb
index 170e36f..8466588 100644
--- a/core/tests/coretests/res/raw/test1.obb
+++ b/core/tests/coretests/res/raw/test1.obb
Binary files differ
diff --git a/core/tests/coretests/res/raw/test1_wrongpackage.obb b/core/tests/coretests/res/raw/test1_wrongpackage.obb
index 2e02eaa..d0aafe1 100644
--- a/core/tests/coretests/res/raw/test1_wrongpackage.obb
+++ b/core/tests/coretests/res/raw/test1_wrongpackage.obb
Binary files differ
diff --git a/docs/html/guide/appendix/install-location.jd b/docs/html/guide/appendix/install-location.jd
index be89caf..914aa66 100644
--- a/docs/html/guide/appendix/install-location.jd
+++ b/docs/html/guide/appendix/install-location.jd
@@ -111,7 +111,7 @@
 <p class="caution"><strong>Caution:</strong> Although XML markup such as this will be ignored by
 older platforms, you must be careful not to use programming APIs introduced in API Level 8
 while your {@code minSdkVersion} is less than "8", unless you perform the work necessary to
-provide backward compatiblity in your code. For information about building
+provide backward compatibility in your code. For information about building
 backward compatibility in your application code, see the <a
 href="{@docRoot}resources/articles/backward-compatibility.html">Backward Compatibility</a>
 article.</p>
@@ -167,6 +167,10 @@
     <dd>Your {@link android.app.admin.DeviceAdminReceiver} and all its admin capabilities will
 be disabled, which can have unforeseeable consequences for the device functionality, which may
 persist after external storage is remounted.</dd>
+  <dt>Broadcast Receivers listening for "boot completed"</dt>
+    <dd>The system delivers the {@link android.content.Intent#ACTION_BOOT_COMPLETED} broadcast
+before the external storage is mounted to the device. If your application is installed on the
+external storage, it can never receive this broadcast.</dd>
 </dl>
 
 <p>If your application uses any of the features listed above, you <strong>should not</strong> allow
diff --git a/docs/html/guide/developing/testing/index.jd b/docs/html/guide/developing/testing/index.jd
index ea61cc3..2164705 100644
--- a/docs/html/guide/developing/testing/index.jd
+++ b/docs/html/guide/developing/testing/index.jd
@@ -1,6 +1,5 @@
 page.title=Testing Overview
 @jd:body
-
 <p>
     Android includes powerful tools for setting up and running test applications.
     Whether you are working in Eclipse with ADT or working from the command line, these tools
@@ -9,7 +8,7 @@
 </p>
 <p>
     If you aren't yet familiar with the Android testing framework, please read the topic
-    <a href="{@docRoot}guide/topics/testing/testing_android.html">Testing and Instrumentation</a>
+    <a href="{@docRoot}guide/topics/testing/testing_android.html">Testing Fundamentals</a>
     before you get started.
     For a step-by-step introduction to Android testing, try the <a
     href="{@docRoot}resources/tutorials/testing/helloandroid_test.html">Hello, Testing</a>
diff --git a/docs/html/guide/developing/testing/testing_eclipse.jd b/docs/html/guide/developing/testing/testing_eclipse.jd
index da1c0f0..ba7eaba 100644
--- a/docs/html/guide/developing/testing/testing_eclipse.jd
+++ b/docs/html/guide/developing/testing/testing_eclipse.jd
@@ -1,28 +1,23 @@
 page.title=Testing In Eclipse, with ADT
 @jd:body
-
 <div id="qv-wrapper">
-  <div id="qv">
-  <h2>In this document</h2>
-  <ol>
-    <li><a href="#CreateTestProjectEclipse">Creating a Test Project</a></li>
-    <li><a href="#CreateTestAppEclipse">Creating a Test Application</a></li>
-    <li><a href="#RunTestEclipse">Running Tests</a></li>
-  </ol>
-  </div>
+    <div id="qv">
+        <h2>In this document</h2>
+            <ol>
+                <li><a href="#CreateTestProjectEclipse">Creating a Test Project</a></li>
+                <li><a href="#CreateTestAppEclipse">Creating a Test Package</a></li>
+                <li><a href="#RunTestEclipse">Running Tests</a></li>
+            </ol>
+    </div>
 </div>
 <p>
-  This topic explains how create and run tests of Android applications in Eclipse with ADT.
-
-  with the basic processes for creating and running applications with ADT, as described in
-  <a href="{@docRoot}guide/developing/eclipse-adt.html">Developing In Eclipse, with ADT</a>.
-
-  Before you read this topic, you should read about how to create a Android application with the
-  basic processes for creating and running applications with ADT, as described in
-  <a href="{@docRoot}guide/developing/eclipse-adt.html">Developing In Eclipse, with ADT</a>.
-  You may also want to read
-  <a href="{@docRoot}guide/topics/testing/testing_android.html">Testing and Instrumentation</a>,
-  which provides an overview of the Android testing framework.
+    This topic explains how create and run tests of Android applications in Eclipse with ADT.
+    Before you read this topic, you should read about how to create a Android application with the
+    basic processes for creating and running applications with ADT, as described in
+    <a href="{@docRoot}guide/developing/eclipse-adt.html">Developing In Eclipse, with ADT</a>.
+    You may also want to read
+    <a href="{@docRoot}guide/topics/testing/testing_android.html">Testing Fundamentals</a>,
+    which provides an overview of the Android testing framework.
 </p>
 <p>
     ADT provides several features that help you set up and manage your testing environment
@@ -32,20 +27,20 @@
         <li>
             It lets you quickly create a test project and link it to the application under test.
             When it creates the test project, it automatically inserts the necessary
-            <code>&lt;instrumentation&gt;</code> element in the test application's manifest file.
+            <code>&lt;instrumentation&gt;</code> element in the test package's manifest file.
         </li>
         <li>
             It lets you quickly import the classes of the application under test, so that your
             tests can inspect them.
         </li>
         <li>
-            It lets you create run configurations for your test application and include in
+            It lets you create run configurations for your test package and include in
             them flags that are passed to the Android testing framework.
         </li>
         <li>
-            It lets you run your test application without leaving Eclipse. ADT builds both the
-            application under test and the test application automatically, installs them if
-            necessary to your device or emulator, runs the test application, and displays the
+            It lets you run your test package without leaving Eclipse. ADT builds both the
+            application under test and the test package automatically, installs them if
+            necessary to your device or emulator, runs the test package, and displays the
             results in a separate window in Eclipse.
         </li>
     </ul>
@@ -55,305 +50,452 @@
     <a href="{@docRoot}guide/developing/testing/testing_otheride.html">Testing in Other IDEs</a>.
 </p>
 <h2 id="CreateTestProjectEclipse">Creating a Test Project</h2>
-  <p>
+<p>
     To set up a test environment for your Android application, you must first create a separate
-    application project that holds the test code. The new project follows the directory structure
+    project that holds the test code. The new project follows the directory structure
     used for any Android application. It includes the same types of content and files, such as
-    source code, resources, a manifest file, and so forth. The test application you
+    source code, resources, a manifest file, and so forth. The test package you
     create is connected to the application under test by an
     <a href="{@docRoot}guide/topics/manifest/instrumentation-element.html">
     <code>&lt;instrumentation&gt;</code></a> element in its manifest file.
-  </p>
-  <p>
-    The <strong>New Android Test Project</strong> dialog makes it easy for you to generate a
-    new test project that has the proper structure, including the
-    <code>&lt;instrumentation&gt;</code> element in the manifest file. You can use the New Android
-    Test Project dialog to generate the test project at any time. The dialog appears just after you
-    create a new Android main application project, but you can also run it to create a test project
-    for a project that you created previously.
-  </p>
+</p>
 <p>
-  To create a test project in Eclipse with ADT:
+    The <em>New Android Test Project</em> dialog makes it easy for you to generate a
+    new test project that has the proper structure, including the
+    <code>&lt;instrumentation&gt;</code> element in the manifest file. You can use the New
+    Android Test Project dialog to generate the test project at any time. The dialog appears
+    just after you create a new Android main application project, but you can also run it to
+    create a test project for a project that you created previously.
+</p>
+<p>
+    To create a test project in Eclipse with ADT:
 </p>
 <ol>
-  <li>
-    In Eclipse, select <strong>File &gt; New &gt; Other</strong>. This
-    opens the Select a Wizard dialog.
-  </li>
-  <li>
-    In the dialog, in the Wizards drop-down list,
-    find the entry for Android, then click the toggle to the left. Select
-    Android Test Project, then at the bottom
-    of the dialog click Next. The New Android Test Project wizard appears.
-  </li>
-  <li>
-    Enter a project name. You may use any name, but you may want to
-    associate the name with the project name for your Application. One
-    way to do this is to take the Application's project name, append the
-    string "Test" to it, and then use this as the test case project name.
-  </li>
-  <li>
-    In the Test Target panel, set
-    An Existing Android Project, click
-    Browse, then select your Android application from
-    the list. You now see that the wizard has completed the Test
-    Target Package, Application Name, and
-    Package Name fields for you (the latter two are in
-    the Properties panel).
-  </li>
-  <li>
-    In the Build Target panel, select the Android SDK
-    platform that you will use to test your application. Make this the same as the
-    build target of the application under test.
-  </li>
-  <li>
-    Click Finish to complete the wizard. If
-    Finish is disabled, look
-    for error messages at the top of the wizard dialog, and then fix
-    any problems.
-  </li>
+    <li>
+        In Eclipse, select <strong>File &gt; New &gt; Other</strong>. This opens the <em>Select a
+        Wizard</em> dialog.
+    </li>
+    <li>
+        In the dialog, in the <em>Wizards</em> drop-down list, find the entry for Android, then
+        click the toggle to the left. Select <strong>Android Test Project</strong>, then at the
+        bottom of the dialog click <strong>Next</strong>. The <em>New Android Test Project</em>
+        wizard appears.
+    </li>
+    <li>
+        Next to <em>Test Project Name</em>, enter a name for the project. You may use any name,
+        but you may want to associate the name with the project name for the application under test.
+        One way to do this is to take the application's project name, append the string "Test" to
+        it, and then use this as the test package project name.
+        <p>
+            The name becomes part of the suggested project path, but you can change this in the
+            next step.
+        </p>
+    </li>
+    <li>
+        In the <em>Content</em> panel, examine the suggested path to the project.
+        If <em>Use default location</em> is set, then the wizard will suggest a path that is
+        a concatenation of the workspace path and the project name you entered. For example,
+        if your workspace path is <code>/usr/local/workspace</code> and your project name is
+        <code>MyTestApp</code>, then the wizard will suggest
+        <code>/usr/local/workspace/MyTestApp</code>. To enter your own
+        choice for a path, unselect <em>Use default location</em>, then enter or browse to the
+        path where you want your project.
+        <p>
+            To learn more about choosing the location of test projects, please read
+            <a href="{@docRoot}guide/topics/testing/testing_android.html#TestProjectPaths">
+            Testing Fundamentals</a>.
+        </p>
+    </li>
+    <li>
+        In the Test Target panel, set An Existing Android Project, click Browse, then select your
+        Android application from the list. You now see that the wizard has completed the Test
+        Target Package, Application Name, and Package Name fields for you (the latter two are in
+        the Properties panel).
+    </li>
+    <li>
+        In the Build Target panel, select the Android SDK platform that the application under test
+        uses.
+    </li>
+    <li>
+        Click Finish to complete the wizard. If Finish is disabled, look for error messages at the
+        top of the wizard dialog, and then fix any problems.
+    </li>
+</ol>
+<h2 id="CreateTestAppEclipse">Creating a Test Package</h2>
+<p>
+    Once you have created a test project, you populate it with a test package. This package does not
+    require an Activity, although you can define one if you wish. Although your test package can
+    combine Activity classes, test case classes, or ordinary classes, your main test case
+    should extend one of the Android test case classes or JUnit classes, because these provide the
+    best testing features.
+</p>
+<p>
+    Test packages do not need to have an Android GUI. When you run the package in
+    Eclipse with ADT, its results appear in the JUnit view. Running tests and seeing the results is
+    described in more detail in the section <a href="#RunTestEclipse">Running Tests</a>.
+</p>
+
+<p>
+    To create a test package, start with one of Android's test case classes defined in
+    {@link android.test android.test}. These extend the JUnit
+    {@link junit.framework.TestCase TestCase} class. The Android test classes for Activity objects
+    also provide instrumentation for testing an Activity. To learn more about test case
+    classes, please read the topic <a href="{@docRoot}guide/topics/testing/testing_android.html">
+    Testing Fundamentals</a>.
+</p>
+<p>
+    Before you create your test package, you choose the Java package identifier you want to use
+    for your test case classes and the Android package name you want to use. To learn more
+    about this, please read
+    <a href="{@docRoot}guide/topics/testing/testing_android.html#PackageNames">
+    Testing Fundamentals</a>.
+</p>
+<p>
+    To add a test case class to your project:
+</p>
+<ol>
+    <li>
+        In the <em>Project Explorer</em> tab, open your test project, then open the <em>src</em>
+        folder.
+    </li>
+    <li>
+        Find the Java package identifier set by the projection creation wizard. If you haven't
+        added classes yet, this node won't have any children, and its icon will not be filled in.
+        If you want to change the identifier value, right-click the identifier and select
+        <strong>Refactor</strong> &gt; <strong>Rename</strong>, then enter the new name.
+    </li>
+    <li>
+        When you are ready, right-click the Java package identifier again and select
+        <strong>New</strong> &gt; <strong>Class</strong>. This displays the <em>New Java Class</em>
+        dialog, with the <em>Source folder</em> and <em>Package</em> values already set.
+    </li>
+    <li>
+        In the <em>Name</em> field, enter a name for the test case class. One way to choose a
+        class name is to append the string "Test" to the class of the component you are testing.
+        For example, if you are testing the class MyAppActivity, your test case class
+        name would be MyAppActivityTest. Leave the modifiers set to <em>public</em>.
+    </li>
+    <li>
+        In the <em>Superclass</em> field, enter the name of the Android test case class you
+        are extending. You can also browse the available classes.
+    </li>
+    <li>
+        In <em>Which method stubs would you like to create?</em>, unset all the options, then
+        click <strong>Finish</strong>. You will set up the constructor manually.
+    </li>
+    <li>
+        Your new class appears in a new Java editor pane.
+    </li>
 </ol>
 <p>
-
-</p>
-<h2 id="CreateTestAppEclipse">Creating a Test Application</h2>
-<p>
-  Once you have created a test project, you populate it with a test
-  Android application. This application does not require an {@link android.app.Activity Activity},
-  although you can define one if you wish. Although your test application can
-  combine Activities, Android test class extensions, JUnit extensions, or
-  ordinary classes, you should extend one of the Android test classes or JUnit classes,
-  because these provide the best testing features.
+    You now have to ensure that the constructor is set up correctly. Create a constructor for your
+    class that has no arguments; this is required by JUnit. As the first statement in this
+    constructor, add a call to the base class' constructor. Each base test case class has its
+    own constructor signature. Refer to the class documentation in the documentation for
+    {@link android.test} for more information.
 </p>
 <p>
-  Test applications do not have an Android GUI. Instead, when you run the application in
-  Eclipse with ADT, its results appear in the JUnit view. If you run
-  your tests with {@link android.test.InstrumentationTestRunner InstrumentationTestRunner} (or a related test runner),
-  then it will run all the methods in each class. You can modify this behavior
-  by using the {@link junit.framework.TestSuite TestSuite} class.
-</p>
-
-<p>
-  To create a test application, start with one of Android's test classes in the Java package {@link android.test android.test}.
-  These extend the JUnit {@link junit.framework.TestCase TestCase} class. With a few exceptions, the Android test classes
-  also provide instrumentation for testing.
-</p>
-<p>
-  For test classes that extend {@link junit.framework.TestCase TestCase}, you probably want to override
-  the <code>setUp()</code> and <code>tearDown()</code> methods:
+    To control your test environment, you will want to override the <code>setUp()</code> and
+    <code>tearDown()</code> methods:
 </p>
 <ul>
-  <li>
-    <code>setUp()</code>: This method is invoked before any of the test methods in the class.
-      Use it to set up the environment for the test. You can use <code>setUp()</code>
-      to instantiate a new <code>Intent</code> object with the action <code>ACTION_MAIN</code>. You can
-      then use this intent to start the Activity under test.
-      <p class="note"><strong>Note:</strong> If you override this method, call
-        <code>super.setUp()</code> as the first statement in your code.
-      </p>
-  </li>
-  <li>
-    <code>tearDown()</code>: This method is invoked after all the test methods in the class. Use
-    it to do garbage collection and re-setting before moving on to the next set of tests.
-    <p class="note"><strong>Note:</strong> If you override this method, you must call
-    <code>super.tearDown()</code> as the <em>last</em> statement in your code.</p>
-  </li>
+    <li>
+        <code>setUp()</code>: This method is invoked before any of the test methods in the class.
+        Use it to set up the environment for the test (the test fixture. You can use
+        <code>setUp()</code> to instantiate a new Intent with the action <code>ACTION_MAIN</code>.
+        You can then use this intent to start the Activity under test.
+    </li>
+    <li>
+        <code>tearDown()</code>: This method is invoked after all the test methods in the class. Use
+        it to do garbage collection and to reset the test fixture.
+    </li>
 </ul>
 <p>
-  Another useful convention is to add the method <code>testPreConditions()</code> to your test
-  class. Use this method to test that the application under test is initialized correctly. If this
-  test fails, you know that that the initial conditions were in error. When this happens, further test
-  results are suspect, regardless of whether or not the tests succeeded.
+    Another useful convention is to add the method <code>testPreconditions()</code> to your test
+    class. Use this method to test that the application under test is initialized correctly. If this
+    test fails, you know that that the initial conditions were in error. When this happens, further
+    test results are suspect, regardless of whether or not the tests succeeded.
 </p>
 <p>
-  The Resources tab contains an <a href="{@docRoot}resources/tutorials/testing/activity_test.html">Activity Testing</a>
-  tutorial with more information about creating test classes and methods.
+    The Resources tab contains an
+    <a href="{@docRoot}resources/tutorials/testing/activity_test.html">Activity Testing</a>
+    tutorial with more information about creating test classes and methods.
 </p>
 <h2 id="RunTestEclipse">Running Tests</h2>
+    <div class="sidebox-wrapper">
+        <div class="sidebox">
+            <h2>Running tests from the command line</h2>
+                <p>
+                    If you've created your tests in Eclipse, you can still run your tests and test
+                    suites by using command-line tools included with the Android SDK. You may want
+                    to do this, for example, if you have a large number of tests to run, if you
+                    have a large test case, or if you want a fine level of control over which
+                    tests are run at a particular time.
+                </p>
+                <p>
+                    To run tests created in Eclipse with ADT with command-line tools, you must first
+                    install additional files into the test project using the <code>android</code>
+                    tool's "create test-project" option. To see how to do this, read
+                   <a href="{@docRoot}guide/developing/testing/testing_otheride.html#CreateProject">
+                    Testing in Other IDEs</a>.
+                </p>
+        </div>
+    </div>
+<p>
+    When you run a test package in Eclipse with ADT, the output appears in the Eclipse JUnit view.
+    You can run the entire test package or one test case class. To do run tests, Eclipse runs the
+    <code>adb</code> command for running a test package, and displays the output, so there is no
+    difference between running tests inside Eclipse and running them from the command line.
+</p>
+<p>
+    As with any other package, to run a test package in Eclipse with ADT you must either attach a
+    device to your computer or use the Android emulator. If you use the emulator, you must have an
+    Android Virtual Device (AVD) that uses the same target as the test package.
+</p>
+<p>
+    To run a test in Eclipse, you have two choices:</p>
+<ul>
+    <li>
+        Run a test just as you run an application, by selecting
+        <strong>Run As... &gt; Android JUnit Test</strong> from the project's context menu or
+        from the main menu's <strong>Run</strong> item.
+    </li>
+    <li>
+        Create an Eclipse run configuration for your test project. This is useful if you want
+        multiple test suites, each consisting of selected tests from the project. To run
+        a test suite, you run the test configuration.
+        <p>
+            Creating and running test configurations is described in the next section.
+        </p>
+    </li>
+</ul>
+<p>
+    To create and run a test suite using a run configuration:
+</p>
+<ol>
+    <li>
+        In the Package Explorer, select the test project, then from the main menu, select
+        <strong>Run &gt; Run Configurations...</strong>. The Run Configurations dialog appears.
+    </li>
+    <li>
+        In the left-hand pane, find the Android JUnit Test entry. In the right-hand pane, click the
+        Test tab. The Name: text box shows the name of your project. The Test class: dropdown box
+        shows one of the test classes in your project.
+    </li>
+    <li>
+        To run one test class, click  Run a single test, then enter your project name in the
+        Project: text box and the class name in the Test class: text box.
+        <p>
+            To run all the test classes, click Run all tests in the selected project or package,
+            then enter the project or package name in the text box.
+        </p>
+    </li>
+    <li>
+        Now click the Target tab.
+        <ul>
+            <li>
+                Optional: If you are using the emulator, click Automatic, then in the Android
+                Virtual Device (AVD) selection table, select an existing AVD.
+            </li>
+            <li>
+                In the Emulator Launch Parameters pane, set the Android emulator flags you want to
+                use. These are documented in the topic
+                <a href="{@docRoot}guide/developing/tools/emulator.html#startup-options">
+                Android Emulator</a>.
+            </li>
+        </ul>
+    </li>
+    <li>
+        Click the Common tab. In the Save As pane, click Local to save this run configuration
+        locally, or click Shared to save it to another project.
+    </li>
+    <li>
+        Optional: Add the configuration to the Run toolbar and the <strong>Favorites</strong>
+        menu: in the Display in Favorites pane click the checkbox next to Run.
+    </li>
+    <li>
+        Optional: To add this configuration to the <strong>Debug</strong> menu and toolbar, click
+        the checkbox next to Debug.
+    </li>
+    <li>
+        To save your settings, click Close.<br/>
+        <p class="note"><strong>Note:</strong>
+            Although you can run the test immediately by clicking Run, you should save the test
+            first and then run it by selecting it from the Eclipse standard toolbar.
+        </p>
+    </li>
+    <li>
+        On the Eclipse standard toolbar, click the down arrow next to the green Run arrow. This
+        displays a menu of saved Run and Debug configurations.
+    </li>
+    <li>
+        Select the test run configuration you just created. The test starts.
+    </li>
+</ol>
+<p>
+    The progress of your test appears in the Console view as a series of messages. Each message is
+    preceded by a timestamp and the <code>.apk</code> filename to which it applies. For example,
+    this message appears when you run a test to the emulator, and the emulator is not yet started:
+</p>
 <div class="sidebox-wrapper">
     <div class="sidebox">
-        <h2>Running tests from the command line</h2>
-            <p>
-                If you've created your tests in Eclipse, you can still run your tests and test
-                suites by using command-line tools included with the Android SDK. You may want to
-                do this, for example, if you have a large number of tests to run, if you have a
-                large test case, or if you want a fine level of control over which tests are run at
-                a particular time.
-            </p>
-            <p>
-                To run tests created in Eclipse with ADT with command-line tools, you must first
-                install additional files into the test project using the <code>android</code> tool's
-                "create test-project" option. To see how to do this, read the section
-                <a href="{@docRoot}guide/developing/testing/testing_otheride.html#CreateProject">
-                Creating a test project</a> in the topic
-                <a href="{@docRoot}guide/developing/testing/testing_otheride.html">Testing in Other
-                IDEs</a>.
-            </p>
+        <h2>Message Examples</h2>
+        <p>
+            The examples shown in this section come from the
+            <a href="{@docRoot}resources/samples/SpinnerTest/index.html">SpinnerTest</a>
+            sample test package, which tests the
+            <a href="{@docRoot}resources/samples/Spinner/index.html">Spinner</a>
+            sample application. This test package is also featured in the
+            <a href="{@docRoot}resources/tutorials/testing/activity_test.html">Activity Testing</a>
+            tutorial.
+        </p>
     </div>
 </div>
+<pre>
+    [<em>yyyy-mm-dd hh:mm:ss</em> - <em>testfile</em>] Waiting for HOME ('android.process.acore') to be launched...
+</pre>
 <p>
-  When you run a test application in Eclipse with ADT, the output appears in
-  an Eclipse view panel. You can run the entire test application, one class, or one
-  method of a class. To do this, Eclipse runs the <code>adb</code> command for running a test application, and
-  displays the output, so there is no difference between running tests inside Eclipse and running them from the command line.
+    In the following description of these messages, <code><em>devicename</em></code> is the name of
+    the device or emulator you are using to run the test, and <code><em>port</em></code> is the
+    port number for the device. The name and port number are in the format used by the
+    <code><a href="{@docRoot}guide/developing/tools/adb.html#devicestatus">adb devices</a></code>
+    command. Also, <code><em>testfile</em></code> is the <code>.apk</code> filename of the test
+    package you are running, and <em>appfile</em> is the filename of the application under test.
 </p>
-<p>
-    As with any other application, to run a test application in Eclipse with ADT you must either attach a device to your
-    computer or use the Android emulator. If you use the emulator, you must have an Android Virtual Device (AVD) that uses
-    the same target
-</p>
-<p>
-  To run a test in Eclipse, you have two choices:</p>
-<ol>
-  <li>
-  Run a test just as you run an application, by selecting
-  <strong>Run As... &gt; Android JUnit Test</strong> from the project's context menu or
-  from the main menu's <strong>Run</strong> item.
-  </li>
-  <li>
-  Create an Eclipse run configuration for your test project. This is useful if you want multiple test suites, each consisting of selected tests from the project. To run
-  a test suite, you run the test configuration.
-  <p>
-    Creating and running test configurations is described in the next section.
-  </p>
-  </li>
-</ol>
-<p>To create and run a test suite using a run configuration:</p>
-<ol>
-  <li>
-    In the Package Explorer, select the test
-    project, then from the main menu, select
-    <strong>Run &gt; Run Configurations...</strong>. The
-    Run Configurations dialog appears.
-  </li>
-  <li>
-    In the left-hand pane, find the
-    Android JUnit Test entry.
-    In the right-hand pane, click the Test tab.
-    The Name: text box
-    shows the name of your project. The
-    Test class: dropdown box shows one your project's classes
-    test classes in your project.
-  </li>
-  <li>
-    To run one test class, click  Run a single test, then enter your project
-    name in the Project: text box and the class name in the
-    Test class: text box.
-    <p>
-        To run all the test classes,
-        click Run all tests in the selected project or package,
-        then enter the project or package name in the text box.
-    </p>
- </li>
-  <li>
-    Now click the Target tab.
-    <ul>
-        <li>
-            Optional: If you are using the emulator, click
-            Automatic, then in the Android Virtual Device (AVD)
-            selection table, select an existing AVD.
-        </li>
-        <li>
-            In the Emulator Launch Parameters pane, set the
-            Android emulator flags you want to use. These are documented in the topic
-            <a href="{@docRoot}guide/developing/tools/emulator.html#startup-options">Emulator Startup Options</a>.
-        </li>
-    </ul>
-  <li>
-    Click the Common tab. In the
-    Save As pane, click Local to save
-    this run configuration locally, or click Shared to
-    save it to another project.
-  </li>
-  <li>
-    Optional: Add the configuration to the Run toolbar and the <strong>Favorites</strong>
-    menu: in the Display in Favorites pane
-    click the checkbox next to Run.
-  </li>
-  <li>
-    Optional: To add this configuration to the <strong>Debug</strong> menu and toolbar, click
-    the checkbox next to Debug.
-  </li>
-  <li>
-    To save your settings, click Close.<br/>
-    <p class="note"><strong>Note:</strong> Although you can run the test immediately by
-    clicking Run, you should save the test first and then
-    run it by selecting it from the Eclipse standard toolbar.</p>
-  </li>
-  <li>
-    On the Eclipse standard toolbar, click the down arrow next to the
-    green Run arrow. This displays a menu of saved Run and Debug
-    configurations.
-  </li>
-  <li>
-    Select the test run configuration you just created.
-  </li>
-  <li>
-    The progress of your test appears in the Console view.
-    You should see the following messages, among others:
-    <ul>
-      <li>
-        <code>Performing Android.test.InstrumentationTestRunner JUnit launch</code><br>
-        The class name that proceeds "JUnit" depends on the Android instrumentation
-        class you have chosen.
-      </li>
-      <li>
-        If you are using an emulator and you have not yet started it, then you will see
+<ul>
+    <li>
+        If you are using an emulator and you have not yet started it, then Eclipse
+        first starts the emulator. When this is complete, you see
         the message:
         <p>
-          <code>Automatic Target Mode: launching new emulator with compatible
-          AVD <em>avdname</em></code><br>(where <em>avdname</em> is the name of
-          the AVD you are using.)
+            <code>HOME is up on device '<em>devicename</em>-<em>port</em>'</code>
         </p>
-      </li>
-      <li>
-        If you have not already installed your test application, then you will see
+    </li>
+    <li>
+        If you have not already installed your test package, then you see
         the message:
         <p>
-          <code>Uploading <em>testclass</em>.apk onto device '<em>device-id</em>'</code><br>
-          where <em>testclass</em> is the name of your unit test class and <em>device-id</em>
-          is the name and port for your test device or emulator, followed by the message <code>Installing <em>testclass</em>.apk</code>
+            <code>Uploading <em>testfile</em> onto device '<em>devicename</em>-<em>port</em>'
+            </code>
         </p>
-      </li>
-      <li>
-       <code>Launching instrumentation Android.test.InstrumentationTestRunner on device <em>device-id</em></code>.<br>
-       This indicates that Android's Instrumentation system is now testing your code. Again, the
-       instrumentation class name depends on the Android instrumentation class you have chosen.
-      </li>
-      <li>
-       <code>Test run complete</code>.<br> When you see this, your unit tests have finished.
-      </li>
-    </ul>
-</ol>
+        <p>
+            then the message <code>Installing <em>testfile</em></code>.
+        </p>
+        <p>
+            and finally the message <code>Success!</code>
+        </p>
+    </li>
+</ul>
 <p>
-        The test results appear in the JUnit view. This is divided into an upper summary pane,
-        and a lower stack trace pane.
+    The following lines are an example of this message sequence:
+</p>
+<code>
+[2010-07-01 12:44:40 - MyTest] HOME is up on device 'emulator-5554'<br>
+[2010-07-01 12:44:40 - MyTest] Uploading MyTest.apk onto device 'emulator-5554'<br>
+[2010-07-01 12:44:40 - MyTest] Installing MyTest.apk...<br>
+[2010-07-01 12:44:49 - MyTest] Success!<br>
+</code>
+<br>
+<ul>
+    <li>
+        Next, if you have not yet installed the application under test to the device or
+        emulator, you see the message
+        <p>
+        <code>Project dependency found, installing: <em>appfile</em></code>
+        </p>
+        <p>
+            then the message <code>Uploading <em>appfile</em></code> onto device
+            '<em>devicename</em>-<em>port</em>'
+        </p>
+        <p>
+            then the message <code>Installing <em>appfile</em></code>
+        </p>
+        <p>
+            and finally the message <code>Success!</code>
+        </p>
+    </li>
+</ul>
+<p>
+    The following lines are an example of this message sequence:
+</p>
+<code>
+[2010-07-01 12:44:49 - MyTest] Project dependency found, installing: MyApp<br>
+[2010-07-01 12:44:49 - MyApp] Uploading MyApp.apk onto device 'emulator-5554'<br>
+[2010-07-01 12:44:49 - MyApp] Installing MyApp.apk...<br>
+[2010-07-01 12:44:54 - MyApp] Success!<br>
+</code>
+<br>
+<ul>
+    <li>
+        Next, you see the message
+        <code>Launching instrumentation <em>instrumentation_class</em> on device
+        <em>devicename</em>-<em>port</em></code>
+        <p>
+            <code>instrumentation_class</code> is the fully-qualified class name of the
+            instrumentation test runner you have specified (usually
+            {@link android.test.InstrumentationTestRunner}.
+        </p>
+    </li>
+    <li>
+        Next, as {@link android.test.InstrumentationTestRunner} builds a list of tests to run,
+        you see the message
+        <p>
+            <code>Collecting test information</code>
+        </p>
+        <p>
+            followed by
+        </p>
+        <p>
+            <code>Sending test information to Eclipse</code>
+        </p>
+    </li>
+    <li>
+        Finally, you see the message <code>Running tests</code>, which indicates that your tests
+        are running. At this point, you should start seeing the test results in the JUnit view.
+        When the tests are finished, you see the console message <code>Test run complete</code>.
+        This indicates that your tests are finished.
+    </li>
+</ul>
+<p>
+    The following lines are an example of this message sequence:
+</p>
+<code>
+[2010-01-01 12:45:02 - MyTest] Launching instrumentation android.test.InstrumentationTestRunner on device emulator-5554<br>
+[2010-01-01 12:45:02 - MyTest] Collecting test information<br>
+[2010-01-01 12:45:02 - MyTest] Sending test information to Eclipse<br>
+[2010-01-01 12:45:02 - MyTest] Running tests...<br>
+[2010-01-01 12:45:22 - MyTest] Test run complete<br>
+</code>
+<br>
+<p>
+    The test results appear in the JUnit view. This is divided into an upper summary pane,
+    and a lower stack trace pane.
 </p>
 <p>
-        The upper pane contains test information. In the pane's header, you see the following
-        information:
+    The upper pane contains test information. In the pane's header, you see the following
+    information:
 </p>
-    <ul>
-        <li>
-           Total time elapsed for the test application (labeled Finished after <em>x</em> seconds).
-        </li>
-        <li>
-           Number of runs (Runs:) - the number of tests in the entire test class.
-        </li>
-        <li>
-           Number of errors (Errors:) - the number of program errors and exceptions encountered
-           during the test run.
-        </li>
-        <li>
-           Number of failures (Failures:) - the number of test failures encountered during the test
-           run. This is the number of assertion failures. A test can fail even if the program does
-           not encounter an error.
-        </li>
-        <li>
-           A progress bar. The progress bar extends from left to right as the tests run. If all the
-           tests succeed, the bar remains green. If a test fails, the bar turns from green to red.
-        </li>
-    </ul>
+<ul>
+    <li>
+        Total time elapsed for the test package (labeled Finished after <em>x</em> seconds).
+    </li>
+    <li>
+        Number of runs (Runs:) - the number of tests in the entire test class.
+    </li>
+    <li>
+        Number of errors (Errors:) - the number of program errors and exceptions encountered
+        during the test run.
+    </li>
+    <li>
+        Number of failures (Failures:) - the number of test failures encountered during the test
+        run. This is the number of assertion failures. A test can fail even if the program does
+        not encounter an error.
+    </li>
+    <li>
+        A progress bar. The progress bar extends from left to right as the tests run. If all the
+        tests succeed, the bar remains green. If a test fails, the bar turns from green to red.
+    </li>
+</ul>
 <p>
     The body of the upper pane contains the details of the test run. For each test case class
     that was run, you see a line with the class name. To look at the results for the individual
@@ -363,8 +505,30 @@
     pane and moves the focus to the first line of the test method.
 </p>
 <p>
+    The results of a successful test are shown in
+    <a href="#TestResults">Figure 1. Messages for a successful test</a>:
+</p>
+<a href="{@docRoot}images/testing/eclipse_test_results.png">
+    <img src="{@docRoot}images/testing/eclipse_test_results.png"
+         alt="Messages for a successful test" height="327px" id="TestResults"/>
+</a>
+<p class="img-caption">
+    <strong>Figure 1.</strong> Messages for a successful test
+</p>
+<p>
     The lower pane is for stack traces. If you highlight a failed test in the upper pane, the
     lower pane contains a stack trace for the test. If a line corresponds to a point in your
     test code, you can double-click it to display the code in an editor view pane, with the
     line highlighted. For a successful test, the lower pane is empty.
 </p>
+<p>
+    The results of a failed test are shown in
+    <a href="#FailedTestResults">Figure 2. Messages for a test failure</a>
+</p>
+<a href="{@docRoot}images/testing/eclipse_test_run_failure.png">
+    <img src="{@docRoot}images/testing/eclipse_test_run_failure.png"
+         alt="Messages for a test failure" height="372px" id="TestRun"/>
+</a>
+<p class="img-caption">
+    <strong>Figure 2.</strong> Messages for a test failure
+</p>
diff --git a/docs/html/guide/developing/testing/testing_otheride.jd b/docs/html/guide/developing/testing/testing_otheride.jd
index 2bdf4d0..523a8e5 100644
--- a/docs/html/guide/developing/testing/testing_otheride.jd
+++ b/docs/html/guide/developing/testing/testing_otheride.jd
@@ -2,122 +2,128 @@
 @jd:body
 
 <div id="qv-wrapper">
-  <div id="qv">
-  <h2>In this document</h2>
-  <ol>
-    <li>
-        <a href="#CreateTestProjectCommand">Working with Test Projects</a>
-        <ol>
-            <li>
-                <a href="#CreateTestProject">Creating a test project</a>
-            </li>
-            <li>
-                <a href="#UpdateTestProject">Updating a test project</a>
-            </li>
-        </ol>
-    </li>
-    <li>
-        <a href="#CreateTestApp">Creating a Test Application</a>
-    </li>
-    <li>
-        <a href="#RunTestsCommand">Running Tests</a>
-        <ol>
-            <li>
-                <a href="#RunTestsAnt">Quick build and run with Ant</a>
-            </li>
-            <li>
-                <a href="#RunTestsDevice">Running tests on a device or emulator</a>
-            </li>
-        </ol>
-    </li>
-    <li>
-        <a href="#AMSyntax">Using the Instrument Command</a>
-        <ol>
-            <li>
-                <a href="#AMOptionsSyntax">Instrument options</a>
-            </li>
-            <li>
-                <a href="#RunTestExamples">Instrument examples</a>
-            </li>
-        </ol>
-    </li>
-
-  </ol>
-  <h2>See Also</h2>
-  <ol>
-    <li>
-        <a
-        href="{@docRoot}guide/topics/testing/testing_android.html">Testing and Instrumentation</a>
-    </li>
-    <li>
-        <a href="{@docRoot}resources/tutorials/testing/activity_test.html">Activity Testing</a>
-    </li>
-    <li>
-        <a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a>
-    </li>
-  </ol>
-  </div>
+    <div id="qv">
+        <h2>In this document</h2>
+            <ol>
+                <li>
+                    <a href="#CreateTestProjectCommand">Working with Test Projects</a>
+                    <ol>
+                        <li>
+                            <a href="#CreateTestProject">Creating a test project</a>
+                        </li>
+                        <li>
+                            <a href="#UpdateTestProject">Updating a test project</a>
+                        </li>
+                    </ol>
+                </li>
+                <li>
+                    <a href="#CreateTestApp">Creating a Test Package</a>
+                </li>
+                <li>
+                    <a href="#RunTestsCommand">Running Tests</a>
+                    <ol>
+                        <li>
+                            <a href="#RunTestsAnt">Quick build and run with Ant</a>
+                        </li>
+                        <li>
+                            <a href="#RunTestsDevice">Running tests on a device or emulator</a>
+                        </li>
+                    </ol>
+                </li>
+                <li>
+                    <a href="#AMSyntax">Using the Instrument Command</a>
+                    <ol>
+                        <li>
+                            <a href="#AMOptionsSyntax">Instrument options</a>
+                        </li>
+                        <li>
+                            <a href="#RunTestExamples">Instrument examples</a>
+                        </li>
+                    </ol>
+                </li>
+            </ol>
+        <h2>See Also</h2>
+            <ol>
+                <li>
+                    <a href="{@docRoot}guide/topics/testing/testing_android.html">
+                        Testing Fundamentals</a>
+                </li>
+                <li>
+                    <a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a>
+                </li>
+            </ol>
+    </div>
 </div>
 <p>
-  This document describes how to create and run tests directly from the command line.
-  You can use the techniques described here if you are developing in an IDE other than Eclipse
-  or if you prefer to work from the command line. This document assumes that you already know how
-  to create a Android application in your programming environment. Before you start this
-  document, you should read the document <a
-  href="{@docRoot}guide/topics/testing/testing_android.html">Testing and Instrumentation</a>,
-  which provides an overview of Android testing.
+    This document describes how to create and run tests directly from the command line.
+    You can use the techniques described here if you are developing in an IDE other than Eclipse
+    or if you prefer to work from the command line. This document assumes that you already know how
+    to create a Android application in your programming environment. Before you start this
+    document, you should read the topic
+    <a href="{@docRoot}guide/topics/testing/testing_android.html">Testing Fundamentals</a>,
+    which provides an overview of Android testing.
 </p>
 <p>
-  If you are developing in Eclipse with ADT, you can set up and run your tests
-directly in Eclipse. For more information, please read <a
-  href="{@docRoot}guide/developing/testing/testing_eclipse.html">Testing&nbsp;in&nbsp;Eclipse,&nbsp;with&nbsp;ADT</a>.
+    If you are developing in Eclipse with ADT, you can set up and run your tests
+    directly in Eclipse. For more information, please read
+    <a href="{@docRoot}guide/developing/testing/testing_eclipse.html">
+    Testing in Eclipse, with ADT</a>.
 </p>
 <h2 id="CreateTestProjectCommand">Working with Test Projects</h2>
 <p>
-  You use the <code>android</code> tool to create test projects.
-  You also use <code>android</code> to convert existing test code into an Android test project,
-  or to add the <code>run-tests</code> Ant target to an existing Android test project.
-  These operations are described in more detail in the section <a
-  href="#UpdateTestProject">Updating a test project</a>.
-  The <code>run-tests</code> target is described in <a
-  href="#RunTestsAnt">Quick build and run with Ant</a>.
+    You use the <code>android</code> tool to create test projects.
+    You also use <code>android</code> to convert existing test code into an Android test project,
+    or to add the <code>run-tests</code> Ant target to an existing Android test project.
+    These operations are described in more detail in the section <a href="#UpdateTestProject">
+    Updating a test project</a>. The <code>run-tests</code> target is described in
+    <a href="#RunTestsAnt">Quick build and run with Ant</a>.
 </p>
 <h3 id="CreateTestProject">Creating a test project</h3>
 <p>
-  To create a test project with the <code>android</code> tool, enter:
-<pre>android create test-project -m &lt;main_path&gt; -n &lt;project_name&gt; -p &lt;test_path&gt;</pre>
+    To create a test project with the <code>android</code> tool, enter:
+</p>
+<pre>
+android create test-project -m &lt;main_path&gt; -n &lt;project_name&gt; -p &lt;test_path&gt;
+</pre>
 <p>
-  You must supply all the flags. The following table explains them in detail:
+    You must supply all the flags. The following table explains them in detail:
 </p>
 <table>
-  <tr>
-    <th>Flag</th>
-    <th>Value</th>
-    <th>Description</th>
-  <tr>
-    <td><code>-m, --main</code></td>
-    <td>
-        Path to the project of the application under test, relative to the test application
-        directory.
-    </td>
-    <td>
-        For example, if the application under test is in <code>source/HelloAndroid</code>, and you
-        want to create the test project in <code>source/HelloAndroidTest</code>, then the value of
-        <code>--main</code> should be <code>../HelloAndroid</code>.
+    <tr>
+        <th>Flag</th>
+        <th>Value</th>
+        <th>Description</th>
+    </tr>
+    <tr>
+        <td><code>-m, --main</code></td>
+        <td>
+            Path to the project of the application under test, relative to the test package
+            directory.
         </td>
-  <tr>
-    <td><code>-n, --name</code></td>
-    <td>Name that you want to give the test project.</td>
-    <td>&nbsp;</td>
-  </tr>
-  <tr>
-    <td><code>-p, --path</code></td>
-    <td>Directory in which you want to create the new test project.</td>
-    <td>
-      The <code>android</code> tool creates the test project files and directory structure in this
-      directory. If the directory does not exist, <code>android</code> creates it.
-    </td>
-  </tr>
+        <td>
+            For example, if the application under test is in <code>source/HelloAndroid</code>, and
+            you want to create the test project in <code>source/HelloAndroidTest</code>, then the
+            value of <code>--main</code> should be <code>../HelloAndroid</code>.
+        <p>
+            To learn more about choosing the location of test projects, please read
+            <a href="{@docRoot}guide/topics/testing/testing_android.html#TestProjects">
+            Testing Fundamentals</a>.
+        </p>
+        </td>
+    </tr>
+    <tr>
+        <td><code>-n, --name</code></td>
+        <td>Name that you want to give the test project.</td>
+        <td>&nbsp;</td>
+    </tr>
+    <tr>
+        <td><code>-p, --path</code></td>
+        <td>Directory in which you want to create the new test project.</td>
+        <td>
+            The <code>android</code> tool creates the test project files and directory structure
+            in this directory. If the directory does not exist, <code>android</code> creates it.
+        </td>
+    </tr>
 </table>
 <p>
     If the operation is successful, <code>android</code> lists to STDOUT the names of the files
@@ -135,11 +141,10 @@
     are testing and control it with instrumentation.
 </p>
 <p>
-    For example, suppose you create the <a
-    href="{@docRoot}resources/tutorials/hello-world.html">Hello, World</a> tutorial application
-    in the directory <code>~/source/HelloAndroid</code>. In the tutorial, this application uses the
-    package name <code>com.example.helloandroid</code> and the activity name
-    <code>HelloAndroid</code>. You can to create the test for this in
+    For example, suppose you create the <a href="{@docRoot}resources/tutorials/hello-world.html">
+    Hello, World</a> tutorial application in the directory <code>~/source/HelloAndroid</code>.
+    In the tutorial, this application uses the package name <code>com.example.helloandroid</code>
+    and the activity name <code>HelloAndroid</code>. You can to create the test for this in
     <code>~/source/HelloAndroidTest</code>. To do so, you enter:
 </p>
 <pre>
@@ -196,7 +201,7 @@
 <p class="note">
     <strong>Note:</strong> If you change the Android package name of the application under test,
     you must <em>manually</em> change the value of the <code>&lt;android:targetPackage&gt;</code>
-    attribute within the <code>AndroidManifest.xml</code> file of the test application.
+    attribute within the <code>AndroidManifest.xml</code> file of the test package.
     Running <code>android update test-project</code> does not do this.
 </p>
 <p>
@@ -205,38 +210,38 @@
 <pre>android update-test-project -m &lt;main_path&gt; -p &lt;test_path&gt;</pre>
 
 <table>
-<tr>
-  <th>Flag</th>
-  <th>Value</th>
-  <th>Description</th>
-</tr>
-<tr>
-  <td><code>-m, --main</code></td>
-  <td>The path to the project of the application under test, relative to the test project</td>
-  <td>
-    For example, if the application under test is in <code>source/HelloAndroid</code>, and
-    the test project is in <code>source/HelloAndroidTest</code>, then the value for
-    <code>--main</code> is <code>../HelloAndroid</code>.
-  </td>
-</tr>
-<tr>
-  <td><code>-p, --path</code></td>
-  <td>The of the test project.</td>
-  <td>
-    For example, if the test project is in <code>source/HelloAndroidTest</code>, then the
-    value for <code>--path</code> is <code>HelloAndroidTest</code>.
-  </td>
-</tr>
+    <tr>
+        <th>Flag</th>
+        <th>Value</th>
+        <th>Description</th>
+    </tr>
+    <tr>
+        <td><code>-m, --main</code></td>
+        <td>The path to the project of the application under test, relative to the test project</td>
+        <td>
+            For example, if the application under test is in <code>source/HelloAndroid</code>, and
+            the test project is in <code>source/HelloAndroidTest</code>, then the value for
+            <code>--main</code> is <code>../HelloAndroid</code>.
+        </td>
+    </tr>
+    <tr>
+        <td><code>-p, --path</code></td>
+        <td>The of the test project.</td>
+        <td>
+            For example, if the test project is in <code>source/HelloAndroidTest</code>, then the
+            value for <code>--path</code> is <code>HelloAndroidTest</code>.
+        </td>
+    </tr>
 </table>
 <p>
     If the operation is successful, <code>android</code> lists to STDOUT the names of the files
     and directories it has created.
 </p>
-<h2 id="CreateTestApp">Creating a Test Application</h2>
+<h2 id="CreateTestApp">Creating a Test Package</h2>
 <p>
-    Once you have created a test project, you populate it with a test application.
+    Once you have created a test project, you populate it with a test package.
     The application does not require an {@link android.app.Activity Activity},
-    although you can define one if you wish. Although your test application can
+    although you can define one if you wish. Although your test package can
     combine Activities, Android test class extensions, JUnit extensions, or
     ordinary classes, you should extend one of the Android test classes or JUnit classes,
     because these provide the best testing features.
@@ -248,7 +253,7 @@
 </p>
 
 <p>
-    To create a test application, start with one of Android's test classes in the Java package
+    To create a test package, start with one of Android's test classes in the Java package
     {@link android.test android.test}. These extend the JUnit
     {@link junit.framework.TestCase TestCase} class. With a few exceptions, the Android test
     classes also provide instrumentation for testing.
@@ -282,24 +287,17 @@
     test results are suspect, regardless of whether or not the tests succeeded.
 </p>
 <p>
-    To learn more about creating test applications, see the topic <a
-    href="{@docRoot}guide/topics/testing/testing_android.html">Testing and Instrumentation</a>,
+    To learn more about creating test packages, see the topic <a
+    href="{@docRoot}guide/topics/testing/testing_android.html">Testing Fundamentals</a>,
     which provides an overview of Android testing. If you prefer to follow a tutorial,
     try the <a href="{@docRoot}resources/tutorials/testing/activity_test.html">Activity Testing</a>
     tutorial, which leads you through the creation of tests for an actual Android application.
 </p>
 <h2 id="RunTestsCommand">Running Tests</h2>
 <p>
-    If you are not developing in Eclipse with ADT, you need to run tests from the command line.
-    You can do this either with Ant or with the {@link android.app.ActivityManager ActivityManager}
-    command line interface.
-</p>
-<p>
-    You can also run tests from the command line even if you are using Eclipse with ADT to develop
-    them. To do this, you need to create the proper files and directory structure in the test
-    project, using the <code>android</code> tool with the option <code>create test-project</code>.
-    This is described in the section <a
-    href="#CreateTestProjectCommand">Working with Test Projects</a>.
+    You run tests from the command line, either with Ant or with an
+    <a href="{@docRoot}http://developer.android.com/guide/developing/tools/adb.html">
+    Android Debug Bridge (adb)</a> shell.
 </p>
 <h3 id="RunTestsAnt">Quick build and run with Ant</h3>
 <p>
@@ -316,57 +314,63 @@
     You can update an existing test project to use this feature. To do this, use the
     <code>android</code> tool with the <code>update test-project</code> option. This is described
     in the section <a href="#UpdateTestProject">Updating a test project</a>.
+</p>
 <h3 id="RunTestsDevice">Running tests on a device or emulator</h3>
 <p>
-    When you run tests from the command line with the ActivityManager (<code>am</code>)
-    command-line tool, you get more options for choosing the tests to run than with any other
-    method. You can select individual test methods, filter tests according to their annotation, or
-    specify testing options. Since the test run is controlled entirely from a command line, you can
-    customize your testing with shell scripts in various ways.
+    When you run tests from the command line with
+    <a href="{@docRoot}http://developer.android.com/guide/developing/tools/adb.html">
+    Android Debug Bridge (adb)</a>, you get more options for choosing the tests
+    to run than with any other method. You can select individual test methods, filter tests
+    according to their annotation, or specify testing options. Since the test run is controlled
+    entirely from a command line, you can customize your testing with shell scripts in various ways.
 </p>
 <p>
-    You run the <code>am</code> tool on an Android device or emulator using the
-    <a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a>
-    (<code>adb</code>) shell. When you do this, you use the ActivityManager
-    <code>instrument</code> option to run your test application using an Android test runner
-    (usually {@link android.test.InstrumentationTestRunner}). You set <code>am</code>
-    options with command-line flags.
+    To run a test from the command line, you run <code>adb shell</code> to start a command-line
+    shell on your device or emulator, and then in the shell run the <code>am instrument</code>
+    command. You control <code>am</code> and your tests with command-line flags.
 </p>
 <p>
-    To run a test with <code>am</code>:
+    As a shortcut, you can start an <code>adb</code> shell, call <code>am instrument</code>, and
+    specify command-line flags all on one input line. The shell opens on the device or emulator,
+    runs your tests, produces output, and then returns to the command line on your computer.
+</p>
+<p>
+    To run a test with <code>am instrument</code>:
 </p>
 <ol>
-  <li>
-    If necessary, re-build your main application and test application.
-  </li>
-  <li>
-    Install your test application and main application Android package files
-    (<code>.apk</code> files) to your current Android device or emulator</li>
-  <li>
-    At the command line, enter:
+    <li>
+        If necessary, rebuild your main application and test package.
+    </li>
+    <li>
+        Install your test package and main application Android package files
+        (<code>.apk</code> files) to your current Android device or emulator</li>
+    <li>
+        At the command line, enter:
 <pre>
 $ adb shell am instrument -w &lt;test_package_name&gt;/&lt;runner_class&gt;
 </pre>
-<p>
-    where <code>&lt;test_package_name&gt;</code> is the Android package name of your test
-    application, and <code>&lt;runner_class&gt;</code> is the name of the Android test runner
-    class you are using. The Android package name is the value of the <code>package</code>
-    attribute of the <code>manifest</code> element in the manifest file
-    (<code>AndroidManifest.xml</code>) of your test application. The Android test runner
-    class is usually <code>InstrumentationTestRunner</code>.
-</p>
-<p>Your test results appear in <code>STDOUT</code>.</p>
-  </li>
+        <p>
+            where <code>&lt;test_package_name&gt;</code> is the Android package name of your test
+            application, and <code>&lt;runner_class&gt;</code> is the name of the Android test
+            runner class you are using. The Android package name is the value of the
+            <code>package</code> attribute of the <code>manifest</code> element in the manifest file
+            (<code>AndroidManifest.xml</code>) of your test package. The Android test runner
+            class is usually {@link android.test.InstrumentationTestRunner}.
+        </p>
+        <p>
+            Your test results appear in <code>STDOUT</code>.
+        </p>
+    </li>
 </ol>
 <p>
-    This operation starts an <code>adb</code> shell, then runs <code>am instrument</code> in it
+    This operation starts an <code>adb</code> shell, then runs <code>am instrument</code>
     with the specified parameters. This particular form of the command will run all of the tests
-    in your test application. You can control this behavior with flags that you pass to
+    in your test package. You can control this behavior with flags that you pass to
     <code>am instrument</code>. These flags are described in the next section.
 </p>
-<h2 id="AMSyntax">Using the Instrument Command</h2>
+<h2 id="AMSyntax">Using the am instrument Command</h2>
 <p>
-  The general syntax of the <code>am instrument</code> command is:
+    The general syntax of the <code>am instrument</code> command is:
 </p>
 <pre>
     am instrument [flags] &lt;test_package&gt;/&lt;runner_class&gt;
@@ -391,11 +395,11 @@
             <code>&lt;test_package&gt;</code>
         </td>
         <td>
-            The Android package name of the test application.
+            The Android package name of the test package.
         </td>
         <td>
             The value of the <code>package</code> attribute of the <code>manifest</code>
-            element in the test application's manifest file.
+            element in the test package's manifest file.
         </td>
     </tr>
     <tr>
@@ -411,7 +415,7 @@
     </tr>
 </table>
 <p>
-The flags for <code>am instrument</code> are described in the following table:
+    The flags for <code>am instrument</code> are described in the following table:
 </p>
 <table>
     <tr>
@@ -461,20 +465,21 @@
              &lt;test_options&gt;
         </td>
         <td>
-            Provides testing options , in the form of key-value pairs. The
+            Provides testing options as key-value pairs. The
             <code>am instrument</code> tool passes these to the specified instrumentation class
             via its <code>onCreate()</code> method. You can specify multiple occurrences of
-            <code>-e &lt;test_options</code>. The keys and values are described in the next table.
+            <code>-e &lt;test_options&gt;</code>. The keys and values are described in the
+            section <a href="#AMOptionsSyntax">am instrument options</a>.
             <p>
-                The only instrumentation class that understands these key-value pairs is
-                <code>InstrumentationTestRunner</code> (or a subclass). Using them with
+                The only instrumentation class that uses these key-value pairs is
+                {@link android.test.InstrumentationTestRunner} (or a subclass). Using them with
                 any other class has no effect.
             </p>
         </td>
     </tr>
 </table>
 
-<h3 id="AMOptionsSyntax">Instrument options</h3>
+<h3 id="AMOptionsSyntax">am instrument options</h3>
 <p>
     The <code>am instrument</code> tool passes testing options to
     <code>InstrumentationTestRunner</code> or a subclass in the form of key-value pairs,
@@ -484,123 +489,127 @@
     -e &lt;key&gt; &lt;value&gt;
 </pre>
 <p>
-    Where applicable, a &lt;key&gt; may have multiple values separated by a comma (,).
+    Some keys accept multiple values. You specify multiple values in a comma-separated list.
     For example, this invocation of <code>InstrumentationTestRunner</code> provides multiple
     values for the <code>package</code> key:
+</p>
 <pre>
-$ adb shell am instrument -w -e package com.android.test.package1,com.android.test.package2 com.android.test/android.test.InstrumentationTestRunner
+$ adb shell am instrument -w -e package com.android.test.package1,com.android.test.package2 \
+&gt; com.android.test/android.test.InstrumentationTestRunner
 </pre>
 <p>
     The following table describes the key-value pairs and their result. Please review the
     <strong>Usage Notes</strong> following the table.
 </p>
 <table>
-<tr>
-    <th>Key</th>
-    <th>Value</th>
-    <th>Description</th>
-</tr>
-<tr>
-    <td>
-        <code>package</code>
-    </td>
-    <td>
-        &lt;Java_package_name&gt;
-    </td>
-    <td>
-        The fully-qualified <em>Java</em> package name for one of the packages in the test
-        application. Any test case class that uses this package name is executed. Notice that this
-        is not an <em>Android</em> package name; a test application has a single Android package
-        name but may have several Java packages within it.
-    </td>
-</tr>
-<tr>
-    <td rowspan="2"><code>class</code></td>
-    <td>&lt;class_name&gt;</td>
-    <td>
-        The fully-qualified Java class name for one of the test case classes. Only this test case
-        class is executed.
-    </td>
-</tr>
-<tr>
-    <td>&lt;class_name&gt;<strong>#</strong>method name</td>
-    <td>
-        A fully-qualified test case class name, and one of its methods. Only this method is
-        executed. Note the hash mark (#) between the class name and the method name.
-    </td>
-</tr>
-<tr>
-    <td><code>func</code></td>
-    <td><code>true</code></td>
-    <td>
-        Runs all test classes that extend {@link android.test.InstrumentationTestCase}.
-    </td>
-</tr>
-<tr>
-    <td><code>unit</code></td>
-    <td><code>true</code></td>
-    <td>
-        Runs all test classes that do <em>not</em> extend either
-        {@link android.test.InstrumentationTestCase} or {@link android.test.PerformanceTestCase}.
-    </td>
-</tr>
-<tr>
-    <td><code>size</code></td>
-    <td>[<code>small</code> | <code>medium</code> | <code>large</code>]
-    </td>
-    <td>
-        Runs a test method annotated by size. The  annotations are <code>@SmallTest</code>,
-        <code>@MediumTest</code>, and <code>@LargeTest</code>.
-    </td>
-</tr>
-<tr>
-    <td><code>perf</code></td>
-    <td><code>true</code></td>
-    <td>
-        Runs all test classes that implement {@link android.test.PerformanceTestCase}.
-        When you use this option, also specify the <code>-r</code> flag for
-        <code>am instrument</code>, so that the output is kept in raw format and not
-        re-formatted as test results.
-    </td>
-</tr>
-<tr>
-    <td><code>debug</code></td>
-    <td><code>true</code></td>
-    <td>
-        Runs tests in debug mode.
-    </td>
-</tr>
-<tr>
-    <td><code>log</code></td>
-    <td><code>true</code></td>
-    <td>
-        Loads and logs all specified tests, but does not run them. The test
-        information appears in <code>STDOUT</code>. Use this to verify combinations of other filters
-        and test specifications.
-    </td>
-</tr>
-<tr>
-    <td><code>emma</code></td>
-    <td><code>true</code></td>
-    <td>
-        Runs an EMMA code coverage analysis and writes the output to <code>/data//coverage.ec</code>
-        on the device. To override the file location, use the <code>coverageFile</code> key that
-        is described in the following entry.
-        <p class="note">
-            <strong>Note:</strong> This option requires an EMMA-instrumented build of the test
-            application, which you can generate with the <code>coverage</code> target.
-        </p>
-    </td>
-</tr>
-<tr>
-    <td><code>coverageFile</code></td>
-    <td><code>&lt;filename&gt;</code></td>
-    <td>
-        Overrides the default location of the EMMA coverage file on the device. Specify this
-        value as a path and filename in UNIX format. The default filename is described in the
-        entry for the <code>emma</code> key.
-    </td>
-</tr>
+    <tr>
+        <th>Key</th>
+        <th>Value</th>
+        <th>Description</th>
+    </tr>
+    <tr>
+        <td>
+            <code>package</code>
+        </td>
+        <td>
+            &lt;Java_package_name&gt;
+        </td>
+        <td>
+            The fully-qualified <em>Java</em> package name for one of the packages in the test
+            application. Any test case class that uses this package name is executed. Notice that
+            this is not an <em>Android</em> package name; a test package has a single
+            Android package name but may have several Java packages within it.
+        </td>
+    </tr>
+    <tr>
+        <td rowspan="2"><code>class</code></td>
+        <td>&lt;class_name&gt;</td>
+        <td>
+            The fully-qualified Java class name for one of the test case classes. Only this test
+            case class is executed.
+        </td>
+    </tr>
+    <tr>
+        <td>&lt;class_name&gt;<strong>#</strong>method name</td>
+        <td>
+            A fully-qualified test case class name, and one of its methods. Only this method is
+            executed. Note the hash mark (#) between the class name and the method name.
+        </td>
+    </tr>
+    <tr>
+        <td><code>func</code></td>
+        <td><code>true</code></td>
+        <td>
+            Runs all test classes that extend {@link android.test.InstrumentationTestCase}.
+        </td>
+    </tr>
+    <tr>
+        <td><code>unit</code></td>
+        <td><code>true</code></td>
+        <td>
+            Runs all test classes that do <em>not</em> extend either
+            {@link android.test.InstrumentationTestCase} or
+            {@link android.test.PerformanceTestCase}.
+        </td>
+    </tr>
+    <tr>
+        <td><code>size</code></td>
+        <td>
+            [<code>small</code> | <code>medium</code> | <code>large</code>]
+        </td>
+        <td>
+            Runs a test method annotated by size. The  annotations are <code>@SmallTest</code>,
+            <code>@MediumTest</code>, and <code>@LargeTest</code>.
+        </td>
+    </tr>
+    <tr>
+        <td><code>perf</code></td>
+        <td><code>true</code></td>
+        <td>
+            Runs all test classes that implement {@link android.test.PerformanceTestCase}.
+            When you use this option, also specify the <code>-r</code> flag for
+            <code>am instrument</code>, so that the output is kept in raw format and not
+            re-formatted as test results.
+        </td>
+    </tr>
+    <tr>
+        <td><code>debug</code></td>
+        <td><code>true</code></td>
+        <td>
+            Runs tests in debug mode.
+        </td>
+    </tr>
+    <tr>
+        <td><code>log</code></td>
+        <td><code>true</code></td>
+        <td>
+            Loads and logs all specified tests, but does not run them. The test
+            information appears in <code>STDOUT</code>. Use this to verify combinations of other
+            filters and test specifications.
+        </td>
+    </tr>
+    <tr>
+        <td><code>emma</code></td>
+        <td><code>true</code></td>
+        <td>
+            Runs an EMMA code coverage analysis and writes the output to
+            <code>/data//coverage.ec</code> on the device. To override the file location, use the
+            <code>coverageFile</code> key that is described in the following entry.
+            <p class="note">
+                <strong>Note:</strong> This option requires an EMMA-instrumented build of the test
+                application, which you can generate with the <code>coverage</code> target.
+            </p>
+        </td>
+    </tr>
+    <tr>
+        <td><code>coverageFile</code></td>
+        <td><code>&lt;filename&gt;</code></td>
+        <td>
+            Overrides the default location of the EMMA coverage file on the device. Specify this
+            value as a path and filename in UNIX format. The default filename is described in the
+            entry for the <code>emma</code> key.
+        </td>
+    </tr>
 </table>
 <strong><code>-e</code> Flag Usage Notes</strong>
 <ul>
@@ -618,13 +627,13 @@
         The <code>func</code> key and <code>unit</code> key are mutually exclusive.
     </li>
 </ul>
-<h3 id="RunTestExamples">Instrument examples</h3>
+<h3 id="RunTestExamples">Usage examples</h3>
 <p>
-Here are some examples of using <code>am instrument</code> to run tests. They are based on
-the following structure:</p>
+The following sections provide examples of using <code>am instrument</code> to run tests.
+They are based on the following structure:</p>
 <ul>
     <li>
-        The test application has the Android package name <code>com.android.demo.app.tests</code>
+        The test package has the Android package name <code>com.android.demo.app.tests</code>
     </li>
     <li>
         There are three test classes:
@@ -647,35 +656,35 @@
         The test runner is {@link android.test.InstrumentationTestRunner}.
     </li>
 </ul>
-<h4>Running the Entire Test Application</h4>
+<h4>Running the entire test package</h4>
 <p>
-    To run all of the test classes in the test application, enter:
+    To run all of the test classes in the test package, enter:
 </p>
 <pre>
 $ adb shell am instrument -w com.android.demo.app.tests/android.test.InstrumentationTestRunner
 </pre>
-<h4>Running All Tests in a Test Case Class</h4>
+<h4>Running all tests in a test case class</h4>
 <p>
     To run all of the tests in the class <code>UnitTests</code>, enter:
 </p>
 <pre>
 $ adb shell am instrument -w  \
--e class com.android.demo.app.tests.UnitTests \
-com.android.demo.app.tests/android.test.InstrumentationTestRunner
+&gt; -e class com.android.demo.app.tests.UnitTests \
+&gt; com.android.demo.app.tests/android.test.InstrumentationTestRunner
 </pre>
 <p>
   <code>am instrument</code> gets the value of the <code>-e</code> flag, detects the
   <code>class</code> keyword, and runs all the methods in the <code>UnitTests</code> class.
 </p>
-<h4>Selecting a Subset of Tests</h4>
+<h4>Selecting a subset of tests</h4>
 <p>
-  To run all of the tests in <code>UnitTests</code>, and the <code>testCamera</code> method in
-  <code>FunctionTests</code>, enter:
+    To run all of the tests in <code>UnitTests</code>, and the <code>testCamera</code> method in
+    <code>FunctionTests</code>, enter:
 </p>
 <pre>
 $ adb shell am instrument -w \
--e class com.android.demo.app.tests.UnitTests,com.android.demo.app.tests.FunctionTests#testCamera \
-com.android.demo.app.tests/android.test.InstrumentationTestRunner
+&gt; -e class com.android.demo.app.tests.UnitTests,com.android.demo.app.tests.FunctionTests#testCamera \
+&gt; com.android.demo.app.tests/android.test.InstrumentationTestRunner
 </pre>
 <p>
     You can find more examples of the command in the documentation for
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index cdf5feb..2b803424 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -254,12 +254,34 @@
             <li><a href="<?cs var:toroot?>guide/topics/search/searchable-config.html">Searchable Configuration</a></li>
           </ul>
       </li>
-      <li><a href="<?cs var:toroot?>guide/topics/testing/testing_android.html">
-            <span class="en">Testing and Instrumentation</span>
-          </a></li>
+      <li class="toggle-list">
+           <div>
+                <a href="<?cs var:toroot ?>guide/topics/testing/index.html">
+                   <span class="en">Testing</span>
+               </a> <span class="new">new!</span>
+           </div>
+           <ul>
+              <li><a href="<?cs var:toroot?>guide/topics/testing/testing_android.html">
+                <span class="en">Testing Fundamentals</span></a>
+              </li>
+              <li><a href="<?cs var:toroot?>guide/topics/testing/activity_testing.html">
+                <span class="en">Activity Testing</span></a>
+              </li>
+              <li><a href="<?cs var:toroot ?>guide/topics/testing/contentprovider_testing.html">
+                <span class="en">Content Provider Testing</span></a>
+              </li>
+              <li><a href="<?cs var:toroot ?>guide/topics/testing/service_testing.html">
+                <span class="en">Service Testing</span></a>
+              </li>
+              <li><a href="<?cs var:toroot ?>guide/topics/testing/what_to_test.html">
+                <span class="en">What To Test</span></a>
+              </li>
+           </ul>
+      </li>
      <li><a href="<?cs var:toroot?>guide/topics/admin/device-admin.html">
             <span class="en">Device Administration</span>
-         </a> <span class="new">new!</span><!-- 10/8/10 --></li>
+         </a> <span class="new">new!</span>
+    </li>
     </ul>
   </li>
 
diff --git a/docs/html/guide/topics/testing/activity_testing.jd b/docs/html/guide/topics/testing/activity_testing.jd
new file mode 100644
index 0000000..6392ad7
--- /dev/null
+++ b/docs/html/guide/topics/testing/activity_testing.jd
@@ -0,0 +1,392 @@
+page.title=Activity Testing
+@jd:body
+
+<div id="qv-wrapper">
+  <div id="qv">
+  <h2>In this document</h2>
+  <ol>
+    <li>
+      <a href="#ActivityTestAPI">The Activity Testing API</a>
+      <ol>
+        <li>
+            <a href="#ActivityInstrumentationTestCase2">ActivityInstrumentationTestCase2</a>
+        </li>
+        <li>
+            <a href="#ActivityUnitTestCase">ActivityUnitTestCase</a>
+        </li>
+        <li>
+            <a href="#SingleLaunchActivityTestCase">SingleLaunchActivityTestCase</a>
+        </li>
+        <li>
+            <a href="#MockObjectNotes">Mock objects and activity testing</a>
+        </li>
+        <li>
+            <a href="#AssertionNotes">Assertions for activity testing</a>
+        </li>
+      </ol>
+    </li>
+    <li>
+        <a href="#WhatToTest">What to Test</a>
+    </li>
+    <li>
+        <a href="#NextSteps">Next Steps</a>
+    </li>
+    <li>
+      <a href="#UITesting">Appendix: UI Testing Notes</a>
+      <ol>
+        <li>
+          <a href="#RunOnUIThread">Testing on the UI thread</a>
+        </li>
+        <li>
+          <a href="#NotouchMode">Turning off touch mode</a>
+        </li>
+        <li>
+          <a href="#UnlockDevice">Unlocking the Emulator or Device</a>
+        </li>
+        <li>
+          <a href="#UITestTroubleshooting">Troubleshooting UI tests</a>
+        </li>
+      </ol>
+    </li>
+    </ol>
+<h2>Key Classes</h2>
+    <ol>
+      <li>{@link android.test.InstrumentationTestRunner}</li>
+      <li>{@link android.test.ActivityInstrumentationTestCase2}</li>
+      <li>{@link android.test.ActivityUnitTestCase}</li>
+    </ol>
+<h2>Related Tutorials</h2>
+    <ol>
+      <li>
+        <a href="{@docRoot}resources/tutorials/testing/helloandroid_test.html">
+        Hello, Testing</a>
+      </li>
+      <li>
+         <a href="{@docRoot}resources/tutorials/testing/activity_test.html">Activity Testing</a>
+      </li>
+    </ol>
+<h2>See Also</h2>
+      <ol>
+        <li>
+          <a href="{@docRoot}guide/developing/testing/testing_eclipse.html">
+          Testing in Eclipse, with ADT</a>
+        </li>
+        <li>
+          <a href="{@docRoot}guide/developing/testing/testing_otheride.html">
+          Testing in Other IDEs</a>
+        </li>
+      </ol>
+  </div>
+</div>
+<p>
+    Activity testing is particularly dependent on the the Android instrumentation framework.
+    Unlike other components, activities have a complex lifecycle based on callback methods; these
+    can't be invoked directly except by instrumentation. Also, the only way to send events to the
+    user interface from a program is through instrumentation.
+</p>
+<p>
+    This document describes how to test activities using instrumentation and other test
+    facilities. The document assumes you have already read
+    <a href="{@docRoot}guide/topics/testing/testing_android.html">Testing Fundamentals</a>,
+    the introduction to the Android testing and instrumentation framework.
+</p>
+<h2 id="ActivityTestAPI">The Activity Testing API</h2>
+<p>
+    The activity testing API base class is {@link android.test.InstrumentationTestCase},
+    which provides instrumentation to the test case subclasses you use for Activities.
+</p>
+<p>
+    For activity testing, this base class provides these functions:
+</p>
+<ul>
+    <li>
+        Lifecycle control: With instrumentation, you can start the activity under test, pause it,
+        and destroy it, using methods provided by the test case classes.
+    </li>
+    <li>
+        Dependency injection: Instrumentation allows you to create mock system objects such as
+        Contexts or Applications and use them to run the activity under test. This
+        helps you control the test environment and isolate it from production systems. You can
+        also set up customized Intents and start an activity with them.
+    </li>
+    <li>
+        User interface interaction: You use instrumentation to send keystrokes or touch events
+        directly to the UI of the activity under test.
+    </li>
+</ul>
+<p>
+    The activity testing classes also provide the JUnit framework by extending
+    {@link junit.framework.TestCase} and {@link junit.framework.Assert}.
+</p>
+<p>
+    The two main testing subclasses are {@link android.test.ActivityInstrumentationTestCase2} and
+    {@link android.test.ActivityUnitTestCase}. To test an Activity that is launched in a mode
+    other than <code>standard</code>, you use {@link android.test.SingleLaunchActivityTestCase}.
+</p>
+<h3 id="ActivityInstrumentationTestCase2">ActivityInstrumentationTestCase2</h3>
+<p>
+    The {@link android.test.ActivityInstrumentationTestCase2} test case class is designed to do
+    functional testing of one or more Activities in an application, using a normal system
+    infrastructure. It runs the Activities in a normal instance of the application under test,
+    using a standard system Context. It allows you to send mock Intents to the activity under
+    test, so you can use it to test an activity that responds to multiple types of intents, or
+    an activity that expects a certain type of data in the intent, or both. Notice, though, that it
+    does not allow mock Contexts or Applications, so you can not isolate the test from the rest of
+    a production system.
+</p>
+<h3 id="ActivityUnitTestCase">ActivityUnitTestCase</h3>
+<p>
+    The {@link android.test.ActivityUnitTestCase} test case class tests a single activity in
+    isolation. Before you start the activity, you can inject a mock Context or Application, or both.
+    You use it to run activity tests in isolation, and to do unit testing of methods
+    that do not interact with Android. You can not send mock Intents to the activity under test,
+    although you can call
+    {@link android.app.Activity#startActivity(Intent) Activity.startActivity(Intent)} and then
+    look at arguments that were received.
+</p>
+<h3 id="SingleLaunchActivityTestCase">SingleLaunchActivityTestCase</h3>
+<p>
+    The {@link android.test.SingleLaunchActivityTestCase} class is a convenience class for
+    testing a single activity in an environment that doesn't change from test to test.
+    It invokes {@link junit.framework.TestCase#setUp() setUp()} and
+    {@link junit.framework.TestCase#tearDown() tearDown()} only once, instead of once per
+    method call. It does not allow you to inject any mock objects.
+</p>
+<p>
+    This test case is useful for testing an activity that runs in a mode other than
+    <code>standard</code>. It ensures that the test fixture is not reset between tests. You
+    can then test that the activity handles multiple calls correctly.
+</p>
+<h3 id="MockObjectNotes">Mock objects and activity testing</h3>
+<p>
+    This section contains notes about the use of the mock objects defined in
+    {@link android.test.mock} with activity tests.
+</p>
+<p>
+    The mock object {@link android.test.mock.MockApplication} is only available for activity
+    testing if you use the {@link android.test.ActivityUnitTestCase} test case class.
+    By default, <code>ActivityUnitTestCase</code>, creates a hidden <code>MockApplication</code>
+    object that is used as the application under test. You can inject your own object using
+    {@link android.test.ActivityUnitTestCase#setApplication(Application) setApplication()}.
+</p>
+<h3 id="AssertionNotes">Assertions for activity testing</h3>
+<p>
+    {@link android.test.ViewAsserts} defines assertions for Views. You use it to verify the
+    alignment and position of View objects, and to look at the state of ViewGroup objects.
+</p>
+<h2 id="WhatToTest">What To Test</h2>
+<ul>
+    <li>
+        Input validation: Test that an activity responds correctly to input values in an
+        EditText View. Set up a keystroke sequence, send it to the activity, and then
+        use {@link android.view.View#findViewById(int)} to examine the state of the View. You can
+        verify that a valid keystroke sequence enables an OK button, while an invalid one leaves the
+        button disabled. You can also verify that the Activity responds to invalid input by
+        setting error messages in the View.
+    </li>
+    <li>
+        Lifecycle events: Test that each of your application's activities handles lifecycle events
+        correctly. In general, lifecycle events are actions, either from the system or from the
+        user, that trigger a callback method such as <code>onCreate()</code> or
+        <code>onClick()</code>. For example, an activity should respond to pause or destroy events
+        by saving its state. Remember that even a change in screen orientation causes the current
+        activity to be destroyed, so you should test that accidental device movements don't
+        accidentally lose the application state.
+    </li>
+    <li>
+        Intents: Test that each activity correctly handles the intents listed in the intent
+        filter specified in its manifest. You can use
+        {@link android.test.ActivityInstrumentationTestCase2} to send mock Intents to the
+        activity under test.
+    </li>
+    <li>
+        Runtime configuration changes: Test that each activity responds correctly to the
+        possible changes in the device's configuration while your application is running. These
+        include a change to the device's orientation, a change to the current language, and so
+        forth. Handling these changes is described in detail in the topic
+        <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Handling Runtime
+        Changes</a>.
+    </li>
+    <li>
+        Screen sizes and resolutions: Before you publish your application, make sure to test it on
+        all of the screen sizes and densities on which you want it to run. You can test the
+        application on multiple sizes and densities using AVDs, or you can test your application
+        directly on the devices that you are targeting. For more information, see the topic
+        <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>.
+    </li>
+</ul>
+<h2 id="NextSteps">Next Steps</h2>
+<p>
+    To learn how to set up and run tests in Eclipse, please refer to <a
+    href="{@docRoot}guide/developing/testing/testing_eclipse.html">Testing in
+    Eclipse, with ADT</a>. If you're not working in Eclipse, refer to <a
+    href="{@docRoot}guide/developing/testing/testing_otheride.html">Testing in Other
+    IDEs</a>.
+</p>
+<p>
+    If you want a step-by-step introduction to testing activities, try one of the
+    testing tutorials:
+</p>
+<ul>
+    <li>
+        The <a
+        href="{@docRoot}resources/tutorials/testing/helloandroid_test.html">Hello,
+        Testing</a> tutorial introduces basic testing concepts and procedures in the
+        context of the Hello, World application.
+    </li>
+    <li>
+        The <a
+        href="{@docRoot}resources/tutorials/testing/activity_test.html">Activity
+        Testing</a> tutorial is an excellent follow-up to the Hello, Testing tutorial.
+        It guides you through a more complex testing scenario that you develop against a
+        more realistic activity-oriented application.
+    </li>
+</ul>
+<h2 id="UITesting">Appendix: UI Testing Notes</h2>
+<p>
+    The following sections have tips for testing the UI of your Android application, specifically
+    to help you handle actions that run in the UI thread, touch screen and keyboard events, and home
+    screen unlock during testing.
+</p>
+<h3 id="RunOnUIThread">Testing on the UI thread</h3>
+<p>
+    An application's activities run on the application's <strong>UI thread</strong>. Once the
+    UI is instantiated, for example in the activity's <code>onCreate()</code> method, then all
+    interactions with the UI must run in the UI thread. When you run the application normally, it
+    has access to the thread and does not have to do anything special.
+</p>
+<p>
+    This changes when you run tests against the application. With instrumentation-based classes,
+    you can invoke methods against the UI of the application under test. The other test classes
+    don't allow this. To run an entire test method on the UI thread, you can annotate the thread
+    with <code>@UIThreadTest</code>. Notice that this will run <em>all</em> of the method statements
+    on the UI thread.  Methods that do not interact with the UI are not allowed; for example, you
+    can't invoke <code>Instrumentation.waitForIdleSync()</code>.
+</p>
+<p>
+    To run a subset of a test method on the UI thread, create an anonymous class of type
+    <code>Runnable</code>, put the statements you want in the <code>run()</code> method, and
+    instantiate a new instance of the class as a parameter to the method
+    <code><em>appActivity</em>.runOnUiThread()</code>, where <code><em>appActivity</em></code> is
+    the instance of the application you are testing.
+</p>
+<p>
+    For example, this code instantiates an activity to test, requests focus (a UI action) for the
+    Spinner displayed by the activity, and then sends a key to it. Notice that the calls to
+    <code>waitForIdleSync</code> and <code>sendKeys</code> aren't allowed to run on the UI thread:
+</p>
+<pre>
+  private MyActivity mActivity; // MyActivity is the class name of the app under test
+  private Spinner mSpinner;
+
+  ...
+
+  protected void setUp() throws Exception {
+      super.setUp();
+      mInstrumentation = getInstrumentation();
+
+      mActivity = getActivity(); // get a references to the app under test
+
+      /*
+       * Get a reference to the main widget of the app under test, a Spinner
+       */
+      mSpinner = (Spinner) mActivity.findViewById(com.android.demo.myactivity.R.id.Spinner01);
+
+  ...
+
+  public void aTest() {
+      /*
+       * request focus for the Spinner, so that the test can send key events to it
+       * This request must be run on the UI thread. To do this, use the runOnUiThread method
+       * and pass it a Runnable that contains a call to requestFocus on the Spinner.
+       */
+      mActivity.runOnUiThread(new Runnable() {
+          public void run() {
+              mSpinner.requestFocus();
+          }
+      });
+
+      mInstrumentation.waitForIdleSync();
+
+      this.sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+</pre>
+
+<h3 id="NotouchMode">Turning off touch mode</h3>
+<p>
+    To control the emulator or a device with key events you send from your tests, you must turn off
+    touch mode. If you do not do this, the key events are ignored.
+</p>
+<p>
+    To turn off touch mode, you invoke
+    <code>ActivityInstrumentationTestCase2.setActivityTouchMode(false)</code>
+    <em>before</em> you call <code>getActivity()</code> to start the activity. You must invoke the
+    method in a test method that is <em>not</em> running on the UI thread. For this reason, you
+    can't invoke the touch mode method from a test method that is annotated with
+    <code>@UIThread</code>. Instead, invoke the touch mode method from <code>setUp()</code>.
+</p>
+<h3 id="UnlockDevice">Unlocking the emulator or device</h3>
+<p>
+    You may find that UI tests don't work if the emulator's or device's home screen is disabled with
+    the keyguard pattern. This is because the application under test can't receive key events sent
+    by <code>sendKeys()</code>. The best way to avoid this is to start your emulator or device
+    first and then disable the keyguard for the home screen.
+</p>
+<p>
+    You can also explicitly disable the keyguard. To do this,
+    you need to add a permission in the manifest file (<code>AndroidManifest.xml</code>) and
+    then disable the keyguard in your application under test. Note, though, that you either have to
+    remove this before you publish your application, or you have to disable it with code in
+    the published application.
+</p>
+<p>
+    To add the the permission, add the element
+    <code>&lt;uses-permission android:name="android.permission.DISABLE_KEYGUARD"/&gt;</code>
+    as a child of the <code>&lt;manifest&gt;</code> element. To disable the KeyGuard, add the
+    following code to the <code>onCreate()</code> method of activities you intend to test:
+</p>
+<pre>
+  mKeyGuardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
+  mLock = mKeyGuardManager.newKeyguardLock("<em>activity_classname</em>");
+  mLock.disableKeyguard();
+</pre>
+<p>where <code><em>activity_classname</em></code> is the class name of the activity.</p>
+<h3 id="UITestTroubleshooting">Troubleshooting UI tests</h3>
+<p>
+    This section lists some of the common test failures you may encounter in UI testing, and their
+    causes:
+</p>
+<dl>
+    <dt><code>WrongThreadException</code></dt>
+    <dd>
+      <p><strong>Problem:</strong></p>
+      For a failed test, the Failure Trace contains the following error message:
+      <code>
+        android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created
+        a view hierarchy can touch its views.
+      </code>
+      <p><strong>Probable Cause:</strong></p>
+        This error is common if you tried to send UI events to the UI thread from outside the UI
+        thread. This commonly happens if you send UI events from the test application, but you don't
+        use the <code>@UIThread</code> annotation or the <code>runOnUiThread()</code> method. The
+        test method tried to interact with the UI outside the UI thread.
+      <p><strong>Suggested Resolution:</strong></p>
+        Run the interaction on the UI thread. Use a test class that provides instrumentation. See
+        the previous section <a href="#RunOnUIThread">Testing on the UI Thread</a>
+        for more details.
+    </dd>
+    <dt><code>java.lang.RuntimeException</code></dt>
+    <dd>
+      <p><strong>Problem:</strong></p>
+        For a failed test, the Failure Trace contains the following error message:
+      <code>
+        java.lang.RuntimeException: This method can not be called from the main application thread
+      </code>
+      <p><strong>Probable Cause:</strong></p>
+        This error is common if your test method is annotated with <code>@UiThreadTest</code> but
+        then tries to do something outside the UI thread or tries to invoke
+        <code>runOnUiThread()</code>.
+      <p><strong>Suggested Resolution:</strong></p>
+        Remove the <code>@UiThreadTest</code> annotation, remove the <code>runOnUiThread()</code>
+        call, or re-factor your tests.
+    </dd>
+</dl>
diff --git a/docs/html/guide/topics/testing/contentprovider_testing.jd b/docs/html/guide/topics/testing/contentprovider_testing.jd
new file mode 100644
index 0000000..893b5c9
--- /dev/null
+++ b/docs/html/guide/topics/testing/contentprovider_testing.jd
@@ -0,0 +1,224 @@
+page.title=Content Provider Testing
+@jd:body
+
+<div id="qv-wrapper">
+  <div id="qv">
+  <h2>In this document</h2>
+  <ol>
+    <li>
+        <a href="#DesignAndTest">Content Provider Design and Testing</a>
+    </li>
+    <li>
+      <a href="#ContentProviderTestAPI">The Content Provider Testing API</a>
+      <ol>
+        <li>
+          <a href="#ProviderTestCase2">ProviderTestCase2 </a>
+        </li>
+        <li>
+          <a href="#MockObjects">Mock object classes</a>
+        </li>
+      </ol>
+    </li>
+    <li>
+        <a href="#WhatToTest">What To Test</a>
+    </li>
+    <li>
+        <a href="#NextSteps">Next Steps</a>
+    </li>
+  </ol>
+  <h2>Key Classes</h2>
+    <ol>
+      <li>{@link android.test.InstrumentationTestRunner}</li>
+      <li>{@link android.test.ProviderTestCase2}</li>
+      <li>{@link android.test.IsolatedContext}</li>
+      <li>{@link android.test.mock.MockContentResolver}</li>
+    </ol>
+  <h2>See Also</h2>
+      <ol>
+        <li>
+          <a
+          href="{@docRoot}guide/topics/testing/topics/testing_android.html">
+          Testing Fundamentals</a>
+        </li>
+        <li>
+          <a href="{@docRoot}guide/developing/testing/testing_eclipse.html">
+          Testing in Eclipse, with ADT</a>
+        </li>
+        <li>
+          <a href="{@docRoot}guide/developing/testing/testing_otheride.html">
+          Testing in Other IDEs</a>
+        </li>
+      </ol>
+  </div>
+</div>
+<p>
+    Content providers, which store and retrieve data and make it accessible across applications,
+    are a key part of the Android API. As an application developer you're allowed to provide your
+    own public providers for use by other applications. If you do, then you should test them
+    using the API you publish.
+</p>
+<p>
+    This document describes how to test public content providers, although the information is
+    also applicable to providers that you keep private to your own application. If you aren't
+    familiar with content  providers or the Android testing framework, please read
+    <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>,
+    the guide to developing content providers, and
+    <a href="{@docRoot}guide/topics/testing/testing_android.html">Testing Fundamentals</a>,
+    the introduction to the Android testing and instrumentation framework.
+</p>
+<h2 id="DesignAndTest">Content Provider Design and Testing</h2>
+<p>
+    In Android, content providers are viewed externally as data APIs that provide
+    tables of data, with their internals hidden from view. A content provider may have many
+    public constants, but it usually has few if any public methods and no public variables.
+    This suggests that you should write your tests based only on the provider's public members.
+    A content provider that is designed like this is offering a contract between itself and its
+    users.
+</p>
+<p>
+    The base test case class for content providers,
+    {@link android.test.ProviderTestCase2}, allows you to test your content provider in an
+    isolated environment. Android mock objects such as {@link android.test.IsolatedContext} and
+    {@link android.test.mock.MockContentResolver} also help provide an isolated test environment.
+</p>
+<p>
+    As with other Android tests, provider test packages are run under the control of the test
+    runner {@link android.test.InstrumentationTestRunner}. The section
+    <a href="{@docRoot}guide/topics/testing/testing_android.html#InstrumentationTestRunner">
+    Running Tests With InstrumentationTestRunner</a> describes the test runner in
+    more detail. The topic <a href="{@docRoot}guide/developing/testing/testing_eclipse.html">
+    Testing in Eclipse, with ADT</a> shows you how to run a test package in Eclipse, and the
+    topic <a href="{@docRoot}guide/developing/testing/testing_otheride.html">
+    Testing in Other IDEs</a>
+    shows you how to run a test package from the command line.
+</p>
+<h2 id="ContentProviderTestAPI">Content Provider Testing API</h2>
+<p>
+    The main focus of the provider testing API is to provide an isolated testing environment. This
+    ensures that tests always run against data dependencies set explicitly in the test case. It
+    also prevents tests from modifying actual user data. For example, you want to avoid writing
+    a test that fails because there was data left over from a previous test, and you want to
+    avoid adding or deleting contact information in a actual provider.
+</p>
+<p>
+    The test case class and mock object classes for provider testing set up this isolated testing
+    environment for you.
+</p>
+<h3 id="ProviderTestCase2">ProviderTestCase2</h3>
+<p>
+    You test a provider with a subclass of {@link android.test.ProviderTestCase2}. This base class
+    extends {@link android.test.AndroidTestCase}, so it provides the JUnit testing framework as well
+    as Android-specific methods for testing application permissions. The most important
+    feature of this class is its initialization, which creates the isolated test environment.
+</p>
+<p>
+    The initialization is done in the constructor for {@link android.test.ProviderTestCase2}, which
+    subclasses call in their own constructors. The {@link android.test.ProviderTestCase2}
+    constructor creates an {@link android.test.IsolatedContext} object that allows file and
+    database operations but stubs out other interactions with the Android system.
+    The file and database operations themselves take place in a directory that is local to the
+    device or emulator and has a special prefix.
+</p>
+<p>
+    The constructor then creates a {@link android.test.mock.MockContentResolver} to use as the
+    resolver for the test. The {@link android.test.mock.MockContentResolver} class is described in
+    detail in the section
+    <a href="{@docRoot}guide/topics/testing/test_android#MockObjectClasses">Mock object classes</a>.
+</p>
+<p>
+    Lastly, the constructor creates an instance of the provider under test. This is a normal
+    {@link android.content.ContentProvider} object, but it takes all of its environment information
+    from the {@link android.test.IsolatedContext}, so it is restricted to
+    working in the isolated test environment. All of the tests done in the test case class run
+    against this isolated object.
+</p>
+<h3 id="MockObjects">Mock object classes</h3>
+<p>
+    {@link android.test.ProviderTestCase2} uses {@link android.test.IsolatedContext} and
+    {@link android.test.mock.MockContentResolver}, which are standard mock object classes. To
+    learn more about them, please read
+    <a href="{@docRoot}guide/topics/testing/test_android#MockObjectClasses">
+    Testing Fundamentals</a>.
+</p>
+<h2 id="WhatToTest">What To Test</h2>
+<p>
+    The topic <a href="{@docRoot}guide/topics/testing/what_to_test.html">What To Test</a>
+    lists general considerations for testing Android components.
+    Here are some specific guidelines for testing content providers.
+</p>
+<ul>
+    <li>
+        Test with resolver methods: Even though you can instantiate a provider object in
+        {@link android.test.ProviderTestCase2}, you should always test with a resolver object
+        using the appropriate URI. This ensures that you are testing the provider using the same
+        interaction that a regular application would use.
+    </li>
+    <li>
+        Test a public provider as a contract: If you intent your provider to be public and
+        available to other applications, you should test it as a contract. This includes
+        the following ideas:
+        <ul>
+            <li>
+                Test with constants that your provider publicly exposes. For
+                example, look for constants that refer to column names in one of the provider's
+                data tables. These should always be constants publicly defined by the provider.
+            </li>
+            <li>
+                Test all the URIs offered by your provider. Your provider may offer several URIs,
+                each one referring to a different aspect of the data. The
+                <a href="{@docRoot}resources/samples/NotePad/index.html">Note Pad</a> sample,
+                for example, features a provider that offers one URI for retrieving a list of notes,
+                another for retrieving an individual note by it's database ID, and a third for
+                displaying notes in a live folder. The sample test package for Note Pad,
+                <a href="{@docRoot}resources/samples/NotePadTest/index.html"> Note Pad Test</a>, has
+                unit tests for two of these URIs.
+            </li>
+            <li>
+                Test invalid URIs: Your unit tests should deliberately call the provider with an
+                invalid URI, and look for errors. Good provider design is to throw an
+                IllegalArgumentException for invalid URIs.
+
+            </li>
+        </ul>
+    </li>
+    <li>
+        Test the standard provider interactions: Most providers offer six access methods:
+        query, insert, delete, update, getType, and onCreate(). Your tests should verify that all
+        of these methods work. These are described in more detail in the topic
+        <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>.
+    </li>
+    <li>
+        Test business logic: Don't forget to test the business logic that your provider should
+        enforce. Business logic includes handling of invalid values, financial or arithmetic
+        calculations, elimination or combining of duplicates, and so forth. A content provider
+        does not have to have business logic, because it may be implemented by activities that
+        modify the data. If the provider does implement business logic, you should test it.
+    </li>
+</ul>
+<h2 id="NextSteps">Next Steps</h2>
+<p>
+    To learn how to set up and run tests in Eclipse, please refer to <a
+    href="{@docRoot}guide/developing/testing/testing_eclipse.html">Testing in
+    Eclipse, with ADT</a>. If you're not working in Eclipse, refer to <a
+    href="{@docRoot}guide/developing/testing/testing_otheride.html">Testing in Other
+    IDEs</a>.
+</p>
+<p>
+    If you want a step-by-step introduction to testing activities, try one of the
+    testing tutorials:
+</p>
+<ul>
+    <li>
+        The <a
+        href="{@docRoot}resources/tutorials/testing/helloandroid_test.html">Hello,
+        Testing</a> tutorial introduces basic testing concepts and procedures in the
+        context of the Hello, World application.
+    </li>
+    <li>
+        The <a
+        href="{@docRoot}resources/tutorials/testing/activity_test.html">Activity
+        Testing</a> tutorial is an excellent follow-up to the Hello, Testing tutorial.
+        It guides you through a more complex testing scenario that you develop against a
+        more realistic activity-oriented application.
+    </li>
+</ul>
diff --git a/docs/html/guide/topics/testing/index.jd b/docs/html/guide/topics/testing/index.jd
new file mode 100644
index 0000000..92ed5a7
--- /dev/null
+++ b/docs/html/guide/topics/testing/index.jd
@@ -0,0 +1,80 @@
+page.title=Testing
+@jd:body
+<p>
+    The Android development environment includes an integrated testing framework that helps you
+    test all aspects of your application.
+</p>
+<h4>Fundamentals</h4>
+<p>
+    To start learning how to use the framework to create tests for your applications, please
+    read the topic <a href="{@docRoot}guide/topics/testing/testing_android.html">
+    Testing Fundamentals</a>.
+</p>
+<h4>Concepts</h4>
+<ul>
+    <li>
+        Testing Tools describes the Eclipse with ADT and command-line tools you use to test
+        Android applications.
+    </li>
+    <li>
+        What to Test is an overview of the types of testing you should do. It focuses on testing
+        system-wide aspects of Android that can affect every component in your application.
+    </li>
+    <li>
+        <a href="{@docRoot}guide/topics/testing/activity_testing.html">
+        Activity Testing</a> focuses on testing activities. It describes how instrumentation allows
+        you to control activities outside the normal application lifecycle. It also lists
+        activity-specific features you should test, and it provides tips for testing Android
+        user interfaces.
+    </li>
+    <li>
+        <a href="{@docRoot}guide/topics/testing/contentprovider_testing.html">
+        Content Provider Testing</a> focuses on testing content providers. It describes the
+        mock system objects you can use, provides tips for designing providers so that they
+        can be tested, and lists provider-specific features you should test.
+    </li>
+    <li>
+        <a href="{@docRoot}guide/topics/testing/service_testing.html">
+        Service Testing</a> focuses on testing services. It also lists service-specific features
+        you should test.
+    </li>
+</ul>
+<h4>Procedures</h4>
+<ul>
+    <li>
+        The topic <a href="{@docRoot}guide/developing/testing/testing_eclipse.html">
+        Testing in Eclipse, with ADT</a> describes how to create and run tests in Eclipse with ADT.
+    </li>
+    <li>
+        The topic <a href="{@docRoot}guide/developing/testing/testing_otheride.html">
+        Testing in other IDEs</a> describes how to create and run tests with command-line tools.
+    </li>
+</ul>
+<h4>Tutorials</h4>
+<ul>
+    <li>
+        The <a href="{@docRoot}resources/tutorials/testing/helloandroid_test.html">
+        Hello, Testing</a> tutorial introduces basic testing concepts and procedures.
+    </li>
+    <li>
+        For a more advanced tutorial, try
+        <a href="{@docRoot}resources/tutorials/testing/activity_test.html">Activity Testing</a>,
+        which guides you through a more complex testing scenario.
+    </li>
+</ul>
+<h4>Samples</h4>
+<ul>
+    <li>
+        <a href="{@docRoot}resources/samples/NotePadTest.html">Note Pad Provider
+        Test</a> is a test package for the
+        <a href="{@docRoot}resources/samples/NotePad.html">Note Pad</a> sample
+        application. It provides a simple example of unit testing
+        a {@link android.content.ContentProvider}.
+    </li>
+    <li>
+        The <a href="{@docRoot}resources/samples/AlarmServiceTest.html">Alarm Service Test</a>
+        is a test package for the <a href="{@docRoot}resources/samples/Alarm.html">Alarm</a>
+        sample application. It provides a simple example of unit
+        testing a {@link android.app.Service}.
+    </li>
+</ul>
diff --git a/docs/html/guide/topics/testing/service_testing.jd b/docs/html/guide/topics/testing/service_testing.jd
new file mode 100644
index 0000000..3979f3c
--- /dev/null
+++ b/docs/html/guide/topics/testing/service_testing.jd
@@ -0,0 +1,178 @@
+page.title=Service Testing
+@jd:body
+
+<div id="qv-wrapper">
+  <div id="qv">
+  <h2>In this document</h2>
+  <ol>
+    <li>
+        <a href="#DesignAndTest">Service Design and Testing</a>
+    </li>
+    <li>
+        <a href="#ServiceTestCase">ServiceTestCase</a>
+    </li>
+    <li>
+        <a href="#MockObjects">Mock object classes</a>
+    </li>
+    <li>
+        <a href="#TestAreas">What to Test</a>
+    </li>
+  </ol>
+  <h2>Key Classes</h2>
+    <ol>
+      <li>{@link android.test.InstrumentationTestRunner}</li>
+      <li>{@link android.test.ServiceTestCase}</li>
+      <li>{@link android.test.mock.MockApplication}</li>
+      <li>{@link android.test.RenamingDelegatingContext}</li>
+    </ol>
+  <h2>Related Tutorials</h2>
+    <ol>
+        <li>
+            <a href="{@docRoot}resources/tutorials/testing/helloandroid_test.html">
+            Hello, Testing</a>
+        </li>
+        <li>
+            <a href="{@docRoot}resources/tutorials/testing/activity_test.html">Activity Testing</a>
+        </li>
+    </ol>
+  <h2>See Also</h2>
+      <ol>
+        <li>
+          <a href="{@docRoot}guide/developing/testing/testing_eclipse.html">
+          Testing in Eclipse, with ADT</a>
+        </li>
+        <li>
+          <a href="{@docRoot}guide/developing/testing/testing_otheride.html">
+          Testing in Other IDEs</a>
+        </li>
+      </ol>
+  </div>
+</div>
+<p>
+    Android provides a testing framework for Service objects that can run them in
+    isolation and provides mock objects. The test case class for Service objects is
+    {@link android.test.ServiceTestCase}. Since the Service class assumes that it is separate
+    from its clients, you can test a Service object without using instrumentation.
+</p>
+<p>
+    This document describes techniques for testing Service objects. If you aren't familiar with the
+    Service class, please read <a href="{@docRoot}guide/topics/fundamentals.html">
+    Application Fundamentals</a>. If you aren't familiar with Android testing, please read
+    <a href="{@docRoot}guide/topics/testing/testing_android.html">Testing Fundamentals</a>,
+    the introduction to the Android testing and instrumentation framework.
+</p>
+<h2 id="DesignAndTest">Service Design and Testing</h2>
+<p>
+    When you design a Service, you should consider how your tests can examine the various states
+    of the Service lifecycle. If the lifecycle methods that start up your Service, such as
+    {@link android.app.Service#onCreate() onCreate()} or
+    {@link android.app.Service#onStartCommand(Intent, int, int) onStartCommand()} do not normally
+    set a global variable to indicate that they were successful, you may want to provide such a
+    variable for testing purposes.
+</p>
+<p>
+    Most other testing is facilitated by the methods in the {@link android.test.ServiceTestCase}
+    test case class. For example, the {@link android.test.ServiceTestCase#getService()} method
+    returns a handle to the Service under test, which you can test to confirm that the Service is
+    running even at the end of your tests.
+</p>
+<h2 id="ServiceTestCase">ServiceTestCase</h2>
+<p>
+    {@link android.test.ServiceTestCase} extends the JUnit {@link junit.framework.TestCase} class
+    with with methods for testing application permissions and for controlling the application and
+    Service under test. It also provides mock application and Context objects that isolate your
+    test from the rest of the system.
+</p>
+<p>
+    {@link android.test.ServiceTestCase} defers initialization of the test environment until you
+    call {@link android.test.ServiceTestCase#startService(Intent) ServiceTestCase.startService()} or
+    {@link android.test.ServiceTestCase#bindService(Intent) ServiceTestCase.bindService()}. This
+    allows you to set up your test environment, particularly your mock objects, before the Service
+    is started.
+</p>
+<p>
+    Notice that the parameters to <code>ServiceTestCase.bindService()</code>are different from
+    those for <code>Service.bindService()</code>. For the <code>ServiceTestCase</code> version,
+    you only provide an Intent. Instead of returning a boolean,
+    <code>ServiceTestCase.bindService()</code> returns an object that subclasses
+    {@link android.os.IBinder}.
+</p>
+<p>
+    The {@link android.test.ServiceTestCase#setUp()} method for {@link android.test.ServiceTestCase}
+    is called before each test. It sets up the test fixture by making a copy of the current system
+    Context before any test methods touch it. You can retrieve this Context by calling
+    {@link android.test.ServiceTestCase#getSystemContext()}. If you override this method, you must
+    call <code>super.setUp()</code> as the first statement in the override.
+</p>
+<p>
+    The methods {@link android.test.ServiceTestCase#setApplication(Application) setApplication()}
+    and {@link android.test.AndroidTestCase#setContext(Context)} setContext()} allow you to set
+    a mock Context or mock Application (or both) for the Service, before you start it. These mock
+    objects are described in <a href="#MockObjects">Mock object classes</a>.
+</p>
+<p>
+    By default, {@link android.test.ServiceTestCase} runs the test method
+    {@link android.test.AndroidTestCase#testAndroidTestCaseSetupProperly()}, which asserts that
+    the base test case class successfully set up a Context before running.
+</p>
+<h2 id="MockObjects">Mock object classes</h2>
+<p>
+    <code>ServiceTestCase</code> assumes that you will use a mock Context or mock Application
+    (or both) for the test environment. These objects isolate the test environment from the
+    rest of the system. If you don't provide your own instances of these objects before you
+    start the Service, then {@link android.test.ServiceTestCase} will create its own internal
+    instances and inject them into the Service. You can override this behavior by creating and
+    injecting your own instances before starting the Service
+</p>
+<p>
+    To inject a mock Application object into the Service under test, first create a subclass of
+    {@link android.test.mock.MockApplication}. <code>MockApplication</code> is a subclass of
+    {@link android.app.Application} in which all the methods throw an Exception, so to use it
+    effectively you subclass it and override the methods you need. You then inject it into the
+    Service with the
+    {@link android.test.ServiceTestCase#setApplication(Application) setApplication()} method.
+    This mock object allows you to control the application values that the Service sees, and
+    isolates it from the real system. In addition, any hidden dependencies your Service has on
+    its application reveal themselves as exceptions when you run the test.
+</p>
+<p>
+    You inject a mock Context into the Service under test with the
+    {@link android.test.AndroidTestCase#setContext(Context) setContext()} method. The mock
+    Context classes you can use are described in more detail in
+    <a href="{@docRoot}guide/topics/testing/testing_android.html#MockObjectClasses">
+    Testing Fundamentals</a>.
+</p>
+<h2 id="TestAreas">What to Test</h2>
+<p>
+    The topic <a href="{@docRoot}guide/topics/testing/what_to_test.html">What To Test</a>
+    lists general considerations for testing Android components.
+    Here are some specific guidelines for testing a Service:
+</p>
+<ul>
+    <li>
+        Ensure that the {@link android.app.Service#onCreate()} is called in response to
+        {@link android.content.Context#startService(Intent) Context.startService()} or
+    {@link android.content.Context#bindService(Intent,ServiceConnection,int) Context.bindService()}.
+        Similarly, you should ensure that {@link android.app.Service#onDestroy()} is called in
+        response to {@link android.content.Context#stopService(Intent) Context.stopService()},
+        {@link android.content.Context#unbindService(ServiceConnection) Context.unbindService()},
+        {@link android.app.Service#stopSelf()}, or
+        {@link android.app.Service#stopSelfResult(int) stopSelfResult()}.
+    </li>
+    <li>
+        Test that your Service correctly handles multiple calls from
+        <code>Context.startService()</code>. Only the first call triggers
+        <code>Service.onCreate()</code>, but all calls trigger a call to
+        <code>Service.onStartCommand()</code>.
+        <p>
+            In addition, remember that <code>startService()</code> calls don't
+            nest, so a single call to <code>Context.stopService()</code> or
+            <code>Service.stopSelf()</code> (but not <code>stopSelf(int)</code>)
+            will stop the Service. You should test that your Service stops at the correct point.
+        </p>
+    </li>
+    <li>
+        Test any business logic that your Service implements. Business logic includes checking for
+        invalid values, financial and arithmetic calculations, and so forth.
+    </li>
+</ul>
diff --git a/docs/html/guide/topics/testing/testing_android.jd b/docs/html/guide/topics/testing/testing_android.jd
index 935aaf9..1d5f911 100755
--- a/docs/html/guide/topics/testing/testing_android.jd
+++ b/docs/html/guide/topics/testing/testing_android.jd
@@ -1,4 +1,4 @@
-page.title=Testing and Instrumentation
+page.title=Testing Fundamentals
 @jd:body
 
 <div id="qv-wrapper">
@@ -6,65 +6,62 @@
   <h2>In this document</h2>
   <ol>
     <li>
-        <a href="#Overview">Overview</a>
+        <a href="#TestStructure">Test Structure</a>
+    </li>
+    <li>
+        <a href="#TestProjects">Test Projects</a>
     </li>
     <li>
       <a href="#TestAPI">The Testing API</a>
       <ol>
         <li>
-          <a href="#Extensions">JUnit test case classes</a>
+          <a href="#JUnit">JUnit</a>
         </li>
         <li>
-          <a href="#Instrumentation">Instrumentation test case classes</a>
+          <a href="#Instrumentation">Instrumentation</a>
         </li>
         <li>
-          <a href="#Assert">Assert classes</a>
+            <a href="#TestCaseClasses">Test case classes</a>
         </li>
         <li>
-          <a href="#MockObjects">Mock object classes</a>
+          <a href="#AssertionClasses">Assertion classes</a>
         </li>
-            <li>
-                <a href="#InstrumentationTestRunner">Instrumentation Test Runner</a>
-            </li>
+        <li>
+          <a href="#MockObjectClasses">Mock object classes</a>
+        </li>
       </ol>
     </li>
     <li>
-     <a href="#TestEnviroment">Working in the Test Environment</a>
+        <a href="#InstrumentationTestRunner">Running Tests</a>
     </li>
     <li>
-        <a href="#TestAreas">What to Test</a>
+        <a href="#TestResults">Seeing Test Results</a>
     </li>
     <li>
-      <a href="#UITesting">Appendix: UI Testing Notes</a>
-      <ol>
-        <li>
-          <a href="#RunOnUIThread">Testing on the UI thread</a>
-        </li>
-        <li>
-          <a href="#NotouchMode">Turning off touch mode</a>
-        </li>
-        <li>
-          <a href="#UnlockDevice">Unlocking the Emulator or Device</a>
-        </li>
-        <li>
-          <a href="#UITestTroubleshooting">Troubleshooting UI tests</a>
-        </li>
-      </ol>
+        <a href="#Monkeys">Monkey and MonkeyRunner</a>
+    </li>
+    <li>
+       <a href="#PackageNames">Working With Package Names</a>
+    </li>
+    <li>
+        <a href="#WhatToTest">What To Test</a>
+    </li>
+    <li>
+        <a href="#NextSteps">Next Steps</a>
     </li>
   </ol>
   <h2>Key classes</h2>
     <ol>
       <li>{@link android.test.InstrumentationTestRunner}</li>
-      <li>{@link android.test.ActivityInstrumentationTestCase2}</li>
-      <li>{@link android.test.ActivityUnitTestCase}</li>
-      <li>{@link android.test.ApplicationTestCase}</li>
-      <li>{@link android.test.ProviderTestCase2}</li>
-      <li>{@link android.test.ServiceTestCase}</li>
+      <li>{@link android.test}</li>
+      <li>{@link android.test.mock}</li>
+      <li>{@link junit.framework}</li>
     </ol>
   <h2>Related tutorials</h2>
     <ol>
         <li>
-            <a href="{@docRoot}resources/tutorials/testing/helloandroid_test.html">Hello, Testing</a>
+            <a href="{@docRoot}resources/tutorials/testing/helloandroid_test.html">
+            Hello, Testing</a>
         </li>
         <li>
             <a href="{@docRoot}resources/tutorials/testing/activity_test.html">Activity Testing</a>
@@ -73,445 +70,590 @@
   <h2>See also</h2>
       <ol>
         <li>
-          <a href="{@docRoot}guide/developing/testing/testing_eclipse.html">Testing in Eclipse, with ADT</a>
+          <a href="{@docRoot}guide/developing/testing/testing_eclipse.html">
+          Testing in Eclipse, with ADT</a>
         </li>
         <li>
-          <a href="{@docRoot}guide/developing/testing/testing_otheride.html">Testing in Other IDEs</a>
+          <a href="{@docRoot}guide/developing/testing/testing_otheride.html">
+          Testing in Other IDEs</a>
         </li>
       </ol>
   </div>
 </div>
-
-<p>Android includes a powerful set of testing tools that extend the
-industry-standard JUnit test framework with features specific to the Android
-environment. Although you can test an Android application with JUnit, the
-Android tools allow you to write much more sophisticated tests for every aspect
-of your application, both at the unit and framework levels.</p>
-
-<p>Key features of the Android testing environment include:</p>
-
+<p>
+    The Android testing framework, an integral part of the development environment,
+    provides an architecture and powerful tools that help you test every aspect of your application
+    at every level from unit to framework.
+</p>
+<p>
+    The testing framework has these key features:
+</p>
 <ul>
-  <li>Android extensions to the JUnit framework that provide access to Android
-system objects.</li>
-  <li>An instrumentation framework that lets tests control and examine the
-application.</li>
-  <li>Mock versions of commonly-used Android system objects.</li>
-  <li>Tools for running single tests or test suites, with or without
-instrumentation.</li>
-  <li>Support for managing tests and test projects in the ADT Plugin for Eclipse
-and at the command line.</li>
+    <li>
+        Android test suites are based on JUnit. You can use plain JUnit to test a class that doesn't
+        call the Android API, or Android's JUnit extensions to test Android components. If you're
+        new to Android testing, you can start with general-purpose test case classes such as {@link
+        android.test.AndroidTestCase} and then go on to use more sophisticated classes.
+    </li>
+    <li>
+        The Android JUnit extensions provide component-specific test case classes. These classes
+        provide helper methods for creating mock objects and methods that help you control the
+        lifecycle of a component.
+    </li>
+    <li>
+        Test suites are contained in test packages that are similar to main application packages, so
+        you don't need to learn a new set of tools or techniques for designing and building tests.
+    </li>
+    <li>
+        The SDK tools for building and tests are available in Eclipse with ADT, and also in
+        command-line form for use with other IDES. These tools get information from the project of
+        the application under test and use this information to automatically create the build files,
+        manifest file, and directory structure for the test package.
+    </li>
+    <li>
+        The SDK also provides
+        <a href="{@docRoot}guide/topics/testing/monkeyrunner.html">MonkeyRunner</a>, an API for
+        testing devices with Jython scripts, and <a
+        href="{@docRoot}guide/developing/tools/monkey.html">Monkey</a>, a command-line tool for
+        stress-testing UIs by sending pseudo-random events to a device.
+    </li>
 </ul>
-
-<p>This document is an overview of the Android testing environment and the way
-you use it. The document assumes you have a basic knowledge of Android
-application programming and JUnit testing methodology.</p>
-
-<h2 id="Overview">Overview</h2>
-
-<p> At the heart of the Android testing environment is an instrumentation
-framework that your test application uses to precisely control the application
-under test. With instrumentation, you can set up mock system objects such as
-Contexts before the main application starts, control your application at various
-points of its lifecycle, send UI events to the application, and examine the
-application's state during its execution. The instrumentation framework
-accomplishes this by running both the main application and the test application
-in the same process. </p>
-
-<p>Your test application is linked to the application under test by means of an
-<a
-href="{@docRoot}guide/topics/manifest/instrumentation-element.html"><code>&lt;instrumentation&gt;</code></a>
-element in the test application's manifest file. The attributes of the element
-specify the package name of the application under test and also tell Android how
-to run the test application. Instrumentation is described in more detail in the
-section <a href="#InstrumentationTestRunner">Instrumentation Test
-Runner</a>.</p>
-
-<p>The following diagram summarizes the Android testing environment:</p>
-
-<img src="{@docRoot}images/testing/android_test_framework.png"/>
-
-<p>In Android, test applications are themselves Android applications, so you
-write them in much the same way as the application you are testing. The SDK
-tools help you create a main application project and its test project at the same
-time. You can run Android tests within Eclipse with ADT or from the command
-line. Eclipse with ADT provides an extensive set of tools for creating tests,
-running them, and viewing their results. You can also use the <code>adb</code>
-tool to run tests, or use a built-in Ant target.</p>
-
-<p>To learn how to set up and run tests in Eclipse, please refer to <a
-href="{@docRoot}guide/developing/testing/testing_eclipse.html">Testing in
-Eclipse, with ADT</a>. If you're not working in Eclipse, refer to <a
-href="{@docRoot}guide/developing/testing/testing_otheride.html">Testing in Other
-IDEs</a>.</p>
-
-<p>If you want a step-by-step introduction to Android testing, try one of the
-testing tutorials:</p>
-
-<ul>
-  <li>The <a
-href="{@docRoot}resources/tutorials/testing/helloandroid_test.html">Hello,
-Testing</a> tutorial introduces basic testing concepts and procedures in the
-context of the Hello, World application.</li>
-  <li>The <a
-href="{@docRoot}resources/tutorials/testing/activity_test.html">Activity
-Testing</a> tutorial is an excellent follow-up to the Hello, Testing tutorial.
-It guides you through a more complex testing scenario that you develop against a
-more realistic application.</li>
-</ul>
-
+<p>
+    This document describes the fundamentals of the Android testing framework, including the
+    structure of tests, the APIs that you use to develop tests, and the tools that you use to run
+    tests and view results. The document assumes you have a basic knowledge of Android application
+    programming and JUnit testing methodology.
+</p>
+<p>
+    The following diagram summarizes the testing framework:
+</p>
+<div style="width: 70%; margin-left:auto; margin-right:auto;">
+<a href="{@docRoot}images/testing/test_framework.png">
+    <img src="{@docRoot}images/testing/test_framework.png"
+        alt="The Android testing framework"/>
+</a>
+</div>
+<h2 id="TestStructure">Test Structure</h2>
+<p>
+    Android's build and test tools assume that test projects are organized into a standard
+    structure of tests, test case classes, test packages, and test projects.
+</p>
+<p>
+    Android testing is based on JUnit. In general, a JUnit test is a method whose
+    statements test a part of the application under test. You organize test methods into classes
+    called test cases (or test suites). Each test is an isolated test of an individual module in
+    the application under test. Each class is a container for related test methods, although it
+    often provides helper methods as well.
+</p>
+<p>
+    In JUnit, you build one or more test source files into a class file. Similarly, in Android you
+    use the SDK's build tools to build one or more test source files into class files in an
+    Android test package. In JUnit, you use a test runner to execute test classes. In Android, you
+    use test tools to load the test package and the application under test, and the tools then
+    execute an Android-specific test runner.
+</p>
+<h2 id="TestProjects">Test Projects</h2>
+<p>
+    Tests, like Android applications, are organized into projects.
+</p>
+<p>
+    A test project is a directory or Eclipse project in which you create the source code, manifest
+    file, and other files for a test package. The Android SDK contains tools for Eclipse with ADT
+    and for the command line that create and update test projects for you. The tools create the
+    directories you use for source code and resources and the manifest file for the test package.
+    The command-line tools also create the Ant build files you need.
+</p>
+<p>
+    You should always use Android tools to create a test project. Among other benefits,
+    the tools:
+</p>
+    <ul>
+        <li>
+            Automatically set up your test package to use
+            {@link android.test.InstrumentationTestRunner} as the test case runner. You must use
+            <code>InstrumentationTestRunner</code> (or a subclass) to run JUnit tests.
+        </li>
+        <li>
+            Create an appropriate name for the test package. If the application
+            under test has a package name of <code>com.mydomain.myapp</code>, then the
+            Android tools set the test package name to <code>com.mydomain.myapp.test</code>. This
+            helps you identify their relationship, while preventing conflicts within the system.
+        </li>
+        <li>
+            Automatically create the proper build files, manifest file, and directory
+            structure for the test project. This helps you to build the test package without
+            having to modify build files and sets up the linkage between your test package and
+            the application under test.
+            The
+        </li>
+    </ul>
+<p>
+    You can create a test project anywhere in your file system, but the best approach is to
+    add the test project so that its root directory <code>tests/</code> is at the same level
+    as the <code>src/</code> directory of the main application's project. This helps you find the
+    tests associated with an application. For example, if your application project's root directory
+    is <code>MyProject</code>, then you should use the following directory structure:
+</p>
+<pre class="classic no-pretty-print">
+  MyProject/
+      AndroidManifest.xml
+      res/
+          ... (resources for main application)
+      src/
+          ... (source code for main application) ...
+      tests/
+          AndroidManifest.xml
+          res/
+              ... (resources for tests)
+          src/
+              ... (source code for tests)
+</pre>
 <h2 id="TestAPI">The Testing API</h2>
 <p>
-    For writing tests and test applications in the Java programming language, Android provides a
-    testing API that is based in part on the JUnit test framework. Adding to that, Android includes
-    a powerful instrumentation framework that lets your tests access the state and runtime objects
-    of the application under tests.
+    The Android testing API is based on the JUnit API and extended with a instrumentation
+    framework and Android-specific testing classes.
 </p>
-<p>The sections below describe the major components of the testing API available in Android.</p>
-<h3 id="Extensions">JUnit test case classes</h3>
+<h3 id="JUnit">JUnit</h3>
 <p>
-  Some of the classes in the testing API extend the JUnit {@link junit.framework.TestCase TestCase} but do not use the instrumentation framework. These classes
-  contain methods for accessing system objects such as the Context of the application under test. With this Context, you can look at its resources, files, databases,
-  and so forth. The base class is {@link android.test.AndroidTestCase}, but you usually use a subclass associated with a particular component.
-<p>
-  The subclasses are:
-</p>
-  <ul>
-    <li>
-      {@link android.test.ApplicationTestCase} - A class for testing an entire application. It allows you to inject a mock Context into the application,
-      set up initial test parameters before the application starts, and examine the application after it finishes but before it is destroyed.
-    </li>
-    <li>
-      {@link android.test.ProviderTestCase2} - A class for isolated testing of a single {@link android.content.ContentProvider}. Since it is restricted to using a
-      {@link android.test.mock.MockContentResolver} for the provider, and it injects an {@link android.test.IsolatedContext}, your provider testing is isolated
-      from the rest of the OS.
-    </li>
-    <li>
-      {@link android.test.ServiceTestCase} - a class for isolated testing of a single {@link android.app.Service}. You can inject a mock Context or
-      mock Application (or both), or let Android provide you a full Context and a {@link android.test.mock.MockApplication}.
-    </li>
-  </ul>
-<h3 id="Instrumentation">Instrumentation test case classes</h3>
-<p>
-  The API for testing activities extends the JUnit {@link junit.framework.TestCase TestCase} class and also uses the instrumentation framework. With instrumentation,
-  Android can automate UI testing by sending events to the application under test, precisely control the start of an activity, and monitor the state of the
-  activity during its life cycle.
+    You can use the JUnit {@link junit.framework.TestCase TestCase} class to do unit testing on
+    a plain Java object. <code>TestCase</code> is also the base class for
+    {@link android.test.AndroidTestCase}, which you can use to test Android-dependent objects.
+    Besides providing the JUnit framework, AndroidTestCase offers Android-specific setup,
+    teardown, and helper methods.
 </p>
 <p>
-  The base class is {@link android.test.InstrumentationTestCase}. All of its subclasses have the ability to send a keystroke or touch event to the UI of the application
-  under test. The subclasses can also inject a mock Intent.
-  The subclasses are:
+    You use the JUnit {@link junit.framework.Assert} class to display test results.
+    The assert methods compare values you expect from a test to the actual results and
+    throw an exception if the comparison fails. Android also provides a class of assertions that
+    extend the possible types of comparisons, and another class of assertions for testing the UI.
+    These are described in more detail in the section <a href="#AssertionClasses">
+    Assertion classes</a>
 </p>
-  <ul>
-    <li>
-      {@link android.test.ActivityTestCase} - A base class for activity test classes.
-    </li>
-    <li>
-      {@link android.test.SingleLaunchActivityTestCase} - A convenience class for testing a single activity.
-      It invokes {@link junit.framework.TestCase#setUp() setUp()} and {@link junit.framework.TestCase#tearDown() tearDown()} only
-      once, instead of once per method call. Use it when all of your test methods run against the same activity.
-    </li>
-    <li>
-      {@link android.test.SyncBaseInstrumentation} - A class that tests synchronization of a content provider. It uses instrumentation to cancel and disable
-      existing synchronizations before starting the test synchronization.
-    </li>
-    <li>
-      {@link android.test.ActivityUnitTestCase} - This class does an isolated test of a single activity. With it, you can inject a mock context or application, or both.
-      It is intended for doing unit tests of an activity, and is the activity equivalent of the test classes described in <a href="#Extensions">JUnit test case classes</a>.
-      <p> Unlike the other instrumentation classes, this test class cannot inject a mock Intent.</p>
-    </li>
-    <li>
-      {@link android.test.ActivityInstrumentationTestCase2} - This class tests a single activity within the normal system environment.
-      You cannot inject a mock Context, but you can inject mock Intents. Also, you can run a test method on the UI thread (the main thread of the application under test),
-      which allows you to send key and touch events to the application UI.
-    </li>
-  </ul>
-<h3 id="Assert">Assert classes</h3>
 <p>
-  Android also extends the JUnit {@link junit.framework.Assert} class that is the basis of <code>assert()</code> calls in tests.
-  There are two extensions to this class, {@link android.test.MoreAsserts} and {@link android.test.ViewAsserts}:
+    To learn more about JUnit, you can read the documentation on the
+    <a href="http://www.junit.org">junit.org</a> home page.
+    Note that the Android testing API supports JUnit 3 code style, but not JUnit 4. Also, you must
+    use Android's instrumented test runner {@link android.test.InstrumentationTestRunner} to run
+    your test case classes. This test runner is described in the
+    section <a href="#InstrumentationTestRunner">Running Tests</a>.
+</p>
+<h3 id="Instrumentation">Instrumentation</h3>
+<p>
+    Android instrumentation is a set of control methods or "hooks" in the Android system. These hooks
+    control an Android component independently of its normal lifecycle. They also control how
+    Android loads applications.
+</p>
+<p>
+    Normally, an Android component runs in a lifecycle determined by the system. For example, an
+    Activity object's lifecycle starts when the Activity is activated by an Intent. The object's
+    <code>onCreate()</code> method is called, followed by <code>onResume()</code>. When the user
+    starts another application, the <code>onPause()</code> method is called. If the Activity
+    code calls the <code>finish()</code> method, the <code>onDestroy()</code> method is called.
+    The Android framework API does not provide a way for your code to invoke these callback
+    methods directly, but you can do so using instrumentation.
+</p>
+<p>
+    Also, the system runs all the components of an application into the same
+    process. You can allow some components, such as content providers, to run in a separate process,
+    but you can't force an application to run in the same process as another application that is
+    already running.
+</p>
+<p>
+    With Android instrumentation, though, you can invoke callback methods in your test code.
+    This allows you to run through the lifecycle of a component step by step, as if you were
+    debugging the component. The following test code snippet demonstrates how to use this to
+    test that an Activity saves and restores its state:
+</p>
+<a name="ActivitySnippet"></a>
+<pre>
+    // Start the main activity of the application under test
+    mActivity = getActivity();
+
+    // Get a handle to the Activity object's main UI widget, a Spinner
+    mSpinner = (Spinner)mActivity.findViewById(com.android.example.spinner.R.id.Spinner01);
+
+    // Set the Spinner to a known position
+    mActivity.setSpinnerPosition(TEST_STATE_DESTROY_POSITION);
+
+    // Stop the activity - The onDestroy() method should save the state of the Spinner
+    mActivity.finish();
+
+    // Re-start the Activity - the onResume() method should restore the state of the Spinner
+    mActivity = getActivity();
+
+    // Get the Spinner's current position
+    int currentPosition = mActivity.getSpinnerPosition();
+
+    // Assert that the current position is the same as the starting position
+    assertEquals(TEST_STATE_DESTROY_POSITION, currentPosition);
+</pre>
+<p>
+    The key method used here is
+    {@link android.test.ActivityInstrumentationTestCase2#getActivity()}, which is a
+    part of the instrumentation API. The Activity under test is not started until you call this
+    method. You can set up the test fixture in advance, and then call this method to start the
+    Activity.
+</p>
+<p>
+    Also, instrumentation can load both a test package and the application under test into the
+    same process. Since the application components and their tests are in the same process, the
+    tests can invoke methods in the components, and modify and examine fields in the components.
+</p>
+<h3 id="TestCaseClasses">Test case classes</h3>
+<p>
+    Android provides several test case classes that extend {@link junit.framework.TestCase} and
+    {@link junit.framework.Assert} with Android-specific setup, teardown, and helper methods.
+</p>
+<h4 id="AndroidTestCase">AndroidTestCase</h4>
+<p>
+    A useful general test case class, especially if you are
+    just starting out with Android testing, is {@link android.test.AndroidTestCase}. It extends
+    both {@link junit.framework.TestCase} and {@link junit.framework.Assert}. It provides the
+    JUnit-standard <code>setUp()</code> and <code>tearDown()</code> methods, as well as well as
+    all of JUnit's Assert methods. In addition, it provides methods for testing permissions, and a
+    method that guards against memory leaks by clearing out certain class references.
+</p>
+<h4 id="ComponentTestCase">Component-specific test cases</h4>
+<p>
+    A key feature of the Android testing framework is its component-specific test case classes.
+    These address specific component testing needs with methods for fixture setup and
+    teardown and component lifecycle control. They also provide methods for setting up mock objects.
+    These classes are described in the component-specific testing topics:
 </p>
 <ul>
-  <li>
-    The <code>MoreAsserts</code> class contains more powerful assertions such as {@link android.test.MoreAsserts#assertContainsRegex} that does regular expression matching.
-  </li>
-  <li>
-    The {@link android.test.ViewAsserts} class contains useful assertions about Android Views, such as {@link android.test.ViewAsserts#assertHasScreenCoordinates} that tests if a View has a particular X and Y
-    position on the visible screen. These asserts simplify testing of geometry and alignment in the UI.
-  </li>
+    <li>
+        <a href="{@docRoot}guide/topics/testing/activity_testing.html">Activity Testing</a>
+    </li>
+    <li>
+        <a href="{@docRoot}guide/topics/testing/contentprovider_testing.html">
+        Content Provider Testing</a>
+    </li>
+    <li>
+        <a href="{@docRoot}guide/topics/testing/service_testing.html">Service Testing</a>
+    </li>
 </ul>
-<h3 id="MockObjects">Mock object classes</h3>
-  <p>
-    Android has convenience classes for creating mock system objects such as applications, contexts, content resolvers, and resources. Android also provides
-    methods in some test classes for creating mock Intents. Use these mocks to facilitate dependency injection, since they are easier to use than creating their
-    real counterparts. These convenience classes are found in {@link android.test} and {@link android.test.mock}. They are:
-  </p>
+<p>
+    Android does not provide a separate test case class for BroadcastReceiver. Instead, test a
+    BroadcastReceiver by testing the component that sends it Intent objects, to verify that the
+    BroadcastReceiver responds correctly.
+</p>
+<h4 id="ApplicationTestCase">ApplicationTestCase</h4>
+<p>
+    You use the {@link android.test.ApplicationTestCase} test case class to test the setup and
+    teardown of {@link android.app.Application} objects. These objects maintain the global state of
+    information that applies to all the components in an application package. The test case can
+    be useful in verifying that the &lt;application&gt; element in the manifest file is correctly
+    set up. Note, however, that this test case does not allow you to control testing of the
+    components within your application package.
+</p>
+<h4 id="InstrumentationTestCase">InstrumentationTestCase</h4>
+<p>
+    If you want to use instrumentation methods in a test case class, you must use
+    {@link android.test.InstrumentationTestCase} or one of its subclasses. The
+    {@link android.app.Activity} test cases extend this base class with other functionality that
+    assists in Activity testing.
+</p>
+
+<h3 id="AssertionClasses">Assertion classes</h3>
+<p>
+    Because Android test case classes extend JUnit, you can use assertion methods to display the
+    results of tests. An assertion method compares an actual value returned by a test to an
+    expected value, and throws an AssertionException if the comparison test fails. Using assertions
+    is more convenient than doing logging, and provides better test performance.
+</p>
+<p>
+    Besides the JUnit {@link junit.framework.Assert} class methods, the testing API also provides
+    the {@link android.test.MoreAsserts} and {@link android.test.ViewAsserts} classes:
+</p>
+<ul>
+    <li>
+        {@link android.test.MoreAsserts} contains more powerful assertions such as
+        {@link android.test.MoreAsserts#assertContainsRegex}, which does regular expression
+        matching.
+    </li>
+    <li>
+        {@link android.test.ViewAsserts} contains useful assertions about Views. For example
+        it contains {@link android.test.ViewAsserts#assertHasScreenCoordinates} that tests if a View
+        has a particular X and Y position on the visible screen. These asserts simplify testing of
+        geometry and alignment in the UI.
+    </li>
+</ul>
+<h3 id="MockObjectClasses">Mock object classes</h3>
+<p>
+    To facilitate dependency injection in testing, Android provides classes that create mock system
+    objects such as {@link android.content.Context} objects,
+    {@link android.content.ContentProvider} objects, {@link android.content.ContentResolver}
+    objects, and {@link android.app.Service} objects. Some test cases also provide mock
+    {@link android.content.Intent} objects. You use these mocks both to isolate tests
+    from the rest of the system and to facilitate dependency injection for testing. These classes
+    are found in the Java packages {@link android.test} and {@link android.test.mock}.
+</p>
+<p>
+    Mock objects isolate tests from a running system by stubbing out or overriding
+    normal operations. For example, a {@link android.test.mock.MockContentResolver}
+    replaces the normal resolver framework with its own local framework, which is isolated
+    from the rest of the system. MockContentResolver also also stubs out the
+    {@link android.content.ContentResolver#notifyChange(Uri, ContentObserver, boolean)} method
+    so that observer objects outside the test environment are not accidentally triggered.
+</p>
+<p>
+    Mock object classes also facilitate dependency injection by providing a subclass of the
+    normal object that is non-functional except for overrides you define. For example, the
+    {@link android.test.mock.MockResources} object provides a subclass of
+    {@link android.content.res.Resources} in which all the methods throw Exceptions when called.
+    To use it, you override only those methods that must provide information.
+</p>
+<p>
+    These are the mock object classes available in Android:
+</p>
+<h4 id="SimpleMocks">Simple mock object classes</h4>
+<p>
+    {@link android.test.mock.MockApplication}, {@link android.test.mock.MockContext},
+    {@link android.test.mock.MockContentProvider}, {@link android.test.mock.MockCursor},
+    {@link android.test.mock.MockDialogInterface}, {@link android.test.mock.MockPackageManager}, and
+    {@link android.test.mock.MockResources} provide a simple and useful mock strategy. They are
+    stubbed-out versions of the corresponding system object class, and all of their methods throw an
+    {@link java.lang.UnsupportedOperationException} exception if called. To use them, you override
+    the methods you need in order to provide mock dependencies.
+</p>
+<p class="Note"><strong>Note:</strong>
+    {@link android.test.mock.MockContentProvider}
+    and {@link android.test.mock.MockCursor} are new as of API level 8.
+</p>
+<h4 id="ResolverMocks">Resolver mock objects</h4>
+<p>
+    {@link android.test.mock.MockContentResolver} provides isolated testing of content providers by
+    masking out the normal system resolver framework. Instead of looking in the system to find a
+    content provider given an authority string, MockContentResolver uses its own internal table. You
+    must explicitly add providers to this table using
+    {@link android.test.mock.MockContentResolver#addProvider(String,ContentProvider)}.
+</p>
+<p>
+    With this feature, you can associate a mock content provider with an authority. You can create
+    an instance of a real provider but use test data in it. You can even set the provider for an
+    authority to <code>null</code>. In effect, a MockContentResolver object isolates your test
+    from providers that contain real data. You can control the
+    function of the provider, and you can prevent your test from affecting real data.
+</p>
+<h3 id="ContextMocks">Contexts for testing</h3>
+<p>
+    Android provides two Context classes that are useful for testing:
+</p>
+<ul>
+    <li>
+        {@link android.test.IsolatedContext} provides an isolated {@link android.content.Context},
+        File, directory, and database operations that use this Context take place in a test area.
+        Though its functionality is limited, this Context has enough stub code to respond to
+        system calls.
+        <p>
+            This class allows you to test an application's data operations without affecting real
+            data that may be present on the device.
+        </p>
+    </li>
+    <li>
+        {@link android.test.RenamingDelegatingContext} provides a Context in which
+        most functions are handled by an existing {@link android.content.Context}, but
+        file and database operations are handled by a {@link android.test.IsolatedContext}.
+        The isolated part uses a test directory and creates special file and directory names.
+        You can control the naming yourself, or let the constructor determine it automatically.
+        <p>
+            This object provides a quick way to set up an isolated area for data operations,
+            while keeping normal functionality for all other Context operations.
+        </p>
+    </li>
+</ul>
+<h2 id="InstrumentationTestRunner">Running Tests</h2>
+<p>
+    Test cases are run by a test runner class that loads the test case class, set ups,
+    runs, and tears down each test. An Android test runner must also be instrumented, so that
+    the system utility for starting applications can control how the test package
+    loads test cases and the application under test. You tell the Android platform
+    which instrumented test runner to use by setting a value in the test package's manifest file.
+</p>
+<p>
+    {@link android.test.InstrumentationTestRunner} is the primary Android test runner class. It
+    extends the JUnit test runner framework and is also instrumented. It can run any of the test
+    case classes provided by Android and supports all possible types of testing.
+</p>
+<p>
+    You specify <code>InstrumentationTestRunner</code> or a subclass in your test package's
+    manifest file, in the <a href="{@docRoot}guide/topics/manifest/instrumentation-element.html">
+    instrumentation</a> element. Also, <code>InstrumentationTestRunner</code> code resides
+    in the shared library <code>android.test.runner</code>,  which is not normally linked to
+    Android code. To include it, you must specify it in a
+    <a href="{@docRoot}guide/topics/manifest/uses-library-element.html">uses-library</a> element.
+    You do not have to set up these elements yourself. Both Eclipse with ADT and the
+    <code>android</code> command-line tool construct them automatically and add them to your
+    test package's manifest file.
+</p>
+<p class="Note">
+    <strong>Note:</strong> If you use a test runner other than
+    <code>InstrumentationTestRunner</code>, you must change the &lt;instrumentation&gt;
+    element to point to the class you want to use.
+</p>
+<p>
+    To run {@link android.test.InstrumentationTestRunner}, you use internal system classes called by
+    Android tools. When you run a test in Eclipse with ADT, the classes are called automatically.
+    When you run a test from the command line, you run these classes with
+    <a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge (adb)</a>.
+</p>
+<p>
+    The system classes load and start the test package, kill any processes that
+    are running an instance of the application under test, and then load a new instance of the
+    application under test. They then pass control to
+    {@link android.test.InstrumentationTestRunner}, which runs
+    each test case class in the test package. You can also control which test cases and
+    methods are run using settings in Eclipse with ADT, or using flags with the command-line tools.
+</p>
+<p>
+    Neither the system classes nor {@link android.test.InstrumentationTestRunner} run
+    the application under test. Instead, the test case does this directly. It either calls methods
+    in the application under test, or it calls its own methods that trigger lifecycle events in
+    the application under test. The application is under the complete control of the test case,
+    which allows it to set up the test environment (the test fixture) before running a test. This
+    is demonstrated in the previous <a href="#ActivitySnippet">code snippet</a> that tests an
+    Activity that displays a Spinner widget.
+</p>
+<p>
+    To learn more about running tests, please read the topics
+    <a href="{@docRoot}guide/developing/testing/testing_eclipse.html"">
+    Testing in Eclipse, with ADT</a> or
+    <a href="{@docRoot}guide/developing/testing/testing_otheride.html">
+    Testing in Other IDes</a>.
+</p>
+<h2 id="TestResults">Seeing Test Results</h2>
+<p>
+    The Android testing framework returns test results back to the tool that started the test.
+    If you run a test in Eclipse with ADT, the results are displayed in a new JUnit view pane. If
+    you run a test from the command line, the results are displayed in <code>STDOUT</code>. In
+    both cases, you see a test summary that displays the name of each test case and method that
+    was run. You also see all the assertion failures that occurred. These include pointers to the
+    line in the test code where the failure occurred. Assertion failures also list the expected
+    value and actual value.
+</p>
+<p>
+    The test results have a format that is specific to the IDE that you are using. The test
+    results format for Eclipse with ADT is described in
+    <a href="{@docRoot}guide/developing/testing/testing_eclipse.html#RunTestEclipse">
+    Testing in Eclipse, with ADT</a>. The test results format for tests run from the
+    command line is described in
+    <a href="{@docRoot}guide/developing/testing/testing_otheride.html#RunTestsCommand">
+    Testing in Other IDEs</a>.
+</p>
+<h2 id="Monkeys">Monkey and MonkeyRunner</h2>
+<p>
+    The SDK provides two tools for functional-level application testing:
+</p>
     <ul>
-      <li>
-        {@link android.test.IsolatedContext} - Mocks a Context so that the application using it runs in isolation.
-        At the same time, it has enough stub code to satisfy OS code that tries to communicate with contexts. This class is useful in unit testing.
-      </li>
-      <li>
-        {@link android.test.RenamingDelegatingContext} - Delegates most context functions to an existing, normal context while changing the default file and database
-        names in the context. Use this to test file and database operations with a normal system context, using test names.
-      </li>
-      <li>
-        {@link android.test.mock.MockApplication}, {@link android.test.mock.MockContentResolver}, {@link android.test.mock.MockContext},
-        {@link android.test.mock.MockDialogInterface}, {@link android.test.mock.MockPackageManager},
-        {@link android.test.mock.MockResources} - Classes that create mock Android system objects for use in testing. They expose only those methods that are
-        useful in managing the object. The default implementations of these methods simply throw an Exception. You are expected to extend the classes and
-        override any methods that are called by the application under test.
-      </li>
+        <li>
+            <a href="{@docRoot}guide/developing/tools/monkey.html">Monkey</a> is a command-line
+            tool that sends pseudo-random streams of keystrokes, touches, and gestures to a
+            device. You run it with the <a href="{@docRoot}guide/developing/tools/adb.html">
+            Android Debug Bridge</a> (adb) tool. You use it to stress-test your application and
+            report back errors that are encountered. You can repeat a stream of events by
+            running the tool each time with the same random number seed.
+        </li>
+        <li>
+            <a href="{@docRoot}guide/topics/testing/monkeyrunner.html">MonkeyRunner</a> is a
+            Jython API that you use in test programs written in Python. The API includes functions
+            for connecting to a device, installing and uninstalling packages, taking screenshots,
+            comparing two images, and running a test package against an application. Using the API
+            with Python, you can write a wide range of large, powerful, and complex tests.
+        </li>
     </ul>
-<h3 id="InstrumentationTestRunner">Instrumentation Test Runner</h3>
+<h2 id="PackageNames">Working With Package names</h2>
 <p>
-  Android provides a custom class for running tests with instrumentation called called
-  {@link android.test.InstrumentationTestRunner}. This class
-  controls of the application under test, runs the test application and the main application in the same process, and routes
-  test output to the appropriate place. Using instrumentation is key to the ability of <code>InstrumentationTestRunner</code> to control the entire test
-  environment at runtime. Notice that you use this test runner even if your test class does not itself use instrumentation.
+    In the test environment, you work with both Android application package names and
+    Java package identifiers. Both use the same naming format, but they represent substantially
+    different entities. You need to know the difference to set up your tests correctly.
 </p>
 <p>
-  When you run a test application, you first run a system utility called Activity Manager. Activity Manager uses the instrumentation framework to start and control the test runner, which in turn uses instrumentation to shut down any running instances
-  of the main application, starts the test application, and then starts the main application in the same process. This allows various aspects of the test application to work directly with the main application.
+    An Android package name is a unique system name for a <code>.apk</code> file, set by the
+    &quot;android:package&quot; attribute of the &lt;manifest&gt; element in the package's
+    manifest. The Android package name of your test package must be different from the
+    Android package name of the application under test. By default, Android tools create the
+    test package name by appending ".test" to the package name of the application under test.
 </p>
 <p>
-  If you are developing in Eclipse, the ADT plugin assists you in the setup of <code>InstrumentationTestRunner</code> or other test runners.
-  The plugin UI prompts you to specify the test runner class to use, as well as the package name of the application under test.
-  The plugin then adds an <code>&lt;instrumentation&gt;</code> element with appropriate attributes to the manifest file of the test application.
-  Eclipse with ADT automatically starts a test application under the control of Activity Manager using instrumentation,
-  and redirects the test output to the Eclipse window's JUnit view.
+    The test package also uses an Android package name to target the application package it
+    tests. This is set in the &quot;android:targetPackage&quot; attribute of the
+    &lt;instrumentation&gt; element in the test package's manifest.
 </p>
 <p>
-  If you prefer working from the command line, you can use Ant and the <code>android</code>
-  tool to help you set up your test projects. To run tests with instrumentation, you can access the
-  Activity Manager through the <a href="{@docRoot}guide/developing/tools/adb.html">Android Debug
-  Bridge</a> (<code>adb</code>) tool and the output is directed to <code>STDOUT</code>.
-</p>
-<h2 id="TestEnviroment">Working in the Test Environment</h2>
-<p>
-    The tests for an Android application are contained in a test application, which itself is an Android application. A test application resides in a separate Android project that has the
-    same files and directories as a regular Android application. The test project is linked to the project of the application it tests
-    (known as the application under test) by its manifest file.
+    A Java package identifier applies to a source file. This package name reflects the directory
+    path of the source file. It also affects the visibility of classes and members to each other.
 </p>
 <p>
-    Each test application contains one or more test case classes based on an Android class for a
-    particular type of component. The test case class contains methods that define tests on some part of the application under test. When you run the test application, Android
-    starts it, loads the application under test into the same process, and then invokes each method in the test case class.
+    Android tools that create test projects set up an Android test package name for you.
+    From your input, the tools set up the test package name and the target package name for the
+    application under test. For these tools to work, the application project must already exist.
 </p>
 <p>
-    The tools and procedures you use with testing depend on the development environment you are using. If you use Eclipse, then the ADT plug in for Eclipse provides tools that
-    allow you to develop and run tests entirely within Eclipse. This is documented in the topic <a href="{@docRoot}guide/developing/testing/testing_eclipse.html">Testing in Eclipse, with ADT</a>.
-    If you use another development environment, then you use Android's command-line tools, as documented in the topic <a href="{@docRoot}guide/developing/testing/testing_otheride.html">Testing in Other IDEs</a>.
+    By default, these tools set the Java package identifier for the test class to be the same
+    as the Android package identifier. You may want to change this if you want to expose
+    members in the application under test by giving them package visibility. If you do this,
+    change only the Java package identifier, not the Android package names, and change only the
+    test case source files. Do not change the Java package name of the generated
+    <code>R.java</code> class in your test package, because it will then conflict with the
+    <code>R.java</code> class in the application under test. Do not change the Android package name
+    of your test package to be the same as the application it tests, because then their names
+    will no longer be unique in the system.
 </p>
-<h3 id="TestProjects">Working with test projects</h3>
+<h2 id="WhatToTest">What to Test</h2>
 <p>
-    To start testing an Android application, you create a test project for it using Android tools. The tools create the project directory and the files and subdirectories needed.
-    The tools also create a manifest file that links the application in the test project to the application under test. The procedure for creating a test project in Eclipse with
-    ADT is documented in <a href="{@docRoot}guide/developing/testing/testing_eclipse.html">Testing in Eclipse, with ADT</a>. The procedure for creating a test project for use with development
-    tools other than Eclipse is documented in <a href="{@docRoot}guide/developing/testing/testing_otheride.html">Testing in Other IDEs</a>.
-</p>
-<h3 id="TestClasses">Working with test case classes</h3>
-<p>
-    A test application contains one or more test case classes that extend an Android test case class. You choose a test case class based on the type of Android component you are testing and the
-    tests you are doing. A test application can test different components, but each test case class is designed to test a single type of component.
-    The Android test case classes are described in the section <a href="#TestAPI">The Testing API</a>.
+    The topic <a href="{@docRoot}guide/topics/testing/what_to_test.html">What To Test</a>
+    describes the key functionality you should test in an Android application, and the key
+    situations that might affect that functionality.
 </p>
 <p>
-    Some Android components have more than one associated test case class. In this case, you choose among the available classes based on the type of tests you want to do. For activities,
-    for example, you have the choice of either {@link android.test.ActivityInstrumentationTestCase2} or {@link android.test.ActivityUnitTestCase}.
-<p>
-    <code>ActivityInstrumentationTestCase2</code> is designed to do functional testing, so it tests activities in a normal system infrastructure. You can inject mocked Intents, but not
-    mocked Contexts. In general, you can't mock dependencies for the activity under test.
+    Most unit testing is specific to the Android component you are testing.
+    The topics <a href="{@docRoot}guide/topics/testing/activity_testing.html">Activity Testing</a>,
+    <a href="{@docRoot}guide/topics/testing/contentprovider_testing.html">
+    Content Provider Testing</a>, and <a href="{@docRoot}guide/topics/testing/service_testing.html">
+    Service Testing</a> each have a section entitled "What To Test" that lists possible testing
+    areas.
 </p>
 <p>
-    In comparison, <code>ActivityUnitTestCase</code> is designed for unit testing, so it tests activities in an isolated system infrastructure. You can inject mocked or wrappered dependencies for
-    the activity under test, particularly mocked Contexts. On the other hand, when you use this test case class the activity under test runs in isolation and can't interact with other activities.
+    When possible, you should run these tests on an actual device. If this is not possible, you can
+    use the <a href="{@docRoot}guide/developing/tools/emulator.html">Android Emulator</a> with
+    <a href="{@docRoot}guide/developing/tools/avd.html">Android Virtual Devices</a> configured for
+    the hardware, screens, and versions you want to test.
+</p>
+<h2 id="NextSteps">Next Steps</h2>
+<p>
+    To learn how to set up and run tests in Eclipse, please refer to <a
+    href="{@docRoot}guide/developing/testing/testing_eclipse.html">Testing in
+    Eclipse, with ADT</a>. If you're not working in Eclipse, refer to <a
+    href="{@docRoot}guide/developing/testing/testing_otheride.html">Testing in Other
+    IDEs</a>.
 </p>
 <p>
-    As a rule of thumb, if you wanted to test an activity's interaction with the rest of Android, you would use <code>ActivityInstrumentationTestCase2</code>. If you wanted to do regression testing
-    on an activity, you would use <code>ActivityUnitTestCase</code>.
+    If you want a step-by-step introduction to Android testing, try one of the
+    testing tutorials or sample test packages:
 </p>
-<h3 id="Tests">Working with test methods</h3>
-<p>
-    Each test case class provides methods that you use to set up the test environment and control the application under test. For example, all test case classes provide the JUnit {@link junit.framework.TestCase#setUp() setUp()}
-    method that you can override to set up fixtures. In addition, you add methods to the class to define individual tests. Each method you add is run once each time you run the test application. If you override the <code>setUp()</code>
-    method, it runs before each of your methods. Similarly, the JUnit {@link junit.framework.TestCase#tearDown() tearDown()} method is run once after each of your methods.
-</p>
-<p>
-    The test case classes give you substantial control over starting and stopping components. For this reason, you have to specifically tell Android to start a component before you run tests against it. For example, you use the
-    {@link android.test.ActivityInstrumentationTestCase2#getActivity()} method to start the activity under test. You can call this method once during the entire test case, or once for each test method. You can even destroy the
-    activity under test by calling its {@link android.app.Activity#finish()} method and then restart it with <code>getActivity()</code> within a single test method.
-</p>
-<h3 id="RunTests">Running tests and seeing the results</h3>
-<p>
-    To run your tests, you build your test project and then run the test application using the system utility Activity Manager with instrumentation. You provide to Activity Manager the name of the test runner (usually
-    {@link android.test.InstrumentationTestRunner}) you specified for your application; the name includes both your test application's package name and the test runner class name. Activity Manager loads and starts your
-    test application, kills any instances of the application under test, loads an instance of the application under test into the same process as the test application, and then passes control to the first test case
-    class in your test application. The test runner then takes control of the tests, running each of your test methods against the application under test until all the methods in all the classes have been run.
-</p>
-<p>
-    If you run a test within Eclipse with ADT, the output appears in a new JUnit view pane. If you run a test from the command line, the output goes to STDOUT.
-</p>
-<h2 id="TestAreas">What to Test</h2>
-<p>
-  In addition to the functional areas you would normally test, here are some areas
-  of Android application testing that you should consider:
-</p>
-  <ul>
+<ul>
     <li>
-      Activity lifecycle events: You should test that your activities handle lifecycle events correctly. For example
-      an activity should respond to pause or destroy events by saving its state. Remember that even a change in screen orientation
-      causes the current activity to be destroyed, so you should test that accidental device movements don't accidentally lose the
-      application state.
+        The <a
+        href="{@docRoot}resources/tutorials/testing/helloandroid_test.html">Hello,
+        Testing</a> tutorial introduces basic testing concepts and procedures in the
+        context of the Hello, World application.
     </li>
     <li>
-      Database operations: You should ensure that database operations correctly handle changes to the application's state.
-      To do this, use mock objects from the package {@link android.test.mock android.test.mock}.
+        The <a href="{@docRoot}resources/tutorials/testing/activity_test.html">Activity
+        Testing</a> tutorial is an excellent follow-up to the Hello, Testing tutorial.
+        It guides you through a more complex testing scenario that you develop against a
+        more realistic application.
     </li>
     <li>
-        Screen sizes and resolutions: Before you publish your application, make sure to test it on all of the
-        screen sizes and densities on which you want it to run. You can test the application on multiple sizes and densities using
-        AVDs, or you can test your application directly on the devices that you are targeting. For more information, see
-        the topic <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>.
+        The sample test package
+        <a href="{@docRoot}resources/samples/NotePadTest">Note Pad Test</a> is an example of
+        testing a {@link android.content.ContentProvider}. It contains a set of unit tests for the
+        Note Pad sample application's {@link android.content.ContentProvider}.
     </li>
-  </ul>
-<p>
-  When possible, you should run these tests on an actual device. If this is not possible, you can
-  use the <a href="{@docRoot}guide/developing/tools/emulator.html">Android Emulator</a> with
-  <a href="{@docRoot}guide/developing/tools/avd.html">Android Virtual Devices</a> configured for
-  the hardware, screens, and versions you want to test.
-</p>
-<h2 id="UITesting">Appendix: UI Testing Notes</h2>
-<p>
-  The following sections have tips for testing the UI of your Android application, specifically
-  to help you handle actions that run in the UI thread, touch screen and keyboard events, and home
-  screen unlock during testing.
-</p>
-<h3 id="RunOnUIThread">Testing on the UI thread</h3>
-<p>
-  An application's activities run on the application's <strong>UI thread</strong>. Once the
-  UI is instantiated, for example in the activity's <code>onCreate()</code> method, then all
-  interactions with the UI must run in the UI thread. When you run the application normally, it
-  has access to the thread and does not have to do anything special.
-</p>
-<p>
-  This changes when you run tests against the application. With instrumentation-based classes,
-  you can invoke methods against the UI of the application under test. The other test classes don't allow this.
-  To run an entire test method on the UI thread, you can annotate the thread with <code>@UIThreadTest</code>.
-  Notice that this will run <em>all</em> of the method statements on the UI thread.  Methods that do not interact with the UI
-  are not allowed; for example, you can't invoke <code>Instrumentation.waitForIdleSync()</code>.
-</p>
-<p>
-  To run a subset of a test method on the UI thread, create an anonymous class of type
-  <code>Runnable</code>, put the statements you want in the <code>run()</code> method, and instantiate a new
-  instance of the class as a parameter to the method <code><em>appActivity</em>.runOnUiThread()</code>, where
-  <code><em>appActivity</em></code> is the instance of the app you are testing.
-</p>
-<p>
-  For example, this code instantiates an activity to test, requests focus (a UI action) for the Spinner displayed
-  by the activity, and then sends a key to it. Notice that the calls to <code>waitForIdleSync</code> and <code>sendKeys</code>
-  aren't allowed to run on the UI thread:</p>
-<pre>
-  private MyActivity mActivity; // MyActivity is the class name of the app under test
-  private Spinner mSpinner;
-
-  ...
-
-  protected void setUp() throws Exception {
-      super.setUp();
-      mInstrumentation = getInstrumentation();
-
-      mActivity = getActivity(); // get a references to the app under test
-
-      /*
-       * Get a reference to the main widget of the app under test, a Spinner
-       */
-      mSpinner = (Spinner) mActivity.findViewById(com.android.demo.myactivity.R.id.Spinner01);
-
-  ...
-
-  public void aTest() {
-      /*
-       * request focus for the Spinner, so that the test can send key events to it
-       * This request must be run on the UI thread. To do this, use the runOnUiThread method
-       * and pass it a Runnable that contains a call to requestFocus on the Spinner.
-       */
-      mActivity.runOnUiThread(new Runnable() {
-          public void run() {
-              mSpinner.requestFocus();
-          }
-      });
-
-      mInstrumentation.waitForIdleSync();
-
-      this.sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
-</pre>
-
-<h3 id="NotouchMode">Turning off touch mode</h3>
-<p>
-  To control the emulator or a device with key events you send from your tests, you must turn off
-  touch mode. If you do not do this, the key events are ignored.
-</p>
-<p>
-  To turn off touch mode, you invoke <code>ActivityInstrumentationTestCase2.setActivityTouchMode(false)</code>
-  <em>before</em> you call <code>getActivity()</code> to start the activity. You must invoke the method in a test method
-  that is <em>not</em> running on the UI thread. For this reason, you can't invoke the touch mode method
-  from a test method that is annotated with <code>@UIThread</code>. Instead, invoke the touch mode method from <code>setUp()</code>.
-</p>
-<h3 id="UnlockDevice">Unlocking the emulator or device</h3>
-<p>
-  You may find that UI tests don't work if the emulator's or device's home screen is disabled with the keyguard pattern.
-  This is because the application under test can't receive key events sent by <code>sendKeys()</code>. The best
-  way to avoid this is to start your emulator or device first and then disable the keyguard for the home screen.
-</p>
-<p>
-  You can also explicitly disable the keyguard. To do this,
-  you need to add a permission in the manifest file (<code>AndroidManifest.xml</code>) and
-  then disable the keyguard in your application under test. Note, though, that you either have to remove this before
-  you publish your application, or you have to disable it programmatically in the published app.
-</p>
-<p>
-  To add the the permission, add the element <code>&lt;uses-permission android:name="android.permission.DISABLE_KEYGUARD"/&gt;</code>
-  as a child of the <code>&lt;manifest&gt;</code> element. To disable the KeyGuard, add the following code
-  to the <code>onCreate()</code> method of activities you intend to test:
-</p>
-<pre>
-  mKeyGuardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
-  mLock = mKeyGuardManager.newKeyguardLock("<em>activity_classname</em>");
-  mLock.disableKeyguard();
-</pre>
-<p>where <code><em>activity_classname</em></code> is the class name of the activity.</p>
-<h3 id="UITestTroubleshooting">Troubleshooting UI tests</h3>
-<p>
-  This section lists some of the common test failures you may encounter in UI testing, and their causes:
-</p>
-<dl>
-    <dt><code>WrongThreadException</code></dt>
-    <dd>
-      <p><strong>Problem:</strong></p>
-      For a failed test, the Failure Trace contains the following error message:
-      <code>
-        android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
-      </code>
-      <p><strong>Probable Cause:</strong></p>
-        This error is common if you tried to send UI events to the UI thread from outside the UI thread. This commonly happens if you send UI events
-        from the test application, but you don't use the <code>@UIThread</code> annotation or the <code>runOnUiThread()</code> method. The test method tried to interact with the UI outside the UI thread.
-      <p><strong>Suggested Resolution:</strong></p>
-        Run the interaction on the UI thread. Use a test class that provides instrumentation. See the previous section <a href="#RunOnUIThread">Testing on the UI Thread</a>
-        for more details.
-    </dd>
-    <dt><code>java.lang.RuntimeException</code></dt>
-    <dd>
-      <p><strong>Problem:</strong></p>
-      For a failed test, the Failure Trace contains the following error message:
-      <code>
-        java.lang.RuntimeException: This method can not be called from the main application thread
-      </code>
-      <p><strong>Probable Cause:</strong></p>
-        This error is common if your test method is annotated with <code>@UiThreadTest</code> but then tries to
-        do something outside the UI thread or tries to invoke <code>runOnUiThread()</code>.
-      <p><strong>Suggested Resolution:</strong></p>
-        Remove the <code>@UiThreadTest</code> annotation, remove the <code>runOnUiThread()</code> call, or re-factor your tests.
-    </dd>
-</dl>
+    <li>
+        The sample test package <a href="{@docRoot}resources/samples/AlarmServiceTest"}>
+        Alarm Service Test</a> is an example of testing a {@link android.app.Service}. It contains
+        a set of unit tests for the Alarm Service sample application's {@link android.app.Service}.
+    </li>
+</ul>
 
diff --git a/docs/html/guide/topics/testing/what_to_test.jd b/docs/html/guide/topics/testing/what_to_test.jd
new file mode 100644
index 0000000..e13538a
--- /dev/null
+++ b/docs/html/guide/topics/testing/what_to_test.jd
@@ -0,0 +1,84 @@
+page.title=What To Test
+@jd:body
+<p>
+    As you develop Android applications, knowing what to test is as important as knowing how to
+    test. This document lists some most common Android-related situations that you should consider
+    when you test, even at the unit test level. This is not an exhaustive list, and you consult the
+    documentation for the features that you use for more ideas. The
+    <a href="http://groups.google.com/group/android-developers">android-developers</a> Google Groups
+    site is another resource for information about testing.
+</p>
+<h2 id="Tests">Ideas for Testing</h2>
+<p>
+    The following sections are organized by behaviors or situations that you should test. Each
+    section contains a scenario that further illustrates the situation and the test or tests you
+    should do.
+</p>
+<h4>Change in orientation</h4>
+<p>
+    For devices that support multiple orientations, Android detects a change in orientation when
+    the user turns the device so that the display is "landscape" (long edge is horizontal) instead
+    of "portrait" (long edge is vertical).
+</p>
+<p>
+    When Android detects a change in orientation, its default behavior is to destroy and then
+    re-start the foreground Activity. You should consider testing the following:
+</p>
+<ul>
+    <li>
+        Is the screen re-drawn correctly? Any custom UI code you have should handle changes in the
+        orientation.
+    </li>
+    <li>
+        Does the application maintain its state? The Activity should not lose anything that the
+        user has already entered into the UI. The application should not "forget" its place in the
+        current transaction.
+    </li>
+</ul>
+<h4>Change in configuration</h4>
+<p>
+    A situation that is more general than a change in orientation is a change in the device's
+    configuration, such as a change in the availability of a keyboard or a change in system
+    language.
+</p>
+<p>
+    A change in configuration also triggers the default behavior of destroying and then restarting
+    the foreground Activity. Besides testing that the application maintains the UI and its
+    transaction state, you should also test that the application updates itself to respond
+    correctly to the new configuration.
+</p>
+<h4>Battery life</h4>
+<p>
+    Mobile devices primarily run on battery power. A device has finite "battery budget", and when it
+    is gone, the device is useless until it is recharged. You need to write your application to
+    minimize battery usage, you need to test its battery performance, and you need to test the
+    methods that manage battery usage.
+</p>
+<p>
+    Techniques for minimizing battery usage were presented at the 2010 Google I/O conference in the
+    presentation
+    <a href="http://code.google.com/events/io/2009/sessions/CodingLifeBatteryLife.html">
+    Coding for Life -- Battery Life, That Is</a>. This presentation describes the impact on battery
+    life of various operations, and the ways you can design your application to minimize these
+    impacts. When you code your application to reduce battery usage, you also write the
+    appropriate unit tests.
+</p>
+<h4>Dependence on external resources</h4>
+<p>
+    If your application depends on network access, SMS, Bluetooth, or GPS, then you should
+    test what happens when the resource or resources are not available.
+</p>
+<p>
+    For example, if your application uses the network,it can notify the user if access is
+    unavailable, or disable network-related features, or do both. For GPS, it can switch to
+    IP-based location awareness. It can also wait for WiFi access before doing large data transfers,
+    since WiFi transfers maximize battery usage compared to transfers over 3G or EDGE.
+</p>
+<p>
+    You can use the emulator to test network access and bandwidth. To learn more, please see
+    <a href="{@docRoot}guide/developing/tools/emulator.html#netspeed">Network Speed Emulation</a>.
+    To test GPS, you can use the emulator console and {@link android.location.LocationManager}. To
+    learn more about the emulator console, please see
+    <a href="{@docRoot}/guide/developing/tools/emulator.html#console">
+    Using the Emulator Console</a>.
+</p>
diff --git a/docs/html/images/testing/android_test_framework.png b/docs/html/images/testing/android_test_framework.png
index 6f80530..459975c 100755
--- a/docs/html/images/testing/android_test_framework.png
+++ b/docs/html/images/testing/android_test_framework.png
Binary files differ
diff --git a/docs/html/images/testing/eclipse_test_results.png b/docs/html/images/testing/eclipse_test_results.png
new file mode 100644
index 0000000..105e149
--- /dev/null
+++ b/docs/html/images/testing/eclipse_test_results.png
Binary files differ
diff --git a/docs/html/images/testing/eclipse_test_run_failure.png b/docs/html/images/testing/eclipse_test_run_failure.png
new file mode 100644
index 0000000..8111127
--- /dev/null
+++ b/docs/html/images/testing/eclipse_test_run_failure.png
Binary files differ
diff --git a/docs/html/images/testing/test_framework.png b/docs/html/images/testing/test_framework.png
new file mode 100644
index 0000000..fbc5fc2
--- /dev/null
+++ b/docs/html/images/testing/test_framework.png
Binary files differ
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index 291b18a..5ab1640 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -76,6 +76,9 @@
     /* Stream over a socket, limited to a single stream */
     OUTPUT_FORMAT_RTP_AVP = 7,
 
+    /* H.264/AAC data encapsulated in MPEG2/TS */
+    OUTPUT_FORMAT_MPEG2TS = 8,
+
     OUTPUT_FORMAT_LIST_END // must be last - used to validate format type
 };
 
diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h
index 9d2cff6..a3da3ed 100644
--- a/include/media/stagefright/DataSource.h
+++ b/include/media/stagefright/DataSource.h
@@ -36,6 +36,7 @@
     enum Flags {
         kWantsPrefetching      = 1,
         kStreamedFromLocalHost = 2,
+        kIsCachingDataSource   = 4,
     };
 
     static sp<DataSource> CreateFromURI(
diff --git a/include/media/stagefright/MPEG2TSWriter.h b/include/media/stagefright/MPEG2TSWriter.h
index 551ca01..f2c6505 100644
--- a/include/media/stagefright/MPEG2TSWriter.h
+++ b/include/media/stagefright/MPEG2TSWriter.h
@@ -25,7 +25,10 @@
 
 namespace android {
 
+struct ABuffer;
+
 struct MPEG2TSWriter : public MediaWriter {
+    MPEG2TSWriter(int fd);
     MPEG2TSWriter(const char *filename);
 
     virtual status_t addSource(const sp<MediaSource> &source);
@@ -59,6 +62,8 @@
     int64_t mNumTSPacketsWritten;
     int64_t mNumTSPacketsBeforeMeta;
 
+    void init();
+
     void writeTS();
     void writeProgramAssociationTable();
     void writeProgramMap();
diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h
index 6533600..de447be 100644
--- a/include/surfaceflinger/ISurfaceComposer.h
+++ b/include/surfaceflinger/ISurfaceComposer.h
@@ -118,6 +118,9 @@
             uint32_t* width, uint32_t* height, PixelFormat* format,
             uint32_t reqWidth, uint32_t reqHeight) = 0;
 
+    virtual status_t turnElectronBeamOff(int32_t mode) = 0;
+    virtual status_t turnElectronBeamOn(int32_t mode) = 0;
+
     /* Signal surfaceflinger that there might be some work to do
      * This is an ASYNCHRONOUS call.
      */
@@ -142,7 +145,9 @@
         FREEZE_DISPLAY,
         UNFREEZE_DISPLAY,
         SIGNAL,
-        CAPTURE_SCREEN
+        CAPTURE_SCREEN,
+        TURN_ELECTRON_BEAM_OFF,
+        TURN_ELECTRON_BEAM_ON
     };
 
     virtual status_t    onTransact( uint32_t code,
diff --git a/include/utils/ObbFile.h b/include/utils/ObbFile.h
index 5243f50..47559cd 100644
--- a/include/utils/ObbFile.h
+++ b/include/utils/ObbFile.h
@@ -27,6 +27,7 @@
 
 // OBB flags (bit 0)
 #define OBB_OVERLAY         (1 << 0)
+#define OBB_SALTED          (1 << 1)
 
 class ObbFile : public RefBase {
 protected:
@@ -70,6 +71,26 @@
         mFlags = flags;
     }
 
+    const unsigned char* getSalt(size_t* length) const {
+        if ((mFlags & OBB_SALTED) == 0) {
+            *length = 0;
+            return NULL;
+        }
+
+        *length = sizeof(mSalt);
+        return mSalt;
+    }
+
+    bool setSalt(const unsigned char* salt, size_t length) {
+        if (length != sizeof(mSalt)) {
+            return false;
+        }
+
+        memcpy(mSalt, salt, sizeof(mSalt));
+        mFlags |= OBB_SALTED;
+        return true;
+    }
+
     bool isOverlay() {
         return (mFlags & OBB_OVERLAY) == OBB_OVERLAY;
     }
@@ -103,6 +124,12 @@
     /* Flags for this OBB type. */
     int32_t mFlags;
 
+    /* Whether the file is salted. */
+    bool mSalted;
+
+    /* The encryption salt. */
+    unsigned char mSalt[8];
+
     const char* mFileName;
 
     size_t mFileSize;
diff --git a/libs/surfaceflinger_client/ISurfaceComposer.cpp b/libs/surfaceflinger_client/ISurfaceComposer.cpp
index d676f5e..969ee79 100644
--- a/libs/surfaceflinger_client/ISurfaceComposer.cpp
+++ b/libs/surfaceflinger_client/ISurfaceComposer.cpp
@@ -142,6 +142,24 @@
         return reply.readInt32();
     }
 
+    virtual status_t turnElectronBeamOff(int32_t mode)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        data.writeInt32(mode);
+        remote()->transact(BnSurfaceComposer::TURN_ELECTRON_BEAM_OFF, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual status_t turnElectronBeamOn(int32_t mode)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        data.writeInt32(mode);
+        remote()->transact(BnSurfaceComposer::TURN_ELECTRON_BEAM_ON, data, &reply);
+        return reply.readInt32();
+    }
+
     virtual void signal() const
     {
         Parcel data, reply;
@@ -224,6 +242,18 @@
             reply->writeInt32(f);
             reply->writeInt32(res);
         } break;
+        case TURN_ELECTRON_BEAM_OFF: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            int32_t mode = data.readInt32();
+            status_t res = turnElectronBeamOff(mode);
+            reply->writeInt32(res);
+        }
+        case TURN_ELECTRON_BEAM_ON: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            int32_t mode = data.readInt32();
+            status_t res = turnElectronBeamOn(mode);
+            reply->writeInt32(res);
+        }
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/libs/utils/ObbFile.cpp b/libs/utils/ObbFile.cpp
index e170ab8..2c3724c 100644
--- a/libs/utils/ObbFile.cpp
+++ b/libs/utils/ObbFile.cpp
@@ -29,10 +29,11 @@
 
 #define kFooterTagSize 8  /* last two 32-bit integers */
 
-#define kFooterMinSize 25 /* 32-bit signature version (4 bytes)
+#define kFooterMinSize 33 /* 32-bit signature version (4 bytes)
                            * 32-bit package version (4 bytes)
                            * 32-bit flags (4 bytes)
-                           * 32-bit package name size (4-bytes)
+                           * 64-bit salt (8 bytes)
+                           * 32-bit package name size (4 bytes)
                            * >=1-character package name (1 byte)
                            * 32-bit footer size (4 bytes)
                            * 32-bit footer marker (4 bytes)
@@ -47,8 +48,9 @@
 /* offsets in version 1 of the header */
 #define kPackageVersionOffset 4
 #define kFlagsOffset          8
-#define kPackageNameLenOffset 12
-#define kPackageNameOffset    16
+#define kSaltOffset           12
+#define kPackageNameLenOffset 20
+#define kPackageNameOffset    24
 
 /*
  * TEMP_FAILURE_RETRY is defined by some, but not all, versions of
@@ -79,11 +81,12 @@
 
 namespace android {
 
-ObbFile::ObbFile() :
-        mPackageName(""),
-        mVersion(-1),
-        mFlags(0)
+ObbFile::ObbFile()
+        : mPackageName("")
+        , mVersion(-1)
+        , mFlags(0)
 {
+    memset(mSalt, 0, sizeof(mSalt));
 }
 
 ObbFile::~ObbFile() {
@@ -192,7 +195,7 @@
 
 #ifdef DEBUG
     for (int i = 0; i < footerSize; ++i) {
-        LOGI("char: 0x%02x", scanBuf[i]);
+        LOGI("char: 0x%02x\n", scanBuf[i]);
     }
 #endif
 
@@ -206,6 +209,8 @@
     mVersion = (int32_t) get4LE((unsigned char*)scanBuf + kPackageVersionOffset);
     mFlags = (int32_t) get4LE((unsigned char*)scanBuf + kFlagsOffset);
 
+    memcpy(&mSalt, (unsigned char*)scanBuf + kSaltOffset, sizeof(mSalt));
+
     uint32_t packageNameLen = get4LE((unsigned char*)scanBuf + kPackageNameLenOffset);
     if (packageNameLen <= 0
             || packageNameLen > (footerSize - kPackageNameOffset)) {
@@ -255,7 +260,7 @@
     my_lseek64(fd, 0, SEEK_END);
 
     if (mPackageName.size() == 0 || mVersion == -1) {
-        LOGW("tried to write uninitialized ObbFile data");
+        LOGW("tried to write uninitialized ObbFile data\n");
         return false;
     }
 
@@ -264,43 +269,48 @@
 
     put4LE(intBuf, kSigVersion);
     if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
-        LOGW("couldn't write signature version: %s", strerror(errno));
+        LOGW("couldn't write signature version: %s\n", strerror(errno));
         return false;
     }
 
     put4LE(intBuf, mVersion);
     if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
-        LOGW("couldn't write package version");
+        LOGW("couldn't write package version\n");
         return false;
     }
 
     put4LE(intBuf, mFlags);
     if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
-        LOGW("couldn't write package version");
+        LOGW("couldn't write package version\n");
+        return false;
+    }
+
+    if (write(fd, mSalt, sizeof(mSalt)) != (ssize_t)sizeof(mSalt)) {
+        LOGW("couldn't write salt: %s\n", strerror(errno));
         return false;
     }
 
     size_t packageNameLen = mPackageName.size();
     put4LE(intBuf, packageNameLen);
     if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
-        LOGW("couldn't write package name length: %s", strerror(errno));
+        LOGW("couldn't write package name length: %s\n", strerror(errno));
         return false;
     }
 
     if (write(fd, mPackageName.string(), packageNameLen) != (ssize_t)packageNameLen) {
-        LOGW("couldn't write package name: %s", strerror(errno));
+        LOGW("couldn't write package name: %s\n", strerror(errno));
         return false;
     }
 
     put4LE(intBuf, kPackageNameOffset + packageNameLen);
     if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
-        LOGW("couldn't write footer size: %s", strerror(errno));
+        LOGW("couldn't write footer size: %s\n", strerror(errno));
         return false;
     }
 
     put4LE(intBuf, kSignature);
     if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
-        LOGW("couldn't write footer magic signature: %s", strerror(errno));
+        LOGW("couldn't write footer magic signature: %s\n", strerror(errno));
         return false;
     }
 
diff --git a/libs/utils/tests/ObbFile_test.cpp b/libs/utils/tests/ObbFile_test.cpp
index 29bb70a..46b30c2 100644
--- a/libs/utils/tests/ObbFile_test.cpp
+++ b/libs/utils/tests/ObbFile_test.cpp
@@ -23,6 +23,7 @@
 #include <gtest/gtest.h>
 
 #include <fcntl.h>
+#include <string.h>
 
 namespace android {
 
@@ -63,6 +64,10 @@
 
     mObbFile->setPackageName(String8(packageName));
     mObbFile->setVersion(versionNum);
+#define SALT_SIZE 8
+    unsigned char salt[SALT_SIZE] = {0x01, 0x10, 0x55, 0xAA, 0xFF, 0x00, 0x5A, 0xA5};
+    EXPECT_TRUE(mObbFile->setSalt(salt, SALT_SIZE))
+            << "Salt should be successfully set";
 
     EXPECT_TRUE(mObbFile->writeTo(mFileName))
             << "couldn't write to fake .obb file";
@@ -77,6 +82,19 @@
     const char* currentPackageName = mObbFile->getPackageName().string();
     EXPECT_STREQ(packageName, currentPackageName)
             << "package name didn't come out the same as it went in";
+
+    size_t saltLen;
+    const unsigned char* newSalt = mObbFile->getSalt(&saltLen);
+
+    EXPECT_EQ(sizeof(salt), saltLen)
+            << "salt sizes were not the same";
+
+    for (int i = 0; i < sizeof(salt); i++) {
+        EXPECT_EQ(salt[i], newSalt[i])
+                << "salt character " << i << " should be equal";
+    }
+    EXPECT_TRUE(memcmp(newSalt, salt, sizeof(salt)) == 0)
+            << "salts should be the same";
 }
 
 }
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 34a86ec..b38124e 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -191,6 +191,9 @@
 
         /** @hide Stream over a socket, limited to a single stream */
         public static final int OUTPUT_FORMAT_RTP_AVP = 7;
+
+        /** @hide H.264/AAC data encapsulated in MPEG2/TS */
+        public static final int OUTPUT_FORMAT_MPEG2TS = 8;
     };
 
     /**
diff --git a/media/libmedia/Metadata.cpp b/media/libmedia/Metadata.cpp
index 35ec6b3..aec96f1 100644
--- a/media/libmedia/Metadata.cpp
+++ b/media/libmedia/Metadata.cpp
@@ -32,7 +32,7 @@
 // All these constants below must be kept in sync with Metadata.java.
 enum MetadataId {
     FIRST_SYSTEM_ID = 1,
-    LAST_SYSTEM_ID = 31,
+    LAST_SYSTEM_ID = 32,
     FIRST_CUSTOM_ID = 8192
 };
 
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 9d53c25..e20e3ba 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -181,7 +181,7 @@
         LOGE("setOutputFormat called in an invalid state: %d", mCurrentState);
         return INVALID_OPERATION;
     }
-    if (mIsVideoSourceSet && of >= OUTPUT_FORMAT_AUDIO_ONLY_START && of != OUTPUT_FORMAT_RTP_AVP) { //first non-video output format
+    if (mIsVideoSourceSet && of >= OUTPUT_FORMAT_AUDIO_ONLY_START && of != OUTPUT_FORMAT_RTP_AVP && of != OUTPUT_FORMAT_MPEG2TS) { //first non-video output format
         LOGE("output format (%d) is meant for audio recording only and incompatible with video recording", of);
         return INVALID_OPERATION;
     }
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index cf01ff6..d37d83d 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -24,6 +24,7 @@
 #include <media/stagefright/AudioSource.h>
 #include <media/stagefright/AMRWriter.h>
 #include <media/stagefright/CameraSource.h>
+#include <media/stagefright/MPEG2TSWriter.h>
 #include <media/stagefright/MPEG4Writer.h>
 #include <media/stagefright/MediaDebug.h>
 #include <media/stagefright/MediaDefs.h>
@@ -632,6 +633,9 @@
         case OUTPUT_FORMAT_RTP_AVP:
             return startRTPRecording();
 
+        case OUTPUT_FORMAT_MPEG2TS:
+            return startMPEG2TSRecording();
+
         default:
             LOGE("Unsupported output file format: %d", mOutputFormat);
             return UNKNOWN_ERROR;
@@ -799,6 +803,52 @@
     return mWriter->start();
 }
 
+status_t StagefrightRecorder::startMPEG2TSRecording() {
+    CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_MPEG2TS);
+
+    sp<MediaWriter> writer = new MPEG2TSWriter(dup(mOutputFd));
+
+    if (mAudioSource != AUDIO_SOURCE_LIST_END) {
+        if (mAudioEncoder != AUDIO_ENCODER_AAC) {
+            return ERROR_UNSUPPORTED;
+        }
+
+        status_t err = setupAudioEncoder(writer);
+
+        if (err != OK) {
+            return err;
+        }
+    }
+
+    if (mVideoSource == VIDEO_SOURCE_DEFAULT
+            || mVideoSource == VIDEO_SOURCE_CAMERA) {
+        if (mVideoEncoder != VIDEO_ENCODER_H264) {
+            return ERROR_UNSUPPORTED;
+        }
+
+        sp<MediaSource> encoder;
+        status_t err = setupVideoEncoder(&encoder);
+
+        if (err != OK) {
+            return err;
+        }
+
+        writer->addSource(encoder);
+    }
+
+    if (mMaxFileDurationUs != 0) {
+        writer->setMaxFileDuration(mMaxFileDurationUs);
+    }
+
+    if (mMaxFileSizeBytes != 0) {
+        writer->setMaxFileSize(mMaxFileSizeBytes);
+    }
+
+    mWriter = writer;
+
+    return mWriter->start();
+}
+
 void StagefrightRecorder::clipVideoFrameRate() {
     LOGV("clipVideoFrameRate: encoder %d", mVideoEncoder);
     int minFrameRate = mEncoderProfiles->getVideoEncoderParamByName(
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 216f6bc..ad0dfa0 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -102,6 +102,7 @@
     status_t startAMRRecording();
     status_t startAACRecording();
     status_t startRTPRecording();
+    status_t startMPEG2TSRecording();
     sp<MediaSource> createAudioSource();
     status_t setupCameraSource();
     status_t setupAudioEncoder(const sp<MediaWriter>& writer);
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index ff28f3b..57bea8c 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -26,6 +26,7 @@
 #include "include/SoftwareRenderer.h"
 #include "include/NuCachedSource2.h"
 #include "include/ThrottledSource.h"
+#include "include/MPEG2TSExtractor.h"
 
 #include "ARTPSession.h"
 #include "APacketSource.h"
@@ -302,6 +303,28 @@
 }
 
 status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
+    // Attempt to approximate overall stream bitrate by summing all
+    // tracks' individual bitrates, if not all of them advertise bitrate,
+    // we have to fail.
+
+    int64_t totalBitRate = 0;
+
+    for (size_t i = 0; i < extractor->countTracks(); ++i) {
+        sp<MetaData> meta = extractor->getTrackMetaData(i);
+
+        int32_t bitrate;
+        if (!meta->findInt32(kKeyBitRate, &bitrate)) {
+            totalBitRate = -1;
+            break;
+        }
+
+        totalBitRate += bitrate;
+    }
+
+    mBitrate = totalBitRate;
+
+    LOGV("mBitrate = %lld bits/sec", mBitrate);
+
     bool haveAudio = false;
     bool haveVideo = false;
     for (size_t i = 0; i < extractor->countTracks(); ++i) {
@@ -440,6 +463,8 @@
 
     delete mSuspensionState;
     mSuspensionState = NULL;
+
+    mBitrate = -1;
 }
 
 void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
@@ -452,17 +477,32 @@
     }
 }
 
+bool AwesomePlayer::getBitrate(int64_t *bitrate) {
+    off_t size;
+    if (mDurationUs >= 0 && mCachedSource != NULL
+            && mCachedSource->getSize(&size) == OK) {
+        *bitrate = size * 8000000ll / mDurationUs;  // in bits/sec
+        return true;
+    }
+
+    if (mBitrate >= 0) {
+        *bitrate = mBitrate;
+        return true;
+    }
+
+    *bitrate = 0;
+
+    return false;
+}
+
 // Returns true iff cached duration is available/applicable.
 bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) {
-    off_t totalSize;
+    int64_t bitrate;
 
     if (mRTSPController != NULL) {
         *durationUs = mRTSPController->getQueueDurationUs(eos);
         return true;
-    } else if (mCachedSource != NULL && mDurationUs >= 0
-            && mCachedSource->getSize(&totalSize) == OK) {
-        int64_t bitrate = totalSize * 8000000ll / mDurationUs;  // in bits/sec
-
+    } else if (mCachedSource != NULL && getBitrate(&bitrate)) {
         size_t cachedDataRemaining = mCachedSource->approxDataRemaining(eos);
         *durationUs = cachedDataRemaining * 8000000ll / bitrate;
         return true;
@@ -489,10 +529,8 @@
                 finishAsyncPrepare_l();
             }
         } else {
-            off_t size;
-            if (mDurationUs >= 0 && mCachedSource->getSize(&size) == OK) {
-                int64_t bitrate = size * 8000000ll / mDurationUs;  // in bits/sec
-
+            int64_t bitrate;
+            if (getBitrate(&bitrate)) {
                 size_t cachedSize = mCachedSource->cachedSize();
                 int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
 
@@ -506,8 +544,8 @@
                 // We don't know the bitrate of the stream, use absolute size
                 // limits to maintain the cache.
 
-                const size_t kLowWaterMarkBytes = 400000;
-                const size_t kHighWaterMarkBytes = 1000000;
+                const size_t kLowWaterMarkBytes = 40000;
+                const size_t kHighWaterMarkBytes = 200000;
 
                 if ((mFlags & PLAYING) && !eos
                         && (cachedDataRemaining < kLowWaterMarkBytes)) {
@@ -1343,14 +1381,17 @@
         String8 uri("http://");
         uri.append(mUri.string() + 11);
 
-        dataSource = new LiveSource(uri.string());
+        sp<LiveSource> liveSource = new LiveSource(uri.string());
 
-        mCachedSource = new NuCachedSource2(dataSource);
+        mCachedSource = new NuCachedSource2(liveSource);
         dataSource = mCachedSource;
 
         sp<MediaExtractor> extractor =
             MediaExtractor::Create(dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
 
+        static_cast<MPEG2TSExtractor *>(extractor.get())
+            ->setLiveSource(liveSource);
+
         return setDataSource_l(extractor);
     } else if (!strncmp("rtsp://gtalk/", mUri.string(), 13)) {
         if (mLooper == NULL) {
diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp
index ee74b88..b3daf67 100644
--- a/media/libstagefright/MPEG2TSWriter.cpp
+++ b/media/libstagefright/MPEG2TSWriter.cpp
@@ -63,6 +63,8 @@
     sp<ALooper> mLooper;
     sp<AMessage> mNotify;
 
+    sp<ABuffer> mAACCodecSpecificData;
+
     sp<ABuffer> mAACBuffer;
 
     unsigned mStreamType;
@@ -125,6 +127,8 @@
 void MPEG2TSWriter::SourceInfo::stop() {
     mLooper->unregisterHandler(id());
     mLooper->stop();
+
+    mSource->stop();
 }
 
 void MPEG2TSWriter::SourceInfo::extractCodecSpecificData() {
@@ -133,18 +137,48 @@
     const char *mime;
     CHECK(meta->findCString(kKeyMIMEType, &mime));
 
+    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
+        uint32_t type;
+        const void *data;
+        size_t size;
+        if (!meta->findData(kKeyESDS, &type, &data, &size)) {
+            // Codec specific data better be in the first data buffer.
+            return;
+        }
+
+        ESDS esds((const char *)data, size);
+        CHECK_EQ(esds.InitCheck(), (status_t)OK);
+
+        const uint8_t *codec_specific_data;
+        size_t codec_specific_data_size;
+        esds.getCodecSpecificInfo(
+                (const void **)&codec_specific_data, &codec_specific_data_size);
+
+        CHECK_GE(codec_specific_data_size, 2u);
+
+        mAACCodecSpecificData = new ABuffer(codec_specific_data_size);
+
+        memcpy(mAACCodecSpecificData->data(), codec_specific_data,
+               codec_specific_data_size);
+
+        return;
+    }
+
     if (strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
         return;
     }
 
+    uint32_t type;
+    const void *data;
+    size_t size;
+    if (!meta->findData(kKeyAVCC, &type, &data, &size)) {
+        // Codec specific data better be part of the data stream then.
+        return;
+    }
+
     sp<ABuffer> out = new ABuffer(1024);
     out->setRange(0, 0);
 
-    uint32_t type;
-    const void *data;
-    size_t size;
-    CHECK(meta->findData(kKeyAVCC, &type, &data, &size));
-
     const uint8_t *ptr = (const uint8_t *)data;
 
     size_t numSeqParameterSets = ptr[5] & 31;
@@ -250,21 +284,7 @@
         mAACBuffer->setRange(0, 0);
     }
 
-    sp<MetaData> meta = mSource->getFormat();
-    uint32_t type;
-    const void *data;
-    size_t size;
-    CHECK(meta->findData(kKeyESDS, &type, &data, &size));
-
-    ESDS esds((const char *)data, size);
-    CHECK_EQ(esds.InitCheck(), (status_t)OK);
-
-    const uint8_t *codec_specific_data;
-    size_t codec_specific_data_size;
-    esds.getCodecSpecificInfo(
-            (const void **)&codec_specific_data, &codec_specific_data_size);
-
-    CHECK_GE(codec_specific_data_size, 2u);
+    const uint8_t *codec_specific_data = mAACCodecSpecificData->data();
 
     unsigned profile = (codec_specific_data[0] >> 3) - 1;
 
@@ -355,7 +375,18 @@
             }
 
             if (err == OK) {
-                if (buffer->range_length() > 0) {
+                if (mStreamType == 0x0f && mAACCodecSpecificData == NULL) {
+                    // The first buffer contains codec specific data.
+
+                    CHECK_GE(buffer->range_length(), 2u);
+
+                    mAACCodecSpecificData = new ABuffer(buffer->range_length());
+
+                    memcpy(mAACCodecSpecificData->data(),
+                           (const uint8_t *)buffer->data()
+                            + buffer->range_offset(),
+                           buffer->range_length());
+                } else if (buffer->range_length() > 0) {
                     if (mStreamType == 0x0f) {
                         appendAACFrames(buffer);
                     } else {
@@ -378,12 +409,25 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
+MPEG2TSWriter::MPEG2TSWriter(int fd)
+    : mFile(fdopen(fd, "wb")),
+      mStarted(false),
+      mNumSourcesDone(0),
+      mNumTSPacketsWritten(0),
+      mNumTSPacketsBeforeMeta(0) {
+    init();
+}
+
 MPEG2TSWriter::MPEG2TSWriter(const char *filename)
     : mFile(fopen(filename, "wb")),
       mStarted(false),
       mNumSourcesDone(0),
       mNumTSPacketsWritten(0),
       mNumTSPacketsBeforeMeta(0) {
+    init();
+}
+
+void MPEG2TSWriter::init() {
     CHECK(mFile != NULL);
 
     mLooper = new ALooper;
@@ -396,6 +440,10 @@
 }
 
 MPEG2TSWriter::~MPEG2TSWriter() {
+    if (mStarted) {
+        stop();
+    }
+
     mLooper->unregisterHandler(mReflector->id());
     mLooper->stop();
 
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 3a0fc41..b67002d 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -179,7 +179,8 @@
       mFinalStatus(OK),
       mLastAccessPos(0),
       mFetching(true),
-      mLastFetchTimeUs(-1) {
+      mLastFetchTimeUs(-1),
+      mSuspended(false) {
     mLooper->setName("NuCachedSource2");
     mLooper->registerHandler(mReflector);
     mLooper->start();
@@ -205,7 +206,7 @@
 }
 
 uint32_t NuCachedSource2::flags() {
-    return mSource->flags();
+    return (mSource->flags() & ~kWantsPrefetching) | kIsCachingDataSource;
 }
 
 void NuCachedSource2::onMessageReceived(const sp<AMessage> &msg) {
@@ -222,6 +223,12 @@
             break;
         }
 
+        case kWhatSuspend:
+        {
+            onSuspend();
+            break;
+        }
+
         default:
             TRESPASS();
     }
@@ -263,6 +270,7 @@
 
     bool keepAlive =
         !mFetching
+            && !mSuspended
             && mFinalStatus == OK
             && ALooper::GetNowUs() >= mLastFetchTimeUs + kKeepAliveIntervalUs;
 
@@ -279,7 +287,7 @@
             LOGI("Cache full, done prefetching for now");
             mFetching = false;
         }
-    } else {
+    } else if (!mSuspended) {
         Mutex::Autolock autoLock(mLock);
         restartPrefetcherIfNecessary_l();
     }
@@ -468,5 +476,39 @@
     return OK;
 }
 
+void NuCachedSource2::clearCacheAndResume() {
+    LOGV("clearCacheAndResume");
+
+    Mutex::Autolock autoLock(mLock);
+
+    CHECK(mSuspended);
+
+    mCacheOffset = 0;
+    mFinalStatus = OK;
+    mLastAccessPos = 0;
+    mLastFetchTimeUs = -1;
+
+    size_t totalSize = mCache->totalSize();
+    CHECK_EQ(mCache->releaseFromStart(totalSize), totalSize);
+
+    mFetching = true;
+    mSuspended = false;
+}
+
+void NuCachedSource2::suspend() {
+    (new AMessage(kWhatSuspend, mReflector->id()))->post();
+
+    while (!mSuspended) {
+        usleep(10000);
+    }
+}
+
+void NuCachedSource2::onSuspend() {
+    Mutex::Autolock autoLock(mLock);
+
+    mFetching = false;
+    mSuspended = true;
+}
+
 }  // namespace android
 
diff --git a/media/libstagefright/httplive/LiveSource.cpp b/media/libstagefright/httplive/LiveSource.cpp
index 943a0fc..4124571 100644
--- a/media/libstagefright/httplive/LiveSource.cpp
+++ b/media/libstagefright/httplive/LiveSource.cpp
@@ -31,6 +31,7 @@
 LiveSource::LiveSource(const char *url)
     : mMasterURL(url),
       mInitCheck(NO_INIT),
+      mDurationUs(-1),
       mPlaylistIndex(0),
       mLastFetchTimeUs(-1),
       mSource(new NuHTTPDataSource),
@@ -40,6 +41,8 @@
       mPrevBandwidthIndex(-1) {
     if (switchToNext()) {
         mInitCheck = OK;
+
+        determineSeekability();
     }
 }
 
@@ -139,7 +142,7 @@
         }
 #else
         // Stay on the lowest bandwidth available.
-        size_t index = 0;  // Lowest bandwidth stream
+        size_t index = mBandwidthItems.size() - 1;  // Highest bandwidth stream
 #endif
 
         mURL = mBandwidthItems.editItemAt(index).mURI;
@@ -336,4 +339,69 @@
     return OK;
 }
 
+bool LiveSource::seekTo(int64_t seekTimeUs) {
+    LOGV("seek to %lld us", seekTimeUs);
+
+    if (!mPlaylist->isComplete()) {
+        return false;
+    }
+
+    int32_t targetDuration;
+    if (!mPlaylist->meta()->findInt32("target-duration", &targetDuration)) {
+        return false;
+    }
+
+    int64_t seekTimeSecs = (seekTimeUs + 500000ll) / 1000000ll;
+
+    int64_t index = seekTimeSecs / targetDuration;
+
+    if (index < 0 || index >= mPlaylist->size()) {
+        return false;
+    }
+
+    size_t newPlaylistIndex = mFirstItemSequenceNumber + index;
+
+    if (newPlaylistIndex == mPlaylistIndex) {
+        return false;
+    }
+
+    mPlaylistIndex = newPlaylistIndex;
+
+    switchToNext();
+    mOffsetBias = 0;
+
+    LOGV("seeking to index %lld", index);
+
+    return true;
+}
+
+bool LiveSource::getDuration(int64_t *durationUs) const {
+    if (mDurationUs >= 0) {
+        *durationUs = mDurationUs;
+        return true;
+    }
+
+    *durationUs = 0;
+    return false;
+}
+
+bool LiveSource::isSeekable() const {
+    return mDurationUs >= 0;
+}
+
+void LiveSource::determineSeekability() {
+    mDurationUs = -1;
+
+    if (!mPlaylist->isComplete()) {
+        return;
+    }
+
+    int32_t targetDuration;
+    if (!mPlaylist->meta()->findInt32("target-duration", &targetDuration)) {
+        return;
+    }
+
+    mDurationUs = targetDuration * 1000000ll * mPlaylist->size();
+}
+
 }  // namespace android
diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp
index 0d7daa9..a68c641 100644
--- a/media/libstagefright/httplive/M3UParser.cpp
+++ b/media/libstagefright/httplive/M3UParser.cpp
@@ -27,7 +27,8 @@
     : mInitCheck(NO_INIT),
       mBaseURI(baseURI),
       mIsExtM3U(false),
-      mIsVariantPlaylist(false) {
+      mIsVariantPlaylist(false),
+      mIsComplete(false) {
     mInitCheck = parse(data, size);
 }
 
@@ -46,6 +47,10 @@
     return mIsVariantPlaylist;
 }
 
+bool M3UParser::isComplete() const {
+    return mIsComplete;
+}
+
 sp<AMessage> M3UParser::meta() {
     return mMeta;
 }
@@ -153,6 +158,8 @@
                     return ERROR_MALFORMED;
                 }
                 err = parseMetaData(line, &mMeta, "media-sequence");
+            } else if (line.startsWith("#EXT-X-ENDLIST")) {
+                mIsComplete = true;
             } else if (line.startsWith("#EXTINF")) {
                 if (mIsVariantPlaylist) {
                     return ERROR_MALFORMED;
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 079adca..46a0c65 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -152,6 +152,8 @@
     bool mSeekNotificationSent;
     int64_t mSeekTimeUs;
 
+    int64_t mBitrate;  // total bitrate of the file (in bps) or -1 if unknown.
+
     bool mWatchForAudioSeekComplete;
     bool mWatchForAudioEOS;
 
@@ -254,6 +256,8 @@
     static void OnRTSPSeekDoneWrapper(void *cookie);
     void onRTSPSeekDone();
 
+    bool getBitrate(int64_t *bitrate);
+
     AwesomePlayer(const AwesomePlayer &);
     AwesomePlayer &operator=(const AwesomePlayer &);
 };
diff --git a/media/libstagefright/include/LiveSource.h b/media/libstagefright/include/LiveSource.h
index 5e89581..55dd45e 100644
--- a/media/libstagefright/include/LiveSource.h
+++ b/media/libstagefright/include/LiveSource.h
@@ -40,6 +40,11 @@
         return kWantsPrefetching;
     }
 
+    bool getDuration(int64_t *durationUs) const;
+
+    bool isSeekable() const;
+    bool seekTo(int64_t seekTimeUs);
+
 protected:
     virtual ~LiveSource();
 
@@ -53,6 +58,7 @@
     AString mMasterURL;
     AString mURL;
     status_t mInitCheck;
+    int64_t mDurationUs;
 
     sp<M3UParser> mPlaylist;
     int32_t mFirstItemSequenceNumber;
@@ -72,6 +78,7 @@
 
     bool switchToNext();
     bool loadPlaylist(bool fetchMaster);
+    void determineSeekability();
 
     DISALLOW_EVIL_CONSTRUCTORS(LiveSource);
 };
diff --git a/media/libstagefright/include/M3UParser.h b/media/libstagefright/include/M3UParser.h
index 69199ab..bd9eebe 100644
--- a/media/libstagefright/include/M3UParser.h
+++ b/media/libstagefright/include/M3UParser.h
@@ -32,6 +32,7 @@
 
     bool isExtM3U() const;
     bool isVariantPlaylist() const;
+    bool isComplete() const;
 
     sp<AMessage> meta();
 
@@ -52,6 +53,7 @@
     AString mBaseURI;
     bool mIsExtM3U;
     bool mIsVariantPlaylist;
+    bool mIsComplete;
 
     sp<AMessage> mMeta;
     Vector<Item> mItems;
diff --git a/media/libstagefright/include/MPEG2TSExtractor.h b/media/libstagefright/include/MPEG2TSExtractor.h
index 1bf4cd1..d83b538 100644
--- a/media/libstagefright/include/MPEG2TSExtractor.h
+++ b/media/libstagefright/include/MPEG2TSExtractor.h
@@ -15,6 +15,7 @@
 struct DataSource;
 struct MPEG2TSSource;
 struct String8;
+struct LiveSource;
 
 struct MPEG2TSExtractor : public MediaExtractor {
     MPEG2TSExtractor(const sp<DataSource> &source);
@@ -25,16 +26,19 @@
 
     virtual sp<MetaData> getMetaData();
 
-    virtual uint32_t flags() const {
-        return CAN_PAUSE;
-    }
+    virtual uint32_t flags() const;
+
+    void setLiveSource(const sp<LiveSource> &liveSource);
+    void seekTo(int64_t seekTimeUs);
 
 private:
     friend struct MPEG2TSSource;
 
-    Mutex mLock;
+    mutable Mutex mLock;
 
     sp<DataSource> mDataSource;
+    sp<LiveSource> mLiveSource;
+
     sp<ATSParser> mParser;
 
     Vector<sp<AnotherPacketSource> > mSourceImpls;
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index 3a20c16..1fb2088 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -42,6 +42,9 @@
     size_t cachedSize();
     size_t approxDataRemaining(bool *eos);
 
+    void suspend();
+    void clearCacheAndResume();
+
 protected:
     virtual ~NuCachedSource2();
 
@@ -61,6 +64,7 @@
     enum {
         kWhatFetchMore  = 'fetc',
         kWhatRead       = 'read',
+        kWhatSuspend    = 'susp',
     };
 
     sp<DataSource> mSource;
@@ -78,10 +82,12 @@
     sp<AMessage> mAsyncResult;
     bool mFetching;
     int64_t mLastFetchTimeUs;
+    bool mSuspended;
 
     void onMessageReceived(const sp<AMessage> &msg);
     void onFetch();
     void onRead(const sp<AMessage> &msg);
+    void onSuspend();
 
     void fetchInternal();
     ssize_t readInternal(off_t offset, void *data, size_t size);
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index 7c9b83a..c88c6c1 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -49,13 +49,17 @@
             unsigned pid, unsigned payload_unit_start_indicator,
             ABitReader *br);
 
-    void signalDiscontinuity();
+    void signalDiscontinuity(bool isASeek);
 
     sp<MediaSource> getSource(SourceType type);
 
+    int64_t convertPTSToTimestamp(uint64_t PTS);
+
 private:
     unsigned mProgramMapPID;
     KeyedVector<unsigned, sp<Stream> > mStreams;
+    bool mFirstPTSValid;
+    uint64_t mFirstPTS;
 
     void parseProgramMap(ABitReader *br);
 
@@ -63,13 +67,13 @@
 };
 
 struct ATSParser::Stream : public RefBase {
-    Stream(unsigned elementaryPID, unsigned streamType);
+    Stream(Program *program, unsigned elementaryPID, unsigned streamType);
 
     void parse(
             unsigned payload_unit_start_indicator,
             ABitReader *br);
 
-    void signalDiscontinuity();
+    void signalDiscontinuity(bool isASeek);
 
     sp<MediaSource> getSource(SourceType type);
 
@@ -77,6 +81,7 @@
     virtual ~Stream();
 
 private:
+    Program *mProgram;
     unsigned mElementaryPID;
     unsigned mStreamType;
 
@@ -101,7 +106,9 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 ATSParser::Program::Program(unsigned programMapPID)
-    : mProgramMapPID(programMapPID) {
+    : mProgramMapPID(programMapPID),
+      mFirstPTSValid(false),
+      mFirstPTS(0) {
 }
 
 bool ATSParser::Program::parsePID(
@@ -128,9 +135,9 @@
     return true;
 }
 
-void ATSParser::Program::signalDiscontinuity() {
+void ATSParser::Program::signalDiscontinuity(bool isASeek) {
     for (size_t i = 0; i < mStreams.size(); ++i) {
-        mStreams.editValueAt(i)->signalDiscontinuity();
+        mStreams.editValueAt(i)->signalDiscontinuity(isASeek);
     }
 }
 
@@ -213,10 +220,12 @@
         ssize_t index = mStreams.indexOfKey(elementaryPID);
 #if 0  // XXX revisit
         CHECK_LT(index, 0);
-        mStreams.add(elementaryPID, new Stream(elementaryPID, streamType));
+        mStreams.add(elementaryPID,
+                     new Stream(this, elementaryPID, streamType));
 #else
         if (index < 0) {
-            mStreams.add(elementaryPID, new Stream(elementaryPID, streamType));
+            mStreams.add(elementaryPID,
+                         new Stream(this, elementaryPID, streamType));
         }
 #endif
 
@@ -239,10 +248,26 @@
     return NULL;
 }
 
+int64_t ATSParser::Program::convertPTSToTimestamp(uint64_t PTS) {
+    if (!mFirstPTSValid) {
+        mFirstPTSValid = true;
+        mFirstPTS = PTS;
+        PTS = 0;
+    } else if (PTS < mFirstPTS) {
+        PTS = 0;
+    } else {
+        PTS -= mFirstPTS;
+    }
+
+    return (PTS * 100) / 9;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
-ATSParser::Stream::Stream(unsigned elementaryPID, unsigned streamType)
-    : mElementaryPID(elementaryPID),
+ATSParser::Stream::Stream(
+        Program *program, unsigned elementaryPID, unsigned streamType)
+    : mProgram(program),
+      mElementaryPID(elementaryPID),
       mStreamType(streamType),
       mBuffer(new ABuffer(128 * 1024)),
       mPayloadStarted(false),
@@ -281,13 +306,21 @@
     mBuffer->setRange(0, mBuffer->size() + payloadSizeBits / 8);
 }
 
-void ATSParser::Stream::signalDiscontinuity() {
+void ATSParser::Stream::signalDiscontinuity(bool isASeek) {
     LOGV("Stream discontinuity");
     mPayloadStarted = false;
     mBuffer->setRange(0, 0);
 
     mQueue.clear();
 
+    if (isASeek) {
+        // This is only a "minor" discontinuity, we stay within the same
+        // bitstream.
+
+        mSource->clear();
+        return;
+    }
+
     if (mStreamType == 0x1b && mSource != NULL) {
         // Don't signal discontinuities on audio streams.
         mSource->queueDiscontinuity();
@@ -467,7 +500,7 @@
     LOGV("onPayloadData mStreamType=0x%02x", mStreamType);
 
     CHECK(PTS_DTS_flags == 2 || PTS_DTS_flags == 3);
-    int64_t timeUs = (PTS * 100) / 9;
+    int64_t timeUs = mProgram->convertPTSToTimestamp(PTS);
 
     status_t err = mQueue.appendData(data, size, timeUs);
     CHECK_EQ(err, (status_t)OK);
@@ -515,9 +548,9 @@
     parseTS(&br);
 }
 
-void ATSParser::signalDiscontinuity() {
+void ATSParser::signalDiscontinuity(bool isASeek) {
     for (size_t i = 0; i < mPrograms.size(); ++i) {
-        mPrograms.editItemAt(i)->signalDiscontinuity();
+        mPrograms.editItemAt(i)->signalDiscontinuity(isASeek);
     }
 }
 
diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h
index 9ec6d7b..11b1de4 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.h
+++ b/media/libstagefright/mpeg2ts/ATSParser.h
@@ -33,7 +33,7 @@
     ATSParser();
 
     void feedTSPacket(const void *data, size_t size);
-    void signalDiscontinuity();
+    void signalDiscontinuity(bool isASeek = false);
 
     enum SourceType {
         AVC_VIDEO,
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index 3f76820..ea747c8 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -91,6 +91,10 @@
         return;
     }
 
+    int64_t timeUs;
+    CHECK(buffer->meta()->findInt64("time", &timeUs));
+    LOGV("queueAccessUnit timeUs=%lld us (%.2f secs)", timeUs, timeUs / 1E6);
+
     Mutex::Autolock autoLock(mLock);
     mBuffers.push_back(buffer);
     mCondition.signal();
@@ -101,10 +105,17 @@
     buffer->meta()->setInt32("discontinuity", true);
 
     Mutex::Autolock autoLock(mLock);
+
     mBuffers.push_back(buffer);
     mCondition.signal();
 }
 
+void AnotherPacketSource::clear() {
+    Mutex::Autolock autoLock(mLock);
+    mBuffers.clear();
+    mEOSResult = OK;
+}
+
 void AnotherPacketSource::signalEOS(status_t result) {
     CHECK(result != OK);
 
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.h b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
index 6b43c4e..6999175 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.h
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
@@ -43,6 +43,8 @@
     void queueDiscontinuity();
     void signalEOS(status_t result);
 
+    void clear();
+
 protected:
     virtual ~AnotherPacketSource();
 
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index a13287e..b0b9e66 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -42,6 +42,7 @@
 
 void ElementaryStreamQueue::clear() {
     mBuffer->setRange(0, 0);
+    mTimestamps.clear();
     mFormat.clear();
 }
 
diff --git a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
index 0d96bd1..3176810 100644
--- a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
+++ b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
@@ -19,8 +19,11 @@
 #include <utils/Log.h>
 
 #include "include/MPEG2TSExtractor.h"
+#include "include/LiveSource.h"
+#include "include/NuCachedSource2.h"
 
 #include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaDebug.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MediaSource.h>
@@ -37,7 +40,8 @@
 struct MPEG2TSSource : public MediaSource {
     MPEG2TSSource(
             const sp<MPEG2TSExtractor> &extractor,
-            const sp<AnotherPacketSource> &impl);
+            const sp<AnotherPacketSource> &impl,
+            bool seekable);
 
     virtual status_t start(MetaData *params = NULL);
     virtual status_t stop();
@@ -50,14 +54,20 @@
     sp<MPEG2TSExtractor> mExtractor;
     sp<AnotherPacketSource> mImpl;
 
+    // If there are both audio and video streams, only the video stream
+    // will be seekable, otherwise the single stream will be seekable.
+    bool mSeekable;
+
     DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSSource);
 };
 
 MPEG2TSSource::MPEG2TSSource(
         const sp<MPEG2TSExtractor> &extractor,
-        const sp<AnotherPacketSource> &impl)
+        const sp<AnotherPacketSource> &impl,
+        bool seekable)
     : mExtractor(extractor),
-      mImpl(impl) {
+      mImpl(impl),
+      mSeekable(seekable) {
 }
 
 status_t MPEG2TSSource::start(MetaData *params) {
@@ -69,13 +79,27 @@
 }
 
 sp<MetaData> MPEG2TSSource::getFormat() {
-    return mImpl->getFormat();
+    sp<MetaData> meta = mImpl->getFormat();
+
+    int64_t durationUs;
+    if (mExtractor->mLiveSource != NULL
+            && mExtractor->mLiveSource->getDuration(&durationUs)) {
+        meta->setInt64(kKeyDuration, durationUs);
+    }
+
+    return meta;
 }
 
 status_t MPEG2TSSource::read(
         MediaBuffer **out, const ReadOptions *options) {
     *out = NULL;
 
+    int64_t seekTimeUs;
+    ReadOptions::SeekMode seekMode;
+    if (mSeekable && options && options->getSeekTo(&seekTimeUs, &seekMode)) {
+        mExtractor->seekTo(seekTimeUs);
+    }
+
     status_t finalResult;
     while (!mImpl->hasBufferAvailable(&finalResult)) {
         if (finalResult != OK) {
@@ -109,7 +133,20 @@
         return NULL;
     }
 
-    return new MPEG2TSSource(this, mSourceImpls.editItemAt(index));
+    bool seekable = true;
+    if (mSourceImpls.size() > 1) {
+        CHECK_EQ(mSourceImpls.size(), 2u);
+
+        sp<MetaData> meta = mSourceImpls.editItemAt(index)->getFormat();
+        const char *mime;
+        CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+        if (!strncasecmp("audio/", mime, 6)) {
+            seekable = false;
+        }
+    }
+
+    return new MPEG2TSSource(this, mSourceImpls.editItemAt(index), seekable);
 }
 
 sp<MetaData> MPEG2TSExtractor::getTrackMetaData(
@@ -189,6 +226,46 @@
     return OK;
 }
 
+void MPEG2TSExtractor::setLiveSource(const sp<LiveSource> &liveSource) {
+    Mutex::Autolock autoLock(mLock);
+
+    mLiveSource = liveSource;
+}
+
+void MPEG2TSExtractor::seekTo(int64_t seekTimeUs) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mLiveSource == NULL) {
+        return;
+    }
+
+    if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
+        static_cast<NuCachedSource2 *>(mDataSource.get())->suspend();
+    }
+
+    if (mLiveSource->seekTo(seekTimeUs)) {
+        mParser->signalDiscontinuity(true  /* isSeek */);
+        mOffset = 0;
+    }
+
+    if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
+        static_cast<NuCachedSource2 *>(mDataSource.get())
+            ->clearCacheAndResume();
+    }
+}
+
+uint32_t MPEG2TSExtractor::flags() const {
+    Mutex::Autolock autoLock(mLock);
+
+    uint32_t flags = CAN_PAUSE;
+
+    if (mLiveSource != NULL && mLiveSource->isSeekable()) {
+        flags |= CAN_SEEK_FORWARD | CAN_SEEK_BACKWARD | CAN_SEEK;
+    }
+
+    return flags;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 bool SniffMPEG2TS(
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index ded3b24..5a1ea5c 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -59,7 +59,8 @@
     sp<AMessage> mNotifyMsg;
     KeyedVector<uint32_t, sp<ARTPSource> > mSources;
 
-    int32_t mNumRTCPPacketsReceived;
+    int64_t mNumRTCPPacketsReceived;
+    int64_t mNumRTPPacketsReceived;
     struct sockaddr_in mRemoteRTCPAddr;
 
     bool mIsInjected;
@@ -168,6 +169,12 @@
             break;
         }
 
+        case kWhatFakeTimestamps:
+        {
+            onFakeTimestamps();
+            break;
+        }
+
         default:
         {
             TRESPASS();
@@ -199,6 +206,7 @@
     CHECK(msg->findMessage("notify", &info->mNotifyMsg));
 
     info->mNumRTCPPacketsReceived = 0;
+    info->mNumRTPPacketsReceived = 0;
     memset(&info->mRemoteRTCPAddr, 0, sizeof(info->mRemoteRTCPAddr));
 
     if (!injected) {
@@ -373,6 +381,12 @@
 }
 
 status_t ARTPConnection::parseRTP(StreamInfo *s, const sp<ABuffer> &buffer) {
+    if (s->mNumRTPPacketsReceived++ == 0) {
+        sp<AMessage> notify = s->mNotifyMsg->dup();
+        notify->setInt32("first-rtp", true);
+        notify->post();
+    }
+
     size_t size = buffer->size();
 
     if (size < 12) {
@@ -638,5 +652,27 @@
     }
 }
 
+void ARTPConnection::fakeTimestamps() {
+    (new AMessage(kWhatFakeTimestamps, id()))->post();
+}
+
+void ARTPConnection::onFakeTimestamps() {
+    List<StreamInfo>::iterator it = mStreams.begin();
+    while (it != mStreams.end()) {
+        StreamInfo &info = *it++;
+
+        for (size_t j = 0; j < info.mSources.size(); ++j) {
+            sp<ARTPSource> source = info.mSources.valueAt(j);
+
+            if (!source->timeEstablished()) {
+                source->timeUpdate(0, 0);
+                source->timeUpdate(0 + 90000, 0x100000000ll);
+
+                mFlags |= kFakeTimestamps;
+            }
+        }
+    }
+}
+
 }  // namespace android
 
diff --git a/media/libstagefright/rtsp/ARTPConnection.h b/media/libstagefright/rtsp/ARTPConnection.h
index 77f81fa..a17b382 100644
--- a/media/libstagefright/rtsp/ARTPConnection.h
+++ b/media/libstagefright/rtsp/ARTPConnection.h
@@ -51,6 +51,8 @@
     static void MakePortPair(
             int *rtpSocket, int *rtcpSocket, unsigned *rtpPort);
 
+    void fakeTimestamps();
+
 protected:
     virtual ~ARTPConnection();
     virtual void onMessageReceived(const sp<AMessage> &msg);
@@ -61,6 +63,7 @@
         kWhatRemoveStream,
         kWhatPollStreams,
         kWhatInjectPacket,
+        kWhatFakeTimestamps,
     };
 
     static const int64_t kSelectTimeoutUs;
@@ -78,6 +81,7 @@
     void onPollStreams();
     void onInjectPacket(const sp<AMessage> &msg);
     void onSendReceiverReports();
+    void onFakeTimestamps();
 
     status_t receive(StreamInfo *info, bool receiveRTP);
 
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 0f4c1f3..1bc9925 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -105,7 +105,9 @@
           mCheckPending(false),
           mCheckGeneration(0),
           mTryTCPInterleaving(false),
+          mTryFakeRTCP(false),
           mReceivedFirstRTCPPacket(false),
+          mReceivedFirstRTPPacket(false),
           mSeekable(false) {
         mNetLooper->setName("rtsp net");
         mNetLooper->start(false /* runOnCallingThread */,
@@ -534,6 +536,7 @@
                 mFirstAccessUnitNTP = 0;
                 mNumAccessUnitsReceived = 0;
                 mReceivedFirstRTCPPacket = false;
+                mReceivedFirstRTPPacket = false;
                 mSeekable = false;
 
                 sp<AMessage> reply = new AMessage('tear', id());
@@ -611,12 +614,17 @@
 
             case 'accu':
             {
-                int32_t firstRTCP;
-                if (msg->findInt32("first-rtcp", &firstRTCP)) {
+                int32_t first;
+                if (msg->findInt32("first-rtcp", &first)) {
                     mReceivedFirstRTCPPacket = true;
                     break;
                 }
 
+                if (msg->findInt32("first-rtp", &first)) {
+                    mReceivedFirstRTPPacket = true;
+                    break;
+                }
+
                 ++mNumAccessUnitsReceived;
                 postAccessUnitTimeoutCheck();
 
@@ -839,9 +847,17 @@
             case 'tiou':
             {
                 if (!mReceivedFirstRTCPPacket) {
-                    if (mTryTCPInterleaving) {
+                    if (mTryFakeRTCP) {
                         LOGW("Never received any data, disconnecting.");
                         (new AMessage('abor', id()))->post();
+                    } else if (mTryTCPInterleaving && mReceivedFirstRTPPacket) {
+                        LOGW("We received RTP packets but no RTCP packets, "
+                             "using fake timestamps.");
+
+                        mTryFakeRTCP = true;
+
+                        mReceivedFirstRTCPPacket = true;
+                        mRTPConn->fakeTimestamps();
                     } else {
                         LOGW("Never received any data, switching transports.");
 
@@ -987,7 +1003,9 @@
     bool mCheckPending;
     int32_t mCheckGeneration;
     bool mTryTCPInterleaving;
+    bool mTryFakeRTCP;
     bool mReceivedFirstRTCPPacket;
+    bool mReceivedFirstRTPPacket;
     bool mSeekable;
 
     struct TrackInfo {
diff --git a/native/include/android/storage_manager.h b/native/include/android/storage_manager.h
index c202693..bad24913 100644
--- a/native/include/android/storage_manager.h
+++ b/native/include/android/storage_manager.h
@@ -74,10 +74,10 @@
     AOBB_STATE_ERROR_ALREADY_MOUNTED = 24,
 
     /*
-     * The current application does not have permission to use this OBB
-     * because the OBB indicates it's owned by a different package or the
-     * key used to open it is incorrect. Can be returned as the status for
-     * callbacks made during asynchronous OBB actions.
+     * The current application does not have permission to use this OBB.
+     * This could be because the OBB indicates it's owned by a different
+     * package. Can be returned as the status for callbacks made during
+     * asynchronous OBB actions.
      */
     AOBB_STATE_ERROR_PERMISSION_DENIED = 25,
 };
diff --git a/preloaded-classes b/preloaded-classes
index 1d5fbc08..8de175a 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -1,115 +1,167 @@
 # Classes which are preloaded by com.android.internal.os.ZygoteInit.
 # Automatically generated by frameworks/base/tools/preload/WritePreloadedClassFile.java.
 # MIN_LOAD_TIME_MICROS=1250
+# MIN_PROCESSES=10
 android.R$styleable
+android.accounts.Account
+android.accounts.Account$1
 android.accounts.AccountManager
-android.accounts.AccountManager$4
-android.accounts.AccountManager$6
-android.accounts.AccountManager$AmsTask
-android.accounts.AccountManager$BaseFutureTask
-android.accounts.AccountManager$Future2Task
-android.accounts.AuthenticatorDescription
-android.accounts.IAccountAuthenticatorResponse$Stub
+android.accounts.AccountManager$12
+android.accounts.IAccountManager
 android.accounts.IAccountManager$Stub
-android.accounts.IAccountManagerResponse$Stub
+android.accounts.IAccountManager$Stub$Proxy
 android.app.Activity
-android.app.ActivityGroup
-android.app.ActivityManager$RunningAppProcessInfo
-android.app.ActivityManager$RunningServiceInfo
 android.app.ActivityManagerNative
 android.app.ActivityManagerProxy
 android.app.ActivityThread
+android.app.ActivityThread$1
+android.app.ActivityThread$2
+android.app.ActivityThread$ActivityClientRecord
+android.app.ActivityThread$AppBindData
 android.app.ActivityThread$ApplicationThread
+android.app.ActivityThread$ContextCleanupInfo
+android.app.ActivityThread$CreateServiceData
+android.app.ActivityThread$GcIdler
 android.app.ActivityThread$H
+android.app.ActivityThread$Idler
+android.app.ActivityThread$ProviderClientRecord
+android.app.ActivityThread$ProviderRefCount
+android.app.ActivityThread$ReceiverData
+android.app.ActivityThread$ResourcesKey
+android.app.ActivityThread$ServiceArgsData
+android.app.ActivityThread$StopInfo
 android.app.AlertDialog
+android.app.AppGlobals
+android.app.Application
+android.app.ApplicationErrorReport$CrashInfo
+android.app.ApplicationLoaders
 android.app.ApplicationThreadNative
 android.app.ContextImpl
+android.app.ContextImpl$ApplicationContentResolver
 android.app.ContextImpl$ApplicationPackageManager
-android.app.DatePickerDialog
+android.app.ContextImpl$ApplicationPackageManager$ResourceName
+android.app.ContextImpl$SharedPreferencesImpl
+android.app.ContextImpl$SharedPreferencesImpl$1
+android.app.ContextImpl$SharedPreferencesImpl$EditorImpl
+android.app.ContextImpl$SharedPreferencesImpl$EditorImpl$1
+android.app.ContextImpl$SharedPreferencesImpl$EditorImpl$2
+android.app.ContextImpl$SharedPreferencesImpl$MemoryCommitResult
 android.app.Dialog
-android.app.ExpandableListActivity
+android.app.Dialog$1
+android.app.Dialog$ListenersHandler
 android.app.IActivityManager
 android.app.IActivityManager$ContentProviderHolder
-android.app.IAlarmManager$Stub
+android.app.IActivityManager$ContentProviderHolder$1
+android.app.IApplicationThread
+android.app.IInstrumentationWatcher
+android.app.IInstrumentationWatcher$Stub
+android.app.INotificationManager
+android.app.INotificationManager$Stub
+android.app.INotificationManager$Stub$Proxy
+android.app.ITransientNotification
 android.app.ITransientNotification$Stub
 android.app.Instrumentation
-android.app.IntentService
+android.app.IntentReceiverLeaked
 android.app.ListActivity
-android.app.LocalActivityManager
-android.app.Notification
+android.app.LoadedApk
+android.app.LoadedApk$ReceiverDispatcher
+android.app.LoadedApk$ReceiverDispatcher$Args
+android.app.LoadedApk$ReceiverDispatcher$InnerReceiver
+android.app.LoadedApk$ServiceDispatcher$ConnectionInfo
+android.app.LoadedApk$ServiceDispatcher$DeathMonitor
+android.app.LoadedApk$ServiceDispatcher$RunConnection
+android.app.LoadedApk$WarningContextClassLoader
+android.app.NativeActivity
+android.app.NotificationManager
 android.app.PendingIntent
-android.app.ProgressDialog
+android.app.PendingIntent$1
+android.app.QueuedWork
+android.app.ReceiverRestrictedContext
 android.app.ResultInfo
+android.app.ResultInfo$1
 android.app.SearchDialog
-android.app.SearchDialog$SearchAutoComplete
-android.app.SearchDialog$SearchBar
-android.app.SearchableInfo
 android.app.Service
-android.app.SuggestionsAdapter
-android.app.SuperNotCalledException
-android.app.TabActivity
-android.app.TimePickerDialog
-android.app.admin.IDevicePolicyManager$Stub
-android.appwidget.AppWidgetHost
-android.appwidget.AppWidgetHostView
-android.appwidget.AppWidgetHostView$ParcelableSparseArray
-android.appwidget.AppWidgetManager
-android.appwidget.AppWidgetProvider
-android.appwidget.AppWidgetProviderInfo
 android.app.backup.BackupDataInput
 android.app.backup.BackupDataInput$EntityHeader
 android.app.backup.BackupDataOutput
-android.app.backup.BackupAgentHelper
 android.app.backup.BackupHelperDispatcher
 android.app.backup.BackupHelperDispatcher$Header
 android.app.backup.FileBackupHelperBase
-android.app.backup.IBackupManager$Stub
-android.app.backup.RestoreSet
-android.bluetooth.BluetoothAdapter
 android.bluetooth.BluetoothAudioGateway
 android.bluetooth.BluetoothSocket
-android.bluetooth.BluetoothUuid
 android.bluetooth.HeadsetBase
 android.bluetooth.IBluetooth
 android.bluetooth.IBluetooth$Stub
 android.bluetooth.IBluetoothA2dp
 android.bluetooth.IBluetoothA2dp$Stub
-android.bluetooth.IBluetoothHeadset$Stub
 android.bluetooth.ScoSocket
+android.content.BroadcastReceiver
+android.content.ComponentCallbacks
 android.content.ComponentName
+android.content.ComponentName$1
+android.content.ContentProvider
 android.content.ContentProvider$Transport
-android.content.ContentProviderOperation
-android.content.ContentProviderResult
+android.content.ContentProviderNative
+android.content.ContentProviderProxy
 android.content.ContentResolver
+android.content.ContentResolver$CursorWrapperInner
+android.content.ContentUris
 android.content.ContentValues
+android.content.ContentValues$1
 android.content.Context
 android.content.ContextWrapper
+android.content.DialogInterface
+android.content.DialogInterface$OnCancelListener
+android.content.DialogInterface$OnClickListener
+android.content.DialogInterface$OnDismissListener
+android.content.IContentProvider
+android.content.IContentService
 android.content.IContentService$Stub
-android.content.ISyncContext$Stub
+android.content.IContentService$Stub$Proxy
+android.content.IIntentReceiver
+android.content.IIntentReceiver$Stub
+android.content.IIntentSender
+android.content.IIntentSender$Stub
+android.content.IIntentSender$Stub$Proxy
 android.content.Intent
+android.content.Intent$1
 android.content.IntentFilter
-android.content.IntentSender
-android.content.SearchRecentSuggestionsProvider
-android.content.SyncResult
-android.content.SyncStats
+android.content.IntentFilter$1
+android.content.ServiceConnection
+android.content.SharedPreferences
+android.content.SharedPreferences$Editor
+android.content.SharedPreferences$OnSharedPreferenceChangeListener
 android.content.UriMatcher
 android.content.pm.ActivityInfo
+android.content.pm.ActivityInfo$1
 android.content.pm.ApplicationInfo
+android.content.pm.ApplicationInfo$1
+android.content.pm.ComponentInfo
 android.content.pm.ConfigurationInfo
-android.content.pm.IPackageDataObserver$Stub
+android.content.pm.ConfigurationInfo$1
+android.content.pm.FeatureInfo
+android.content.pm.FeatureInfo$1
+android.content.pm.IPackageManager
 android.content.pm.IPackageManager$Stub
 android.content.pm.IPackageManager$Stub$Proxy
-android.content.pm.IPackageStatsObserver$Stub
 android.content.pm.InstrumentationInfo
+android.content.pm.InstrumentationInfo$1
 android.content.pm.PackageInfo
+android.content.pm.PackageInfo$1
+android.content.pm.PackageItemInfo
 android.content.pm.PackageManager
-android.content.pm.PackageManager$NameNotFoundException
-android.content.pm.PackageStats
+android.content.pm.PathPermission
+android.content.pm.PathPermission$1
 android.content.pm.PermissionInfo
+android.content.pm.PermissionInfo$1
 android.content.pm.ProviderInfo
+android.content.pm.ProviderInfo$1
 android.content.pm.ResolveInfo
-android.content.pm.ResolveInfo$DisplayNameComparator
+android.content.pm.ResolveInfo$1
+android.content.pm.ServiceInfo
+android.content.pm.ServiceInfo$1
 android.content.pm.Signature
+android.content.pm.Signature$1
 android.content.res.AssetFileDescriptor
 android.content.res.AssetFileDescriptor$1
 android.content.res.AssetManager
@@ -120,34 +172,59 @@
 android.content.res.CompatibilityInfo$1
 android.content.res.Configuration
 android.content.res.Configuration$1
+android.content.res.ObbInfo
+android.content.res.ObbInfo$1
+android.content.res.ObbScanner
 android.content.res.Resources
 android.content.res.Resources$1
+android.content.res.Resources$Theme
 android.content.res.StringBlock
+android.content.res.StringBlock$StyleIDs
 android.content.res.TypedArray
 android.content.res.XmlBlock
 android.content.res.XmlBlock$Parser
 android.content.res.XmlResourceParser
 android.database.AbstractCursor
+android.database.AbstractCursor$SelfContentObserver
 android.database.AbstractWindowedCursor
+android.database.BulkCursorNative
+android.database.BulkCursorProxy
 android.database.BulkCursorToCursorAdaptor
 android.database.CharArrayBuffer
-android.database.CursorToBulkCursorAdaptor
+android.database.ContentObservable
+android.database.ContentObserver
+android.database.ContentObserver$NotificationRunnable
+android.database.ContentObserver$Transport
+android.database.CrossProcessCursor
+android.database.Cursor
 android.database.CursorWindow
 android.database.CursorWindow$1
 android.database.CursorWrapper
-android.database.MatrixCursor
+android.database.DataSetObservable
+android.database.DataSetObserver
+android.database.DatabaseUtils
+android.database.DatabaseUtils$InsertHelper
+android.database.IBulkCursor
+android.database.IContentObserver
+android.database.IContentObserver$Stub
+android.database.Observable
+android.database.sqlite.DatabaseObjectNotClosedException
 android.database.sqlite.SQLiteClosable
 android.database.sqlite.SQLiteCompiledSql
-android.database.sqlite.SQLiteContentHelper
 android.database.sqlite.SQLiteCursor
+android.database.sqlite.SQLiteCursorDriver
 android.database.sqlite.SQLiteDatabase
+android.database.sqlite.SQLiteDatabase$ActiveDatabases
 android.database.sqlite.SQLiteDebug
+android.database.sqlite.SQLiteDebug$DbStats
 android.database.sqlite.SQLiteDebug$PagerStats
+android.database.sqlite.SQLiteDirectCursorDriver
+android.database.sqlite.SQLiteOpenHelper
 android.database.sqlite.SQLiteProgram
 android.database.sqlite.SQLiteQuery
 android.database.sqlite.SQLiteQueryBuilder
 android.database.sqlite.SQLiteStatement
-android.database.sqlite.SqliteWrapper
+android.ddm.DdmHandleAppName
 android.ddm.DdmHandleExit
 android.ddm.DdmHandleHeap
 android.ddm.DdmHandleHello
@@ -160,7 +237,6 @@
 android.graphics.AvoidXfermode
 android.graphics.Bitmap
 android.graphics.Bitmap$1
-android.graphics.Bitmap$CompressFormat
 android.graphics.Bitmap$Config
 android.graphics.BitmapFactory
 android.graphics.BitmapFactory$Options
@@ -168,7 +244,7 @@
 android.graphics.BlurMaskFilter
 android.graphics.Camera
 android.graphics.Canvas
-android.graphics.Canvas$VertexMode
+android.graphics.Canvas$EdgeType
 android.graphics.Color
 android.graphics.ColorFilter
 android.graphics.ColorMatrixColorFilter
@@ -180,11 +256,13 @@
 android.graphics.DrawFilter
 android.graphics.EmbossMaskFilter
 android.graphics.Interpolator
+android.graphics.Interpolator$Result
 android.graphics.LayerRasterizer
 android.graphics.LightingColorFilter
 android.graphics.LinearGradient
 android.graphics.MaskFilter
 android.graphics.Matrix
+android.graphics.Matrix$ScaleToFit
 android.graphics.Movie
 android.graphics.NinePatch
 android.graphics.Paint
@@ -216,13 +294,13 @@
 android.graphics.RectF$1
 android.graphics.Region
 android.graphics.Region$1
-android.graphics.Region$Op
 android.graphics.RegionIterator
 android.graphics.Shader
 android.graphics.Shader$TileMode
 android.graphics.SumPathEffect
 android.graphics.SweepGradient
 android.graphics.TableMaskFilter
+android.graphics.TemporaryBuffer
 android.graphics.Typeface
 android.graphics.Xfermode
 android.graphics.YuvImage
@@ -251,77 +329,88 @@
 android.graphics.drawable.NinePatchDrawable
 android.graphics.drawable.NinePatchDrawable$NinePatchState
 android.graphics.drawable.ShapeDrawable
+android.graphics.drawable.ShapeDrawable$ShapeState
 android.graphics.drawable.StateListDrawable
 android.graphics.drawable.StateListDrawable$StateListState
 android.graphics.drawable.TransitionDrawable
 android.graphics.drawable.TransitionDrawable$TransitionState
+android.graphics.drawable.shapes.RectShape
+android.graphics.drawable.shapes.RoundRectShape
+android.graphics.drawable.shapes.Shape
 android.graphics.utils.BoundaryPatch
 android.hardware.Camera
-android.hardware.Camera$Parameters
-android.hardware.GeomagneticField
+android.hardware.Camera$CameraInfo
 android.hardware.SensorManager
-android.location.Address
-android.location.Criteria
-android.location.GeocoderParams
-android.location.IGpsStatusListener$Stub
+android.inputmethodservice.ExtractEditText
+android.inputmethodservice.InputMethodService
+android.location.GpsSatellite
+android.location.GpsStatus
+android.location.GpsStatus$1
+android.location.ILocationManager
 android.location.ILocationManager$Stub
 android.location.ILocationManager$Stub$Proxy
-android.location.Location
 android.location.LocationManager
+android.media.AmrInputStream
 android.media.AudioFormat
 android.media.AudioManager
+android.media.AudioManager$1
+android.media.AudioManager$FocusEventHandlerDelegate
+android.media.AudioManager$FocusEventHandlerDelegate$1
 android.media.AudioRecord
 android.media.AudioSystem
 android.media.AudioTrack
+android.media.CamcorderProfile
+android.media.DecoderCapabilities
 android.media.ExifInterface
+android.media.IAudioFocusDispatcher
+android.media.IAudioFocusDispatcher$Stub
+android.media.IAudioService
 android.media.IAudioService$Stub
+android.media.IAudioService$Stub$Proxy
 android.media.JetPlayer
-android.media.MediaFile
-android.media.MediaMetadataRetriever
 android.media.MediaPlayer
+android.media.MediaPlayer$OnCompletionListener
+android.media.MediaPlayer$OnErrorListener
+android.media.MediaPlayer$OnPreparedListener
 android.media.MediaScanner
-android.media.Metadata
-android.media.MiniThumbFile
-android.media.ThumbnailUtils
+android.media.SoundPool
 android.media.ToneGenerator
 android.net.ConnectivityManager
 android.net.Credentials
 android.net.DhcpInfo
 android.net.DhcpInfo$1
-android.net.Downloads
-android.net.Downloads$ByUri
+android.net.IConnectivityManager
 android.net.IConnectivityManager$Stub
+android.net.IConnectivityManager$Stub$Proxy
 android.net.LocalServerSocket
 android.net.LocalSocket
 android.net.LocalSocketImpl
 android.net.LocalSocketImpl$SocketInputStream
 android.net.LocalSocketImpl$SocketOutputStream
 android.net.NetworkInfo
+android.net.NetworkInfo$1
 android.net.NetworkInfo$DetailedState
+android.net.NetworkInfo$State
 android.net.NetworkUtils
-android.net.SSLCertificateSocketFactory
 android.net.TrafficStats
 android.net.Uri
+android.net.Uri$1
+android.net.Uri$AbstractHierarchicalUri
+android.net.Uri$AbstractPart
+android.net.Uri$Builder
 android.net.Uri$HierarchicalUri
 android.net.Uri$OpaqueUri
 android.net.Uri$Part
+android.net.Uri$Part$EmptyPart
+android.net.Uri$PathPart
+android.net.Uri$PathSegments
+android.net.Uri$PathSegmentsBuilder
+android.net.Uri$StringUri
 android.net.WebAddress
 android.net.http.AndroidHttpClient
-android.net.http.AndroidHttpClientConnection
+android.net.http.AndroidHttpClient$1
 android.net.http.EventHandler
-android.net.http.Headers
 android.net.http.HttpsConnection
-com.android.internal.http.HttpDateTime
-android.net.http.Request
-android.net.http.RequestQueue
-android.net.http.SslCertificate
-android.net.http.SslError
-android.net.wifi.IWifiManager$Stub
-android.net.wifi.ScanResult
-android.net.wifi.SupplicantState
-android.net.wifi.WifiConfiguration
-android.net.wifi.WifiInfo
-android.net.wifi.WifiManager
 android.net.wifi.WifiNative
 android.opengl.ETC1
 android.opengl.GLES10
@@ -329,313 +418,403 @@
 android.opengl.GLES11
 android.opengl.GLES11Ext
 android.opengl.GLES20
-android.opengl.GLSurfaceView
-android.opengl.GLSurfaceView$ComponentSizeChooser
 android.opengl.GLUtils
 android.opengl.Matrix
 android.opengl.Visibility
+android.os.AsyncTask$1
+android.os.AsyncTask$AsyncTaskResult
 android.os.Binder
 android.os.BinderProxy
 android.os.Build
 android.os.Build$VERSION
 android.os.Bundle
+android.os.Bundle$1
 android.os.Debug
 android.os.Debug$MemoryInfo
 android.os.Debug$MemoryInfo$1
-android.os.DropBoxManager$Entry
 android.os.Environment
 android.os.FileObserver$ObserverThread
 android.os.FileUtils
 android.os.FileUtils$FileStatus
 android.os.Handler
+android.os.HandlerThread
 android.os.IBinder
+android.os.IBinder$DeathRecipient
 android.os.IInterface
+android.os.IPowerManager
 android.os.IPowerManager$Stub
+android.os.IPowerManager$Stub$Proxy
+android.os.IServiceManager
 android.os.Looper
 android.os.MemoryFile
 android.os.Message
+android.os.Message$1
+android.os.MessageQueue
+android.os.MessageQueue$IdleHandler
 android.os.Parcel
 android.os.Parcel$1
 android.os.ParcelFileDescriptor
 android.os.ParcelFileDescriptor$1
-android.os.ParcelUuid
 android.os.Parcelable
 android.os.Parcelable$Creator
+android.os.PatternMatcher
+android.os.PatternMatcher$1
 android.os.Power
+android.os.PowerManager
+android.os.PowerManager$WakeLock
+android.os.PowerManager$WakeLock$1
 android.os.Process
-android.os.RecoverySystem
-android.os.ResultReceiver
+android.os.ServiceManager
+android.os.ServiceManagerNative
+android.os.ServiceManagerProxy
 android.os.StatFs
+android.os.StrictMode
+android.os.StrictMode$1
+android.os.StrictMode$2
+android.os.StrictMode$AndroidBlockGuardPolicy
+android.os.StrictMode$AndroidBlockGuardPolicy$1
+android.os.StrictMode$LogStackTrace
+android.os.StrictMode$StrictModeDiskReadViolation
+android.os.StrictMode$StrictModeDiskWriteViolation
+android.os.StrictMode$ViolationInfo
 android.os.SystemClock
 android.os.SystemProperties
 android.os.UEventObserver
-android.os.storage.IMountService$Stub
-android.os.storage.IMountService$Stub$Proxy
 android.pim.EventRecurrence
-android.pim.RecurrenceSet
-android.preference.CheckBoxPreference$SavedState
-android.preference.DialogPreference
-android.preference.ListPreference
-android.preference.Preference
-android.preference.PreferenceActivity
-android.preference.PreferenceGroup
-android.preference.PreferenceGroupAdapter
-android.preference.PreferenceInflater
 android.preference.PreferenceManager
-android.preference.PreferenceScreen
-android.preference.RingtonePreference
-android.preference.VolumePreference
-android.preference.VolumePreference$SeekBarVolumizer
-android.provider.Browser
-android.provider.Calendar
-android.provider.Calendar$Attendees
-android.provider.Calendar$CalendarAlerts
-android.provider.Calendar$Calendars
-android.provider.Calendar$EventDays
-android.provider.Calendar$Events
-android.provider.Calendar$Reminders
-android.provider.Contacts
-android.provider.Contacts$ContactMethods
-android.provider.ContactsContract
-android.provider.ContactsContract$CommonDataKinds$Email
-android.provider.ContactsContract$CommonDataKinds$Phone
-android.provider.ContactsContract$CommonDataKinds$StructuredPostal
-android.provider.ContactsContract$Contacts
-android.provider.ContactsContract$Data
-android.provider.ContactsContract$DataColumnsWithJoins
-android.provider.ContactsContract$PhoneLookup
-android.provider.ContactsContract$RawContacts
-android.provider.ContactsContract$RawContacts$EntityIteratorImpl
-android.provider.ContactsContract$RawContactsEntity
-android.provider.Downloads
-android.provider.Downloads$Impl
-android.provider.MediaStore
-android.provider.MediaStore$Audio$Artists
-android.provider.MediaStore$Audio$Media
-android.provider.MediaStore$Images$Media
-android.provider.MediaStore$Images$Thumbnails
-android.provider.MediaStore$Video$Media
-android.provider.SearchRecentSuggestions
+android.provider.BaseColumns
+android.provider.Settings$NameValueCache
+android.provider.Settings$NameValueTable
 android.provider.Settings$Secure
 android.provider.Settings$System
-android.provider.UserDictionary$Words
-android.security.KeyStore
+android.renderscript.RenderScript
 android.security.Md5MessageDigest
 android.security.MessageDigest
 android.security.Sha1MessageDigest
 android.server.BluetoothA2dpService
 android.server.BluetoothEventLoop
 android.server.BluetoothService
-android.speech.tts.ITts$Stub
-android.speech.tts.ITts$Stub$Proxy
-android.speech.tts.ITtsCallback$Stub
-android.speech.tts.TextToSpeech
 android.telephony.PhoneNumberUtils
-android.telephony.ServiceState
-android.telephony.SignalStrength
-android.telephony.SmsMessage
-android.telephony.SmsMessage$MessageClass
 android.telephony.TelephonyManager
+android.text.AndroidBidi
 android.text.AndroidCharacter
+android.text.AutoText
 android.text.BoringLayout
+android.text.BoringLayout$Metrics
 android.text.DynamicLayout
+android.text.DynamicLayout$ChangeWatcher
+android.text.Editable
+android.text.Editable$Factory
+android.text.GetChars
+android.text.GraphicsOperations
 android.text.Html$HtmlParser
-android.text.HtmlToSpannedConverter
+android.text.InputFilter
+android.text.InputType
 android.text.Layout
+android.text.Layout$Alignment
+android.text.Layout$Directions
+android.text.NoCopySpan
+android.text.NoCopySpan$Concrete
+android.text.PackedIntVector
+android.text.PackedObjectVector
+android.text.ParcelableSpan
 android.text.Selection
+android.text.Selection$END
+android.text.Selection$START
+android.text.SpanWatcher
+android.text.Spannable
+android.text.Spannable$Factory
+android.text.SpannableString
 android.text.SpannableStringBuilder
+android.text.SpannableStringInternal
+android.text.Spanned
 android.text.SpannedString
+android.text.StaticLayout
+android.text.Styled
+android.text.TextPaint
 android.text.TextUtils
-android.text.format.DateUtils
-android.text.format.Formatter
+android.text.TextUtils$1
+android.text.TextUtils$EllipsizeCallback
+android.text.TextUtils$TruncateAt
+android.text.TextWatcher
 android.text.format.Time
 android.text.method.ArrowKeyMovementMethod
 android.text.method.BaseKeyListener
-android.text.method.DigitsKeyListener
-android.text.method.LinkMovementMethod
+android.text.method.KeyListener
 android.text.method.MetaKeyKeyListener
+android.text.method.MovementMethod
 android.text.method.QwertyKeyListener
-android.text.method.ReplacementTransformationMethod$SpannedReplacementCharSequence
+android.text.method.ReplacementTransformationMethod
 android.text.method.SingleLineTransformationMethod
 android.text.method.TextKeyListener
 android.text.method.TextKeyListener$Capitalize
-android.text.style.ImageSpan
-android.text.style.RelativeSizeSpan
-android.text.style.ScaleXSpan
+android.text.method.TransformationMethod
+android.text.style.AlignmentSpan
+android.text.style.CharacterStyle
+android.text.style.ClickableSpan
+android.text.style.LeadingMarginSpan
+android.text.style.LineBackgroundSpan
+android.text.style.LineHeightSpan
+android.text.style.MetricAffectingSpan
+android.text.style.ParagraphStyle
+android.text.style.ReplacementSpan
 android.text.style.StyleSpan
-android.text.style.TextAppearanceSpan
-android.text.util.Linkify
+android.text.style.URLSpan
+android.text.style.UpdateAppearance
+android.text.style.UpdateLayout
+android.text.style.WrapTogetherSpan
+android.util.AndroidException
+android.util.AndroidRuntimeException
 android.util.AttributeSet
-android.util.Base64$Encoder
 android.util.DisplayMetrics
 android.util.EventLog
 android.util.EventLog$Event
+android.util.FinitePool
 android.util.FloatMath
 android.util.Log
+android.util.Log$1
+android.util.Log$TerribleFailureHandler
 android.util.LongSparseArray
-android.util.MonthDisplayHelper
+android.util.Pair
 android.util.Patterns
+android.util.Pool
+android.util.Poolable
+android.util.PoolableManager
+android.util.Pools
 android.util.SparseArray
+android.util.SparseIntArray
 android.util.StateSet
+android.util.SynchronizedPool
 android.util.TypedValue
 android.util.Xml
-android.util.Xml$Encoding
 android.view.AbsSavedState
+android.view.AbsSavedState$1
+android.view.AbsSavedState$2
+android.view.ContextMenu
+android.view.ContextMenu$ContextMenuInfo
 android.view.ContextThemeWrapper
 android.view.Display
 android.view.FocusFinder
-android.view.GestureDetector
+android.view.FocusFinder$1
+android.view.Gravity
+android.view.IWindow
 android.view.IWindow$Stub
+android.view.IWindowManager
 android.view.IWindowManager$Stub
 android.view.IWindowManager$Stub$Proxy
+android.view.IWindowSession
 android.view.IWindowSession$Stub
+android.view.IWindowSession$Stub$Proxy
+android.view.InputChannel
+android.view.InputChannel$1
+android.view.InputEvent
+android.view.InputEvent$1
+android.view.InputHandler
+android.view.InputQueue
+android.view.InputQueue$Callback
+android.view.InputQueue$FinishedCallback
 android.view.KeyCharacterMap
 android.view.KeyCharacterMap$KeyData
 android.view.KeyEvent
+android.view.KeyEvent$1
+android.view.KeyEvent$Callback
+android.view.KeyEvent$DispatcherState
+android.view.LayoutInflater
+android.view.LayoutInflater$Factory
+android.view.LayoutInflater$Filter
+android.view.Menu
+android.view.MenuItem
 android.view.MotionEvent
-android.view.ScaleGestureDetector
+android.view.MotionEvent$1
 android.view.Surface
 android.view.Surface$1
+android.view.Surface$CompatibleCanvas
+android.view.SurfaceHolder
+android.view.SurfaceHolder$Callback
+android.view.SurfaceHolder$Callback2
 android.view.SurfaceSession
-android.view.SurfaceView
-android.view.SurfaceView$MyWindow
 android.view.VelocityTracker
+android.view.VelocityTracker$1
+android.view.VelocityTracker$Pointer
 android.view.View
+android.view.View$AttachInfo
 android.view.View$AttachInfo$Callbacks
-android.view.View$AttachInfo$InvalidateInfo
 android.view.View$BaseSavedState
+android.view.View$BaseSavedState$1
+android.view.View$CheckForTap
+android.view.View$MeasureSpec
+android.view.View$OnClickListener
+android.view.View$OnCreateContextMenuListener
+android.view.View$OnLongClickListener
+android.view.View$OnTouchListener
+android.view.View$PerformClick
+android.view.View$ScrollabilityCache
+android.view.View$UnsetPressedState
 android.view.ViewConfiguration
+android.view.ViewDebug
 android.view.ViewGroup
+android.view.ViewGroup$LayoutParams
+android.view.ViewGroup$MarginLayoutParams
+android.view.ViewGroup$OnHierarchyChangeListener
+android.view.ViewManager
 android.view.ViewParent
 android.view.ViewRoot
+android.view.ViewRoot$1
+android.view.ViewRoot$2
+android.view.ViewRoot$InputMethodCallback
+android.view.ViewRoot$ResizedInfo
+android.view.ViewRoot$RunQueue
+android.view.ViewRoot$TrackballAxis
 android.view.ViewRoot$W
-android.view.ViewStub
+android.view.ViewTreeObserver
+android.view.ViewTreeObserver$InternalInsetsInfo
+android.view.ViewTreeObserver$OnGlobalFocusChangeListener
+android.view.ViewTreeObserver$OnGlobalLayoutListener
+android.view.ViewTreeObserver$OnPreDrawListener
+android.view.ViewTreeObserver$OnScrollChangedListener
+android.view.ViewTreeObserver$OnTouchModeChangeListener
 android.view.Window
+android.view.Window$Callback
+android.view.Window$LocalWindowManager
+android.view.WindowLeaked
+android.view.WindowManager
 android.view.WindowManager$LayoutParams
+android.view.WindowManager$LayoutParams$1
 android.view.WindowManagerImpl
 android.view.accessibility.AccessibilityEvent
+android.view.accessibility.AccessibilityEventSource
+android.view.accessibility.AccessibilityManager
+android.view.accessibility.AccessibilityManager$1
+android.view.accessibility.AccessibilityManager$MyHandler
+android.view.accessibility.IAccessibilityManager
+android.view.accessibility.IAccessibilityManager$Stub
+android.view.accessibility.IAccessibilityManager$Stub$Proxy
+android.view.accessibility.IAccessibilityManagerClient
+android.view.accessibility.IAccessibilityManagerClient$Stub
+android.view.animation.AccelerateDecelerateInterpolator
+android.view.animation.AlphaAnimation
 android.view.animation.Animation
-android.view.animation.AnimationSet
+android.view.animation.AnimationUtils
+android.view.animation.DecelerateInterpolator
+android.view.animation.Interpolator
+android.view.animation.LinearInterpolator
+android.view.animation.Transformation
 android.view.inputmethod.BaseInputConnection
-android.view.inputmethod.CompletionInfo
+android.view.inputmethod.ComposingText
 android.view.inputmethod.EditorInfo
+android.view.inputmethod.EditorInfo$1
 android.view.inputmethod.ExtractedText
+android.view.inputmethod.ExtractedText$1
+android.view.inputmethod.ExtractedTextRequest
+android.view.inputmethod.InputConnection
 android.view.inputmethod.InputMethodManager
+android.view.inputmethod.InputMethodManager$1
+android.view.inputmethod.InputMethodManager$ControlledInputConnectionWrapper
+android.view.inputmethod.InputMethodManager$H
 android.webkit.BrowserFrame
-android.webkit.CacheManager
-android.webkit.CallbackProxy
-android.webkit.ConsoleMessage$MessageLevel
-android.webkit.CookieManager
-android.webkit.CookieSyncManager
-android.webkit.DownloadListener
-android.webkit.FileLoader
 android.webkit.GeolocationPermissions
-android.webkit.GeolocationService
 android.webkit.HTML5VideoViewProxy
 android.webkit.JWebCoreJavaBridge
 android.webkit.LoadListener
+android.webkit.MockGeolocation
 android.webkit.PluginManager
-android.webkit.URLUtil
-android.webkit.WebIconDatabase$EventHandler$IconResult
-android.webkit.WebIconDatabase$IconListener
+android.webkit.WebBackForwardList
+android.webkit.WebHistoryItem
+android.webkit.WebIconDatabase
 android.webkit.WebSettings
 android.webkit.WebSettings$TextSize
 android.webkit.WebStorage
-android.webkit.WebTextView
 android.webkit.WebView
-android.webkit.WebView$DragTrackerHandler
-android.webkit.WebView$ScaleDetectorListener
 android.webkit.WebViewCore
-android.webkit.WebViewCore$4
-android.webkit.WebViewCore$TextSelectionData
-android.webkit.WebViewCore$TouchEventData
-android.webkit.WebViewCore$TouchUpData
-android.webkit.WebViewDatabase
 android.widget.AbsListView
-android.widget.AbsListView$3
-android.widget.AbsListView$CheckForKeyLongPress
-android.widget.AbsListView$PerformClick
-android.widget.AbsListView$SavedState
-android.widget.AbsSeekBar
+android.widget.AbsListView$2
+android.widget.AbsListView$LayoutParams
+android.widget.AbsListView$RecycleBin
 android.widget.AbsSpinner
-android.widget.AbsSpinner$SavedState
 android.widget.AbsoluteLayout
+android.widget.Adapter
 android.widget.AdapterView
-android.widget.ArrayAdapter
+android.widget.AdapterView$AdapterDataSetObserver
+android.widget.AdapterView$OnItemClickListener
 android.widget.AutoCompleteTextView
-android.widget.AutoCompleteTextView$DropDownItemClickListener
-android.widget.AutoCompleteTextView$DropDownListView
 android.widget.BaseAdapter
-android.widget.BaseExpandableListAdapter
+android.widget.Button
 android.widget.CheckBox
+android.widget.Checkable
 android.widget.CompoundButton
-android.widget.CompoundButton$SavedState
-android.widget.CursorAdapter
-android.widget.CursorTreeAdapter
-android.widget.DatePicker
+android.widget.EdgeGlow
 android.widget.EditText
-android.widget.ExpandableListConnector
-android.widget.ExpandableListView
+android.widget.Filter$FilterListener
+android.widget.Filterable
 android.widget.FrameLayout
+android.widget.FrameLayout$LayoutParams
+android.widget.Gallery
 android.widget.GridView
-android.widget.HeaderViewListAdapter
+android.widget.HorizontalScrollView
+android.widget.ImageButton
 android.widget.ImageView
 android.widget.ImageView$ScaleType
 android.widget.LinearLayout
+android.widget.LinearLayout$LayoutParams
+android.widget.ListAdapter
 android.widget.ListView
-android.widget.ListView$SavedState
-android.widget.MediaController
-android.widget.MediaController$4
-android.widget.MultiAutoCompleteTextView
+android.widget.ListView$ArrowScrollFocusResult
 android.widget.NumberPicker
+android.widget.OverScroller
+android.widget.OverScroller$MagneticOverScroller
 android.widget.PopupWindow
-android.widget.PopupWindow$PopupViewContainer
+android.widget.PopupWindow$1
 android.widget.ProgressBar
-android.widget.ProgressBar$SavedState
-android.widget.QuickContactBadge
-android.widget.RatingBar
 android.widget.RelativeLayout
+android.widget.RelativeLayout$DependencyGraph
 android.widget.RelativeLayout$DependencyGraph$Node
+android.widget.RelativeLayout$DependencyGraph$Node$1
+android.widget.RelativeLayout$LayoutParams
 android.widget.RemoteViews
-android.widget.ResourceCursorAdapter
+android.widget.RemoteViews$1
+android.widget.RemoteViews$Action
+android.widget.RemoteViews$ReflectionAction
 android.widget.ScrollBarDrawable
 android.widget.ScrollView
-android.widget.SeekBar
-android.widget.SimpleCursorAdapter
-android.widget.SlidingDrawer
-android.widget.Spinner
+android.widget.SpinnerAdapter
 android.widget.TabHost
 android.widget.TabWidget
 android.widget.TableLayout
 android.widget.TableRow
 android.widget.TextView
-android.widget.TextView$CommitSelectionReceiver
-android.widget.TextView$Marquee
-android.widget.TimePicker
-android.widget.TwoLineListItem
-android.widget.VideoView
+android.widget.TextView$3
+android.widget.TextView$Blink
+android.widget.TextView$BufferType
+android.widget.TextView$ChangeWatcher
+android.widget.TextView$CharWrapper
+android.widget.TextView$CursorController
+android.widget.TextView$Drawables
+android.widget.TextView$HandleView
+android.widget.TextView$InsertionPointCursorController
+android.widget.TextView$InsertionPointCursorController$1
+android.widget.TextView$SelectionModifierCursorController
+android.widget.TextView$SelectionModifierCursorController$1
+android.widget.Toast
+android.widget.Toast$TN
+android.widget.Toast$TN$1
+android.widget.Toast$TN$2
 android.widget.ViewAnimator
-android.widget.ViewSwitcher
 android.widget.ZoomButton
-android.widget.ZoomButtonsController
 android.widget.ZoomControls
 com.android.internal.R$styleable
-com.android.internal.app.AlertActivity
 com.android.internal.app.AlertController
+com.android.internal.app.AlertController$1
 com.android.internal.app.AlertController$AlertParams
-com.android.internal.app.AlertController$RecycleListView
-com.android.internal.app.ChooserActivity
-com.android.internal.app.ResolverActivity
-com.android.internal.app.ResolverActivity$ResolveListAdapter
+com.android.internal.app.AlertController$ButtonHandler
+com.android.internal.appwidget.IAppWidgetService
 com.android.internal.appwidget.IAppWidgetService$Stub
-com.android.internal.content.SyncStateContentProviderHelper
 com.android.internal.graphics.NativeUtils
-com.android.internal.location.DummyLocationProvider
+com.android.internal.logging.AndroidConfig
 com.android.internal.logging.AndroidHandler
+com.android.internal.logging.AndroidHandler$1
 com.android.internal.os.AndroidPrintStream
 com.android.internal.os.BinderInternal
 com.android.internal.os.BinderInternal$GcWatcher
-com.android.internal.os.IResultReceiver$Stub
 com.android.internal.os.LoggingPrintStream
 com.android.internal.os.LoggingPrintStream$1
 com.android.internal.os.RuntimeInit
@@ -645,53 +824,53 @@
 com.android.internal.os.ZygoteConnection
 com.android.internal.os.ZygoteConnection$Arguments
 com.android.internal.os.ZygoteInit
-com.android.internal.net.DomainNameValidator
+com.android.internal.os.ZygoteInit$MethodAndArgsCaller
+com.android.internal.policy.IPolicy
 com.android.internal.policy.PolicyManager
 com.android.internal.policy.impl.PhoneLayoutInflater
 com.android.internal.policy.impl.PhoneWindow
+com.android.internal.policy.impl.PhoneWindow$1
+com.android.internal.policy.impl.PhoneWindow$ContextMenuCallback
 com.android.internal.policy.impl.PhoneWindow$DecorView
+com.android.internal.policy.impl.PhoneWindow$PanelFeatureState
 com.android.internal.policy.impl.PhoneWindow$PanelFeatureState$SavedState
-com.android.internal.policy.impl.PhoneWindowManager
+com.android.internal.policy.impl.PhoneWindow$PanelFeatureState$SavedState$1
 com.android.internal.policy.impl.Policy
-com.android.internal.statusbar.IStatusBar
-com.android.internal.statusbar.IStatusBar$Stub
-com.android.internal.statusbar.IStatusBarService$Stub
-com.android.internal.statusbar.IStatusBarService$Stub
-com.android.internal.statusbar.StatusBarIcon
-com.android.internal.telephony.GsmAlphabet
-com.android.internal.telephony.ITelephony$Stub
-com.android.internal.telephony.ITelephony$Stub$Proxy
+com.android.internal.telephony.ITelephonyRegistry
 com.android.internal.telephony.ITelephonyRegistry$Stub
-com.android.internal.telephony.IccCard$State
+com.android.internal.telephony.ITelephonyRegistry$Stub$Proxy
 com.android.internal.telephony.Phone$State
-com.android.internal.telephony.SmsAddress
-com.android.internal.telephony.SmsMessageBase
-com.android.internal.telephony.gsm.GsmSmsAddress
-com.android.internal.telephony.gsm.SmsMessage
-com.android.internal.telephony.gsm.SmsMessage$PduParser
 com.android.internal.util.ArrayUtils
-com.android.internal.util.FastMath
 com.android.internal.util.FastXmlSerializer
-com.android.internal.util.HanziToPinyin
 com.android.internal.util.XmlUtils
 com.android.internal.view.IInputConnectionWrapper
+com.android.internal.view.IInputConnectionWrapper$MyHandler
+com.android.internal.view.IInputContext
 com.android.internal.view.IInputContext$Stub
+com.android.internal.view.IInputMethodCallback
+com.android.internal.view.IInputMethodCallback$Stub
+com.android.internal.view.IInputMethodClient
+com.android.internal.view.IInputMethodClient$Stub
+com.android.internal.view.IInputMethodManager
 com.android.internal.view.IInputMethodManager$Stub
+com.android.internal.view.IInputMethodManager$Stub$Proxy
+com.android.internal.view.IInputMethodSession
+com.android.internal.view.IInputMethodSession$Stub
+com.android.internal.view.IInputMethodSession$Stub$Proxy
+com.android.internal.view.InputBindResult
+com.android.internal.view.InputBindResult$1
+com.android.internal.view.RootViewSurfaceTaker
 com.android.internal.view.menu.ContextMenuBuilder
 com.android.internal.view.menu.IconMenuItemView
 com.android.internal.view.menu.IconMenuView
-com.android.internal.view.menu.IconMenuView$SavedState
-com.android.internal.view.menu.ListMenuItemView
 com.android.internal.view.menu.MenuBuilder
-com.android.internal.view.menu.MenuItemImpl
-com.android.internal.view.menu.SubMenuBuilder
+com.android.internal.view.menu.MenuBuilder$Callback
 com.android.internal.widget.ContactHeaderWidget
 com.android.internal.widget.DialogTitle
-com.android.internal.widget.EditableInputConnection
-com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient
-com.android.internal.widget.LockPatternUtils
-com.android.internal.widget.LockPatternView
-com.android.internal.widget.LockPatternView$Cell
+com.android.internal.widget.WeightedLinearLayout
+com.android.server.Watchdog
+com.google.android.collect.Lists
+com.google.android.collect.Maps
 com.google.android.gles_jni.EGLImpl
 com.google.android.gles_jni.GLImpl
 com.ibm.icu4jni.charset.CharsetDecoderICU
@@ -699,16 +878,24 @@
 com.ibm.icu4jni.charset.CharsetICU
 com.ibm.icu4jni.charset.NativeConverter
 com.ibm.icu4jni.common.ErrorCode
-com.ibm.icu4jni.text.Collator
 com.ibm.icu4jni.text.NativeBreakIterator
 com.ibm.icu4jni.text.NativeCollation
 com.ibm.icu4jni.text.NativeDecimalFormat
-com.ibm.icu4jni.text.RuleBasedCollator
+com.ibm.icu4jni.text.NativeDecimalFormat$FieldPositionIterator
+com.ibm.icu4jni.util.ICU
+com.ibm.icu4jni.util.LocaleData
+dalvik.system.BlockGuard
+dalvik.system.BlockGuard$1
+dalvik.system.BlockGuard$2
+dalvik.system.BlockGuard$BlockGuardPolicyException
+dalvik.system.BlockGuard$Policy
+dalvik.system.BlockGuard$WrappedFileSystem
+dalvik.system.BlockGuard$WrappedNetworkSystem
 dalvik.system.DalvikLogHandler
 dalvik.system.DalvikLogging
+dalvik.system.DexFile
 dalvik.system.NativeStart
 dalvik.system.PathClassLoader
-dalvik.system.SamplingProfiler
 dalvik.system.TouchDex
 dalvik.system.VMDebug
 dalvik.system.VMRuntime
@@ -720,8 +907,11 @@
 java.io.BufferedInputStream
 java.io.BufferedReader
 java.io.ByteArrayInputStream
+java.io.ByteArrayOutputStream
 java.io.Closeable
+java.io.Console
 java.io.DataInput
+java.io.DataInputStream
 java.io.DataOutput
 java.io.DataOutputStream
 java.io.File
@@ -742,25 +932,25 @@
 java.io.ObjectOutput
 java.io.ObjectOutputStream
 java.io.ObjectStreamClass
-java.io.ObjectStreamClass$OSCThreadLocalCache
 java.io.ObjectStreamConstants
-java.io.ObjectStreamException
 java.io.ObjectStreamField
 java.io.OutputStream
 java.io.OutputStreamWriter
 java.io.PrintStream
 java.io.PrintWriter
-java.io.PushbackReader
+java.io.PushbackInputStream
 java.io.RandomAccessFile
 java.io.Reader
 java.io.Serializable
-java.io.StreamCorruptedException
+java.io.StringWriter
+java.io.Writer
 java.lang.AbstractStringBuilder
 java.lang.Appendable
 java.lang.ArrayIndexOutOfBoundsException
 java.lang.Boolean
 java.lang.BootClassLoader
 java.lang.Byte
+java.lang.CaseMapper
 java.lang.CharSequence
 java.lang.Character
 java.lang.Character$UnicodeBlock
@@ -769,6 +959,7 @@
 java.lang.ClassCache$EnumComparator
 java.lang.ClassLoader
 java.lang.ClassLoader$SystemClassLoader
+java.lang.ClassNotFoundException
 java.lang.Cloneable
 java.lang.Comparable
 java.lang.Double
@@ -777,8 +968,11 @@
 java.lang.Exception
 java.lang.Float
 java.lang.IllegalArgumentException
+java.lang.IllegalStateException
 java.lang.IndexOutOfBoundsException
 java.lang.Integer
+java.lang.IntegralToString
+java.lang.IntegralToString$1
 java.lang.InternalError
 java.lang.InterruptedException
 java.lang.Iterable
@@ -787,12 +981,15 @@
 java.lang.Long
 java.lang.Math
 java.lang.NoClassDefFoundError
-java.lang.NoSuchMethodError
+java.lang.NoSuchMethodException
+java.lang.NullPointerException
 java.lang.Number
 java.lang.NumberFormatException
 java.lang.Object
 java.lang.OutOfMemoryError
 java.lang.Readable
+java.lang.RealToString
+java.lang.RealToString$1
 java.lang.Runnable
 java.lang.Runtime
 java.lang.RuntimeException
@@ -817,6 +1014,7 @@
 java.lang.ThreadLocal
 java.lang.ThreadLocal$Values
 java.lang.Throwable
+java.lang.UnsafeByteSequence
 java.lang.UnsatisfiedLinkError
 java.lang.UnsupportedOperationException
 java.lang.VMClassLoader
@@ -838,6 +1036,7 @@
 java.lang.reflect.InvocationHandler
 java.lang.reflect.Member
 java.lang.reflect.Method
+java.lang.reflect.Method$1
 java.lang.reflect.Modifier
 java.lang.reflect.Proxy
 java.lang.reflect.ReflectionAccessImpl
@@ -845,32 +1044,39 @@
 java.math.BigDecimal
 java.math.BigInt
 java.math.BigInteger
-java.math.Multiplication
 java.math.NativeBN
+java.math.RoundingMode
 java.net.AddressCache
 java.net.AddressCache$1
-java.net.ConnectException
+java.net.AddressCache$AddressCacheEntry
 java.net.ContentHandler
 java.net.DatagramPacket
+java.net.HttpURLConnection
 java.net.Inet4Address
 java.net.InetAddress
 java.net.InetAddress$1
-java.net.InetAddress$2
 java.net.InetAddress$WaitReachable
 java.net.InetSocketAddress
+java.net.InterfaceAddress
 java.net.JarURLConnection
+java.net.MulticastGroupRequest
 java.net.NetPermission
 java.net.NetworkInterface
-java.net.ServerSocket
+java.net.Proxy
 java.net.Socket
-java.net.SocketException
+java.net.Socket$ConnectLock
+java.net.SocketAddress
 java.net.SocketImpl
+java.net.SocketImplFactory
 java.net.SocketOptions
+java.net.SocketTimeoutException
 java.net.URI
+java.net.URIEncoderDecoder
 java.net.URL
 java.net.URLConnection
 java.net.URLConnection$DefaultContentHandler
 java.net.URLStreamHandler
+java.net.UnknownHostException
 java.nio.BaseByteBuffer
 java.nio.Buffer
 java.nio.BufferFactory
@@ -879,14 +1085,13 @@
 java.nio.CharArrayBuffer
 java.nio.CharBuffer
 java.nio.CharSequenceAdapter
-java.nio.CharToByteBufferAdapter
 java.nio.DirectByteBuffer
-java.nio.FloatToByteBufferAdapter
+java.nio.DirectByteBuffer$SafeAddress
 java.nio.HeapByteBuffer
-java.nio.IntToByteBufferAdapter
-java.nio.LongBuffer
-java.nio.LongToByteBufferAdapter
+java.nio.MappedByteBuffer
+java.nio.MappedByteBufferAdapter
 java.nio.NIOAccess
+java.nio.ReadOnlyDirectByteBuffer
 java.nio.ReadWriteCharArrayBuffer
 java.nio.ReadWriteDirectByteBuffer
 java.nio.ReadWriteHeapByteBuffer
@@ -894,6 +1099,7 @@
 java.nio.channels.ByteChannel
 java.nio.channels.Channel
 java.nio.channels.FileChannel
+java.nio.channels.FileChannel$MapMode
 java.nio.channels.GatheringByteChannel
 java.nio.channels.InterruptibleChannel
 java.nio.channels.ReadableByteChannel
@@ -901,39 +1107,60 @@
 java.nio.channels.WritableByteChannel
 java.nio.channels.spi.AbstractInterruptibleChannel
 java.nio.channels.spi.AbstractInterruptibleChannel$1
-java.nio.channels.spi.AbstractInterruptibleChannel$2
 java.nio.charset.Charset
 java.nio.charset.Charset$1
 java.nio.charset.CharsetDecoder
 java.nio.charset.CharsetEncoder
+java.nio.charset.Charsets
 java.nio.charset.CoderResult
 java.nio.charset.CodingErrorAction
-java.nio.charset.spi.CharsetProvider
+java.nio.charset.ModifiedUtf8
 java.security.AccessControlContext
 java.security.AccessController
 java.security.BasicPermission
 java.security.Guard
 java.security.KeyStore
-java.security.MessageDigest
+java.security.KeyStore$1
+java.security.KeyStoreSpi
 java.security.Permission
+java.security.Principal
 java.security.PrivilegedAction
 java.security.PrivilegedExceptionAction
 java.security.ProtectionDomain
 java.security.Provider
+java.security.Provider$Service
+java.security.Provider$Service$1
+java.security.SecureRandom
+java.security.SecureRandomSpi
 java.security.Security
+java.security.Security$1
+java.security.Security$SecurityDoor
+java.security.cert.CertPathParameters
+java.security.cert.CertPathValidator
+java.security.cert.CertPathValidatorSpi
+java.security.cert.Certificate
+java.security.cert.CertificateFactory
+java.security.cert.CertificateFactorySpi
+java.security.cert.PKIXParameters
+java.security.cert.TrustAnchor
 java.security.cert.X509Certificate
-java.text.AttributedCharacterIterator$Attribute
-java.text.Collator
+java.security.cert.X509Extension
 java.text.DateFormat
-java.text.DateFormat$Field
+java.text.DateFormatSymbols
 java.text.DecimalFormat
+java.text.DecimalFormat$1
 java.text.DecimalFormatSymbols
 java.text.Format
 java.text.NumberFormat
+java.text.ParsePosition
 java.text.SimpleDateFormat
 java.util.AbstractCollection
 java.util.AbstractList
+java.util.AbstractList$FullListIterator
+java.util.AbstractList$SimpleListIterator
 java.util.AbstractMap
+java.util.AbstractQueue
+java.util.AbstractSequentialList
 java.util.AbstractSet
 java.util.ArrayList
 java.util.ArrayList$ArrayListIterator
@@ -946,87 +1173,141 @@
 java.util.Collections$EmptyList
 java.util.Collections$EmptyMap
 java.util.Collections$EmptySet
-java.util.Collections$SingletonSet
 java.util.Collections$UnmodifiableCollection
 java.util.Collections$UnmodifiableCollection$1
+java.util.Collections$UnmodifiableList
+java.util.Collections$UnmodifiableMap
 java.util.Collections$UnmodifiableRandomAccessList
 java.util.Collections$UnmodifiableSet
+java.util.ComparableTimSort
 java.util.Comparator
+java.util.Currency
 java.util.Date
+java.util.Deque
 java.util.Dictionary
 java.util.EnumMap
 java.util.EnumSet
 java.util.Enumeration
 java.util.EventListener
 java.util.EventObject
+java.util.Formattable
 java.util.Formatter
+java.util.Formatter$1
+java.util.Formatter$FormatSpecifierParser
+java.util.Formatter$FormatToken
 java.util.GregorianCalendar
 java.util.HashMap
+java.util.HashMap$EntryIterator
+java.util.HashMap$EntrySet
 java.util.HashMap$HashIterator
 java.util.HashMap$HashMapEntry
 java.util.HashMap$KeyIterator
 java.util.HashMap$KeySet
+java.util.HashMap$ValueIterator
 java.util.HashMap$Values
 java.util.HashSet
 java.util.Hashtable
+java.util.Hashtable$EntryIterator
+java.util.Hashtable$EntrySet
 java.util.Hashtable$HashIterator
 java.util.Hashtable$HashtableEntry
 java.util.Hashtable$KeyEnumeration
 java.util.Hashtable$ValueIterator
 java.util.Hashtable$Values
-java.util.IdentityHashMap
 java.util.Iterator
 java.util.LinkedHashMap
+java.util.LinkedHashMap$KeyIterator
 java.util.LinkedHashMap$LinkedEntry
 java.util.LinkedHashMap$LinkedHashIterator
 java.util.LinkedHashMap$ValueIterator
 java.util.LinkedList
+java.util.LinkedList$Link
+java.util.LinkedList$LinkIterator
 java.util.List
 java.util.ListIterator
 java.util.Locale
 java.util.Map
 java.util.Map$Entry
-java.util.MiniEnumSet
+java.util.NavigableMap
+java.util.NavigableSet
 java.util.Properties
 java.util.PropertyPermission
+java.util.Queue
+java.util.Random
 java.util.RandomAccess
-java.util.ResourceBundle
 java.util.Set
 java.util.SimpleTimeZone
 java.util.SortedMap
 java.util.SortedSet
-java.util.SpecialAccess
-java.util.Stack
 java.util.StringTokenizer
+java.util.TimSort
 java.util.TimeZone
 java.util.TreeMap
+java.util.TreeMap$1
+java.util.TreeMap$2
+java.util.TreeMap$Bound
+java.util.TreeMap$Bound$1
+java.util.TreeMap$Bound$2
+java.util.TreeMap$Bound$3
+java.util.TreeMap$EntrySet
+java.util.TreeMap$EntrySet$1
+java.util.TreeMap$KeySet
+java.util.TreeMap$KeySet$1
+java.util.TreeMap$MapIterator
+java.util.TreeMap$Node
+java.util.TreeMap$Relation
 java.util.TreeSet
-java.util.UUID
 java.util.Vector
+java.util.Vector$1
 java.util.WeakHashMap
 java.util.WeakHashMap$Entry
-java.util.concurrent.ConcurrentHashMap
+java.util.WeakHashMap$Entry$Type
+java.util.WeakHashMap$HashIterator
+java.util.concurrent.AbstractExecutorService
+java.util.concurrent.BlockingQueue
+java.util.concurrent.Callable
 java.util.concurrent.ConcurrentLinkedQueue
 java.util.concurrent.ConcurrentLinkedQueue$Node
 java.util.concurrent.CopyOnWriteArrayList
 java.util.concurrent.CopyOnWriteArrayList$COWIterator
+java.util.concurrent.CountDownLatch
+java.util.concurrent.CountDownLatch$Sync
+java.util.concurrent.Executor
+java.util.concurrent.ExecutorService
+java.util.concurrent.Executors
+java.util.concurrent.Executors$DefaultThreadFactory
 java.util.concurrent.Executors$DelegatedExecutorService
+java.util.concurrent.Executors$FinalizableDelegatedExecutorService
+java.util.concurrent.Future
 java.util.concurrent.FutureTask
+java.util.concurrent.FutureTask$Sync
 java.util.concurrent.LinkedBlockingQueue
-java.util.concurrent.Semaphore
+java.util.concurrent.LinkedBlockingQueue$Node
+java.util.concurrent.RejectedExecutionHandler
+java.util.concurrent.RunnableFuture
+java.util.concurrent.ThreadFactory
 java.util.concurrent.ThreadPoolExecutor
+java.util.concurrent.ThreadPoolExecutor$AbortPolicy
+java.util.concurrent.ThreadPoolExecutor$Worker
 java.util.concurrent.TimeUnit
-java.util.concurrent.atomic.AtomicBoolean
+java.util.concurrent.TimeUnit$1
+java.util.concurrent.TimeUnit$2
+java.util.concurrent.TimeUnit$3
+java.util.concurrent.TimeUnit$4
+java.util.concurrent.TimeUnit$5
+java.util.concurrent.TimeUnit$6
+java.util.concurrent.TimeUnit$7
 java.util.concurrent.atomic.AtomicInteger
-java.util.concurrent.atomic.AtomicLong
-java.util.concurrent.atomic.AtomicReference
 java.util.concurrent.atomic.UnsafeAccess
 java.util.concurrent.locks.AbstractOwnableSynchronizer
 java.util.concurrent.locks.AbstractQueuedSynchronizer
 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject
 java.util.concurrent.locks.AbstractQueuedSynchronizer$Node
+java.util.concurrent.locks.Condition
 java.util.concurrent.locks.Lock
+java.util.concurrent.locks.LockSupport
 java.util.concurrent.locks.ReentrantLock
+java.util.concurrent.locks.ReentrantLock$FairSync
 java.util.concurrent.locks.ReentrantLock$NonfairSync
 java.util.concurrent.locks.ReentrantLock$Sync
 java.util.concurrent.locks.UnsafeAccess
@@ -1038,6 +1319,9 @@
 java.util.jar.JarFile$1JarFileEnumerator
 java.util.jar.JarVerifier
 java.util.jar.Manifest
+java.util.logging.ConsoleHandler
+java.util.logging.ErrorManager
+java.util.logging.Formatter
 java.util.logging.Handler
 java.util.logging.Level
 java.util.logging.LogManager
@@ -1048,13 +1332,18 @@
 java.util.logging.Logger
 java.util.logging.Logger$1
 java.util.logging.LoggingPermission
+java.util.logging.SimpleFormatter
+java.util.logging.StreamHandler
 java.util.regex.MatchResult
 java.util.regex.Matcher
 java.util.regex.Pattern
+java.util.regex.PatternSyntaxException
+java.util.regex.Splitter
 java.util.zip.Adler32
 java.util.zip.CRC32
 java.util.zip.Checksum
 java.util.zip.Deflater
+java.util.zip.GZIPInputStream
 java.util.zip.Inflater
 java.util.zip.InflaterInputStream
 java.util.zip.ZipConstants
@@ -1064,9 +1353,6 @@
 java.util.zip.ZipFile$2
 java.util.zip.ZipFile$RAFStream
 java.util.zip.ZipFile$ZipInflaterInputStream
-javax.crypto.Cipher
-javax.crypto.Mac
-javax.crypto.spec.IvParameterSpec
 javax.microedition.khronos.egl.EGL
 javax.microedition.khronos.egl.EGL10
 javax.microedition.khronos.opengles.GL
@@ -1075,18 +1361,41 @@
 javax.microedition.khronos.opengles.GL11
 javax.microedition.khronos.opengles.GL11Ext
 javax.microedition.khronos.opengles.GL11ExtensionPack
+javax.net.SocketFactory
 javax.net.ssl.DefaultHostnameVerifier
+javax.net.ssl.HostnameVerifier
 javax.net.ssl.HttpsURLConnection
-javax.net.ssl.SSLServerSocket
-javax.net.ssl.SSLSession
+javax.net.ssl.KeyManager
+javax.net.ssl.KeyManagerFactory
+javax.net.ssl.KeyManagerFactory$1
+javax.net.ssl.KeyManagerFactorySpi
+javax.net.ssl.SSLContextSpi
+javax.net.ssl.SSLSessionContext
 javax.net.ssl.SSLSocket
 javax.net.ssl.SSLSocketFactory
+javax.net.ssl.SSLSocketFactory$1
+javax.net.ssl.TrustManager
+javax.net.ssl.TrustManagerFactory
+javax.net.ssl.TrustManagerFactory$1
+javax.net.ssl.TrustManagerFactorySpi
+javax.net.ssl.X509ExtendedKeyManager
+javax.net.ssl.X509KeyManager
+javax.net.ssl.X509TrustManager
 javax.security.auth.x500.X500Principal
-javax.security.cert.X509Certificate
-junit.framework.Assert
+libcore.base.Objects
+libcore.icu.NativeIDN
+libcore.icu.NativeNormalizer
+libcore.icu.NativePluralRules
+libcore.icu.TimeZones
+libcore.icu.TimeZones$CachedTimeZones
+libcore.io.IoUtils
+org.apache.commons.logging.Log
 org.apache.commons.logging.LogFactory
+org.apache.commons.logging.impl.Jdk14Logger
+org.apache.commons.logging.impl.WeakHashtable
 org.apache.harmony.archive.util.Util
 org.apache.harmony.dalvik.NativeTestTarget
+org.apache.harmony.dalvik.ddmc.Chunk
 org.apache.harmony.dalvik.ddmc.ChunkHandler
 org.apache.harmony.dalvik.ddmc.DdmServer
 org.apache.harmony.kernel.vm.LangAccess
@@ -1095,166 +1404,432 @@
 org.apache.harmony.lang.annotation.AnnotationMember
 org.apache.harmony.luni.internal.net.www.protocol.file.FileURLConnection
 org.apache.harmony.luni.internal.net.www.protocol.file.Handler
-org.apache.harmony.luni.internal.net.www.protocol.http.Handler
 org.apache.harmony.luni.internal.net.www.protocol.jar.Handler
 org.apache.harmony.luni.internal.net.www.protocol.jar.JarURLConnectionImpl
 org.apache.harmony.luni.internal.net.www.protocol.jar.JarURLConnectionImpl$JarURLConnectionInputStream
 org.apache.harmony.luni.internal.util.TimezoneGetter
+org.apache.harmony.luni.internal.util.ZoneInfo
 org.apache.harmony.luni.internal.util.ZoneInfoDB
-org.apache.harmony.luni.net.GenericIPMreq
 org.apache.harmony.luni.net.PlainSocketImpl
-org.apache.harmony.luni.platform.Endianness
-org.apache.harmony.luni.platform.ICommonDataTypes
+org.apache.harmony.luni.net.SocketInputStream
+org.apache.harmony.luni.net.SocketOutputStream
 org.apache.harmony.luni.platform.IFileSystem
-org.apache.harmony.luni.platform.IMemorySystem
 org.apache.harmony.luni.platform.INetworkSystem
+org.apache.harmony.luni.platform.MappedPlatformAddress
 org.apache.harmony.luni.platform.OSFileSystem
 org.apache.harmony.luni.platform.OSMemory
 org.apache.harmony.luni.platform.OSNetworkSystem
 org.apache.harmony.luni.platform.Platform
 org.apache.harmony.luni.platform.PlatformAddress
 org.apache.harmony.luni.platform.PlatformAddressFactory
+org.apache.harmony.luni.platform.RuntimeMemorySpy
+org.apache.harmony.luni.platform.RuntimeMemorySpy$AddressWrapper
 org.apache.harmony.luni.util.FloatingPointParser
 org.apache.harmony.luni.util.InputStreamHelper
 org.apache.harmony.luni.util.InputStreamHelper$1
 org.apache.harmony.luni.util.InputStreamHelper$ExposedByteArrayInputStream
-org.apache.harmony.luni.util.LocaleCache
-org.apache.harmony.luni.util.NumberConverter
 org.apache.harmony.luni.util.PriviAction
-org.apache.harmony.luni.util.ThreadLocalCache
-org.apache.harmony.luni.util.ThreadLocalCache$1
-org.apache.harmony.luni.util.ThreadLocalCache$2
-org.apache.harmony.luni.util.ThreadLocalCache$3
-org.apache.harmony.luni.util.ThreadLocalCache$4
-org.apache.harmony.luni.util.ThreadLocalCache$5
+org.apache.harmony.luni.util.TwoKeyHashMap
+org.apache.harmony.luni.util.TwoKeyHashMap$Entry
+org.apache.harmony.luni.util.TwoKeyHashMap$EntryIteratorImpl
+org.apache.harmony.luni.util.TwoKeyHashMap$ValueIteratorImpl
+org.apache.harmony.luni.util.TwoKeyHashMap$ValuesCollectionImpl
 org.apache.harmony.luni.util.Util
 org.apache.harmony.nio.FileChannelFactory
 org.apache.harmony.nio.internal.DirectBuffer
 org.apache.harmony.nio.internal.FileChannelImpl
 org.apache.harmony.nio.internal.FileChannelImpl$RepositioningLock
-org.apache.harmony.nio.internal.FileLockImpl
 org.apache.harmony.nio.internal.LockManager
 org.apache.harmony.nio.internal.LockManager$1
+org.apache.harmony.nio.internal.ReadOnlyFileChannel
 org.apache.harmony.nio.internal.WriteOnlyFileChannel
-org.apache.harmony.security.asn1.ASN1GeneralizedTime
+org.apache.harmony.security.Util
+org.apache.harmony.security.asn1.ASN1Any
+org.apache.harmony.security.asn1.ASN1Choice
+org.apache.harmony.security.asn1.ASN1Constants
+org.apache.harmony.security.asn1.ASN1Constructured
 org.apache.harmony.security.asn1.ASN1Oid
+org.apache.harmony.security.asn1.ASN1Oid$1
+org.apache.harmony.security.asn1.ASN1Primitive
+org.apache.harmony.security.asn1.ASN1Sequence
+org.apache.harmony.security.asn1.ASN1SequenceOf
+org.apache.harmony.security.asn1.ASN1SetOf
 org.apache.harmony.security.asn1.ASN1StringType
+org.apache.harmony.security.asn1.ASN1StringType$1
+org.apache.harmony.security.asn1.ASN1StringType$2
+org.apache.harmony.security.asn1.ASN1StringType$3
+org.apache.harmony.security.asn1.ASN1StringType$4
+org.apache.harmony.security.asn1.ASN1StringType$5
+org.apache.harmony.security.asn1.ASN1StringType$6
+org.apache.harmony.security.asn1.ASN1StringType$7
+org.apache.harmony.security.asn1.ASN1Type
+org.apache.harmony.security.asn1.ASN1TypeCollection
+org.apache.harmony.security.asn1.ASN1ValueCollection
+org.apache.harmony.security.asn1.BerInputStream
 org.apache.harmony.security.asn1.DerInputStream
-org.apache.harmony.security.asn1.DerOutputStream
 org.apache.harmony.security.fortress.Engine
+org.apache.harmony.security.fortress.SecurityAccess
 org.apache.harmony.security.fortress.SecurityUtils
 org.apache.harmony.security.fortress.Services
-org.apache.harmony.security.pkcs7.ContentInfo
+org.apache.harmony.security.fortress.Services$1
+org.apache.harmony.security.provider.cert.Cache
 org.apache.harmony.security.provider.cert.DRLCertFactory
+org.apache.harmony.security.provider.cert.DRLCertFactory$1
 org.apache.harmony.security.provider.cert.X509CertFactoryImpl
-org.apache.harmony.security.provider.cert.X509CertImpl
-org.apache.harmony.security.provider.cert.X509CertPathImpl
+org.apache.harmony.security.provider.crypto.CryptoProvider
+org.apache.harmony.security.provider.crypto.CryptoProvider$1
 org.apache.harmony.security.provider.crypto.RandomBitsSupplier
+org.apache.harmony.security.provider.crypto.RandomBitsSupplier$1
 org.apache.harmony.security.provider.crypto.SHA1PRNG_SecureRandomImpl
+org.apache.harmony.security.provider.crypto.SHA1_Data
 org.apache.harmony.security.utils.AlgNameMapper
+org.apache.harmony.security.utils.ObjectIdentifier
 org.apache.harmony.security.x501.AttributeTypeAndValue
+org.apache.harmony.security.x501.AttributeTypeAndValue$1
+org.apache.harmony.security.x501.AttributeTypeAndValue$2
+org.apache.harmony.security.x501.AttributeTypeAndValueComparator
+org.apache.harmony.security.x501.AttributeValue
 org.apache.harmony.security.x501.DirectoryString
+org.apache.harmony.security.x501.DirectoryString$1
 org.apache.harmony.security.x501.Name
-org.apache.harmony.security.x509.AlgorithmIdentifier
-org.apache.harmony.security.x509.BasicConstraints
-org.apache.harmony.security.x509.Certificate
-org.apache.harmony.security.x509.EDIPartyName
-org.apache.harmony.security.x509.Extension
-org.apache.harmony.security.x509.Extensions
+org.apache.harmony.security.x501.Name$1
 org.apache.harmony.security.x509.GeneralName
-org.apache.harmony.security.x509.GeneralNames
-org.apache.harmony.security.x509.KeyUsage
-org.apache.harmony.security.x509.ORAddress
-org.apache.harmony.security.x509.OtherName
-org.apache.harmony.security.x509.SubjectPublicKeyInfo
-org.apache.harmony.security.x509.TBSCertificate
-org.apache.harmony.security.x509.Time
-org.apache.harmony.security.x509.Validity
+org.apache.harmony.text.BidiRun
+org.apache.harmony.text.NativeBidi
 org.apache.harmony.xml.ExpatAttributes
 org.apache.harmony.xml.ExpatParser
+org.apache.harmony.xml.ExpatParser$ClonedAttributes
+org.apache.harmony.xml.ExpatParser$CurrentAttributes
+org.apache.harmony.xml.ExpatParser$ExpatLocator
 org.apache.harmony.xml.ExpatPullParser
-org.apache.harmony.xml.parsers.SAXParserFactoryImpl
-org.apache.harmony.xnet.provider.jsse.FileClientSessionCache
+org.apache.harmony.xml.ExpatPullParser$ByteDocument
+org.apache.harmony.xml.ExpatPullParser$Document
+org.apache.harmony.xml.ExpatPullParser$Document$SaxHandler
+org.apache.harmony.xml.ExpatPullParser$EndTagEvent
+org.apache.harmony.xml.ExpatPullParser$Event
+org.apache.harmony.xml.ExpatPullParser$NamespaceStack
+org.apache.harmony.xml.ExpatPullParser$NamespaceStack$Builder
+org.apache.harmony.xml.ExpatPullParser$StartDocumentEvent
+org.apache.harmony.xml.ExpatPullParser$StartTagEvent
+org.apache.harmony.xml.ExpatPullParser$TextEvent
+org.apache.harmony.xml.ExpatReader
+org.apache.harmony.xnet.provider.jsse.AbstractSessionContext
+org.apache.harmony.xnet.provider.jsse.AbstractSessionContext$1
+org.apache.harmony.xnet.provider.jsse.ClientSessionContext
+org.apache.harmony.xnet.provider.jsse.DefaultSSLContextImpl
+org.apache.harmony.xnet.provider.jsse.IndexedPKIXParameters
+org.apache.harmony.xnet.provider.jsse.IndexedPKIXParameters$Bytes
+org.apache.harmony.xnet.provider.jsse.JSSEProvider
+org.apache.harmony.xnet.provider.jsse.JSSEProvider$1
+org.apache.harmony.xnet.provider.jsse.KeyManagerFactoryImpl
+org.apache.harmony.xnet.provider.jsse.KeyManagerFactoryImpl$1
+org.apache.harmony.xnet.provider.jsse.KeyManagerImpl
 org.apache.harmony.xnet.provider.jsse.NativeCrypto
-org.apache.harmony.xnet.provider.jsse.OpenSSLServerSocketImpl
-org.apache.harmony.xnet.provider.jsse.OpenSSLSessionImpl
+org.apache.harmony.xnet.provider.jsse.NativeCrypto$SSLHandshakeCallbacks
+org.apache.harmony.xnet.provider.jsse.OpenSSLContextImpl
+org.apache.harmony.xnet.provider.jsse.OpenSSLProvider
+org.apache.harmony.xnet.provider.jsse.OpenSSLSocketFactoryImpl
 org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl
-org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$LoggerHolder
 org.apache.harmony.xnet.provider.jsse.ProtocolVersion
 org.apache.harmony.xnet.provider.jsse.SSLContextImpl
-org.apache.harmony.xnet.provider.jsse.SSLParameters
+org.apache.harmony.xnet.provider.jsse.SSLParametersImpl
 org.apache.harmony.xnet.provider.jsse.ServerSessionContext
+org.apache.harmony.xnet.provider.jsse.TrustManagerFactoryImpl
+org.apache.harmony.xnet.provider.jsse.TrustManagerFactoryImpl$1
+org.apache.harmony.xnet.provider.jsse.TrustManagerFactoryImpl$2
+org.apache.harmony.xnet.provider.jsse.TrustManagerImpl
+org.apache.http.ConnectionReuseStrategy
+org.apache.http.FormattedHeader
+org.apache.http.Header
+org.apache.http.HeaderElement
+org.apache.http.HeaderElementIterator
+org.apache.http.HeaderIterator
+org.apache.http.HttpClientConnection
+org.apache.http.HttpConnection
+org.apache.http.HttpConnectionMetrics
+org.apache.http.HttpEntity
+org.apache.http.HttpEntityEnclosingRequest
+org.apache.http.HttpHost
+org.apache.http.HttpInetConnection
+org.apache.http.HttpMessage
+org.apache.http.HttpRequest
+org.apache.http.HttpRequestInterceptor
+org.apache.http.HttpResponse
+org.apache.http.HttpResponseFactory
+org.apache.http.HttpResponseInterceptor
 org.apache.http.HttpVersion
+org.apache.http.NameValuePair
+org.apache.http.ProtocolVersion
+org.apache.http.ReasonPhraseCatalog
+org.apache.http.RequestLine
+org.apache.http.StatusLine
+org.apache.http.auth.AuthSchemeFactory
+org.apache.http.auth.AuthSchemeRegistry
+org.apache.http.auth.AuthState
+org.apache.http.client.AuthenticationHandler
+org.apache.http.client.CredentialsProvider
+org.apache.http.client.HttpClient
+org.apache.http.client.HttpRequestRetryHandler
+org.apache.http.client.RedirectHandler
+org.apache.http.client.RequestDirector
+org.apache.http.client.ResponseHandler
+org.apache.http.client.UserTokenHandler
+org.apache.http.client.methods.AbortableHttpRequest
 org.apache.http.client.methods.HttpEntityEnclosingRequestBase
-org.apache.http.client.methods.HttpGet
 org.apache.http.client.methods.HttpPost
 org.apache.http.client.methods.HttpRequestBase
+org.apache.http.client.methods.HttpUriRequest
+org.apache.http.client.params.HttpClientParams
+org.apache.http.client.protocol.RequestAddCookies
+org.apache.http.client.protocol.RequestDefaultHeaders
+org.apache.http.client.protocol.RequestProxyAuthentication
+org.apache.http.client.protocol.RequestTargetAuthentication
+org.apache.http.client.protocol.ResponseProcessCookies
+org.apache.http.client.utils.URIUtils
 org.apache.http.conn.BasicManagedEntity
+org.apache.http.conn.ClientConnectionManager
+org.apache.http.conn.ClientConnectionOperator
+org.apache.http.conn.ClientConnectionRequest
+org.apache.http.conn.ConnectionKeepAliveStrategy
+org.apache.http.conn.ConnectionReleaseTrigger
+org.apache.http.conn.EofSensorInputStream
+org.apache.http.conn.EofSensorWatcher
+org.apache.http.conn.ManagedClientConnection
+org.apache.http.conn.OperatedClientConnection
+org.apache.http.conn.params.ConnManagerPNames
 org.apache.http.conn.params.ConnManagerParams
+org.apache.http.conn.params.ConnManagerParams$1
+org.apache.http.conn.params.ConnPerRoute
+org.apache.http.conn.params.ConnRoutePNames
 org.apache.http.conn.params.ConnRouteParams
+org.apache.http.conn.routing.BasicRouteDirector
 org.apache.http.conn.routing.HttpRoute
+org.apache.http.conn.routing.HttpRouteDirector
+org.apache.http.conn.routing.HttpRoutePlanner
+org.apache.http.conn.routing.RouteInfo
+org.apache.http.conn.routing.RouteInfo$LayerType
+org.apache.http.conn.routing.RouteInfo$TunnelType
+org.apache.http.conn.routing.RouteTracker
+org.apache.http.conn.scheme.LayeredSocketFactory
+org.apache.http.conn.scheme.PlainSocketFactory
+org.apache.http.conn.scheme.Scheme
+org.apache.http.conn.scheme.SchemeRegistry
+org.apache.http.conn.scheme.SocketFactory
 org.apache.http.conn.ssl.AbstractVerifier
+org.apache.http.conn.ssl.AllowAllHostnameVerifier
+org.apache.http.conn.ssl.BrowserCompatHostnameVerifier
 org.apache.http.conn.ssl.SSLSocketFactory
+org.apache.http.conn.ssl.StrictHostnameVerifier
+org.apache.http.conn.ssl.X509HostnameVerifier
 org.apache.http.conn.util.InetAddressUtils
+org.apache.http.cookie.CookieSpecFactory
+org.apache.http.cookie.CookieSpecRegistry
+org.apache.http.entity.AbstractHttpEntity
+org.apache.http.entity.BasicHttpEntity
+org.apache.http.entity.ContentLengthStrategy
+org.apache.http.entity.HttpEntityWrapper
 org.apache.http.impl.AbstractHttpClientConnection
+org.apache.http.impl.DefaultConnectionReuseStrategy
+org.apache.http.impl.DefaultHttpResponseFactory
 org.apache.http.impl.EnglishReasonPhraseCatalog
+org.apache.http.impl.HttpConnectionMetricsImpl
 org.apache.http.impl.SocketHttpClientConnection
+org.apache.http.impl.auth.BasicSchemeFactory
+org.apache.http.impl.auth.DigestSchemeFactory
 org.apache.http.impl.client.AbstractAuthenticationHandler
 org.apache.http.impl.client.AbstractHttpClient
-org.apache.http.impl.client.BasicCookieStore
+org.apache.http.impl.client.BasicCredentialsProvider
+org.apache.http.impl.client.ClientParamsStack
+org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy
 org.apache.http.impl.client.DefaultHttpClient
+org.apache.http.impl.client.DefaultHttpRequestRetryHandler
+org.apache.http.impl.client.DefaultProxyAuthenticationHandler
+org.apache.http.impl.client.DefaultRedirectHandler
+org.apache.http.impl.client.DefaultRequestDirector
+org.apache.http.impl.client.DefaultTargetAuthenticationHandler
+org.apache.http.impl.client.DefaultUserTokenHandler
 org.apache.http.impl.client.EntityEnclosingRequestWrapper
+org.apache.http.impl.client.RequestWrapper
+org.apache.http.impl.client.RoutedRequest
 org.apache.http.impl.conn.AbstractClientConnAdapter
+org.apache.http.impl.conn.AbstractPoolEntry
 org.apache.http.impl.conn.AbstractPooledConnAdapter
 org.apache.http.impl.conn.DefaultClientConnection
-org.apache.http.impl.conn.SingleClientConnManager
+org.apache.http.impl.conn.DefaultClientConnectionOperator
+org.apache.http.impl.conn.DefaultHttpRoutePlanner
+org.apache.http.impl.conn.DefaultResponseParser
+org.apache.http.impl.conn.IdleConnectionHandler
+org.apache.http.impl.conn.IdleConnectionHandler$TimeValues
+org.apache.http.impl.conn.tsccm.AbstractConnPool
+org.apache.http.impl.conn.tsccm.BasicPoolEntry
+org.apache.http.impl.conn.tsccm.BasicPoolEntryRef
+org.apache.http.impl.conn.tsccm.BasicPooledConnAdapter
 org.apache.http.impl.conn.tsccm.ConnPoolByRoute
+org.apache.http.impl.conn.tsccm.ConnPoolByRoute$1
+org.apache.http.impl.conn.tsccm.PoolEntryRequest
+org.apache.http.impl.conn.tsccm.RefQueueHandler
+org.apache.http.impl.conn.tsccm.RefQueueWorker
+org.apache.http.impl.conn.tsccm.RouteSpecificPool
 org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager
-org.apache.http.impl.cookie.BasicClientCookie
-org.apache.http.impl.cookie.BrowserCompatSpec
-org.apache.http.impl.cookie.DateUtils
-org.apache.http.impl.cookie.DateUtils$DateFormatHolder
-org.apache.http.impl.cookie.RFC2109Spec
+org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager$1
+org.apache.http.impl.conn.tsccm.WaitingThreadAborter
+org.apache.http.impl.cookie.BestMatchSpecFactory
+org.apache.http.impl.cookie.BrowserCompatSpecFactory
+org.apache.http.impl.cookie.NetscapeDraftSpecFactory
+org.apache.http.impl.cookie.RFC2109SpecFactory
+org.apache.http.impl.cookie.RFC2965SpecFactory
+org.apache.http.impl.entity.EntityDeserializer
+org.apache.http.impl.entity.EntitySerializer
+org.apache.http.impl.entity.LaxContentLengthStrategy
+org.apache.http.impl.entity.StrictContentLengthStrategy
+org.apache.http.impl.io.AbstractMessageParser
+org.apache.http.impl.io.AbstractMessageWriter
+org.apache.http.impl.io.AbstractSessionInputBuffer
+org.apache.http.impl.io.AbstractSessionOutputBuffer
+org.apache.http.impl.io.ContentLengthInputStream
+org.apache.http.impl.io.ContentLengthOutputStream
+org.apache.http.impl.io.HttpRequestWriter
+org.apache.http.impl.io.HttpTransportMetricsImpl
 org.apache.http.impl.io.SocketInputBuffer
-org.apache.http.message.BasicHttpEntityEnclosingRequest
-org.apache.http.message.BasicHttpRequest
+org.apache.http.impl.io.SocketOutputBuffer
+org.apache.http.io.HttpMessageParser
+org.apache.http.io.HttpMessageWriter
+org.apache.http.io.HttpTransportMetrics
+org.apache.http.io.SessionInputBuffer
+org.apache.http.io.SessionOutputBuffer
+org.apache.http.message.AbstractHttpMessage
+org.apache.http.message.BasicHeader
+org.apache.http.message.BasicHeaderElement
+org.apache.http.message.BasicHeaderElementIterator
+org.apache.http.message.BasicHeaderValueParser
 org.apache.http.message.BasicHttpResponse
+org.apache.http.message.BasicLineFormatter
 org.apache.http.message.BasicLineParser
+org.apache.http.message.BasicListHeaderIterator
 org.apache.http.message.BasicNameValuePair
-org.apache.http.message.BasicTokenIterator
+org.apache.http.message.BasicRequestLine
+org.apache.http.message.BasicStatusLine
+org.apache.http.message.BufferedHeader
+org.apache.http.message.HeaderGroup
+org.apache.http.message.HeaderValueParser
+org.apache.http.message.LineFormatter
+org.apache.http.message.LineParser
+org.apache.http.message.ParserCursor
+org.apache.http.params.AbstractHttpParams
 org.apache.http.params.BasicHttpParams
+org.apache.http.params.CoreConnectionPNames
+org.apache.http.params.CoreProtocolPNames
+org.apache.http.params.HttpConnectionParams
+org.apache.http.params.HttpParams
+org.apache.http.params.HttpProtocolParams
+org.apache.http.protocol.BasicHttpContext
 org.apache.http.protocol.BasicHttpProcessor
 org.apache.http.protocol.HTTP
+org.apache.http.protocol.HttpContext
+org.apache.http.protocol.HttpProcessor
+org.apache.http.protocol.HttpRequestExecutor
+org.apache.http.protocol.HttpRequestInterceptorList
+org.apache.http.protocol.HttpResponseInterceptorList
+org.apache.http.protocol.RequestConnControl
+org.apache.http.protocol.RequestContent
+org.apache.http.protocol.RequestExpectContinue
+org.apache.http.protocol.RequestTargetHost
+org.apache.http.protocol.RequestUserAgent
+org.apache.http.util.ByteArrayBuffer
+org.apache.http.util.CharArrayBuffer
+org.apache.http.util.LangUtils
+org.bouncycastle.asn1.ASN1Choice
+org.bouncycastle.asn1.ASN1Collection
+org.bouncycastle.asn1.ASN1Collection$ASN1CollectionEnumeration
+org.bouncycastle.asn1.ASN1Encodable
+org.bouncycastle.asn1.ASN1EncodableVector
+org.bouncycastle.asn1.ASN1InputStream
+org.bouncycastle.asn1.ASN1Null
+org.bouncycastle.asn1.ASN1Object
+org.bouncycastle.asn1.ASN1OctetString
+org.bouncycastle.asn1.ASN1OctetStringParser
+org.bouncycastle.asn1.ASN1OutputStream
+org.bouncycastle.asn1.ASN1Sequence
+org.bouncycastle.asn1.ASN1SequenceParser
+org.bouncycastle.asn1.ASN1Set
+org.bouncycastle.asn1.ASN1StreamParser
+org.bouncycastle.asn1.ASN1TaggedObject
+org.bouncycastle.asn1.ASN1TaggedObjectParser
+org.bouncycastle.asn1.BERTaggedObjectParser
+org.bouncycastle.asn1.DERBitString
+org.bouncycastle.asn1.DERBoolean
+org.bouncycastle.asn1.DEREncodable
+org.bouncycastle.asn1.DEREncodableVector
+org.bouncycastle.asn1.DERFactory
+org.bouncycastle.asn1.DERIA5String
+org.bouncycastle.asn1.DERInteger
 org.bouncycastle.asn1.DERNull
 org.bouncycastle.asn1.DERObject
 org.bouncycastle.asn1.DERObjectIdentifier
+org.bouncycastle.asn1.DEROctetString
+org.bouncycastle.asn1.DEROctetStringParser
+org.bouncycastle.asn1.DEROutputStream
+org.bouncycastle.asn1.DERPrintableString
+org.bouncycastle.asn1.DERSequence
+org.bouncycastle.asn1.DERSequenceParser
+org.bouncycastle.asn1.DERSet
+org.bouncycastle.asn1.DERString
+org.bouncycastle.asn1.DERT61String
+org.bouncycastle.asn1.DERTaggedObject
+org.bouncycastle.asn1.DERTags
+org.bouncycastle.asn1.DERUTCTime
+org.bouncycastle.asn1.DERUTF8String
+org.bouncycastle.asn1.DERUniversalString
+org.bouncycastle.asn1.DefiniteLengthInputStream
+org.bouncycastle.asn1.IndefiniteLengthInputStream
+org.bouncycastle.asn1.LimitedInputStream
+org.bouncycastle.asn1.OIDTokenizer
+org.bouncycastle.asn1.OrderedTable
+org.bouncycastle.asn1.bc.BCObjectIdentifiers
 org.bouncycastle.asn1.iana.IANAObjectIdentifiers
 org.bouncycastle.asn1.nist.NISTObjectIdentifiers
 org.bouncycastle.asn1.oiw.OIWObjectIdentifiers
 org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers
+org.bouncycastle.asn1.x509.AlgorithmIdentifier
+org.bouncycastle.asn1.x509.BasicConstraints
+org.bouncycastle.asn1.x509.SubjectPublicKeyInfo
+org.bouncycastle.asn1.x509.TBSCertificateStructure
+org.bouncycastle.asn1.x509.Time
+org.bouncycastle.asn1.x509.X509CertificateStructure
+org.bouncycastle.asn1.x509.X509Extension
 org.bouncycastle.asn1.x509.X509Extensions
 org.bouncycastle.asn1.x509.X509Name
-org.bouncycastle.crypto.digests.SHA1Digest
+org.bouncycastle.asn1.x509.X509NameElementList
+org.bouncycastle.asn1.x509.X509ObjectIdentifiers
+org.bouncycastle.crypto.Digest
+org.bouncycastle.crypto.ExtendedDigest
+org.bouncycastle.crypto.Mac
+org.bouncycastle.crypto.digests.OpenSSLDigest
+org.bouncycastle.crypto.digests.OpenSSLDigest$SHA1
 org.bouncycastle.crypto.engines.AESFastEngine
 org.bouncycastle.crypto.macs.HMac
+org.bouncycastle.jce.ProviderConfigurationPermission
+org.bouncycastle.jce.interfaces.BCKeyStore
+org.bouncycastle.jce.interfaces.ConfigurableProvider
+org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier
 org.bouncycastle.jce.provider.BouncyCastleProvider
-org.bouncycastle.jce.provider.CertPathValidatorUtilities
-org.bouncycastle.jce.provider.JCEBlockCipher
+org.bouncycastle.jce.provider.BouncyCastleProvider$1
 org.bouncycastle.jce.provider.JDKKeyStore
+org.bouncycastle.jce.provider.JDKKeyStore$StoreEntry
 org.bouncycastle.jce.provider.JDKX509CertificateFactory
+org.bouncycastle.jce.provider.PEMUtil
+org.bouncycastle.jce.provider.PKCS12BagAttributeCarrierImpl
 org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi
-org.bouncycastle.jce.provider.WrapCipherSpi
+org.bouncycastle.jce.provider.ProviderUtil
 org.bouncycastle.jce.provider.X509CertificateObject
-org.ccil.cowan.tagsoup.HTMLScanner
-org.ccil.cowan.tagsoup.HTMLSchema
+org.bouncycastle.jce.provider.symmetric.AESMappings
+org.bouncycastle.util.Strings
+org.bouncycastle.util.io.Streams
 org.ccil.cowan.tagsoup.Parser
-org.json.JSONObject
-org.kxml2.io.KXmlParser
-org.kxml2.io.KXmlSerializer
 org.xml.sax.Attributes
-org.xml.sax.InputSource
-org.xml.sax.helpers.AttributesImpl
-org.xml.sax.helpers.DefaultHandler
+org.xml.sax.ContentHandler
+org.xml.sax.Locator
+org.xml.sax.XMLReader
 org.xmlpull.v1.XmlPullParser
-org.xmlpull.v1.XmlPullParserFactory
+org.xmlpull.v1.XmlSerializer
 sun.misc.Unsafe
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 775f5c8..8cf8f6a 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -17,7 +17,6 @@
 package com.android.server;
 
 import com.android.internal.app.IMediaContainerService;
-import com.android.internal.util.HexDump;
 import com.android.server.am.ActivityManagerService;
 
 import android.content.BroadcastReceiver;
@@ -46,13 +45,15 @@
 import android.os.storage.IObbActionListener;
 import android.os.storage.OnObbStateChangeListener;
 import android.os.storage.StorageResultCode;
-import android.security.MessageDigest;
 import android.util.Slog;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.math.BigInteger;
 import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -62,6 +63,10 @@
 import java.util.Map;
 import java.util.Map.Entry;
 
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+
 /**
  * MountService implements back-end services for platform storage
  * management.
@@ -154,6 +159,18 @@
     final private HashSet<String> mAsecMountSet = new HashSet<String>();
 
     /**
+     * The size of the crypto algorithm key in bits for OBB files. Currently
+     * Twofish is used which takes 128-bit keys.
+     */
+    private static final int CRYPTO_ALGORITHM_KEY_SIZE = 128;
+
+    /**
+     * The number of times to run SHA1 in the PBKDF2 function for OBB files.
+     * 1024 is reasonably secure and not too slow.
+     */
+    private static final int PBKDF2_HASH_ROUNDS = 1024;
+
+    /**
      * Mounted OBB tracking information. Used to track the current state of all
      * OBBs.
      */
@@ -1901,16 +1918,23 @@
             if (mKey == null) {
                 hashedKey = "none";
             } else {
-                final MessageDigest md;
                 try {
-                    md = MessageDigest.getInstance("MD5");
+                    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
+
+                    KeySpec ks = new PBEKeySpec(mKey.toCharArray(), obbInfo.salt,
+                            PBKDF2_HASH_ROUNDS, CRYPTO_ALGORITHM_KEY_SIZE);
+                    SecretKey key = factory.generateSecret(ks);
+                    BigInteger bi = new BigInteger(key.getEncoded());
+                    hashedKey = bi.toString(16);
                 } catch (NoSuchAlgorithmException e) {
-                    Slog.e(TAG, "Could not load MD5 algorithm", e);
-                    sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
+                    Slog.e(TAG, "Could not load PBKDF2 algorithm", e);
+                    sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
+                    return;
+                } catch (InvalidKeySpecException e) {
+                    Slog.e(TAG, "Invalid key spec when loading PBKDF2 algorithm", e);
+                    sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
                     return;
                 }
-
-                hashedKey = HexDump.toHexString(md.digest(mKey.getBytes()));
             }
 
             int rc = StorageResultCode.OperationSucceeded;
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index bc802a8..9d7c58e 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -5156,9 +5156,6 @@
                     // we don't consider this to be a failure of the core package deletion
                 }
             }
-            if (libraryPath != null) {
-                NativeLibraryHelper.removeNativeBinariesLI(libraryPath);
-            }
         }
 
         private boolean setPermissions() {
@@ -7208,6 +7205,8 @@
                     pw.print("    pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
                             pw.print(" installStatus="); pw.print(ps.installStatus);
                             pw.print(" enabled="); pw.println(ps.enabled);
+                    pw.print("    versionCode="); pw.print(ps.versionCode);
+                            pw.print(" versionName="); pw.println(ps.pkg.mVersionName);
                     if (ps.disabledComponents.size() > 0) {
                         pw.println("    disabledComponents:");
                         for (String s : ps.disabledComponents) {
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 88a4c90..f53ce2d 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -141,9 +141,7 @@
     // used for noChangeLights in setPowerState()
     private static final int LIGHTS_MASK        = SCREEN_BRIGHT_BIT | BUTTON_BRIGHT_BIT | KEYBOARD_BRIGHT_BIT;
 
-    static final boolean ANIMATE_SCREEN_LIGHTS = true;
-    static final boolean ANIMATE_BUTTON_LIGHTS = false;
-    static final boolean ANIMATE_KEYBOARD_LIGHTS = false;
+    boolean mAnimateScreenLights = true;
 
     static final int ANIM_STEPS = 60/4;
     // Slower animation for autobrightness changes
@@ -201,15 +199,12 @@
     private UnsynchronizedWakeLock mPreventScreenOnPartialLock;
     private UnsynchronizedWakeLock mProximityPartialLock;
     private HandlerThread mHandlerThread;
+    private HandlerThread mScreenOffThread;
+    private Handler mScreenOffHandler;
     private Handler mHandler;
     private final TimeoutTask mTimeoutTask = new TimeoutTask();
-    private final LightAnimator mLightAnimator = new LightAnimator();
     private final BrightnessState mScreenBrightness
             = new BrightnessState(SCREEN_BRIGHT_BIT);
-    private final BrightnessState mKeyboardBrightness
-            = new BrightnessState(KEYBOARD_BRIGHT_BIT);
-    private final BrightnessState mButtonBrightness
-            = new BrightnessState(BUTTON_BRIGHT_BIT);
     private boolean mStillNeedSleepNotification;
     private boolean mIsPowered = false;
     private IActivityManager mActivityService;
@@ -261,6 +256,7 @@
     
     private native void nativeInit();
     private native void nativeSetPowerState(boolean screenOn, boolean screenBright);
+    private native void nativeStartSurfaceFlingerAnimation();
 
     /*
     static PrintStream mLog;
@@ -485,6 +481,35 @@
         mKeyboardLight = lights.getLight(LightsService.LIGHT_ID_KEYBOARD);
         mAttentionLight = lights.getLight(LightsService.LIGHT_ID_ATTENTION);
 
+        nativeInit();
+        synchronized (mLocks) {
+            updateNativePowerStateLocked();
+        }
+
+        mInitComplete = false;
+        mScreenOffThread = new HandlerThread("PowerManagerService.mScreenOffThread") {
+            @Override
+            protected void onLooperPrepared() {
+                mScreenOffHandler = new Handler();
+                synchronized (mScreenOffThread) {
+                    mInitComplete = true;
+                    mScreenOffThread.notifyAll();
+                }
+            }
+        };
+        mScreenOffThread.start();
+
+        synchronized (mScreenOffThread) {
+            while (!mInitComplete) {
+                try {
+                    mScreenOffThread.wait();
+                } catch (InterruptedException e) {
+                    // Ignore
+                }
+            }
+        }
+        
+        mInitComplete = false;
         mHandlerThread = new HandlerThread("PowerManagerService") {
             @Override
             protected void onLooperPrepared() {
@@ -531,6 +556,9 @@
 
         Resources resources = mContext.getResources();
 
+        mAnimateScreenLights = resources.getBoolean(
+                com.android.internal.R.bool.config_animateScreenLights);
+
         mUnplugTurnsOnScreen = resources.getBoolean(
                 com.android.internal.R.bool.config_unplugTurnsOnScreen);
 
@@ -1093,8 +1121,6 @@
             pw.println("  mUseSoftwareAutoBrightness=" + mUseSoftwareAutoBrightness);
             pw.println("  mAutoBrightessEnabled=" + mAutoBrightessEnabled);
             mScreenBrightness.dump(pw, "  mScreenBrightness: ");
-            mKeyboardBrightness.dump(pw, "  mKeyboardBrightness: ");
-            mButtonBrightness.dump(pw, "  mButtonBrightness: ");
 
             int N = mLocks.size();
             pw.println();
@@ -1724,7 +1750,8 @@
         // I don't think we need to check the current state here because all of these
         // Power.setScreenState and sendNotificationLocked can both handle being
         // called multiple times in the same state. -joeo
-        EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, reason, mTotalTouchDownTime, mTouchCycles);
+        EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, reason, mTotalTouchDownTime,
+                mTouchCycles);
         mLastTouchDown = 0;
         int err = setScreenStateLocked(false);
         if (err == 0) {
@@ -1754,145 +1781,95 @@
         int onMask = 0;
 
         int preferredBrightness = getPreferredBrightness();
-        boolean startAnimation = false;
 
         if ((difference & KEYBOARD_BRIGHT_BIT) != 0) {
-            if (ANIMATE_KEYBOARD_LIGHTS) {
-                if ((newState & KEYBOARD_BRIGHT_BIT) == 0) {
-                    mKeyboardBrightness.setTargetLocked(Power.BRIGHTNESS_OFF,
-                            ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS,
-                            Power.BRIGHTNESS_ON);
-                } else {
-                    mKeyboardBrightness.setTargetLocked(Power.BRIGHTNESS_ON,
-                            ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS,
-                            Power.BRIGHTNESS_OFF);
-                }
-                startAnimation = true;
+            if ((newState & KEYBOARD_BRIGHT_BIT) == 0) {
+                offMask |= KEYBOARD_BRIGHT_BIT;
             } else {
-                if ((newState & KEYBOARD_BRIGHT_BIT) == 0) {
-                    offMask |= KEYBOARD_BRIGHT_BIT;
-                } else {
-                    onMask |= KEYBOARD_BRIGHT_BIT;
-                }
+                onMask |= KEYBOARD_BRIGHT_BIT;
             }
         }
 
         if ((difference & BUTTON_BRIGHT_BIT) != 0) {
-            if (ANIMATE_BUTTON_LIGHTS) {
-                if ((newState & BUTTON_BRIGHT_BIT) == 0) {
-                    mButtonBrightness.setTargetLocked(Power.BRIGHTNESS_OFF,
-                            ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS,
-                            Power.BRIGHTNESS_ON);
-                } else {
-                    mButtonBrightness.setTargetLocked(Power.BRIGHTNESS_ON,
-                            ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS,
-                            Power.BRIGHTNESS_OFF);
-                }
-                startAnimation = true;
+            if ((newState & BUTTON_BRIGHT_BIT) == 0) {
+                offMask |= BUTTON_BRIGHT_BIT;
             } else {
-                if ((newState & BUTTON_BRIGHT_BIT) == 0) {
-                    offMask |= BUTTON_BRIGHT_BIT;
-                } else {
-                    onMask |= BUTTON_BRIGHT_BIT;
-                }
+                onMask |= BUTTON_BRIGHT_BIT;
             }
         }
 
         if ((difference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {
-            if (ANIMATE_SCREEN_LIGHTS) {
-                int nominalCurrentValue = -1;
-                // If there was an actual difference in the light state, then
-                // figure out the "ideal" current value based on the previous
-                // state.  Otherwise, this is a change due to the brightness
-                // override, so we want to animate from whatever the current
-                // value is.
-                if ((realDifference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {
-                    switch (oldState & (SCREEN_BRIGHT_BIT|SCREEN_ON_BIT)) {
-                        case SCREEN_BRIGHT_BIT | SCREEN_ON_BIT:
-                            nominalCurrentValue = preferredBrightness;
-                            break;
-                        case SCREEN_ON_BIT:
-                            nominalCurrentValue = Power.BRIGHTNESS_DIM;
-                            break;
-                        case 0:
-                            nominalCurrentValue = Power.BRIGHTNESS_OFF;
-                            break;
-                        case SCREEN_BRIGHT_BIT:
-                        default:
-                            // not possible
-                            nominalCurrentValue = (int)mScreenBrightness.curValue;
-                            break;
-                    }
+            int nominalCurrentValue = -1;
+            // If there was an actual difference in the light state, then
+            // figure out the "ideal" current value based on the previous
+            // state.  Otherwise, this is a change due to the brightness
+            // override, so we want to animate from whatever the current
+            // value is.
+            if ((realDifference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {
+                switch (oldState & (SCREEN_BRIGHT_BIT|SCREEN_ON_BIT)) {
+                    case SCREEN_BRIGHT_BIT | SCREEN_ON_BIT:
+                        nominalCurrentValue = preferredBrightness;
+                        break;
+                    case SCREEN_ON_BIT:
+                        nominalCurrentValue = Power.BRIGHTNESS_DIM;
+                        break;
+                    case 0:
+                        nominalCurrentValue = Power.BRIGHTNESS_OFF;
+                        break;
+                    case SCREEN_BRIGHT_BIT:
+                    default:
+                        // not possible
+                        nominalCurrentValue = (int)mScreenBrightness.curValue;
+                        break;
                 }
-                int brightness = preferredBrightness;
-                int steps = ANIM_STEPS;
-                if ((newState & SCREEN_BRIGHT_BIT) == 0) {
-                    // dim or turn off backlight, depending on if the screen is on
-                    // the scale is because the brightness ramp isn't linear and this biases
-                    // it so the later parts take longer.
-                    final float scale = 1.5f;
-                    float ratio = (((float)Power.BRIGHTNESS_DIM)/preferredBrightness);
-                    if (ratio > 1.0f) ratio = 1.0f;
-                    if ((newState & SCREEN_ON_BIT) == 0) {
-                        if ((oldState & SCREEN_BRIGHT_BIT) != 0) {
-                            // was bright
-                            steps = ANIM_STEPS;
-                        } else {
-                            // was dim
-                            steps = (int)(ANIM_STEPS*ratio*scale);
-                        }
-                        brightness = Power.BRIGHTNESS_OFF;
+            }
+            int brightness = preferredBrightness;
+            int steps = ANIM_STEPS;
+            if ((newState & SCREEN_BRIGHT_BIT) == 0) {
+                // dim or turn off backlight, depending on if the screen is on
+                // the scale is because the brightness ramp isn't linear and this biases
+                // it so the later parts take longer.
+                final float scale = 1.5f;
+                float ratio = (((float)Power.BRIGHTNESS_DIM)/preferredBrightness);
+                if (ratio > 1.0f) ratio = 1.0f;
+                if ((newState & SCREEN_ON_BIT) == 0) {
+                    if ((oldState & SCREEN_BRIGHT_BIT) != 0) {
+                        // was bright
+                        steps = ANIM_STEPS;
                     } else {
-                        if ((oldState & SCREEN_ON_BIT) != 0) {
-                            // was bright
-                            steps = (int)(ANIM_STEPS*(1.0f-ratio)*scale);
-                        } else {
-                            // was dim
-                            steps = (int)(ANIM_STEPS*ratio);
-                        }
-                        if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) {
-                            // If the "stay on while plugged in" option is
-                            // turned on, then the screen will often not
-                            // automatically turn off while plugged in.  To
-                            // still have a sense of when it is inactive, we
-                            // will then count going dim as turning off.
-                            mScreenOffTime = SystemClock.elapsedRealtime();
-                        }
-                        brightness = Power.BRIGHTNESS_DIM;
+                        // was dim
+                        steps = (int)(ANIM_STEPS*ratio*scale);
                     }
-                }
-                long identity = Binder.clearCallingIdentity();
-                try {
-                    mBatteryStats.noteScreenBrightness(brightness);
-                } catch (RemoteException e) {
-                    // Nothing interesting to do.
-                } finally {
-                    Binder.restoreCallingIdentity(identity);
-                }
-                if (mScreenBrightness.setTargetLocked(brightness,
-                        steps, INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue)) {
-                    startAnimation = true;
-                }
-            } else {
-                if ((newState & SCREEN_BRIGHT_BIT) == 0) {
-                    // dim or turn off backlight, depending on if the screen is on
-                    if ((newState & SCREEN_ON_BIT) == 0) {
-                        offMask |= SCREEN_BRIGHT_BIT;
-                    } else {
-                        dimMask |= SCREEN_BRIGHT_BIT;
-                    }
+                    brightness = Power.BRIGHTNESS_OFF;
                 } else {
-                    onMask |= SCREEN_BRIGHT_BIT;
+                    if ((oldState & SCREEN_ON_BIT) != 0) {
+                        // was bright
+                        steps = (int)(ANIM_STEPS*(1.0f-ratio)*scale);
+                    } else {
+                        // was dim
+                        steps = (int)(ANIM_STEPS*ratio);
+                    }
+                    if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) {
+                        // If the "stay on while plugged in" option is
+                        // turned on, then the screen will often not
+                        // automatically turn off while plugged in.  To
+                        // still have a sense of when it is inactive, we
+                        // will then count going dim as turning off.
+                        mScreenOffTime = SystemClock.elapsedRealtime();
+                    }
+                    brightness = Power.BRIGHTNESS_DIM;
                 }
             }
-        }
-
-        if (startAnimation) {
-            if (mSpew) {
-                Slog.i(TAG, "Scheduling light animator!");
+            long identity = Binder.clearCallingIdentity();
+            try {
+                mBatteryStats.noteScreenBrightness(brightness);
+            } catch (RemoteException e) {
+                // Nothing interesting to do.
+            } finally {
+                Binder.restoreCallingIdentity(identity);
             }
-            mHandler.removeCallbacks(mLightAnimator);
-            mHandler.post(mLightAnimator);
+            mScreenBrightness.setTargetLocked(brightness, steps,
+                    INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue);
         }
 
         if (offMask != 0) {
@@ -1934,7 +1911,7 @@
         }
     }
 
-    class BrightnessState {
+    class BrightnessState implements Runnable {
         final int mask;
 
         boolean initialized;
@@ -1954,13 +1931,13 @@
                     + " delta=" + delta);
         }
 
-        boolean setTargetLocked(int target, int stepsToTarget, int initialValue,
+        void setTargetLocked(int target, int stepsToTarget, int initialValue,
                 int nominalCurrentValue) {
             if (!initialized) {
                 initialized = true;
                 curValue = (float)initialValue;
             } else if (targetValue == target) {
-                return false;
+                return;
             }
             targetValue = target;
             delta = (targetValue -
@@ -1974,7 +1951,12 @@
                         + noticeMe);
             }
             animating = true;
-            return true;
+
+            if (mSpew) {
+                Slog.i(TAG, "scheduling light animator");
+            }
+            mScreenOffHandler.removeCallbacks(this);
+            mScreenOffHandler.post(this);
         }
 
         boolean stepLocked() {
@@ -2000,32 +1982,50 @@
                     more = false;
                 }
             }
-            //Slog.i(TAG, "Animating brightess " + curIntValue + ": " + mask);
+            if (mSpew) Slog.d(TAG, "Animating curIntValue=" + curIntValue + ": " + mask);
             setLightBrightness(mask, curIntValue);
+            finishAnimation(more, curIntValue);
+            return more;
+        }
+
+        void jumpToTarget() {
+            if (mSpew) Slog.d(TAG, "jumpToTarget targetValue=" + targetValue + ": " + mask);
+            setLightBrightness(mask, targetValue);
+            final int tv = targetValue;
+            curValue = tv;
+            targetValue = -1;
+            finishAnimation(false, tv);
+        }
+
+        private void finishAnimation(boolean more, int curIntValue) {
             animating = more;
             if (!more) {
                 if (mask == SCREEN_BRIGHT_BIT && curIntValue == Power.BRIGHTNESS_OFF) {
                     screenOffFinishedAnimatingLocked(mScreenOffReason);
                 }
             }
-            return more;
         }
-    }
 
-    private class LightAnimator implements Runnable {
         public void run() {
-            synchronized (mLocks) {
-                long now = SystemClock.uptimeMillis();
-                boolean more = mScreenBrightness.stepLocked();
-                if (mKeyboardBrightness.stepLocked()) {
-                    more = true;
+            if (mAnimateScreenLights) {
+                synchronized (mLocks) {
+                    long now = SystemClock.uptimeMillis();
+                    boolean more = mScreenBrightness.stepLocked();
+                    if (more) {
+                        mScreenOffHandler.postAtTime(this, now+(1000/60));
+                    }
                 }
-                if (mButtonBrightness.stepLocked()) {
-                    more = true;
+            } else {
+                boolean animate;
+                boolean jump;
+                synchronized (mLocks) {
+                    jump = animating; // we haven't already run this animation
+                    animate = jump && targetValue == Power.BRIGHTNESS_OFF; // we're turning off
                 }
-                if (more) {
-                    mHandler.postAtTime(mLightAnimator, now+(1000/60));
+                if (animate) {
+                    nativeStartSurfaceFlingerAnimation();
                 }
+                mScreenBrightness.jumpToTarget();
             }
         }
     }
@@ -2343,49 +2343,15 @@
                     Slog.d(TAG, "keyboardValue " + keyboardValue);
                 }
 
-                boolean startAnimation = false;
                 if (mAutoBrightessEnabled && mScreenBrightnessOverride < 0) {
-                    if (ANIMATE_SCREEN_LIGHTS) {
-                        if (mScreenBrightness.setTargetLocked(lcdValue,
-                                AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_SCREEN_BRIGHTNESS,
-                                (int)mScreenBrightness.curValue)) {
-                            startAnimation = true;
-                        }
-                    } else {
-                        int brightnessMode = (mAutoBrightessEnabled
-                                            ? LightsService.BRIGHTNESS_MODE_SENSOR
-                                            : LightsService.BRIGHTNESS_MODE_USER);
-                        mLcdLight.setBrightness(lcdValue, brightnessMode);
-                    }
+                    mScreenBrightness.setTargetLocked(lcdValue, AUTOBRIGHTNESS_ANIM_STEPS,
+                            INITIAL_SCREEN_BRIGHTNESS, (int)mScreenBrightness.curValue);
                 }
                 if (mButtonBrightnessOverride < 0) {
-                    if (ANIMATE_BUTTON_LIGHTS) {
-                        if (mButtonBrightness.setTargetLocked(buttonValue,
-                                AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS,
-                                (int)mButtonBrightness.curValue)) {
-                            startAnimation = true;
-                        }
-                    } else {
-                         mButtonLight.setBrightness(buttonValue);
-                    }
+                    mButtonLight.setBrightness(buttonValue);
                 }
                 if (mButtonBrightnessOverride < 0 || !mKeyboardVisible) {
-                    if (ANIMATE_KEYBOARD_LIGHTS) {
-                        if (mKeyboardBrightness.setTargetLocked(keyboardValue,
-                                AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS,
-                                (int)mKeyboardBrightness.curValue)) {
-                            startAnimation = true;
-                        }
-                    } else {
-                        mKeyboardLight.setBrightness(keyboardValue);
-                    }
-                }
-                if (startAnimation) {
-                    if (mDebugLightSensor) {
-                        Slog.i(TAG, "lightSensorChangedLocked scheduling light animator");
-                    }
-                    mHandler.removeCallbacks(mLightAnimator);
-                    mHandler.post(mLightAnimator);
+                    mKeyboardLight.setBrightness(keyboardValue);
                 }
             }
         }
@@ -2753,6 +2719,7 @@
         }
     }
 
+    // for watchdog
     public void monitor() {
         synchronized (mLocks) { }
     }
@@ -2772,34 +2739,23 @@
     public void setBacklightBrightness(int brightness) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
         // Don't let applications turn the screen all the way off
-        brightness = Math.max(brightness, Power.BRIGHTNESS_DIM);
-        mLcdLight.setBrightness(brightness);
-        mKeyboardLight.setBrightness(mKeyboardVisible ? brightness : 0);
-        mButtonLight.setBrightness(brightness);
-        long identity = Binder.clearCallingIdentity();
-        try {
-            mBatteryStats.noteScreenBrightness(brightness);
-        } catch (RemoteException e) {
-            Slog.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e);
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
+        synchronized (mLocks) {
+            brightness = Math.max(brightness, Power.BRIGHTNESS_DIM);
+            mLcdLight.setBrightness(brightness);
+            mKeyboardLight.setBrightness(mKeyboardVisible ? brightness : 0);
+            mButtonLight.setBrightness(brightness);
+            long identity = Binder.clearCallingIdentity();
+            try {
+                mBatteryStats.noteScreenBrightness(brightness);
+            } catch (RemoteException e) {
+                Slog.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e);
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
 
-        // update our animation state
-        if (ANIMATE_SCREEN_LIGHTS) {
-            mScreenBrightness.curValue = brightness;
-            mScreenBrightness.animating = false;
-            mScreenBrightness.targetValue = -1;
-        }
-        if (ANIMATE_KEYBOARD_LIGHTS) {
-            mKeyboardBrightness.curValue = brightness;
-            mKeyboardBrightness.animating = false;
-            mKeyboardBrightness.targetValue = -1;
-        }
-        if (ANIMATE_BUTTON_LIGHTS) {
-            mButtonBrightness.curValue = brightness;
-            mButtonBrightness.animating = false;
-            mButtonBrightness.targetValue = -1;
+            // update our animation state
+            mScreenBrightness.targetValue = brightness;
+            mScreenBrightness.jumpToTarget();
         }
     }
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 26071ae..a2a5e67 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import com.android.server.am.ActivityManagerService;
+import com.android.internal.app.ShutdownThread;
 import com.android.internal.os.BinderInternal;
 import com.android.internal.os.SamplingProfilerIntegration;
 import com.trustedlogic.trustednfc.android.server.NfcService;
@@ -89,6 +90,24 @@
         BinderInternal.disableBackgroundScheduling(true);
         android.os.Process.setCanSelfBackground(false);
 
+        // Check whether we failed to shut down last time we tried.
+        {
+            final String shutdownAction = SystemProperties.get(
+                    ShutdownThread.SHUTDOWN_ACTION_PROPERTY, "");
+            if (shutdownAction != null && shutdownAction.length() > 0) {
+                boolean reboot = (shutdownAction.charAt(0) == '1');
+
+                final String reason;
+                if (shutdownAction.length() > 1) {
+                    reason = shutdownAction.substring(1, shutdownAction.length());
+                } else {
+                    reason = null;
+                }
+
+                ShutdownThread.rebootOrShutdown(reboot, reason);
+            }
+        }
+
         String factoryTestStr = SystemProperties.get("ro.factorytest");
         int factoryTest = "".equals(factoryTestStr) ? SystemServer.FACTORY_TEST_OFF
                 : Integer.parseInt(factoryTestStr);
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 016ddcd..86c7bdf 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -2535,7 +2535,7 @@
                     mWaitingActivityLaunched.add(outResult);
                     do {
                         try {
-                            wait();
+                            mService.wait();
                         } catch (InterruptedException e) {
                         }
                     } while (!outResult.timeout && outResult.who == null);
@@ -2551,7 +2551,7 @@
                         mWaitingActivityVisible.add(outResult);
                         do {
                             try {
-                                wait();
+                                mService.wait();
                             } catch (InterruptedException e) {
                             }
                         } while (!outResult.timeout && outResult.who == null);
diff --git a/services/java/com/trustedlogic/trustednfc/android/server/NfcService.java b/services/java/com/trustedlogic/trustednfc/android/server/NfcService.java
index 431b798..bddbafc 100644
--- a/services/java/com/trustedlogic/trustednfc/android/server/NfcService.java
+++ b/services/java/com/trustedlogic/trustednfc/android/server/NfcService.java
@@ -17,44 +17,43 @@
 package com.trustedlogic.trustednfc.android.server;
 
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.ListIterator;
-import java.util.Set;
 
-import com.trustedlogic.trustednfc.android.ILlcpConnectionlessSocket;
-import com.trustedlogic.trustednfc.android.ILlcpServiceSocket;
-import com.trustedlogic.trustednfc.android.INfcManager;
-import com.trustedlogic.trustednfc.android.ILlcpSocket;
-import com.trustedlogic.trustednfc.android.INfcTag;
-import com.trustedlogic.trustednfc.android.IP2pInitiator;
-import com.trustedlogic.trustednfc.android.IP2pTarget;
-import com.trustedlogic.trustednfc.android.LlcpPacket;
-import com.trustedlogic.trustednfc.android.NdefMessage;
-import com.trustedlogic.trustednfc.android.NfcException;
-import com.trustedlogic.trustednfc.android.NfcManager;
+import android.nfc.ErrorCodes;
+import android.nfc.FormatException;
+import android.nfc.ILlcpConnectionlessSocket;
+import android.nfc.ILlcpServiceSocket;
+import android.nfc.INfcAdapter;
+import android.nfc.ILlcpSocket;
+import android.nfc.INfcTag;
+import android.nfc.IP2pInitiator;
+import android.nfc.IP2pTarget;
+import android.nfc.LlcpPacket;
+import android.nfc.NdefMessage;
+import android.nfc.Tag;
+//import android.nfc.NfcException;
+//import android.nfc.NfcManager;
+import android.nfc.NfcAdapter;
 import com.trustedlogic.trustednfc.android.internal.NativeLlcpConnectionlessSocket;
 import com.trustedlogic.trustednfc.android.internal.NativeLlcpServiceSocket;
 import com.trustedlogic.trustednfc.android.internal.NativeLlcpSocket;
 import com.trustedlogic.trustednfc.android.internal.NativeNfcManager;
 import com.trustedlogic.trustednfc.android.internal.NativeNfcTag;
 import com.trustedlogic.trustednfc.android.internal.NativeP2pDevice;
-import com.trustedlogic.trustednfc.android.internal.ErrorCodes;
-
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.os.Process;
 import android.os.RemoteException;
 import android.provider.Settings;
-import android.provider.Settings.SettingNotFoundException;
 import android.util.Log;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 
-public class NfcService extends INfcManager.Stub implements Runnable {
+public class NfcService extends INfcAdapter.Stub implements Runnable {
 
     /**
      * NFC Service tag
@@ -188,15 +187,15 @@
 
     private static final String PROPERTY_NFC_DISCOVERY_NFCIP_VALUE = "discovery.nfcip";
 
-    private Context mContext;
+    private final Context mContext;
 
-    private HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
+    private final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
 
-    private HashMap<Integer, Object> mSocketMap = new HashMap<Integer, Object>();
+    private final HashMap<Integer, Object> mSocketMap = new HashMap<Integer, Object>();
 
-    private LinkedList<RegisteredSocket> mRegisteredSocketList = new LinkedList<RegisteredSocket>();
+    private final LinkedList<RegisteredSocket> mRegisteredSocketList = new LinkedList<RegisteredSocket>();
 
-    private int mLlcpLinkState = NfcManager.LLCP_LINK_STATE_DEACTIVATED;
+    private int mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_DEACTIVATED;
 
     private int mGeneratedSocketHandle = 0;
 
@@ -216,9 +215,42 @@
 
     private boolean mOpenPending = false;
 
-    private NativeNfcManager mManager;
+    private final NativeNfcManager mManager;
 
-    private ILlcpSocket mLlcpSocket = new ILlcpSocket.Stub() {
+    private final ILlcpSocket mLlcpSocket = new ILlcpSocket.Stub() {
+
+        private final int CONNECT_FLAG = 0x01;
+        private final int CLOSE_FLAG   = 0x02;
+        private final int RECV_FLAG    = 0x04;
+        private final int SEND_FLAG    = 0x08;
+
+        private int concurrencyFlags;
+        private Object sync;
+
+        private void enterCritical(int mask, int current) {
+            int result = -1;
+            try {
+                while (result != 0) {
+                    synchronized(this) {
+                        result = concurrencyFlags & mask;
+                    }
+                    sync.wait();
+                }
+            }
+            catch(InterruptedException e) {
+            }
+            // Set flag
+            concurrencyFlags |= current;
+        }
+
+        private void leaveCritical(int current) {
+            synchronized(this) {
+                // Clear flag
+                concurrencyFlags &= ~current;
+            }
+            // Release waiting threads
+            sync.notifyAll();
+        }
 
         public int close(int nativeHandle) throws RemoteException {
             NativeLlcpSocket socket = null;
@@ -232,7 +264,7 @@
             /* find the socket in the hmap */
             socket = (NativeLlcpSocket) findSocket(nativeHandle);
             if (socket != null) {
-                if (mLlcpLinkState == NfcManager.LLCP_LINK_STATE_ACTIVATED) {
+                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
                     isSuccess = socket.doClose();
                     if (isSuccess) {
                         /* Remove the socket closed from the hmap */
@@ -476,7 +508,7 @@
 
     };
 
-    private ILlcpServiceSocket mLlcpServerSocketService = new ILlcpServiceSocket.Stub() {
+    private final ILlcpServiceSocket mLlcpServerSocketService = new ILlcpServiceSocket.Stub() {
 
         public int accept(int nativeHandle) throws RemoteException {
             NativeLlcpServiceSocket socket = null;
@@ -522,7 +554,7 @@
             /* find the socket in the hmap */
             socket = (NativeLlcpServiceSocket) findSocket(nativeHandle);
             if (socket != null) {
-                if (mLlcpLinkState == NfcManager.LLCP_LINK_STATE_ACTIVATED) {
+                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
                     isSuccess = socket.doClose();
                     if (isSuccess) {
                         /* Remove the socket closed from the hmap */
@@ -571,7 +603,7 @@
         }
     };
 
-    private ILlcpConnectionlessSocket mLlcpConnectionlessSocketService = new ILlcpConnectionlessSocket.Stub() {
+    private final ILlcpConnectionlessSocket mLlcpConnectionlessSocketService = new ILlcpConnectionlessSocket.Stub() {
 
         public void close(int nativeHandle) throws RemoteException {
             NativeLlcpConnectionlessSocket socket = null;
@@ -585,7 +617,7 @@
             /* find the socket in the hmap */
             socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
             if (socket != null) {
-                if (mLlcpLinkState == NfcManager.LLCP_LINK_STATE_ACTIVATED) {
+                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
                     isSuccess = socket.doClose();
                     if (isSuccess) {
                         /* Remove the socket closed from the hmap */
@@ -669,7 +701,7 @@
         }
     };
 
-    private INfcTag mNfcTagService = new INfcTag.Stub() {
+    private final INfcTag mNfcTagService = new INfcTag.Stub() {
 
         public int close(int nativeHandle) throws RemoteException {
             NativeNfcTag tag = null;
@@ -807,34 +839,55 @@
                 /* Create an NdefMessage */
                 try {
                     return new NdefMessage(buf);
-                } catch (NfcException e) {
+                } catch (FormatException e) {
                     return null;
                 }
             }
             return null;
         }
 
-        public boolean write(int nativeHandle, NdefMessage msg) throws RemoteException {
+        public int write(int nativeHandle, NdefMessage msg) throws RemoteException {
             NativeNfcTag tag;
-            boolean isSuccess = false;
 
             // Check if NFC is enabled
             if (!mIsNfcEnabled) {
-                return isSuccess;
+                return ErrorCodes.ERROR_NOT_INITIALIZED;
             }
 
             /* find the tag in the hmap */
             tag = (NativeNfcTag) findObject(nativeHandle);
-            if (tag != null) {
-                isSuccess = tag.doWrite(msg.toByteArray());
+            if (tag == null) {
+                return ErrorCodes.ERROR_IO;
             }
-            return isSuccess;
+
+            if (tag.doWrite(msg.toByteArray())) {
+                return ErrorCodes.SUCCESS;
+            }
+            else {
+                return ErrorCodes.ERROR_IO;
+            }
 
         }
 
+        public int getLastError(int nativeHandle) throws RemoteException {
+            // TODO Auto-generated method stub
+            return 0;
+        }
+
+        public int getModeHint(int nativeHandle) throws RemoteException {
+            // TODO Auto-generated method stub
+            return 0;
+        }
+
+        public int makeReadOnly(int nativeHandle) throws RemoteException {
+            // TODO Auto-generated method stub
+            return 0;
+        }
+
+
     };
 
-    private IP2pInitiator mP2pInitiatorService = new IP2pInitiator.Stub() {
+    private final IP2pInitiator mP2pInitiatorService = new IP2pInitiator.Stub() {
 
         public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
             NativeP2pDevice device;
@@ -911,7 +964,7 @@
         }
     };
 
-    private IP2pTarget mP2pTargetService = new IP2pTarget.Stub() {
+    private final IP2pTarget mP2pTargetService = new IP2pTarget.Stub() {
 
         public int connect(int nativeHandle) throws RemoteException {
             NativeP2pDevice device;
@@ -1033,8 +1086,8 @@
                 NativeNfcManager.INTERNAL_LLCP_LINK_STATE_CHANGED_ACTION));
 
         mContext.registerReceiver(mNfcServiceReceiver, new IntentFilter(
-                NfcManager.LLCP_LINK_STATE_CHANGED_ACTION));
-        
+                NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED));
+
         mContext.registerReceiver(mNfcServiceReceiver, new IntentFilter(
                 NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION));
 
@@ -1088,7 +1141,7 @@
             /* Store the socket handle */
             int sockeHandle = mGeneratedSocketHandle;
 
-            if (mLlcpLinkState == NfcManager.LLCP_LINK_STATE_ACTIVATED) {
+            if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
                 NativeLlcpConnectionlessSocket socket;
 
                 socket = mManager.doCreateLlcpConnectionlessSocket(sap);
@@ -1167,7 +1220,7 @@
         if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
             int sockeHandle = mGeneratedSocketHandle;
 
-            if (mLlcpLinkState == NfcManager.LLCP_LINK_STATE_ACTIVATED) {
+            if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
                 NativeLlcpServiceSocket socket;
 
                 socket = mManager.doCreateLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
@@ -1251,7 +1304,7 @@
 
             int sockeHandle = mGeneratedSocketHandle;
 
-            if (mLlcpLinkState == NfcManager.LLCP_LINK_STATE_ACTIVATED) {
+            if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
                 NativeLlcpSocket socket;
 
                 socket = mManager.doCreateLlcpSocket(sap, miu, rw, linearBufferLength);
@@ -1333,7 +1386,7 @@
             mManager.doDeselectSecureElement(mSelectedSeId);
         mNfcSecureElementState = 0;
             mSelectedSeId = 0;
-        
+
         /* Store that a secure element is deselected */
         Settings.System.putInt(mContext.getContentResolver(),
                 Settings.System.NFC_SECURE_ELEMENT_ON, 0);
@@ -1341,9 +1394,9 @@
         /* Reset Secure Element ID */
         Settings.System.putInt(mContext.getContentResolver(),
                 Settings.System.NFC_SECURE_ELEMENT_ID, 0);
-        
 
-        return ErrorCodes.SUCCESS; 
+
+        return ErrorCodes.SUCCESS;
     }
 
     public boolean disable() throws RemoteException {
@@ -1615,30 +1668,10 @@
 
     }
 
-    public int openTagConnection() throws RemoteException {
-        NativeNfcTag tag;
-        // Check if NFC is enabled
-        if (!mIsNfcEnabled) {
-            return ErrorCodes.ERROR_NOT_INITIALIZED;
-        }
+    public void openTagConnection(Tag tag) throws RemoteException {
+        NativeNfcTag nativeTag = new NativeNfcTag(tag.getHandle(), "", tag.getId());
 
-        mContext.enforceCallingPermission(android.Manifest.permission.NFC_RAW,
-                "NFC_RAW permission required to open NFC Tag connection");
-        if (!mOpenPending) {
-            mOpenPending = true;
-            tag = mManager.doOpenTagConnection(mTimeout);
-            if (tag != null) {
-                mObjectMap.put(tag.getHandle(), tag);
-                return tag.getHandle();
-            } else {
-                mOpenPending = false;
-                /* Restart polling loop for notification */
-                mManager.enableDiscovery(DISCOVERY_MODE_READER);
-                return ErrorCodes.ERROR_IO;
-            }
-        } else {
-            return ErrorCodes.ERROR_BUSY;
-        }
+        mObjectMap.put(nativeTag.getHandle(), nativeTag);
     }
 
     public int selectSecureElement(int seId) throws RemoteException {
@@ -1646,7 +1679,7 @@
         if (!mIsNfcEnabled) {
             return ErrorCodes.ERROR_NOT_INITIALIZED;
         }
-        
+
         if (mSelectedSeId == seId) {
             return ErrorCodes.ERROR_SE_ALREADY_SELECTED;
         }
@@ -1668,7 +1701,7 @@
         /* Store the ID of the Secure Element Selected */
         Settings.System.putInt(mContext.getContentResolver(),
                 Settings.System.NFC_SECURE_ELEMENT_ID, mSelectedSeId);
-        
+
         mNfcSecureElementState = 1;
 
         return ErrorCodes.SUCCESS;
@@ -1847,6 +1880,16 @@
         return ErrorCodes.SUCCESS;
     }
 
+    public NdefMessage localGet() throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public void localSet(NdefMessage message) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
     // Reset all internals
     private void reset() {
 
@@ -1856,7 +1899,7 @@
         mRegisteredSocketList.clear();
 
         // Reset variables
-        mLlcpLinkState = NfcManager.LLCP_LINK_STATE_DEACTIVATED;
+        mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_DEACTIVATED;
         mNbSocketCreated = 0;
         mIsNfcEnabled = false;
         mSelectedSeId = 0;
@@ -1869,6 +1912,9 @@
         Object device = null;
 
         device = mObjectMap.get(key);
+        if (device == null) {
+            Log.w(TAG, "Handle not found !");
+        }
 
         return device;
     }
@@ -1947,11 +1993,11 @@
      * LLCP link in not activated
      */
     private class RegisteredSocket {
-        private int mType;
+        private final int mType;
 
-        private int mHandle;
+        private final int mHandle;
 
-        private int mSap;
+        private final int mSap;
 
         private int mMiu;
 
@@ -1988,17 +2034,17 @@
         }
     }
 
-    private BroadcastReceiver mNfcServiceReceiver = new BroadcastReceiver() {
+    private final BroadcastReceiver mNfcServiceReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
             Log.d(TAG, "Internal NFC Intent received");
 
             /* LLCP Link deactivation */
-            if (intent.getAction().equals(NfcManager.LLCP_LINK_STATE_CHANGED_ACTION)) {
-                mLlcpLinkState = intent.getIntExtra(NfcManager.LLCP_LINK_STATE_CHANGED_EXTRA,
-                        NfcManager.LLCP_LINK_STATE_DEACTIVATED);
+            if (intent.getAction().equals(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED)) {
+                mLlcpLinkState = intent.getIntExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
+                        NfcAdapter.LLCP_LINK_STATE_DEACTIVATED);
 
-                if (mLlcpLinkState == NfcManager.LLCP_LINK_STATE_DEACTIVATED) {
+                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_DEACTIVATED) {
                     /* restart polling loop */
                     mManager.enableDiscovery(DISCOVERY_MODE_READER);
                 }
@@ -2010,9 +2056,9 @@
 
                 mLlcpLinkState = intent.getIntExtra(
                         NativeNfcManager.INTERNAL_LLCP_LINK_STATE_CHANGED_EXTRA,
-                        NfcManager.LLCP_LINK_STATE_DEACTIVATED);
+                        NfcAdapter.LLCP_LINK_STATE_DEACTIVATED);
 
-                if (mLlcpLinkState == NfcManager.LLCP_LINK_STATE_ACTIVATED) {
+                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
                     /* check if sockets are registered */
                     ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
 
@@ -2086,16 +2132,16 @@
 
                     /* Broadcast Intent Link LLCP activated */
                     Intent LlcpLinkIntent = new Intent();
-                    LlcpLinkIntent.setAction(NfcManager.LLCP_LINK_STATE_CHANGED_ACTION);
+                    LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
 
-                    LlcpLinkIntent.putExtra(NfcManager.LLCP_LINK_STATE_CHANGED_EXTRA,
-                            NfcManager.LLCP_LINK_STATE_ACTIVATED);
+                    LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
+                            NfcAdapter.LLCP_LINK_STATE_ACTIVATED);
 
                     Log.d(TAG, "Broadcasting LLCP activation");
                     mContext.sendOrderedBroadcast(LlcpLinkIntent,
                             android.Manifest.permission.NFC_LLCP);
                 }
-            }            
+            }
             /* Target Deactivated */
             else if (intent.getAction().equals(
                     NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) {
@@ -2104,8 +2150,8 @@
                 }
                 /* Restart polling loop for notification */
                 mManager.enableDiscovery(DISCOVERY_MODE_READER);
-                
+
             }
         }
     };
-}
+}
\ No newline at end of file
diff --git a/services/jni/Android.mk b/services/jni/Android.mk
index cdc0a6f..c90879d 100644
--- a/services/jni/Android.mk
+++ b/services/jni/Android.mk
@@ -23,7 +23,8 @@
 	libnativehelper \
     libsystem_server \
 	libutils \
-	libui
+	libui \
+    libsurfaceflinger_client
 
 ifeq ($(TARGET_SIMULATOR),true)
 ifeq ($(TARGET_OS),linux)
diff --git a/services/jni/com_android_server_PowerManagerService.cpp b/services/jni/com_android_server_PowerManagerService.cpp
index 146c177..2ec20bd 100644
--- a/services/jni/com_android_server_PowerManagerService.cpp
+++ b/services/jni/com_android_server_PowerManagerService.cpp
@@ -20,9 +20,14 @@
 
 #include "JNIHelp.h"
 #include "jni.h"
+
 #include <limits.h>
+
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/Timers.h>
+#include <surfaceflinger/ISurfaceComposer.h>
+#include <surfaceflinger/SurfaceComposerClient.h>
+
 #include "com_android_server_PowerManagerService.h"
 
 namespace android {
@@ -119,6 +124,12 @@
     gScreenBright = screenBright;
 }
 
+static void android_server_PowerManagerService_nativeStartSurfaceFlingerAnimation(JNIEnv* env,
+        jobject obj) {
+    sp<ISurfaceComposer> s(ComposerService::getComposerService());
+    s->turnElectronBeamOff(0);
+}
+
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod gPowerManagerServiceMethods[] = {
@@ -127,6 +138,8 @@
             (void*) android_server_PowerManagerService_nativeInit },
     { "nativeSetPowerState", "(ZZ)V",
             (void*) android_server_PowerManagerService_nativeSetPowerState },
+    { "nativeStartSurfaceFlingerAnimation", "()V",
+            (void*) android_server_PowerManagerService_nativeStartSurfaceFlingerAnimation },
 };
 
 #define FIND_CLASS(var, className) \
diff --git a/services/jni/com_android_server_location_GpsLocationProvider.cpp b/services/jni/com_android_server_location_GpsLocationProvider.cpp
index 43e8467..1d93f82 100755
--- a/services/jni/com_android_server_location_GpsLocationProvider.cpp
+++ b/services/jni/com_android_server_location_GpsLocationProvider.cpp
@@ -590,9 +590,7 @@
         jboolean connected, int type, jboolean roaming, jstring extraInfo)
 {
     const AGpsRilInterface* interface = GetAGpsRilInterface(env, obj);
-    if (interface &&
-            (interface->size > ((char *)&interface->update_network_state - (char *)&interface)) &&
-            interface->update_network_state) {
+    if (interface && interface->update_network_state) {
         if (extraInfo) {
             const char *extraInfoStr = env->GetStringUTFChars(extraInfo, NULL);
             interface->update_network_state(connected, type, roaming, extraInfoStr);
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
index 1d09f84..90865da 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
@@ -359,7 +359,7 @@
 
 DisplayHardwareBase::DisplayHardwareBase(const sp<SurfaceFlinger>& flinger,
         uint32_t displayIndex) 
-    : mCanDraw(true)
+    : mCanDraw(true), mScreenAcquired(true)
 {
     mDisplayEventThread = new DisplayEventThread(flinger);
     if (mDisplayEventThread->initCheck() != NO_ERROR) {
@@ -374,18 +374,21 @@
     mDisplayEventThread->requestExitAndWait();
 }
 
+void DisplayHardwareBase::setCanDraw(bool canDraw)
+{
+    mCanDraw = canDraw;
+}
 
 bool DisplayHardwareBase::canDraw() const
 {
-    return mCanDraw;
+    return mCanDraw && mScreenAcquired;
 }
 
 void DisplayHardwareBase::releaseScreen() const
 {
     status_t err = mDisplayEventThread->releaseScreen();
     if (err >= 0) {
-        //LOGD("screen given-up");
-        mCanDraw = false;
+        mScreenAcquired = false;
     }
 }
 
@@ -393,9 +396,13 @@
 {
     status_t err = mDisplayEventThread->acquireScreen();
     if (err >= 0) {
-        //LOGD("screen returned");
-        mCanDraw = true;
+        mScreenAcquired = true;
     }
 }
 
+bool DisplayHardwareBase::isScreenAcquired() const
+{
+    return mScreenAcquired;
+}
+
 }; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
index 8369bb8..fa6a0c4 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
@@ -40,7 +40,11 @@
     // console managment
     void releaseScreen() const;
     void acquireScreen() const;
+    bool isScreenAcquired() const;
+
     bool canDraw() const;
+    void setCanDraw(bool canDraw);
+
 
 private:
     class DisplayEventThreadBase : public Thread {
@@ -89,6 +93,7 @@
 
     sp<DisplayEventThreadBase>  mDisplayEventThread;
     mutable int                 mCanDraw;
+    mutable int                 mScreenAcquired;
 };
 
 }; // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e5e87c6..3734969 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -80,6 +80,7 @@
         mVisibleRegionsDirty(false),
         mDeferReleaseConsole(false),
         mFreezeDisplay(false),
+        mElectronBeamAnimation(false),
         mFreezeCount(0),
         mFreezeDisplayTime(0),
         mDebugRegion(0),
@@ -421,16 +422,20 @@
     int what = android_atomic_and(0, &mConsoleSignals);
     if (what & eConsoleAcquired) {
         hw.acquireScreen();
+        // this is a temporary work-around, eventually this should be called
+        // by the power-manager
+        if (mElectronBeamAnimation)
+            SurfaceFlinger::turnElectronBeamOn(0);
     }
 
-    if (mDeferReleaseConsole && hw.canDraw()) {
+    if (mDeferReleaseConsole && hw.isScreenAcquired()) {
         // We got the release signal before the acquire signal
         mDeferReleaseConsole = false;
         hw.releaseScreen();
     }
 
     if (what & eConsoleReleased) {
-        if (hw.canDraw()) {
+        if (hw.isScreenAcquired()) {
             hw.releaseScreen();
         } else {
             mDeferReleaseConsole = true;
@@ -1456,6 +1461,8 @@
         case FREEZE_DISPLAY:
         case UNFREEZE_DISPLAY:
         case BOOT_FINISHED:
+        case TURN_ELECTRON_BEAM_OFF:
+        case TURN_ELECTRON_BEAM_ON:
         {
             // codes that require permission check
             IPCThreadState* ipc = IPCThreadState::self();
@@ -1546,6 +1553,446 @@
 
 // ---------------------------------------------------------------------------
 
+status_t SurfaceFlinger::renderScreenToTextureLocked(DisplayID dpy,
+        GLuint* textureName, GLfloat* uOut, GLfloat* vOut)
+{
+    if (!GLExtensions::getInstance().haveFramebufferObject())
+        return INVALID_OPERATION;
+
+    // get screen geometry
+    const DisplayHardware& hw(graphicPlane(dpy).displayHardware());
+    const uint32_t hw_w = hw.getWidth();
+    const uint32_t hw_h = hw.getHeight();
+    GLfloat u = 1;
+    GLfloat v = 1;
+
+    // make sure to clear all GL error flags
+    while ( glGetError() != GL_NO_ERROR ) ;
+
+    // create a FBO
+    GLuint name, tname;
+    glGenTextures(1, &tname);
+    glBindTexture(GL_TEXTURE_2D, tname);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
+            hw_w, hw_h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
+    if (glGetError() != GL_NO_ERROR) {
+        GLint tw = (2 << (31 - clz(hw_w)));
+        GLint th = (2 << (31 - clz(hw_h)));
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
+                tw, th, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
+        u = GLfloat(hw_w) / tw;
+        v = GLfloat(hw_h) / th;
+    }
+    glGenFramebuffersOES(1, &name);
+    glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
+    glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES,
+            GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0);
+
+    // redraw the screen entirely...
+    glClearColor(0,0,0,1);
+    glClear(GL_COLOR_BUFFER_BIT);
+    const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
+    const size_t count = layers.size();
+    for (size_t i=0 ; i<count ; ++i) {
+        const sp<LayerBase>& layer(layers[i]);
+        layer->drawForSreenShot();
+    }
+
+    // back to main framebuffer
+    glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
+    glDisable(GL_SCISSOR_TEST);
+    glDeleteFramebuffersOES(1, &name);
+
+    *textureName = tname;
+    *uOut = u;
+    *vOut = v;
+    return NO_ERROR;
+}
+
+// ---------------------------------------------------------------------------
+
+status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
+{
+    status_t result = PERMISSION_DENIED;
+
+    if (!GLExtensions::getInstance().haveFramebufferObject())
+        return INVALID_OPERATION;
+
+    // get screen geometry
+    const DisplayHardware& hw(graphicPlane(0).displayHardware());
+    const uint32_t hw_w = hw.getWidth();
+    const uint32_t hw_h = hw.getHeight();
+    const Region screenBounds(hw.bounds());
+
+    GLfloat u, v;
+    GLuint tname;
+    result = renderScreenToTextureLocked(0, &tname, &u, &v);
+    if (result != NO_ERROR) {
+        return result;
+    }
+
+    GLfloat vtx[8];
+    const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };
+    glEnable(GL_TEXTURE_2D);
+    glBindTexture(GL_TEXTURE_2D, tname);
+    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+    glVertexPointer(2, GL_FLOAT, 0, vtx);
+
+    class s_curve_interpolator {
+        const float nbFrames, s, v;
+    public:
+        s_curve_interpolator(int nbFrames, float s)
+        : nbFrames(1.0f / (nbFrames-1)), s(s),
+          v(1.0f + expf(-s + 0.5f*s)) {
+        }
+        float operator()(int f) {
+            const float x = f * nbFrames;
+            return ((1.0f/(1.0f + expf(-x*s + 0.5f*s))) - 0.5f) * v + 0.5f;
+        }
+    };
+
+    class v_stretch {
+        const GLfloat hw_w, hw_h;
+    public:
+        v_stretch(uint32_t hw_w, uint32_t hw_h)
+        : hw_w(hw_w), hw_h(hw_h) {
+        }
+        void operator()(GLfloat* vtx, float v) {
+            const GLfloat w = hw_w + (hw_w * v);
+            const GLfloat h = hw_h - (hw_h * v);
+            const GLfloat x = (hw_w - w) * 0.5f;
+            const GLfloat y = (hw_h - h) * 0.5f;
+            vtx[0] = x;         vtx[1] = y;
+            vtx[2] = x;         vtx[3] = y + h;
+            vtx[4] = x + w;     vtx[5] = y + h;
+            vtx[6] = x + w;     vtx[7] = y;
+        }
+    };
+
+    class h_stretch {
+        const GLfloat hw_w, hw_h;
+    public:
+        h_stretch(uint32_t hw_w, uint32_t hw_h)
+        : hw_w(hw_w), hw_h(hw_h) {
+        }
+        void operator()(GLfloat* vtx, float v) {
+            const GLfloat w = hw_w - (hw_w * v);
+            const GLfloat h = 1.0f;
+            const GLfloat x = (hw_w - w) * 0.5f;
+            const GLfloat y = (hw_h - h) * 0.5f;
+            vtx[0] = x;         vtx[1] = y;
+            vtx[2] = x;         vtx[3] = y + h;
+            vtx[4] = x + w;     vtx[5] = y + h;
+            vtx[6] = x + w;     vtx[7] = y;
+        }
+    };
+
+    // the full animation is 24 frames
+    const int nbFrames = 12;
+    s_curve_interpolator itr(nbFrames, 7.5f);
+    s_curve_interpolator itg(nbFrames, 8.0f);
+    s_curve_interpolator itb(nbFrames, 8.5f);
+
+    v_stretch vverts(hw_w, hw_h);
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_ONE, GL_ONE);
+    for (int i=0 ; i<nbFrames ; i++) {
+        float x, y, w, h;
+        const float vr = itr(i);
+        const float vg = itg(i);
+        const float vb = itb(i);
+
+        // clear screen
+        glColorMask(1,1,1,1);
+        glClear(GL_COLOR_BUFFER_BIT);
+        glEnable(GL_TEXTURE_2D);
+
+        // draw the red plane
+        vverts(vtx, vr);
+        glColorMask(1,0,0,1);
+        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+        // draw the green plane
+        vverts(vtx, vg);
+        glColorMask(0,1,0,1);
+        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+        // draw the blue plane
+        vverts(vtx, vb);
+        glColorMask(0,0,1,1);
+        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+        // draw the white highlight (we use the last vertices)
+        glDisable(GL_TEXTURE_2D);
+        glColorMask(1,1,1,1);
+        glColor4f(vg, vg, vg, 1);
+        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+        hw.flip(screenBounds);
+    }
+
+    h_stretch hverts(hw_w, hw_h);
+    glDisable(GL_BLEND);
+    glDisable(GL_TEXTURE_2D);
+    glColorMask(1,1,1,1);
+    for (int i=0 ; i<nbFrames ; i++) {
+        const float v = itg(i);
+        hverts(vtx, v);
+        glClear(GL_COLOR_BUFFER_BIT);
+        glColor4f(1-v, 1-v, 1-v, 1);
+        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+        hw.flip(screenBounds);
+    }
+
+    glColorMask(1,1,1,1);
+    glEnable(GL_SCISSOR_TEST);
+    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+    glDeleteTextures(1, &tname);
+    return NO_ERROR;
+}
+
+status_t SurfaceFlinger::electronBeamOnAnimationImplLocked()
+{
+    status_t result = PERMISSION_DENIED;
+
+    if (!GLExtensions::getInstance().haveFramebufferObject())
+        return INVALID_OPERATION;
+
+
+    // get screen geometry
+    const DisplayHardware& hw(graphicPlane(0).displayHardware());
+    const uint32_t hw_w = hw.getWidth();
+    const uint32_t hw_h = hw.getHeight();
+    const Region screenBounds(hw.bounds());
+
+    GLfloat u, v;
+    GLuint tname;
+    result = renderScreenToTextureLocked(0, &tname, &u, &v);
+    if (result != NO_ERROR) {
+        return result;
+    }
+
+    // back to main framebuffer
+    glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
+    glDisable(GL_SCISSOR_TEST);
+
+    GLfloat vtx[8];
+    const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };
+    glEnable(GL_TEXTURE_2D);
+    glBindTexture(GL_TEXTURE_2D, tname);
+    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+    glVertexPointer(2, GL_FLOAT, 0, vtx);
+
+    class s_curve_interpolator {
+        const float nbFrames, s, v;
+    public:
+        s_curve_interpolator(int nbFrames, float s)
+        : nbFrames(1.0f / (nbFrames-1)), s(s),
+          v(1.0f + expf(-s + 0.5f*s)) {
+        }
+        float operator()(int f) {
+            const float x = f * nbFrames;
+            return ((1.0f/(1.0f + expf(-x*s + 0.5f*s))) - 0.5f) * v + 0.5f;
+        }
+    };
+
+    class v_stretch {
+        const GLfloat hw_w, hw_h;
+    public:
+        v_stretch(uint32_t hw_w, uint32_t hw_h)
+        : hw_w(hw_w), hw_h(hw_h) {
+        }
+        void operator()(GLfloat* vtx, float v) {
+            const GLfloat w = hw_w + (hw_w * v);
+            const GLfloat h = hw_h - (hw_h * v);
+            const GLfloat x = (hw_w - w) * 0.5f;
+            const GLfloat y = (hw_h - h) * 0.5f;
+            vtx[0] = x;         vtx[1] = y;
+            vtx[2] = x;         vtx[3] = y + h;
+            vtx[4] = x + w;     vtx[5] = y + h;
+            vtx[6] = x + w;     vtx[7] = y;
+        }
+    };
+
+    class h_stretch {
+        const GLfloat hw_w, hw_h;
+    public:
+        h_stretch(uint32_t hw_w, uint32_t hw_h)
+        : hw_w(hw_w), hw_h(hw_h) {
+        }
+        void operator()(GLfloat* vtx, float v) {
+            const GLfloat w = hw_w - (hw_w * v);
+            const GLfloat h = 1.0f;
+            const GLfloat x = (hw_w - w) * 0.5f;
+            const GLfloat y = (hw_h - h) * 0.5f;
+            vtx[0] = x;         vtx[1] = y;
+            vtx[2] = x;         vtx[3] = y + h;
+            vtx[4] = x + w;     vtx[5] = y + h;
+            vtx[6] = x + w;     vtx[7] = y;
+        }
+    };
+
+    // the full animation is 24 frames
+    const int nbFrames = 12;
+    s_curve_interpolator itr(nbFrames, 7.5f);
+    s_curve_interpolator itg(nbFrames, 8.0f);
+    s_curve_interpolator itb(nbFrames, 8.5f);
+
+    h_stretch hverts(hw_w, hw_h);
+    glDisable(GL_BLEND);
+    glDisable(GL_TEXTURE_2D);
+    glColorMask(1,1,1,1);
+    for (int i=nbFrames-1 ; i>=0 ; i--) {
+        const float v = itg(i);
+        hverts(vtx, v);
+        glClear(GL_COLOR_BUFFER_BIT);
+        glColor4f(1-v, 1-v, 1-v, 1);
+        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+        hw.flip(screenBounds);
+    }
+
+    v_stretch vverts(hw_w, hw_h);
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_ONE, GL_ONE);
+    for (int i=nbFrames-1 ; i>=0 ; i--) {
+        float x, y, w, h;
+        const float vr = itr(i);
+        const float vg = itg(i);
+        const float vb = itb(i);
+
+        // clear screen
+        glColorMask(1,1,1,1);
+        glClear(GL_COLOR_BUFFER_BIT);
+        glEnable(GL_TEXTURE_2D);
+
+        // draw the red plane
+        vverts(vtx, vr);
+        glColorMask(1,0,0,1);
+        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+        // draw the green plane
+        vverts(vtx, vg);
+        glColorMask(0,1,0,1);
+        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+        // draw the blue plane
+        vverts(vtx, vb);
+        glColorMask(0,0,1,1);
+        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+        hw.flip(screenBounds);
+    }
+
+    glColorMask(1,1,1,1);
+    glEnable(GL_SCISSOR_TEST);
+    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+    glDeleteTextures(1, &tname);
+
+    return NO_ERROR;
+}
+
+// ---------------------------------------------------------------------------
+
+status_t SurfaceFlinger::turnElectronBeamOffImplLocked()
+{
+    DisplayHardware& hw(graphicPlane(0).editDisplayHardware());
+    if (!hw.canDraw()) {
+        // we're already off
+        return NO_ERROR;
+    }
+    status_t result = electronBeamOffAnimationImplLocked();
+    if (result == NO_ERROR) {
+        hw.setCanDraw(false);
+    }
+    return result;
+}
+
+status_t SurfaceFlinger::turnElectronBeamOff(int32_t mode)
+{
+    if (!GLExtensions::getInstance().haveFramebufferObject())
+        return INVALID_OPERATION;
+
+    class MessageTurnElectronBeamOff : public MessageBase {
+        SurfaceFlinger* flinger;
+        status_t result;
+    public:
+        MessageTurnElectronBeamOff(SurfaceFlinger* flinger)
+            : flinger(flinger), result(PERMISSION_DENIED) {
+        }
+        status_t getResult() const {
+            return result;
+        }
+        virtual bool handler() {
+            Mutex::Autolock _l(flinger->mStateLock);
+            result = flinger->turnElectronBeamOffImplLocked();
+            return true;
+        }
+    };
+
+    sp<MessageBase> msg = new MessageTurnElectronBeamOff(this);
+    status_t res = postMessageSync(msg);
+    if (res == NO_ERROR) {
+        res = static_cast<MessageTurnElectronBeamOff*>( msg.get() )->getResult();
+
+        // work-around: when the power-manager calls us we activate the
+        // animation. eventually, the "on" animation will be called
+        // by the power-manager itself
+        mElectronBeamAnimation = true;
+    }
+    return res;
+}
+
+// ---------------------------------------------------------------------------
+
+status_t SurfaceFlinger::turnElectronBeamOnImplLocked()
+{
+    DisplayHardware& hw(graphicPlane(0).editDisplayHardware());
+    if (hw.canDraw()) {
+        // we're already on
+        return NO_ERROR;
+    }
+    status_t result = electronBeamOnAnimationImplLocked();
+    if (result == NO_ERROR) {
+        hw.setCanDraw(true);
+    }
+    return result;
+}
+
+status_t SurfaceFlinger::turnElectronBeamOn(int32_t mode)
+{
+    if (!GLExtensions::getInstance().haveFramebufferObject())
+        return INVALID_OPERATION;
+
+    class MessageTurnElectronBeamOn : public MessageBase {
+        SurfaceFlinger* flinger;
+        status_t result;
+    public:
+        MessageTurnElectronBeamOn(SurfaceFlinger* flinger)
+            : flinger(flinger), result(PERMISSION_DENIED) {
+        }
+        status_t getResult() const {
+            return result;
+        }
+        virtual bool handler() {
+            Mutex::Autolock _l(flinger->mStateLock);
+            result = flinger->turnElectronBeamOnImplLocked();
+            return true;
+        }
+    };
+
+    postMessageAsync( new MessageTurnElectronBeamOn(this) );
+    return NO_ERROR;
+}
+
+// ---------------------------------------------------------------------------
+
 status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy,
         sp<IMemoryHeap>* heap,
         uint32_t* w, uint32_t* h, PixelFormat* f,
@@ -2005,6 +2452,10 @@
     return *mHw;
 }
 
+DisplayHardware& GraphicPlane::editDisplayHardware() {
+    return *mHw;
+}
+
 const Transform& GraphicPlane::transform() const {
     return mGlobalTransform;
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index f0a167b..d07a3ad 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -141,6 +141,7 @@
         int                     getHeight() const;
 
         const DisplayHardware&  displayHardware() const;
+        DisplayHardware&        editDisplayHardware();
         const Transform&        transform() const;
         EGLDisplay              getEGLDisplay() const;
         
@@ -200,6 +201,8 @@
                                                       PixelFormat* format,
                                                       uint32_t reqWidth,
                                                       uint32_t reqHeight);
+    virtual status_t                    turnElectronBeamOff(int32_t mode);
+    virtual status_t                    turnElectronBeamOn(int32_t mode);
 
             void                        screenReleased(DisplayID dpy);
             void                        screenAcquired(DisplayID dpy);
@@ -325,6 +328,13 @@
                     uint32_t* width, uint32_t* height, PixelFormat* format,
                     uint32_t reqWidth = 0, uint32_t reqHeight = 0);
 
+            status_t turnElectronBeamOffImplLocked();
+            status_t turnElectronBeamOnImplLocked();
+            status_t electronBeamOffAnimationImplLocked();
+            status_t electronBeamOnAnimationImplLocked();
+            status_t renderScreenToTextureLocked(DisplayID dpy,
+                    GLuint* textureName, GLfloat* uOut, GLfloat* vOut);
+
             friend class FreezeLock;
             sp<FreezeLock> getFreezeLock() const;
             inline void incFreezeCount() {
@@ -385,6 +395,7 @@
                 bool                        mVisibleRegionsDirty;
                 bool                        mDeferReleaseConsole;
                 bool                        mFreezeDisplay;
+                bool                        mElectronBeamAnimation;
                 int32_t                     mFreezeCount;
                 nsecs_t                     mFreezeDisplayTime;
                 Vector< sp<LayerBase> >     mVisibleLayersSortedByZ;
diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java
index 360d35e..1e9b930 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfo.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfo.java
@@ -383,8 +383,8 @@
      */
     public String toString() {
         return new StringBuilder(384)
-                .append("\nname: " + name)
-                .append("\nphoneNumber: " + phoneNumber)
+                .append("\nname: " + /*name*/ "nnnnnn")
+                .append("\nphoneNumber: " + /*phoneNumber*/ "xxxxxxx")
                 .append("\ncnapName: " + cnapName)
                 .append("\nnumberPresentation: " + numberPresentation)
                 .append("\nnamePresentation: " + namePresentation)
@@ -395,8 +395,8 @@
                 .append("\nphotoResource: " + photoResource)
                 .append("\nperson_id: " + person_id)
                 .append("\nneedUpdate: " + needUpdate)
-                .append("\ncontactRefUri: " + contactRefUri)
-                .append("\ncontactRingtoneUri: " + contactRefUri)
+                .append("\ncontactRefUri: " + /*contactRefUri*/ "xxxxxxx")
+                .append("\ncontactRingtoneUri: " + /*contactRefUri*/ "xxxxxxx")
                 .append("\nshouldSendToVoicemail: " + shouldSendToVoicemail)
                 .append("\ncachedPhoto: " + cachedPhoto)
                 .append("\nisCachedPhotoCurrent: " + isCachedPhotoCurrent)
diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
index 25ca559..46ef118 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
@@ -24,6 +24,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.SystemProperties;
 import android.provider.ContactsContract.CommonDataKinds.SipAddress;
 import android.provider.ContactsContract.Data;
 import android.provider.ContactsContract.PhoneLookup;
@@ -36,8 +37,7 @@
  */
 
 public class CallerInfoAsyncQuery {
-
-    private static final boolean DBG = true; // STOPSHIP: disable debugging before ship
+    private static final boolean DBG = (SystemProperties.getInt("ro.debuggable", 0) == 1);
     private static final String LOG_TAG = "CallerInfoAsyncQuery";
 
     private static final int EVENT_NEW_QUERY = 1;
@@ -135,7 +135,7 @@
                 } else {
 
                     if (DBG) log("Processing event: " + cw.event + " token (arg1): " + msg.arg1 +
-                            " command: " + msg.what + " query URI: " + args.uri);
+                        " command: " + msg.what + " query URI: " + sanitizeUriToString(args.uri));
 
                     switch (cw.event) {
                         case EVENT_NEW_QUERY:
@@ -297,7 +297,7 @@
             OnQueryCompleteListener listener, Object cookie) {
         if (DBG) {
             log("##### CallerInfoAsyncQuery startQuery()... #####");
-            log("- number: " + number);
+            log("- number: " + /*number*/ "xxxxxxx");
             log("- cookie: " + cookie);
         }
 
@@ -309,7 +309,7 @@
 
         if (PhoneNumberUtils.isUriNumber(number)) {
             // "number" is really a SIP address.
-            if (DBG) log("  - Treating number as a SIP address: " + number);
+            if (DBG) log("  - Treating number as a SIP address: " + /*number*/ "xxxxxxx");
 
             // We look up SIP addresses directly in the Data table:
             contactRef = Data.CONTENT_URI;
@@ -341,7 +341,7 @@
         }
 
         if (DBG) {
-            log("==> contactRef: " + contactRef);
+            log("==> contactRef: " + sanitizeUriToString(contactRef));
             log("==> selection: " + selection);
             if (selectionArgs != null) {
                 for (int i = 0; i < selectionArgs.length; i++) {
@@ -383,8 +383,8 @@
      */
     public void addQueryListener(int token, OnQueryCompleteListener listener, Object cookie) {
 
-        if (DBG) log("adding listener to query: " + mHandler.mQueryUri + " handler: " +
-                mHandler.toString());
+        if (DBG) log("adding listener to query: " + sanitizeUriToString(mHandler.mQueryUri) +
+                " handler: " + mHandler.toString());
 
         //create cookieWrapper, add query request to end of queue.
         CookieWrapper cw = new CookieWrapper();
@@ -418,6 +418,20 @@
         mHandler = null;
     }
 
+    private static String sanitizeUriToString(Uri uri) {
+        if (uri != null) {
+            String uriString = uri.toString();
+            int indexOfLastSlash = uriString.lastIndexOf('/');
+            if (indexOfLastSlash > 0) {
+                return uriString.substring(0, indexOfLastSlash) + "/xxxxxxx";
+            } else {
+                return uriString;
+            }
+        } else {
+            return "";
+        }
+    }
+
     /**
      * static logging method
      */
diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
index d711a80..b14896a 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
@@ -238,7 +238,7 @@
         msisdn = number;
         msisdnTag = alphaTag;
 
-        if(DBG) log("Set MSISDN: " + msisdnTag +" " + msisdn);
+        if(DBG) log("Set MSISDN: " + msisdnTag + " " + /*msisdn*/ "xxxxxxx");
 
 
         AdnRecord adn = new AdnRecord(msisdnTag, msisdn);
@@ -496,7 +496,7 @@
                     imsi = null;
                 }
 
-                Log.d(LOG_TAG, "IMSI: " + imsi.substring(0, 6) + "xxxxxxxxx");
+                Log.d(LOG_TAG, "IMSI: " + imsi.substring(0, 6) + "xxxxxxx");
 
                 if (mncLength == UNKNOWN) {
                     // the SIM has told us all it knows, but it didn't know the mnc length.
@@ -619,7 +619,7 @@
                 msisdn = adn.getNumber();
                 msisdnTag = adn.getAlphaTag();
 
-                Log.d(LOG_TAG, "MSISDN: " + msisdn);
+                Log.d(LOG_TAG, "MSISDN: " + /*msisdn*/ "xxxxxxx");
             break;
 
             case EVENT_SET_MSISDN_DONE:
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index f71ebb9..873ebac 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -871,6 +871,15 @@
                                     error.string());
                                 goto bail;
                         }
+                    } else if (tag == "uses-gl-texture") {
+                        String8 name = getAttribute(tree, NAME_ATTR, &error);
+                        if (name != "" && error == "") {
+                            printf("uses-gl-texture:'%s'\n", name.string());
+                        } else {
+                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
+                                    error.string());
+                                goto bail;
+                        }
                     }
                 } else if (depth == 3 && withinApplication) {
                     withinActivity = false;
diff --git a/tools/obbtool/Android.mk b/tools/obbtool/Android.mk
index b02c1cb..9866876 100644
--- a/tools/obbtool/Android.mk
+++ b/tools/obbtool/Android.mk
@@ -13,6 +13,8 @@
 LOCAL_SRC_FILES := \
 	Main.cpp
 
+LOCAL_CFLAGS := -Wall -Werror
+
 #LOCAL_C_INCLUDES +=
 
 LOCAL_STATIC_LIBRARIES := \
@@ -27,4 +29,21 @@
 
 include $(BUILD_HOST_EXECUTABLE)
 
+# Non-Linux hosts might not have OpenSSL libcrypto
+ifeq ($(HOST_OS),linux)
+    include $(CLEAR_VARS)
+
+    LOCAL_MODULE := pbkdf2gen
+
+    LOCAL_MODULE_TAGS := optional
+
+    LOCAL_CFLAGS := -Wall -Werror
+
+    LOCAL_SRC_FILES := pbkdf2gen.cpp
+
+    LOCAL_SHARED_LIBRARIES := libcrypto
+
+    include $(BUILD_HOST_EXECUTABLE)
+endif # HOST_OS == linux
+
 endif # TARGET_BUILD_APPS
diff --git a/tools/obbtool/Main.cpp b/tools/obbtool/Main.cpp
index 49e077f..932dbec 100644
--- a/tools/obbtool/Main.cpp
+++ b/tools/obbtool/Main.cpp
@@ -20,6 +20,7 @@
 #include <getopt.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 
 using namespace android;
 
@@ -29,7 +30,9 @@
 static int wantUsage = 0;
 static int wantVersion = 0;
 
-#define ADD_OPTS "n:v:o"
+#define SALT_LEN 8
+
+#define ADD_OPTS "n:v:os:"
 static const struct option longopts[] = {
     {"help",       no_argument, &wantUsage,   1},
     {"version",    no_argument, &wantVersion, 1},
@@ -38,14 +41,27 @@
     {"name",       required_argument, NULL, 'n'},
     {"version",    required_argument, NULL, 'v'},
     {"overlay",    optional_argument, NULL, 'o'},
+    {"salt",       required_argument, NULL, 's'},
 
     {NULL, 0, NULL, '\0'}
 };
 
-struct package_info_t {
+class PackageInfo {
+public:
+    PackageInfo()
+            : packageName(NULL)
+            , packageVersion(-1)
+            , overlay(false)
+            , salted(false)
+    {
+        memset(&salt, 0, sizeof(salt));
+    }
+
     char* packageName;
     int packageVersion;
     bool overlay;
+    bool salted;
+    unsigned char salt[SALT_LEN];
 };
 
 /*
@@ -59,6 +75,13 @@
         " %s a[dd] [ OPTIONS ] FILENAME\n"
         "   Adds an OBB signature to the file.\n\n", gProgName);
     fprintf(stderr,
+        "   Options:\n"
+        "     -n <package name>      sets the OBB package name (required)\n"
+        "     -v <OBB version>       sets the OBB version (required)\n"
+        "     -o                     sets the OBB overlay flag\n"
+        "     -s <8 byte hex salt>   sets the crypto key salt (if encrypted)\n"
+        "\n");
+    fprintf(stderr,
         " %s r[emove] FILENAME\n"
         "   Removes the OBB signature from the file.\n\n", gProgName);
     fprintf(stderr,
@@ -66,7 +89,7 @@
         "   Prints the OBB signature information of a file.\n\n", gProgName);
 }
 
-void doAdd(const char* filename, struct package_info_t* info) {
+void doAdd(const char* filename, struct PackageInfo* info) {
     ObbFile *obb = new ObbFile();
     if (obb->readFrom(filename)) {
         fprintf(stderr, "ERROR: %s: OBB signature already present\n", filename);
@@ -76,6 +99,9 @@
     obb->setPackageName(String8(info->packageName));
     obb->setVersion(info->packageVersion);
     obb->setOverlay(info->overlay);
+    if (info->salted) {
+        obb->setSalt(info->salt, SALT_LEN);
+    }
 
     if (!obb->writeTo(filename)) {
         fprintf(stderr, "ERROR: %s: couldn't write OBB signature: %s\n",
@@ -113,6 +139,40 @@
     printf("     Version: %d\n", obb->getVersion());
     printf("       Flags: 0x%08x\n", obb->getFlags());
     printf("     Overlay: %s\n", obb->isOverlay() ? "true" : "false");
+    printf("        Salt: ");
+
+    size_t saltLen;
+    const unsigned char* salt = obb->getSalt(&saltLen);
+    if (salt != NULL) {
+        for (int i = 0; i < SALT_LEN; i++) {
+            printf("%02x", salt[i]);
+        }
+        printf("\n");
+    } else {
+        printf("<empty>\n");
+    }
+}
+
+bool fromHex(char h, unsigned char *b) {
+    if (h >= '0' && h <= '9') {
+        *b = h - '0';
+        return true;
+    } else if (h >= 'a' && h <= 'f') {
+        *b = h - 'a' + 10;
+        return true;
+    } else if (h >= 'A' && h <= 'F') {
+        *b = h - 'A' + 10;
+        return true;
+    }
+    return false;
+}
+
+bool hexToByte(char h1, char h2, unsigned char* b) {
+    unsigned char first, second;
+    if (!fromHex(h1, &first)) return false;
+    if (!fromHex(h2, &second)) return false;
+    *b = (first << 4) | second;
+    return true;
 }
 
 /*
@@ -120,11 +180,9 @@
  */
 int main(int argc, char* const argv[])
 {
-    const char *prog = argv[0];
-    struct options *options;
     int opt;
     int option_index = 0;
-    struct package_info_t package_info;
+    struct PackageInfo package_info;
 
     int result = 1;    // pessimistically assume an error.
 
@@ -145,7 +203,7 @@
             package_info.packageName = optarg;
             break;
         case 'v': {
-            char *end;
+            char* end;
             package_info.packageVersion = strtol(optarg, &end, 10);
             if (*optarg == '\0' || *end != '\0') {
                 fprintf(stderr, "ERROR: invalid version; should be integer!\n\n");
@@ -157,6 +215,25 @@
         case 'o':
             package_info.overlay = true;
             break;
+        case 's':
+            if (strlen(optarg) != SALT_LEN * 2) {
+                fprintf(stderr, "ERROR: salt must be 8 bytes in hex (e.g., ABCD65031337D00D)\n\n");
+                wantUsage = 1;
+                goto bail;
+            }
+
+            package_info.salted = true;
+
+            unsigned char b;
+            for (int i = 0, j = 0; i < SALT_LEN; i++, j+=2) {
+                if (!hexToByte(optarg[j], optarg[j+1], &b)) {
+                    fprintf(stderr, "ERROR: salt must be in hex (e.g., ABCD65031337D00D)\n");
+                    wantUsage = 1;
+                    goto bail;
+                }
+                package_info.salt[i] = b;
+            }
+            break;
         case '?':
             wantUsage = 1;
             goto bail;
diff --git a/tools/obbtool/mkobb.sh b/tools/obbtool/mkobb.sh
index ba5256f..725250d 100755
--- a/tools/obbtool/mkobb.sh
+++ b/tools/obbtool/mkobb.sh
@@ -35,6 +35,7 @@
     UMOUNTBIN=`which umount`
     DDBIN=`which dd`
     RSYNCBIN=`which rsync`
+    PBKDF2GEN=`which pbkdf2gen`
 }
 
 check_prereqs() {
@@ -76,6 +77,11 @@
         echo "ERROR: ${LOSETUPBIN} is not executable!"
         exit 1
     fi
+
+    if [ "${PBKDF2GEN}x" = "x" ]; then \
+        echo "ERROR: Could not find pbkdf2gen in your path!"
+        exit 1
+    fi
 }
 
 cleanup() {
@@ -142,7 +148,6 @@
 usage() {
     echo "mkobb.sh -- Create OBB files for use on Android"
     echo ""
-    echo " -c             Use an encrypted OBB; must specify key"
     echo " -d <directory> Use <directory> as input for OBB files"
     echo " -k <key>       Use <key> to encrypt OBB file"
     echo " -K             Prompt for key to encrypt OBB file"
@@ -156,7 +161,7 @@
 
 use_crypto=0
 
-args=`getopt -o cd:hk:Ko:v -- "$@"`
+args=`getopt -o d:hk:Ko:v -- "$@"`
 eval set -- "$args"
 
 while true; do \
@@ -223,9 +228,9 @@
 ${LOSETUPBIN} ${loop_dev} ${tempfile} || ( echo "ERROR: couldn't create loopback device"; exit 1 )
 
 if [ ${use_crypto} -eq 1 ]; then \
-    hashed_key=`echo -n "${key}" | md5sum | awk '{ print $1 }'`
+    eval `${PBKDF2GEN} ${key}`
     unique_dm_name=`basename ${tempfile}`
-    echo "0 `blockdev --getsize ${loop_dev}` crypt ${CRYPTO} ${hashed_key} 0 ${loop_dev} 0" | dmsetup create ${unique_dm_name}
+    echo "0 `blockdev --getsize ${loop_dev}` crypt ${CRYPTO} ${key} 0 ${loop_dev} 0" | dmsetup create ${unique_dm_name}
     old_loop_dev=${loop_dev}
     loop_dev=/dev/mapper/${unique_dm_name}
 fi
@@ -253,6 +258,11 @@
 
 echo "Successfully created \`${filename}'"
 
+if [ ${use_crypto} -eq 1 ]; then \
+    echo "salt for use with obbtool is:"
+    echo "${salt}"
+fi
+
 #
 # Undo all the temporaries
 #
diff --git a/tools/obbtool/pbkdf2gen.cpp b/tools/obbtool/pbkdf2gen.cpp
new file mode 100644
index 0000000..98d67c0
--- /dev/null
+++ b/tools/obbtool/pbkdf2gen.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <openssl/evp.h>
+
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+/**
+ * Simple program to generate a key based on PBKDF2 with preset inputs.
+ *
+ * Will print out the salt and key in hex.
+ */
+
+#define SALT_LEN 8
+#define ROUNDS 1024
+#define KEY_BITS 128
+
+int main(int argc, char* argv[])
+{
+    if (argc != 2) {
+        fprintf(stderr, "Usage: %s <password>\n", argv[0]);
+        exit(1);
+    }
+
+    int fd = open("/dev/urandom", O_RDONLY);
+    if (fd < 0) {
+        fprintf(stderr, "Could not open /dev/urandom: %s\n", strerror(errno));
+        close(fd);
+        exit(1);
+    }
+
+    unsigned char salt[SALT_LEN];
+
+    if (read(fd, &salt, SALT_LEN) != SALT_LEN) {
+        fprintf(stderr, "Could not read salt from /dev/urandom: %s\n", strerror(errno));
+        close(fd);
+        exit(1);
+    }
+    close(fd);
+
+    unsigned char rawKey[KEY_BITS];
+
+    if (PKCS5_PBKDF2_HMAC_SHA1(argv[1], strlen(argv[1]), salt, SALT_LEN,
+            ROUNDS, KEY_BITS, rawKey) != 1) {
+        fprintf(stderr, "Could not generate PBKDF2 output: %s\n", strerror(errno));
+        exit(1);
+    }
+
+    printf("salt=");
+    for (int i = 0; i < SALT_LEN; i++) {
+        printf("%02x", salt[i]);
+    }
+    printf("\n");
+
+    printf("key=");
+    for (int i = 0; i < (KEY_BITS / 8); i++) {
+        printf("%02x", rawKey[i]);
+    }
+    printf("\n");
+}
diff --git a/tools/preload/WritePreloadedClassFile.java b/tools/preload/WritePreloadedClassFile.java
index 96c539b..b067bc2 100644
--- a/tools/preload/WritePreloadedClassFile.java
+++ b/tools/preload/WritePreloadedClassFile.java
@@ -34,6 +34,11 @@
      */
     static final int MIN_LOAD_TIME_MICROS = 1250;
 
+    /**
+     * Preload any class that was loaded by at least MIN_PROCESSES processes.
+     */
+    static final int MIN_PROCESSES = 10;
+
     public static void main(String[] args) throws IOException,
             ClassNotFoundException {
         if (args.length != 1) {
@@ -58,6 +63,7 @@
         out.write("# Automatically generated by frameworks/base/tools/preload/"
             + WritePreloadedClassFile.class.getSimpleName() + ".java.\n");
         out.write("# MIN_LOAD_TIME_MICROS=" + MIN_LOAD_TIME_MICROS + "\n");
+        out.write("# MIN_PROCESSES=" + MIN_PROCESSES + "\n");
 
         /*
          * The set of classes to preload. We preload a class if:
@@ -73,7 +79,12 @@
         // the memory associated with these classes will be shared.
         for (LoadedClass loadedClass : root.loadedClasses.values()) {
             Set<String> names = loadedClass.processNames();
-            if (shouldPreload(loadedClass) && names.size() > 1) {
+            if (!Policy.isPreloadable(loadedClass)) {
+                continue;
+            }
+
+            if (names.size() >= MIN_PROCESSES ||
+                    (loadedClass.medianTimeMicros() > MIN_LOAD_TIME_MICROS && names.size() > 1)) {
                 toPreload.add(loadedClass);
             }
         }
diff --git a/tools/preload/loadclass/Android.mk b/tools/preload/loadclass/Android.mk
index 435699d..65828be 100644
--- a/tools/preload/loadclass/Android.mk
+++ b/tools/preload/loadclass/Android.mk
@@ -2,6 +2,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_MODULE := loadclass
 
diff --git a/voip/java/com/android/server/sip/SipService.java b/voip/java/com/android/server/sip/SipService.java
index 6f426c9..f41f156c 100644
--- a/voip/java/com/android/server/sip/SipService.java
+++ b/voip/java/com/android/server/sip/SipService.java
@@ -39,6 +39,7 @@
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
+import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -54,6 +55,7 @@
 import java.util.Collection;
 import java.util.Comparator;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Timer;
@@ -92,7 +94,8 @@
             new HashMap<String, ISipSession>();
 
     private ConnectivityReceiver mConnectivityReceiver;
-    private boolean mScreenOn;
+    private boolean mWifiEnabled;
+    private MyWakeLock mMyWakeLock;
 
     /**
      * Starts the SIP service. Do nothing if the SIP API is not supported on the
@@ -112,23 +115,34 @@
         mConnectivityReceiver = new ConnectivityReceiver();
         context.registerReceiver(mConnectivityReceiver,
                 new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
-        context.registerReceiver(mScreenOnOffReceiver,
-                new IntentFilter(Intent.ACTION_SCREEN_ON));
-        context.registerReceiver(mScreenOnOffReceiver,
-                new IntentFilter(Intent.ACTION_SCREEN_OFF));
+        context.registerReceiver(mWifiStateReceiver,
+                new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION));
+        mMyWakeLock = new MyWakeLock((PowerManager)
+                context.getSystemService(Context.POWER_SERVICE));
 
         mTimer = new WakeupTimer(context);
         mWifiOnly = SipManager.isSipWifiOnly(context);
     }
 
-    BroadcastReceiver mScreenOnOffReceiver = new BroadcastReceiver() {
+    BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
-            if (Intent.ACTION_SCREEN_OFF.equals(action)) {
-                mScreenOn = true;
-            } else if (Intent.ACTION_SCREEN_ON.equals(action)) {
-                mScreenOn = false;
+            if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
+                int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
+                        WifiManager.WIFI_STATE_UNKNOWN);
+                synchronized (SipService.this) {
+                    switch (state) {
+                        case WifiManager.WIFI_STATE_ENABLED:
+                            mWifiEnabled = true;
+                            if (anyOpened()) grabWifiLock();
+                            break;
+                        case WifiManager.WIFI_STATE_DISABLED:
+                            mWifiEnabled = false;
+                            releaseWifiLock();
+                            break;
+                    }
+                }
             }
         }
     };
@@ -182,7 +196,7 @@
                     incomingCallPendingIntent, listener);
             if (localProfile.getAutoRegistration()) {
                 group.openToReceiveCalls();
-                if (isWifiActive()) grabWifiLock();
+                if (mWifiEnabled) grabWifiLock();
             }
         } catch (SipException e) {
             Log.e(TAG, "openToReceiveCalls()", e);
@@ -216,7 +230,11 @@
         group = mSipGroups.remove(localProfileUri);
         notifyProfileRemoved(group.getLocalProfile());
         group.close();
-        if (isWifiActive() && !anyOpened()) releaseWifiLock();
+
+        if (!anyOpened()) {
+            releaseWifiLock();
+            mMyWakeLock.reset(); // in case there's leak
+        }
     }
 
     public synchronized boolean isOpened(String localProfileUri) {
@@ -349,7 +367,7 @@
 
     private void grabWifiLock() {
         if (mWifiLock == null) {
-            if (DEBUG) Log.d(TAG, "acquire wifi lock");
+            if (DEBUG) Log.d(TAG, "~~~~~~~~~~~~~~~~~~~~~ acquire wifi lock");
             mWifiLock = ((WifiManager)
                     mContext.getSystemService(Context.WIFI_SERVICE))
                     .createWifiLock(WifiManager.WIFI_MODE_FULL, TAG);
@@ -359,16 +377,12 @@
 
     private void releaseWifiLock() {
         if (mWifiLock != null) {
-            if (DEBUG) Log.d(TAG, "release wifi lock");
+            if (DEBUG) Log.d(TAG, "~~~~~~~~~~~~~~~~~~~~~ release wifi lock");
             mWifiLock.release();
             mWifiLock = null;
         }
     }
 
-    private boolean isWifiActive() {
-        return "WIFI".equalsIgnoreCase(mNetworkType);
-    }
-
     private synchronized void onConnectivityChanged(
             String type, boolean connected) {
         if (DEBUG) Log.d(TAG, "onConnectivityChanged(): "
@@ -382,14 +396,6 @@
         boolean isWifi = "WIFI".equalsIgnoreCase(type);
         boolean wifiOff = (isWifi && !connected) || (wasWifi && !sameType);
         boolean wifiOn = isWifi && connected;
-        if (wifiOff) {
-            if (mScreenOn) releaseWifiLock();
-            // If the screen is off, we still keep the wifi lock in order
-            // to be able to reassociate with any available AP. Otherwise,
-            // the wifi driver could be stopped after 15 mins of idle time.
-        } else if (wifiOn) {
-            if (anyOpened()) grabWifiLock();
-        }
 
         try {
             boolean wasConnected = mConnected;
@@ -408,8 +414,9 @@
                 for (SipSessionGroupExt group : mSipGroups.values()) {
                     group.onConnectivityChanged(true);
                 }
+            } else {
+                mMyWakeLock.reset(); // in case there's a leak
             }
-
         } catch (SipException e) {
             Log.e(TAG, "onConnectivityChanged()", e);
         }
@@ -585,7 +592,7 @@
     }
 
     // KeepAliveProcess is controlled by AutoRegistrationProcess.
-    // All methods will be invoked in sync with SipService.this except realRun()
+    // All methods will be invoked in sync with SipService.this.
     private class KeepAliveProcess implements Runnable {
         private static final String TAG = "\\KEEPALIVE/";
         private static final int INTERVAL = 10;
@@ -604,43 +611,33 @@
 
         // timeout handler
         public void run() {
-            if (!mRunning) return;
-            final SipSessionGroup.SipSessionImpl session = mSession;
-
-            // delegate to mExecutor
-            getExecutor().addTask(new Runnable() {
-                public void run() {
-                    realRun(session);
-                }
-            });
-        }
-
-        // real timeout handler
-        private void realRun(SipSessionGroup.SipSessionImpl session) {
             synchronized (SipService.this) {
-                if (notCurrentSession(session)) return;
+                if (!mRunning) return;
 
-                session = session.duplicate();
-                if (DEBUGV) Log.v(TAG, "~~~ keepalive");
-                mTimer.cancel(this);
-                session.sendKeepAlive();
-                if (session.isReRegisterRequired()) {
-                    mSession.register(EXPIRY_TIME);
-                } else {
-                    mTimer.set(INTERVAL * 1000, this);
+                if (DEBUGV) Log.v(TAG, "~~~ keepalive: "
+                        + mSession.getLocalProfile().getUriString());
+                SipSessionGroup.SipSessionImpl session = mSession.duplicate();
+                try {
+                    session.sendKeepAlive();
+                    if (session.isReRegisterRequired()) {
+                        // Acquire wake lock for the registration process. The
+                        // lock will be released when registration is complete.
+                        mMyWakeLock.acquire(mSession);
+                        mSession.register(EXPIRY_TIME);
+                    }
+                } catch (Throwable t) {
+                    Log.w(TAG, "keepalive error: " + t);
                 }
             }
         }
 
         public void stop() {
+            if (DEBUGV && (mSession != null)) Log.v(TAG, "stop keepalive:"
+                    + mSession.getLocalProfile().getUriString());
             mRunning = false;
             mSession = null;
             mTimer.cancel(this);
         }
-
-        private boolean notCurrentSession(ISipSession session) {
-            return (session != mSession) || !mRunning;
-        }
     }
 
     private class AutoRegistrationProcess extends SipSessionAdapter
@@ -671,6 +668,7 @@
                 // start unregistration to clear up old registration at server
                 // TODO: when rfc5626 is deployed, use reg-id and sip.instance
                 // in registration to avoid adding duplicate entries to server
+                mMyWakeLock.acquire(mSession);
                 mSession.unregister();
                 if (DEBUG) Log.d(TAG, "start AutoRegistrationProcess for "
                         + mSession.getLocalProfile().getUriString());
@@ -680,8 +678,11 @@
         public void stop() {
             if (!mRunning) return;
             mRunning = false;
-            mSession.setListener(null);
-            if (mConnected && mRegistered) mSession.unregister();
+            mMyWakeLock.release(mSession);
+            if (mSession != null) {
+                mSession.setListener(null);
+                if (mConnected && mRegistered) mSession.unregister();
+            }
 
             mTimer.cancel(this);
             if (mKeepAliveProcess != null) {
@@ -738,29 +739,18 @@
             return mRegistered;
         }
 
-        // timeout handler
+        // timeout handler: re-register
         public void run() {
             synchronized (SipService.this) {
                 if (!mRunning) return;
-                final SipSessionGroup.SipSessionImpl session = mSession;
 
-                // delegate to mExecutor
-                getExecutor().addTask(new Runnable() {
-                    public void run() {
-                        realRun(session);
-                    }
-                });
-            }
-        }
-
-        // real timeout handler
-        private void realRun(SipSessionGroup.SipSessionImpl session) {
-            synchronized (SipService.this) {
-                if (notCurrentSession(session)) return;
                 mErrorCode = SipErrorCode.NO_ERROR;
                 mErrorMessage = null;
                 if (DEBUG) Log.d(TAG, "~~~ registering");
-                if (mConnected) session.register(EXPIRY_TIME);
+                if (mConnected) {
+                    mMyWakeLock.acquire(mSession);
+                    mSession.register(EXPIRY_TIME);
+                }
             }
         }
 
@@ -810,6 +800,7 @@
         private boolean notCurrentSession(ISipSession session) {
             if (session != mSession) {
                 ((SipSessionGroup.SipSessionImpl) session).setListener(null);
+                mMyWakeLock.release(session);
                 return true;
             }
             return !mRunning;
@@ -846,6 +837,7 @@
                             mKeepAliveProcess.start();
                         }
                     }
+                    mMyWakeLock.release(session);
                 } else {
                     mRegistered = false;
                     mExpiryTime = -1L;
@@ -876,6 +868,7 @@
                 mErrorCode = errorCode;
                 mErrorMessage = message;
                 mProxy.onRegistrationFailed(session, errorCode, message);
+                mMyWakeLock.release(session);
             }
         }
 
@@ -888,6 +881,7 @@
                 mErrorCode = SipErrorCode.TIME_OUT;
                 mProxy.onRegistrationTimeout(session);
                 restartLater();
+                mMyWakeLock.release(session);
             }
         }
 
@@ -906,7 +900,16 @@
         private MyTimerTask mTask;
 
         @Override
-        public void onReceive(Context context, Intent intent) {
+        public void onReceive(final Context context, final Intent intent) {
+            // Run the handler in MyExecutor to be protected by wake lock
+            getExecutor().execute(new Runnable() {
+                public void run() {
+                    onReceiveInternal(context, intent);
+                }
+            });
+        }
+
+        private void onReceiveInternal(Context context, Intent intent) {
             String action = intent.getAction();
             if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
                 Bundle b = intent.getExtras();
@@ -974,11 +977,13 @@
                     if (mTask != null) mTask.cancel();
                     mTask = new MyTimerTask(type, connected);
                     mTimer.schedule(mTask, 2 * 1000L);
-                    // TODO: hold wakup lock so that we can finish change before
-                    // the device goes to sleep
+                    // hold wakup lock so that we can finish changes before the
+                    // device goes to sleep
+                    mMyWakeLock.acquire(mTask);
                 } else {
                     if ((mTask != null) && mTask.mNetworkType.equals(type)) {
                         mTask.cancel();
+                        mMyWakeLock.release(mTask);
                     }
                     onConnectivityChanged(type, false);
                 }
@@ -998,7 +1003,7 @@
             @Override
             public void run() {
                 // delegate to mExecutor
-                getExecutor().addTask(new Runnable() {
+                getExecutor().execute(new Runnable() {
                     public void run() {
                         realRun();
                     }
@@ -1016,6 +1021,7 @@
                     if (DEBUG) Log.d(TAG, " deliver change for " + mNetworkType
                             + (mConnected ? " CONNECTED" : "DISCONNECTED"));
                     onConnectivityChanged(mNetworkType, mConnected);
+                    mMyWakeLock.release(this);
                 }
             }
         }
@@ -1023,7 +1029,6 @@
 
     // TODO: clean up pending SipSession(s) periodically
 
-
     /**
      * Timer that can schedule events to occur even when the device is in sleep.
      * Only used internally in this package.
@@ -1213,7 +1218,8 @@
         }
 
         @Override
-        public synchronized void onReceive(Context context, Intent intent) {
+        public void onReceive(Context context, Intent intent) {
+            // This callback is already protected by AlarmManager's wake lock.
             String action = intent.getAction();
             if (getAction().equals(action)
                     && intent.getExtras().containsKey(TRIGGER_TIME)) {
@@ -1240,7 +1246,7 @@
             }
         }
 
-        private void execute(long triggerTime) {
+        private synchronized void execute(long triggerTime) {
             if (DEBUG_TIMER) Log.d(TAG, "time's up, triggerTime = "
                     + showTime(triggerTime) + ": " + mEventQueue.size());
             if (stopped() || mEventQueue.isEmpty()) return;
@@ -1252,9 +1258,8 @@
                 event.mLastTriggerTime = event.mTriggerTime;
                 event.mTriggerTime += event.mPeriod;
 
-                // run the callback in a new thread to prevent deadlock
-                new Thread(event.mCallback, "SipServiceTimerCallbackThread")
-                        .start();
+                // run the callback in the handler thread to prevent deadlock
+                getExecutor().execute(event.mCallback);
             }
             if (DEBUG_TIMER) {
                 Log.d(TAG, "after timeout execution");
@@ -1318,29 +1323,78 @@
         }
     }
 
-    // Single-threaded executor
-    private static class MyExecutor extends Handler {
+    private static Looper createLooper() {
+        HandlerThread thread = new HandlerThread("SipService.Executor");
+        thread.start();
+        return thread.getLooper();
+    }
+
+    // Executes immediate tasks in a single thread.
+    // Hold/release wake lock for running tasks
+    private class MyExecutor extends Handler {
         MyExecutor() {
             super(createLooper());
         }
 
-        private static Looper createLooper() {
-            HandlerThread thread = new HandlerThread("SipService");
-            thread.start();
-            return thread.getLooper();
-        }
-
-        void addTask(Runnable task) {
+        void execute(Runnable task) {
+            mMyWakeLock.acquire(task);
             Message.obtain(this, 0/* don't care */, task).sendToTarget();
         }
 
         @Override
         public void handleMessage(Message msg) {
             if (msg.obj instanceof Runnable) {
-                ((Runnable) msg.obj).run();
+                executeInternal((Runnable) msg.obj);
             } else {
                 Log.w(TAG, "can't handle msg: " + msg);
             }
         }
+
+        private void executeInternal(Runnable task) {
+            try {
+                task.run();
+            } catch (Throwable t) {
+                Log.e(TAG, "run task: " + task, t);
+            } finally {
+                mMyWakeLock.release(task);
+            }
+        }
+    }
+
+    private static class MyWakeLock {
+        private PowerManager mPowerManager;
+        private PowerManager.WakeLock mWakeLock;
+        private HashSet<Object> mHolders = new HashSet<Object>();
+
+        MyWakeLock(PowerManager powerManager) {
+            mPowerManager = powerManager;
+        }
+
+        synchronized void reset() {
+            mHolders.clear();
+            release(null);
+            if (DEBUGV) Log.v(TAG, "~~~ hard reset wakelock");
+        }
+
+        synchronized void acquire(Object holder) {
+            mHolders.add(holder);
+            if (mWakeLock == null) {
+                mWakeLock = mPowerManager.newWakeLock(
+                        PowerManager.PARTIAL_WAKE_LOCK, "SipWakeLock");
+            }
+            if (!mWakeLock.isHeld()) mWakeLock.acquire();
+            if (DEBUGV) Log.v(TAG, "acquire wakelock: holder count="
+                    + mHolders.size());
+        }
+
+        synchronized void release(Object holder) {
+            mHolders.remove(holder);
+            if ((mWakeLock != null) && mHolders.isEmpty()
+                    && mWakeLock.isHeld()) {
+                mWakeLock.release();
+            }
+            if (DEBUGV) Log.v(TAG, "release wakelock: holder count="
+                    + mHolders.size());
+        }
     }
 }
diff --git a/voip/java/com/android/server/sip/SipSessionGroup.java b/voip/java/com/android/server/sip/SipSessionGroup.java
index 57b3710..2b8058f 100644
--- a/voip/java/com/android/server/sip/SipSessionGroup.java
+++ b/voip/java/com/android/server/sip/SipSessionGroup.java
@@ -153,7 +153,13 @@
     }
 
     synchronized void onConnectivityChanged() {
-        for (SipSessionImpl s : mSessionMap.values()) {
+        SipSessionImpl[] ss = mSessionMap.values().toArray(
+                    new SipSessionImpl[mSessionMap.size()]);
+        // Iterate on the copied array instead of directly on mSessionMap to
+        // avoid ConcurrentModificationException being thrown when
+        // SipSessionImpl removes itself from mSessionMap in onError() in the
+        // following loop.
+        for (SipSessionImpl s : ss) {
             s.onError(SipErrorCode.DATA_CONNECTION_LOST,
                     "data connection lost");
         }
@@ -541,8 +547,14 @@
             mState = SipSession.State.PINGING;
             try {
                 processCommand(new OptionsCommand());
-                while (SipSession.State.PINGING == mState) {
-                    Thread.sleep(1000);
+                for (int i = 0; i < 15; i++) {
+                    if (SipSession.State.PINGING != mState) break;
+                    Thread.sleep(200);
+                }
+                if (SipSession.State.PINGING == mState) {
+                    // FIXME: what to do if server doesn't respond
+                    reset();
+                    if (DEBUG) Log.w(TAG, "no response from ping");
                 }
             } catch (SipException e) {
                 Log.e(TAG, "sendKeepAlive failed", e);
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index 281077c..06f6696 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -1285,15 +1285,13 @@
                         if (macaddr != null) {
                             mWifiInfo.setMacAddress(macaddr);
                         }
-                        if (mRunState == RUN_STATE_STARTING) {
-                            mRunState = RUN_STATE_RUNNING;
-                            if (!mIsScanOnly) {
-                                reconnectCommand();
-                            } else {
-                                // In some situations, supplicant needs to be kickstarted to
-                                // start the background scanning
-                                scan(true);
-                            }
+                        mRunState = RUN_STATE_RUNNING;
+                        if (!mIsScanOnly) {
+                            reconnectCommand();
+                        } else {
+                            // In some situations, supplicant needs to be kickstarted to
+                            // start the background scanning
+                            scan(true);
                         }
                     }
                     break;
@@ -1613,12 +1611,10 @@
     }
 
     public synchronized boolean restart() {
-        if (mRunState == RUN_STATE_STOPPED) {
+        if (isDriverStopped()) {
             mRunState = RUN_STATE_STARTING;
             resetConnections(true);
             return startDriver();
-        } else if (mRunState == RUN_STATE_STOPPING) {
-            mRunState = RUN_STATE_STARTING;
         }
         return true;
     }