Merge "Do not merge: Add some input checking to prevent problems" into honeycomb-LTE
diff --git a/Android.mk b/Android.mk
index a28bde2..de0112c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -123,10 +123,10 @@
 	core/java/android/nfc/ILlcpServiceSocket.aidl \
 	core/java/android/nfc/ILlcpSocket.aidl \
 	core/java/android/nfc/INfcAdapter.aidl \
+	core/java/android/nfc/INfcAdapterExtras.aidl \
 	core/java/android/nfc/INfcTag.aidl \
 	core/java/android/nfc/IP2pInitiator.aidl \
 	core/java/android/nfc/IP2pTarget.aidl \
-    core/java/android/nfc/INfcSecureElement.aidl \
 	core/java/android/os/IHardwareService.aidl \
 	core/java/android/os/IMessenger.aidl \
 	core/java/android/os/INetworkManagementService.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 2eee813..023ce59 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -95,7 +95,7 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/PerfTest_intermediates/)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/RSTest_intermediates/)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/hardware/IUsbManager.java)
-
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/nfc)
 
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index d439a48..870127c 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -28,7 +28,7 @@
 import android.nfc.INfcTag;
 import android.nfc.IP2pTarget;
 import android.nfc.IP2pInitiator;
-import android.nfc.INfcSecureElement;
+import android.nfc.INfcAdapterExtras;
 
 /**
  * @hide
@@ -41,13 +41,12 @@
     INfcTag getNfcTagInterface();
     IP2pTarget getP2pTargetInterface();
     IP2pInitiator getP2pInitiatorInterface();
-    INfcSecureElement getNfcSecureElementInterface();
+    INfcAdapterExtras getNfcAdapterExtrasInterface();
 
     // NfcAdapter-class related methods
     boolean isEnabled();
     NdefMessage localGet();
     void localSet(in NdefMessage message);
-    void openTagConnection(in Tag tag);
     void enableForegroundDispatch(in ComponentName activity, in PendingIntent intent,
             in IntentFilter[] filters, in TechListParcel techLists);
     void disableForegroundDispatch(in ComponentName activity);
@@ -59,12 +58,8 @@
     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/android/nfc/INfcSecureElement.aidl b/core/java/android/nfc/INfcAdapterExtras.aidl
similarity index 63%
rename from core/java/android/nfc/INfcSecureElement.aidl
rename to core/java/android/nfc/INfcAdapterExtras.aidl
index aa98dd2..ab5c1a6 100755
--- a/core/java/android/nfc/INfcSecureElement.aidl
+++ b/core/java/android/nfc/INfcAdapterExtras.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2011 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,13 +16,15 @@
 
 package android.nfc;
 
+import android.os.Bundle;
+
 /**
  * {@hide}
  */
-interface INfcSecureElement {
-    int openSecureElementConnection();
-    int closeSecureElementConnection(int nativeHandle);
-    byte[] exchangeAPDU(int nativeHandle, in byte[] data);
-    int[] getSecureElementTechList(int nativeHandle);
-    byte[] getSecureElementUid(int nativeHandle);
-}
\ No newline at end of file
+interface INfcAdapterExtras {
+    Bundle open(IBinder b);
+    Bundle close();
+    Bundle transceive(in byte[] data_in);
+    int getCardEmulationRoute();
+    void setCardEmulationRoute(int route);    
+}
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 8c56fda..4689804 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -157,31 +157,6 @@
     public static final String EXTRA_ID = "android.nfc.extra.ID";
 
     /**
-     * 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";
-
-    /**
-     * Broadcast Action: an RF field ON has been detected.
-     * @hide
-     */
-    public static final String ACTION_RF_FIELD_ON_DETECTED =
-            "android.nfc.action.RF_FIELD_ON_DETECTED";
-
-    /**
-     * Broadcast Action: an RF Field OFF has been detected.
-     * @hide
-     */
-    public static final String ACTION_RF_FIELD_OFF_DETECTED =
-            "android.nfc.action.RF_FIELD_OFF_DETECTED";
-
-    /**
      * Broadcast Action: an adapter's state changed between enabled and disabled.
      *
      * The new value is stored in the extra EXTRA_NEW_BOOLEAN_STATE and just contains
@@ -201,15 +176,6 @@
     public static final String EXTRA_NEW_BOOLEAN_STATE = "android.nfc.isEnabled";
 
     /**
-     * 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
      */
@@ -691,39 +657,14 @@
     }
 
     /**
-     * Create an Nfc Secure Element Connection
      * @hide
      */
-    public NfcSecureElement createNfcSecureElementConnection() {
+    public INfcAdapterExtras getNfcAdapterExtrasInterface() {
         try {
-            return new NfcSecureElement(sService.getNfcSecureElementInterface());
+            return sService.getNfcAdapterExtrasInterface();
         } catch (RemoteException e) {
-            Log.e(TAG, "createNfcSecureElementConnection failed", e);
+            attemptDeadServiceRecovery(e);
             return null;
         }
     }
-
-    /**
-     * To change the Secure Element Card Emulation state (ON/OFF)
-     * @hide
-     */
-    public void changeNfcSecureElementCardEmulationState(boolean state)
-    {
-        int seId = 11259375;
-        if(state){
-            /* Enable card emulation */
-            try {
-                sService.selectSecureElement(seId);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Enable card emulation failed", e);
-            }
-        }else{
-            /* Disable card emulation */
-            try {
-                sService.deselectSecureElement();
-            } catch (RemoteException e) {
-                Log.e(TAG, " card emulation failed", e);
-            }
-        }
-    }
 }
diff --git a/core/java/android/nfc/NfcSecureElement.java b/core/java/android/nfc/NfcSecureElement.java
deleted file mode 100755
index 3b5f39e..0000000
--- a/core/java/android/nfc/NfcSecureElement.java
+++ /dev/null
@@ -1,138 +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 android.nfc;
-
-import android.nfc.tech.TagTechnology;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.io.IOException;
-
-//import android.util.Log;
-
-/**
- * This class provides the primary API for managing all aspects Secure Element.
- * Get an instance of this class by calling
- * Context.getSystemService(Context.NFC_SERVICE).
- * @hide
- */
-public final class NfcSecureElement {
-
-    private static final String TAG = "NfcSecureElement";
-
-    private INfcSecureElement mService;
-
-
-    /**
-     * @hide
-     */
-    public NfcSecureElement(INfcSecureElement mSecureElementService) {
-        mService = mSecureElementService;
-    }
-
-    public int openSecureElementConnection(String seType) throws IOException {
-        if (seType.equals("SmartMX")) {
-            try {
-                int handle = mService.openSecureElementConnection();
-                // Handle potential errors
-                if (handle != 0) {
-                    return handle;
-                } else {
-                    throw new IOException("SmartMX connection not allowed");
-                }
-            } catch (RemoteException e) {
-                Log.e(TAG, "RemoteException in openSecureElementConnection(): ", e);
-                return 0;
-            }
-
-        } else if (seType.equals("UICC")) {
-            return 0;
-        } else {
-        	throw new IOException("Wrong Secure Element type");
-        }
-    }
-
-
-    public byte [] exchangeAPDU(int handle,byte [] data) throws IOException {
-
-
-        // Perform exchange APDU
-        try {
-            byte[] response = mService.exchangeAPDU(handle, data);
-            // Handle potential errors
-            if (response == null) {
-            	throw new IOException("Exchange APDU failed");
-            }
-            return response;
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in exchangeAPDU(): ", e);
-            return null;
-        }
-    }
-
-    public void closeSecureElementConnection(int handle) throws IOException {
-
-        try {
-            int status = mService.closeSecureElementConnection(handle);
-            // Handle potential errors
-            if (ErrorCodes.isError(status)) {
-            	throw new IOException("Error during the conection close");
-            };
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in closeSecureElement(): ", e);
-        }
-    }
-
-
-    /**
-     * Returns target type. constants.
-     *
-     * @return Secure Element technology type. The possible values are defined in
-     * {@link TagTechnology}
-     *
-     */
-    public int[] getSecureElementTechList(int handle) throws IOException {
-        try {
-            return mService.getSecureElementTechList(handle);
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in getType(): ", e);
-            return null;
-        }
-    }
-
-    /**
-     * Returns Secure Element UID.
-     *
-     * @return Secure Element UID.
-     */
-    public byte[] getSecureElementUid(int handle) throws IOException {
-
-        byte[] uid = null;
-        try {
-            uid = mService.getSecureElementUid(handle);
-            // Handle potential errors
-            if (uid == null) {
-                throw new IOException("Get Secure Element UID failed");
-            }
-            return uid;
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in getType(): ", e);
-            return null;
-        }
-    }
-
-}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index c684e7e..0c9a2ef 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -91,10 +91,15 @@
     <protected-broadcast android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
 
     <protected-broadcast android:name="android.nfc.action.LLCP_LINK_STATE_CHANGED" />
+    <protected-broadcast android:name="com.android.nfc_extras.action.RF_FIELD_ON_DETECTED" />
+    <protected-broadcast android:name="com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED" />
+    <protected-broadcast android:name="com.android.nfc_extras.action.AID_SELECTED" />
+
     <protected-broadcast android:name="android.nfc.action.TRANSACTION_DETECTED" />
     <protected-broadcast android:name="android.intent.action.CLEAR_DNS_CACHE" />
     <protected-broadcast android:name="android.intent.action.PROXY_CHANGE" />
 
+
     <!-- ====================================== -->
     <!-- Permissions for things that cost money -->
     <!-- ====================================== -->
diff --git a/core/res/res/drawable-hdpi/ic_paste_bubble_holo_disabled.png b/core/res/res/drawable-hdpi/ic_paste_bubble_holo_disabled.png
new file mode 100644
index 0000000..15bd8b2
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_paste_bubble_holo_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_paste_bubble_holo_disabled.png b/core/res/res/drawable-mdpi/ic_paste_bubble_holo_disabled.png
new file mode 100644
index 0000000..e483e84
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_paste_bubble_holo_disabled.png
Binary files differ
diff --git a/core/res/res/layout/text_edit_no_paste_window.xml b/core/res/res/layout/text_edit_no_paste_window.xml
index fa50275..f804986 100644
--- a/core/res/res/layout/text_edit_no_paste_window.xml
+++ b/core/res/res/layout/text_edit_no_paste_window.xml
@@ -25,7 +25,7 @@
         android:paddingRight="16dip"
         android:paddingTop="8dip"
         android:paddingBottom="8dip"
-        android:drawableLeft="@android:drawable/ic_menu_paste_dark"
+        android:drawableLeft="@android:drawable/ic_paste_bubble_holo_disabled"
         android:drawablePadding="8dip"
         android:gravity="center"
         android:textAppearance="?android:attr/textAppearanceMediumInverse"
diff --git a/core/res/res/layout/text_edit_side_no_paste_window.xml b/core/res/res/layout/text_edit_side_no_paste_window.xml
index 0ed3849..903bcb6 100644
--- a/core/res/res/layout/text_edit_side_no_paste_window.xml
+++ b/core/res/res/layout/text_edit_side_no_paste_window.xml
@@ -25,7 +25,7 @@
         android:paddingRight="16dip"
         android:paddingTop="8dip"
         android:paddingBottom="8dip"
-        android:drawableLeft="@android:drawable/ic_menu_paste_dark"
+        android:drawableLeft="@android:drawable/ic_paste_bubble_holo_disabled"
         android:drawablePadding="8dip"
         android:gravity="center"
         android:textAppearance="?android:attr/textAppearanceMediumInverse"
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index fd12e19..9d0cba3 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -110,6 +110,8 @@
     private static final int MSG_PLAY_SOUND_EFFECT = 7;
     private static final int MSG_BTA2DP_DOCK_TIMEOUT = 8;
     private static final int MSG_LOAD_SOUND_EFFECTS = 9;
+    private static final int MSG_SET_FORCE_USE = 10;
+
 
     private static final int BTA2DP_DOCK_TIMEOUT_MILLIS = 8000;
 
@@ -1170,22 +1172,15 @@
         if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) {
             return;
         }
-        if (on) {
-            AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_SPEAKER);
-            mForcedUseForComm = AudioSystem.FORCE_SPEAKER;
-        } else {
-            AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_NONE);
-            mForcedUseForComm = AudioSystem.FORCE_NONE;
-        }
+        mForcedUseForComm = on ? AudioSystem.FORCE_SPEAKER : AudioSystem.FORCE_NONE;
+
+        sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SHARED_MSG, SENDMSG_QUEUE,
+                AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0);
     }
 
     /** @see AudioManager#isSpeakerphoneOn() */
     public boolean isSpeakerphoneOn() {
-        if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER) {
-            return true;
-        } else {
-            return false;
-        }
+        return (mForcedUseForComm == AudioSystem.FORCE_SPEAKER);
     }
 
     /** @see AudioManager#setBluetoothScoOn() */
@@ -1193,24 +1188,17 @@
         if (!checkAudioSettingsPermission("setBluetoothScoOn()")) {
             return;
         }
-        if (on) {
-            AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_BT_SCO);
-            AudioSystem.setForceUse(AudioSystem.FOR_RECORD, AudioSystem.FORCE_BT_SCO);
-            mForcedUseForComm = AudioSystem.FORCE_BT_SCO;
-        } else {
-            AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_NONE);
-            AudioSystem.setForceUse(AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE);
-            mForcedUseForComm = AudioSystem.FORCE_NONE;
-        }
+        mForcedUseForComm = on ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE;
+
+        sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SHARED_MSG, SENDMSG_QUEUE,
+                AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0);
+        sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SHARED_MSG, SENDMSG_QUEUE,
+                AudioSystem.FOR_RECORD, mForcedUseForComm, null, 0);
     }
 
     /** @see AudioManager#isBluetoothScoOn() */
     public boolean isBluetoothScoOn() {
-        if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
-            return true;
-        } else {
-            return false;
-        }
+        return (mForcedUseForComm == AudioSystem.FORCE_BT_SCO);
     }
 
     /** @see AudioManager#startBluetoothSco() */
@@ -1935,6 +1923,10 @@
             }
         }
 
+        private void setForceUse(int usage, int config) {
+            AudioSystem.setForceUse(usage, config);
+        }
+
         @Override
         public void handleMessage(Message msg) {
             int baseMsgWhat = getMsgBase(msg.what);
@@ -2026,6 +2018,10 @@
                     // msg.obj  == address of BTA2DP device
                     makeA2dpDeviceUnavailableNow( (String) msg.obj );
                     break;
+
+                case MSG_SET_FORCE_USE:
+                    setForceUse(msg.arg1, msg.arg2);
+                    break;
             }
         }
     }
diff --git a/nfc-extras/Android.mk b/nfc-extras/Android.mk
new file mode 100644
index 0000000..2033508
--- /dev/null
+++ b/nfc-extras/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_MODULE:= com.android.nfc_extras
+
+include $(BUILD_JAVA_LIBRARY)
+
+# put the com.android.nfc_extras.jar into the dist directory
+$(call dist-for-goals, droidcore, $(LOCAL_BUILT_MODULE):com.android.nfc_extras.jar)
diff --git a/nfc-extras/com.android.nfc_extras.xml b/nfc-extras/com.android.nfc_extras.xml
new file mode 100644
index 0000000..370145d
--- /dev/null
+++ b/nfc-extras/com.android.nfc_extras.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<permissions>
+    <library name="com.android.nfc_extras"
+            file="/system/framework/com.android.nfc_extras.jar" />
+</permissions>
diff --git a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
new file mode 100644
index 0000000..cf38bd1
--- /dev/null
+++ b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.nfc_extras;
+
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.nfc.INfcAdapterExtras;
+import android.nfc.NfcAdapter;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * Provides additional methods on an {@link NfcAdapter} for Card Emulation
+ * and management of {@link NfcExecutionEnvironment}'s.
+ *
+ * There is a 1-1 relationship between an {@link NfcAdapterExtras} object and
+ * a {@link NfcAdapter} object.
+ */
+public final class NfcAdapterExtras {
+    private static final String TAG = "NfcAdapterExtras";
+
+    /**
+     * Broadcast Action: an RF field ON has been detected.
+     *
+     * <p class="note">This is an unreliable signal, and will be removed.
+     * <p class="note">
+     * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission
+     * to receive.
+     */
+    public static final String ACTION_RF_FIELD_ON_DETECTED =
+            "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED";
+
+    /**
+     * Broadcast Action: an RF field OFF has been detected.
+     *
+     * <p class="note">This is an unreliable signal, and will be removed.
+     * <p class="note">
+     * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission
+     * to receive.
+     */
+    public static final String ACTION_RF_FIELD_OFF_DETECTED =
+            "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED";
+
+    // protected by NfcAdapterExtras.class, and final after first construction
+    private static INfcAdapterExtras sService;
+    private static boolean sIsInitialized = false;
+    private static NfcAdapterExtras sSingleton;
+    private static NfcExecutionEnvironment sEmbeddedEe;
+    private static CardEmulationRoute sRouteOff;
+    private static CardEmulationRoute sRouteOnWhenScreenOn;
+
+    /**
+     * Get the {@link NfcAdapterExtras} for the given {@link NfcAdapter}.
+     *
+     * <p class="note">
+     * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
+     *
+     * @param adapter a {@link NfcAdapter}, must not be null
+     * @return the {@link NfcAdapterExtras} object for the given {@link NfcAdapter}
+     */
+    public static NfcAdapterExtras get(NfcAdapter adapter) {
+        synchronized(NfcAdapterExtras.class) {
+            if (!sIsInitialized) {
+               sIsInitialized = true;
+               sService = adapter.getNfcAdapterExtrasInterface();
+               sEmbeddedEe = new NfcExecutionEnvironment(sService);
+               sRouteOff = new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null);
+               sRouteOnWhenScreenOn = new CardEmulationRoute(
+                       CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON, sEmbeddedEe);
+               sSingleton = new NfcAdapterExtras();
+            }
+            return sSingleton;
+        }
+    }
+
+    private NfcAdapterExtras() {}
+
+    /**
+     * Immutable data class that describes a card emulation route.
+     */
+    public final static class CardEmulationRoute {
+        /**
+         * Card Emulation is turned off on this NfcAdapter.
+         * <p>This is the default routing state after boot.
+         */
+        public static final int ROUTE_OFF = 1;
+
+        /**
+         * Card Emulation is routed to {@link #nfcEe} only when the screen is on,
+         * otherwise it is turned off.
+         */
+        public static final int ROUTE_ON_WHEN_SCREEN_ON = 2;
+
+        /**
+         * A route such as {@link #ROUTE_OFF} or {@link #ROUTE_ON_WHEN_SCREEN_ON}.
+         */
+        public final int route;
+
+        /**
+         * The {@link NFcExecutionEnvironment} that is Card Emulation is routed to.
+         * <p>null if {@link #route} is {@link #ROUTE_OFF}, otherwise not null.
+         */
+        public final NfcExecutionEnvironment nfcEe;
+
+        public CardEmulationRoute(int route, NfcExecutionEnvironment nfcEe) {
+            if (route == ROUTE_OFF && nfcEe != null) {
+                throw new IllegalArgumentException("must not specifiy a NFC-EE with ROUTE_OFF");
+            } else if (route != ROUTE_OFF && nfcEe == null) {
+                throw new IllegalArgumentException("must specifiy a NFC-EE for this route");
+            }
+            this.route = route;
+            this.nfcEe = nfcEe;
+        }
+    }
+
+    /**
+     * Get the routing state of this NFC EE.
+     *
+     * <p class="note">
+     * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
+     *
+     * @return
+     */
+    public CardEmulationRoute getCardEmulationRoute() {
+        try {
+            int route = sService.getCardEmulationRoute();
+            return route == CardEmulationRoute.ROUTE_OFF ?
+                    sRouteOff :
+                    sRouteOnWhenScreenOn;
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+            return sRouteOff;
+        }
+    }
+
+    /**
+     * Set the routing state of this NFC EE.
+     *
+     * <p>This routing state is not persisted across reboot.
+     *
+     * <p class="note">
+     * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
+     *
+     * @param route a {@link #CardEmulationRoute}
+     */
+    public void setCardEmulationRoute(CardEmulationRoute route) {
+        try {
+            sService.setCardEmulationRoute(route.route);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        }
+    }
+
+    /**
+     * Get the {@link NfcExecutionEnvironment} that is embedded with the
+     * {@link NFcAdapter}.
+     *
+     * <p class="note">
+     * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
+     *
+     * @return a {@link NfcExecutionEnvironment}, or null if there is no embedded NFC-EE
+     */
+    public NfcExecutionEnvironment getEmbeddedExecutionEnvironment() {
+        return sEmbeddedEe;
+    }
+}
diff --git a/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java b/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java
new file mode 100644
index 0000000..3efe492
--- /dev/null
+++ b/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.nfc_extras;
+
+import java.io.IOException;
+
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.content.Context;
+import android.nfc.INfcAdapterExtras;
+import android.nfc.NfcAdapter;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+public class NfcExecutionEnvironment {
+    private final INfcAdapterExtras mService;
+
+    /**
+     * Broadcast Action: An ISO-DEP AID was selected.
+     *
+     * <p>This happens as the result of a 'SELECT AID' command from an
+     * external NFC reader/writer.
+     *
+     * <p>Always contains the extra field {@link #EXTRA_AID}
+     *
+     * <p class="note">
+     * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission
+     * to receive.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_AID_SELECTED =
+        "com.android.nfc_extras.action.AID_SELECTED";
+
+    /**
+     * Mandatory byte array extra field in {@link #ACTION_AID_SELECTED}.
+     *
+     * <p>Contains the AID selected.
+     * @hide
+     */
+    public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID";
+
+    NfcExecutionEnvironment(INfcAdapterExtras service) {
+        mService = service;
+    }
+
+    /**
+     * Open the NFC Execution Environment on its contact interface.
+     *
+     * <p>Only one process may open the secure element at a time. If it is
+     * already open, an {@link IOException} is thrown.
+     *
+     * <p>All other NFC functionality is disabled while the NFC-EE is open
+     * on its contact interface, so make sure to call {@link #close} once complete.
+     *
+     * <p class="note">
+     * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
+     *
+     * @throws IOException if the NFC-EE is already open, or some other error occurs
+     */
+    public void open() throws IOException {
+        try {
+            Bundle b = mService.open(new Binder());
+            throwBundle(b);
+        } catch (RemoteException e) {
+            return;
+        }
+    }
+
+    /**
+     * Close the NFC Execution Environment on its contact interface.
+     *
+     * <p class="note">
+     * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
+     *
+     * @throws IOException if the NFC-EE is already open, or some other error occurs
+     */
+    public void close() throws IOException {
+        try {
+            throwBundle(mService.close());
+        } catch (RemoteException e) {
+            return;
+        }
+    }
+
+    /**
+     * Send raw commands to the NFC-EE and receive the response.
+     *
+     * <p class="note">
+     * Requires the {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
+     *
+     * @throws IOException if the NFC-EE is not open, or some other error occurs
+     */
+    public byte[] transceive(byte[] in) throws IOException {
+        Bundle b;
+        try {
+            b = mService.transceive(in);
+        } catch (RemoteException e) {
+            throw new IOException(e.getMessage());
+        }
+        throwBundle(b);
+        return b.getByteArray("out");
+    }
+
+    private static void throwBundle(Bundle b) throws IOException {
+        if (b.getInt("e") == -1) {
+            throw new IOException(b.getString("m"));
+        }
+    }
+}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index fa63edb..744798e 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -27,6 +27,7 @@
 import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.FileWriter;
+import java.io.InputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.util.Arrays;
@@ -58,15 +59,20 @@
     private static final String KEY_SECURE = "secure";
     private static final String KEY_LOCALE = "locale";
 
+    //Version 2 adds STATE_WIFI_CONFIG
+    private static final int STATE_VERSION_1       = 1;
+    private static final int STATE_VERSION_1_SIZE  = 4;
+
     // Versioning of the state file.  Increment this version
     // number any time the set of state items is altered.
-    private static final int STATE_VERSION = 1;
+    private static final int STATE_VERSION = 2;
 
-    private static final int STATE_SYSTEM = 0;
-    private static final int STATE_SECURE = 1;
-    private static final int STATE_LOCALE = 2;
-    private static final int STATE_WIFI   = 3;
-    private static final int STATE_SIZE   = 4; // The number of state items
+    private static final int STATE_SYSTEM          = 0;
+    private static final int STATE_SECURE          = 1;
+    private static final int STATE_LOCALE          = 2;
+    private static final int STATE_WIFI_SUPPLICANT = 3;
+    private static final int STATE_WIFI_CONFIG     = 4;
+    private static final int STATE_SIZE            = 5; // The number of state items
 
     private static String[] sortedSystemKeys = null;
     private static String[] sortedSecureKeys = null;
@@ -91,12 +97,18 @@
     // the key to store the WIFI data under, should be sorted as last, so restore happens last.
     // use very late unicode character to quasi-guarantee last sort position.
     private static final String KEY_WIFI_SUPPLICANT = "\uffedWIFI";
+    private static final String KEY_WIFI_CONFIG = "\uffedCONFIG_WIFI";
 
     private SettingsHelper mSettingsHelper;
+    private WifiManager mWfm;
+    private static String mWifiConfigFile;
 
     public void onCreate() {
         mSettingsHelper = new SettingsHelper(this);
         super.onCreate();
+
+        WifiManager mWfm = (WifiManager) getSystemService(Context.WIFI_SERVICE);
+        if (mWfm != null) mWifiConfigFile = mWfm.getConfigFile();
     }
 
     @Override
@@ -106,7 +118,8 @@
         byte[] systemSettingsData = getSystemSettings();
         byte[] secureSettingsData = getSecureSettings();
         byte[] locale = mSettingsHelper.getLocaleData();
-        byte[] wifiData = getWifiSupplicant(FILE_WIFI_SUPPLICANT);
+        byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT);
+        byte[] wifiConfigData = getFileData(mWifiConfigFile);
 
         long[] stateChecksums = readOldChecksums(oldState);
 
@@ -116,8 +129,12 @@
                 writeIfChanged(stateChecksums[STATE_SECURE], KEY_SECURE, secureSettingsData, data);
         stateChecksums[STATE_LOCALE] =
                 writeIfChanged(stateChecksums[STATE_LOCALE], KEY_LOCALE, locale, data);
-        stateChecksums[STATE_WIFI] =
-                writeIfChanged(stateChecksums[STATE_WIFI], KEY_WIFI_SUPPLICANT, wifiData, data);
+        stateChecksums[STATE_WIFI_SUPPLICANT] =
+                writeIfChanged(stateChecksums[STATE_WIFI_SUPPLICANT], KEY_WIFI_SUPPLICANT,
+                wifiSupplicantData, data);
+        stateChecksums[STATE_WIFI_CONFIG] =
+                writeIfChanged(stateChecksums[STATE_WIFI_CONFIG], KEY_WIFI_CONFIG, wifiConfigData,
+                data);
 
         writeNewChecksums(stateChecksums, newState);
     }
@@ -148,7 +165,9 @@
                 byte[] localeData = new byte[size];
                 data.readEntityData(localeData, 0, size);
                 mSettingsHelper.setLocaleData(localeData);
-            } else {
+            } else if (KEY_WIFI_CONFIG.equals(key)) {
+                restoreFileData(mWifiConfigFile, data);
+             } else {
                 data.skipEntityData();
             }
         }
@@ -162,7 +181,11 @@
 
         try {
             int stateVersion = dataInput.readInt();
-            if (stateVersion == STATE_VERSION) {
+            if (stateVersion == STATE_VERSION_1) {
+                for (int i = 0; i < STATE_VERSION_1_SIZE; i++) {
+                    stateChecksums[i] = dataInput.readLong();
+                }
+            } else if (stateVersion == STATE_VERSION) {
                 for (int i = 0; i < STATE_SIZE; i++) {
                     stateChecksums[i] = dataInput.readLong();
                 }
@@ -353,6 +376,60 @@
         return result;
     }
 
+    private byte[] getFileData(String filename) {
+        InputStream is = null;
+        try {
+            File file = new File(filename);
+            is = new FileInputStream(file);
+
+            //Will truncate read on a very long file,
+            //should not happen for a config file
+            byte[] bytes = new byte[(int)file.length()];
+
+            int offset = 0;
+            int numRead = 0;
+            while (offset < bytes.length
+                    && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
+                offset += numRead;
+            }
+
+            //read failure
+            if (offset < bytes.length) {
+                Log.w(TAG, "Couldn't backup " + filename);
+                return EMPTY_DATA;
+            }
+            return bytes;
+        } catch (IOException ioe) {
+            Log.w(TAG, "Couldn't backup " + filename);
+            return EMPTY_DATA;
+        } finally {
+            if (is != null) {
+                try {
+                    is.close();
+                } catch (IOException e) {
+                }
+            }
+        }
+
+    }
+
+    private void restoreFileData(String filename, BackupDataInput data) {
+        byte[] bytes = new byte[data.getDataSize()];
+        if (bytes.length <= 0) return;
+        try {
+            data.readEntityData(bytes, 0, bytes.length);
+            File file = new File(filename);
+            if (file.exists()) file.delete();
+
+            OutputStream os = new BufferedOutputStream(new FileOutputStream(filename, true));
+            os.write(bytes);
+            os.close();
+        } catch (IOException ioe) {
+            Log.w(TAG, "Couldn't restore " + filename);
+        }
+    }
+
+
     private byte[] getWifiSupplicant(String filename) {
         BufferedReader br = null;
         try {
@@ -455,10 +532,9 @@
     }
 
     private int enableWifi(boolean enable) {
-        WifiManager wfm = (WifiManager) getSystemService(Context.WIFI_SERVICE);
-        if (wfm != null) {
-            int state = wfm.getWifiState();
-            wfm.setWifiEnabled(enable);
+        if (mWfm != null) {
+            int state = mWfm.getWifiState();
+            mWfm.setWifiEnabled(enable);
             return state;
         }
         return WifiManager.WIFI_STATE_UNKNOWN;
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 3c6c427..0000237 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -29,12 +29,12 @@
 import android.content.pm.PackageManager;
 import android.database.ContentObserver;
 import android.net.wifi.IWifiManager;
+import android.net.wifi.ScanResult;
+import android.net.wifi.SupplicantState;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiStateMachine;
-import android.net.wifi.ScanResult;
 import android.net.wifi.WifiConfiguration;
-import android.net.wifi.SupplicantState;
 import android.net.wifi.WifiConfiguration.KeyMgmt;
 import android.net.wifi.WpsConfiguration;
 import android.net.wifi.WpsResult;
@@ -882,8 +882,6 @@
         mWifiStateMachine.clearBlacklist();
     }
 
-
-
     /**
      * Get a reference to handler. This is used by a client to establish
      * an AsyncChannel communication with WifiService
@@ -898,6 +896,14 @@
         return new Messenger(mAsyncServiceHandler);
     }
 
+    /**
+     * Get the IP and proxy configuration file
+     */
+    public String getConfigFile() {
+        enforceAccessPermission();
+        return mWifiStateMachine.getConfigFile();
+    }
+
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 1d115b1..16a61db 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -104,5 +104,7 @@
     void clearBlacklist();
 
     Messenger getMessenger();
+
+    String getConfigFile();
 }
 
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index e6decc88..6455d84 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -1347,4 +1347,8 @@
         }
         return sb.toString();
     }
+
+    public static String getConfigFile() {
+        return ipConfigFile;
+    }
 }
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 5238899..2e49a77 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1176,6 +1176,18 @@
     }
 
     /**
+     * Returns the file in which IP and proxy configuration data is stored
+     * @hide
+     */
+    public String getConfigFile() {
+        try {
+            return mService.getConfigFile();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
      * Allows an application to keep the Wi-Fi radio awake.
      * Normally the Wi-Fi radio may turn off when the user has not used the device in a while.
      * Acquiring a WifiLock will keep the radio on until the lock is released.  Multiple
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 717dcf0..4346b327 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -887,6 +887,13 @@
     }
 
     /**
+     * Returns the wifi configuration file
+     */
+    public String getConfigFile() {
+        return WifiConfigStore.getConfigFile();
+    }
+
+    /**
      * Send a message indicating bluetooth adapter connection state changed
      */
     public void sendBluetoothAdapterStateChange(int state) {