Merge "Revert to using epoll_wait()." 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..da1d46f8 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 84ccd45..0efc466 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -1145,6 +1145,17 @@
  visibility="public"
 >
 </field>
+<field name="USE_SIP"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.permission.USE_SIP&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="VIBRATE"
  type="java.lang.String"
  transient="false"
@@ -24538,7 +24549,7 @@
 </parameter>
 </method>
 <method name="remove"
- return="void"
+ return="int"
  abstract="false"
  native="false"
  synchronized="false"
@@ -24547,7 +24558,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="id" type="long">
+<parameter name="ids" type="long...">
 </parameter>
 </method>
 <field name="ACTION_DOWNLOAD_COMPLETE"
@@ -24638,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"
@@ -24940,7 +24962,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="id" type="long">
+<parameter name="ids" type="long...">
 </parameter>
 </method>
 <method name="setFilterByStatus"
@@ -48191,6 +48213,16 @@
  visibility="public"
 >
 </field>
+<field name="firstInstallTime"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="gids"
  type="int[]"
  transient="false"
@@ -48213,6 +48245,16 @@
  visibility="public"
 >
 </field>
+<field name="lastUpdateTime"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="packageName"
  type="java.lang.String"
  transient="false"
@@ -79272,7 +79314,7 @@
  type="float"
  transient="false"
  volatile="false"
- value="0.001f"
+ value="0.0010f"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -99439,6 +99481,1945 @@
 </field>
 </class>
 </package>
+<package name="android.net.sip"
+>
+<class name="SipAudioCall"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="SipAudioCall"
+ type="android.net.sip.SipAudioCall"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="localProfile" type="android.net.sip.SipProfile">
+</parameter>
+</constructor>
+<method name="answerCall"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="timeout" type="int">
+</parameter>
+<exception name="SipException" type="android.net.sip.SipException">
+</exception>
+</method>
+<method name="attachCall"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="session" type="android.net.sip.SipSession">
+</parameter>
+<parameter name="sessionDescription" type="java.lang.String">
+</parameter>
+<exception name="SipException" type="android.net.sip.SipException">
+</exception>
+</method>
+<method name="close"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="continueCall"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="timeout" type="int">
+</parameter>
+<exception name="SipException" type="android.net.sip.SipException">
+</exception>
+</method>
+<method name="endCall"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="SipException" type="android.net.sip.SipException">
+</exception>
+</method>
+<method name="getLocalProfile"
+ return="android.net.sip.SipProfile"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPeerProfile"
+ return="android.net.sip.SipProfile"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getState"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="holdCall"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="timeout" type="int">
+</parameter>
+<exception name="SipException" type="android.net.sip.SipException">
+</exception>
+</method>
+<method name="isInCall"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isMuted"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isOnHold"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="makeCall"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="peerProfile" type="android.net.sip.SipProfile">
+</parameter>
+<parameter name="sipSession" type="android.net.sip.SipSession">
+</parameter>
+<parameter name="timeout" type="int">
+</parameter>
+<exception name="SipException" type="android.net.sip.SipException">
+</exception>
+</method>
+<method name="sendDtmf"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="code" type="int">
+</parameter>
+</method>
+<method name="sendDtmf"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="code" type="int">
+</parameter>
+<parameter name="result" type="android.os.Message">
+</parameter>
+</method>
+<method name="setListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.net.sip.SipAudioCall.Listener">
+</parameter>
+</method>
+<method name="setListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.net.sip.SipAudioCall.Listener">
+</parameter>
+<parameter name="callbackImmediately" type="boolean">
+</parameter>
+</method>
+<method name="setRingbackToneEnabled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enabled" type="boolean">
+</parameter>
+</method>
+<method name="setRingtoneEnabled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enabled" type="boolean">
+</parameter>
+</method>
+<method name="setSpeakerMode"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="speakerMode" type="boolean">
+</parameter>
+</method>
+<method name="startAudio"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="toggleMute"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="SipAudioCall.Listener"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="SipAudioCall.Listener"
+ type="android.net.sip.SipAudioCall.Listener"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="onCallBusy"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="call" type="android.net.sip.SipAudioCall">
+</parameter>
+</method>
+<method name="onCallEnded"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="call" type="android.net.sip.SipAudioCall">
+</parameter>
+</method>
+<method name="onCallEstablished"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="call" type="android.net.sip.SipAudioCall">
+</parameter>
+</method>
+<method name="onCallHeld"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="call" type="android.net.sip.SipAudioCall">
+</parameter>
+</method>
+<method name="onCalling"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="call" type="android.net.sip.SipAudioCall">
+</parameter>
+</method>
+<method name="onChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="call" type="android.net.sip.SipAudioCall">
+</parameter>
+</method>
+<method name="onError"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="call" type="android.net.sip.SipAudioCall">
+</parameter>
+<parameter name="errorCode" type="int">
+</parameter>
+<parameter name="errorMessage" type="java.lang.String">
+</parameter>
+</method>
+<method name="onReadyToCall"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="call" type="android.net.sip.SipAudioCall">
+</parameter>
+</method>
+<method name="onRinging"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="call" type="android.net.sip.SipAudioCall">
+</parameter>
+<parameter name="caller" type="android.net.sip.SipProfile">
+</parameter>
+</method>
+<method name="onRingingBack"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="call" type="android.net.sip.SipAudioCall">
+</parameter>
+</method>
+</class>
+<class name="SipErrorCode"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="toString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="errorCode" type="int">
+</parameter>
+</method>
+<field name="CLIENT_ERROR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CROSS_DOMAIN_AUTHENTICATION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-11"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA_CONNECTION_LOST"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-10"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="INVALID_CREDENTIALS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="INVALID_REMOTE_URI"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="IN_PROGRESS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-9"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NO_ERROR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PEER_NOT_REACHABLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SERVER_ERROR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SERVER_UNREACHABLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-12"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SOCKET_ERROR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TIME_OUT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TRANSACTION_TERMINTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="SipException"
+ extends="java.lang.Exception"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="SipException"
+ type="android.net.sip.SipException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="SipException"
+ type="android.net.sip.SipException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="SipException"
+ type="android.net.sip.SipException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="cause" type="java.lang.Throwable">
+</parameter>
+</constructor>
+</class>
+<class name="SipManager"
+ 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"
+>
+<parameter name="localProfileUri" type="java.lang.String">
+</parameter>
+<exception name="SipException" type="android.net.sip.SipException">
+</exception>
+</method>
+<method name="createSipSession"
+ return="android.net.sip.SipSession"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="localProfile" type="android.net.sip.SipProfile">
+</parameter>
+<parameter name="listener" type="android.net.sip.SipSession.Listener">
+</parameter>
+<exception name="SipException" type="android.net.sip.SipException">
+</exception>
+</method>
+<method name="getCallId"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="incomingCallIntent" type="android.content.Intent">
+</parameter>
+</method>
+<method name="getOfferSessionDescription"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="incomingCallIntent" type="android.content.Intent">
+</parameter>
+</method>
+<method name="getSessionFor"
+ return="android.net.sip.SipSession"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="incomingCallIntent" type="android.content.Intent">
+</parameter>
+<exception name="SipException" type="android.net.sip.SipException">
+</exception>
+</method>
+<method name="isApiSupported"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</method>
+<method name="isIncomingCallIntent"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+</method>
+<method name="isOpened"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="localProfileUri" type="java.lang.String">
+</parameter>
+<exception name="SipException" type="android.net.sip.SipException">
+</exception>
+</method>
+<method name="isRegistered"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="localProfileUri" type="java.lang.String">
+</parameter>
+<exception name="SipException" type="android.net.sip.SipException">
+</exception>
+</method>
+<method name="isSipWifiOnly"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</method>
+<method name="isVoipSupported"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</method>
+<method name="makeAudioCall"
+ return="android.net.sip.SipAudioCall"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="localProfile" type="android.net.sip.SipProfile">
+</parameter>
+<parameter name="peerProfile" type="android.net.sip.SipProfile">
+</parameter>
+<parameter name="listener" type="android.net.sip.SipAudioCall.Listener">
+</parameter>
+<parameter name="timeout" type="int">
+</parameter>
+<exception name="SipException" type="android.net.sip.SipException">
+</exception>
+</method>
+<method name="makeAudioCall"
+ return="android.net.sip.SipAudioCall"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="localProfileUri" type="java.lang.String">
+</parameter>
+<parameter name="peerProfileUri" type="java.lang.String">
+</parameter>
+<parameter name="listener" type="android.net.sip.SipAudioCall.Listener">
+</parameter>
+<parameter name="timeout" type="int">
+</parameter>
+<exception name="SipException" type="android.net.sip.SipException">
+</exception>
+</method>
+<method name="newInstance"
+ return="android.net.sip.SipManager"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</method>
+<method name="open"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="localProfile" type="android.net.sip.SipProfile">
+</parameter>
+<exception name="SipException" type="android.net.sip.SipException">
+</exception>
+</method>
+<method name="open"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="localProfile" type="android.net.sip.SipProfile">
+</parameter>
+<parameter name="incomingCallPendingIntent" type="android.app.PendingIntent">
+</parameter>
+<parameter name="listener" type="android.net.sip.SipRegistrationListener">
+</parameter>
+<exception name="SipException" type="android.net.sip.SipException">
+</exception>
+</method>
+<method name="register"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="localProfile" type="android.net.sip.SipProfile">
+</parameter>
+<parameter name="expiryTime" type="int">
+</parameter>
+<parameter name="listener" type="android.net.sip.SipRegistrationListener">
+</parameter>
+<exception name="SipException" type="android.net.sip.SipException">
+</exception>
+</method>
+<method name="setRegistrationListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="localProfileUri" type="java.lang.String">
+</parameter>
+<parameter name="listener" type="android.net.sip.SipRegistrationListener">
+</parameter>
+<exception name="SipException" type="android.net.sip.SipException">
+</exception>
+</method>
+<method name="takeAudioCall"
+ return="android.net.sip.SipAudioCall"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="incomingCallIntent" type="android.content.Intent">
+</parameter>
+<parameter name="listener" type="android.net.sip.SipAudioCall.Listener">
+</parameter>
+<exception name="SipException" type="android.net.sip.SipException">
+</exception>
+</method>
+<method name="takeAudioCall"
+ return="android.net.sip.SipAudioCall"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="incomingCallIntent" type="android.content.Intent">
+</parameter>
+<parameter name="listener" type="android.net.sip.SipAudioCall.Listener">
+</parameter>
+<parameter name="ringtoneEnabled" type="boolean">
+</parameter>
+<exception name="SipException" type="android.net.sip.SipException">
+</exception>
+</method>
+<method name="unregister"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="localProfile" type="android.net.sip.SipProfile">
+</parameter>
+<parameter name="listener" type="android.net.sip.SipRegistrationListener">
+</parameter>
+<exception name="SipException" type="android.net.sip.SipException">
+</exception>
+</method>
+<field name="EXTRA_CALL_ID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android:sipCallID&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_OFFER_SD"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android:sipOfferSD&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="INCOMING_CALL_RESULT_CODE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="101"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="SipProfile"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.Cloneable">
+</implements>
+<implements name="android.os.Parcelable">
+</implements>
+<implements name="java.io.Serializable">
+</implements>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getAutoRegistration"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDisplayName"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPassword"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPort"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getProfileName"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getProtocol"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getProxyAddress"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSendKeepAlive"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSipDomain"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getUriString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getUserName"
+ 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="out" 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>
+</class>
+<class name="SipProfile.Builder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="SipProfile.Builder"
+ type="android.net.sip.SipProfile.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="profile" type="android.net.sip.SipProfile">
+</parameter>
+</constructor>
+<constructor name="SipProfile.Builder"
+ type="android.net.sip.SipProfile.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uriString" type="java.lang.String">
+</parameter>
+<exception name="ParseException" type="java.text.ParseException">
+</exception>
+</constructor>
+<constructor name="SipProfile.Builder"
+ type="android.net.sip.SipProfile.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="username" type="java.lang.String">
+</parameter>
+<parameter name="serverDomain" type="java.lang.String">
+</parameter>
+<exception name="ParseException" type="java.text.ParseException">
+</exception>
+</constructor>
+<method name="build"
+ return="android.net.sip.SipProfile"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setAutoRegistration"
+ return="android.net.sip.SipProfile.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="flag" type="boolean">
+</parameter>
+</method>
+<method name="setDisplayName"
+ return="android.net.sip.SipProfile.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="displayName" type="java.lang.String">
+</parameter>
+</method>
+<method name="setOutboundProxy"
+ return="android.net.sip.SipProfile.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="outboundProxy" type="java.lang.String">
+</parameter>
+</method>
+<method name="setPassword"
+ return="android.net.sip.SipProfile.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="password" type="java.lang.String">
+</parameter>
+</method>
+<method name="setPort"
+ return="android.net.sip.SipProfile.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="port" type="int">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+</method>
+<method name="setProfileName"
+ return="android.net.sip.SipProfile.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="setProtocol"
+ return="android.net.sip.SipProfile.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="protocol" type="java.lang.String">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+</method>
+<method name="setSendKeepAlive"
+ return="android.net.sip.SipProfile.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="flag" type="boolean">
+</parameter>
+</method>
+</class>
+<interface name="SipRegistrationListener"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onRegistering"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="localProfileUri" type="java.lang.String">
+</parameter>
+</method>
+<method name="onRegistrationDone"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="localProfileUri" type="java.lang.String">
+</parameter>
+<parameter name="expiryTime" type="long">
+</parameter>
+</method>
+<method name="onRegistrationFailed"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="localProfileUri" type="java.lang.String">
+</parameter>
+<parameter name="errorCode" type="int">
+</parameter>
+<parameter name="errorMessage" type="java.lang.String">
+</parameter>
+</method>
+</interface>
+<class name="SipSession"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="answerCall"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sessionDescription" type="java.lang.String">
+</parameter>
+<parameter name="timeout" type="int">
+</parameter>
+</method>
+<method name="changeCall"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sessionDescription" type="java.lang.String">
+</parameter>
+<parameter name="timeout" type="int">
+</parameter>
+</method>
+<method name="endCall"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCallId"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getLocalIp"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getLocalProfile"
+ return="android.net.sip.SipProfile"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPeerProfile"
+ return="android.net.sip.SipProfile"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getState"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isInCall"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="makeCall"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="callee" type="android.net.sip.SipProfile">
+</parameter>
+<parameter name="sessionDescription" type="java.lang.String">
+</parameter>
+<parameter name="timeout" type="int">
+</parameter>
+</method>
+<method name="register"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="duration" type="int">
+</parameter>
+</method>
+<method name="setListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.net.sip.SipSession.Listener">
+</parameter>
+</method>
+<method name="unregister"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="SipSession.Listener"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="SipSession.Listener"
+ type="android.net.sip.SipSession.Listener"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="onCallBusy"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="session" type="android.net.sip.SipSession">
+</parameter>
+</method>
+<method name="onCallChangeFailed"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="session" type="android.net.sip.SipSession">
+</parameter>
+<parameter name="errorCode" type="int">
+</parameter>
+<parameter name="errorMessage" type="java.lang.String">
+</parameter>
+</method>
+<method name="onCallEnded"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="session" type="android.net.sip.SipSession">
+</parameter>
+</method>
+<method name="onCallEstablished"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="session" type="android.net.sip.SipSession">
+</parameter>
+<parameter name="sessionDescription" type="java.lang.String">
+</parameter>
+</method>
+<method name="onCalling"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="session" type="android.net.sip.SipSession">
+</parameter>
+</method>
+<method name="onError"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="session" type="android.net.sip.SipSession">
+</parameter>
+<parameter name="errorCode" type="int">
+</parameter>
+<parameter name="errorMessage" type="java.lang.String">
+</parameter>
+</method>
+<method name="onRegistering"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="session" type="android.net.sip.SipSession">
+</parameter>
+</method>
+<method name="onRegistrationDone"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="session" type="android.net.sip.SipSession">
+</parameter>
+<parameter name="duration" type="int">
+</parameter>
+</method>
+<method name="onRegistrationFailed"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="session" type="android.net.sip.SipSession">
+</parameter>
+<parameter name="errorCode" type="int">
+</parameter>
+<parameter name="errorMessage" type="java.lang.String">
+</parameter>
+</method>
+<method name="onRegistrationTimeout"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="session" type="android.net.sip.SipSession">
+</parameter>
+</method>
+<method name="onRinging"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="session" type="android.net.sip.SipSession">
+</parameter>
+<parameter name="caller" type="android.net.sip.SipProfile">
+</parameter>
+<parameter name="sessionDescription" type="java.lang.String">
+</parameter>
+</method>
+<method name="onRingingBack"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="session" type="android.net.sip.SipSession">
+</parameter>
+</method>
+</class>
+<class name="SipSession.State"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="toString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="state" type="int">
+</parameter>
+</method>
+<field name="DEREGISTERING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="INCOMING_CALL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="INCOMING_CALL_ANSWERING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="IN_CALL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NOT_DEFINED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="101"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OUTGOING_CALL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OUTGOING_CALL_CANCELING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OUTGOING_CALL_RING_BACK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PINGING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="9"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="READY_TO_CALL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="REGISTERING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+</package>
 <package name="android.net.wifi"
 >
 <class name="ScanResult"
@@ -101014,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"
@@ -101353,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"
 >
@@ -123867,6 +126501,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="java.io.Closeable">
+</implements>
 <implements name="android.os.Parcelable">
 </implements>
 <constructor name="DropBoxManager.Entry"
@@ -129732,9 +132368,97 @@
 >
 <parameter name="path" type="java.lang.String">
 </parameter>
-<parameter name="state" type="java.lang.String">
+<parameter name="state" type="int">
 </parameter>
 </method>
+<field name="ERROR_ALREADY_MOUNTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="24"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_COULD_NOT_MOUNT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="21"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_COULD_NOT_UNMOUNT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="22"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_INTERNAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="20"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_NOT_MOUNTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="23"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_PERMISSION_DENIED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="25"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MOUNTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="UNMOUNTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <class name="StorageManager"
  extends="java.lang.Object"
@@ -129769,8 +132493,6 @@
 >
 <parameter name="filename" type="java.lang.String">
 </parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
 </method>
 <method name="mountObb"
  return="boolean"
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index f6f80d1..a5b3e0e 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -936,3 +936,157 @@
 done:
     return 0;
 }
+
+int linklib(const char* dataDir, const char* asecLibDir)
+{
+    char libdir[PKG_PATH_MAX];
+    struct stat s, libStat;
+    int rc = 0;
+
+    const size_t libdirLen = strlen(dataDir) + strlen(PKG_LIB_POSTFIX);
+    if (libdirLen >= PKG_PATH_MAX) {
+        LOGE("library dir len too large");
+        rc = -1;
+        goto out;
+    }
+
+    if (snprintf(libdir, sizeof(libdir), "%s%s", dataDir, PKG_LIB_POSTFIX) != (ssize_t)libdirLen) {
+        LOGE("library dir not written successfully: %s\n", strerror(errno));
+        rc = -1;
+        goto out;
+    }
+
+    if (stat(dataDir, &s) < 0) return -1;
+
+    if (chown(dataDir, 0, 0) < 0) {
+        LOGE("failed to chown '%s': %s\n", dataDir, strerror(errno));
+        return -1;
+    }
+
+    if (chmod(dataDir, 0700) < 0) {
+        LOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno));
+        rc = -1;
+        goto out;
+    }
+
+    if (lstat(libdir, &libStat) < 0) {
+        LOGE("couldn't stat lib dir: %s\n", strerror(errno));
+        rc = -1;
+        goto out;
+    }
+
+    if (S_ISDIR(libStat.st_mode)) {
+        if (delete_dir_contents(libdir, 1, 0) < 0) {
+            rc = -1;
+            goto out;
+        }
+    } else if (S_ISLNK(libStat.st_mode)) {
+        if (unlink(libdir) < 0) {
+            rc = -1;
+            goto out;
+        }
+    }
+
+    if (symlink(asecLibDir, libdir) < 0) {
+        LOGE("couldn't symlink directory '%s' -> '%s': %s\n", libdir, asecLibDir, strerror(errno));
+        rc = -errno;
+        goto out;
+    }
+
+    if (lchown(libdir, AID_SYSTEM, AID_SYSTEM) < 0) {
+        LOGE("cannot chown dir '%s': %s\n", libdir, strerror(errno));
+        unlink(libdir);
+        rc = -errno;
+        goto out;
+    }
+
+out:
+    if (chmod(dataDir, s.st_mode) < 0) {
+        LOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno));
+        return -errno;
+    }
+
+    if (chown(dataDir, s.st_uid, s.st_gid) < 0) {
+        LOGE("failed to chown '%s' : %s\n", dataDir, strerror(errno));
+        return -errno;
+    }
+
+    return rc;
+}
+
+int unlinklib(const char* dataDir)
+{
+    char libdir[PKG_PATH_MAX];
+    struct stat s, libStat;
+    int rc = 0;
+
+    const size_t libdirLen = strlen(dataDir) + strlen(PKG_LIB_POSTFIX);
+    if (libdirLen >= PKG_PATH_MAX) {
+        return -1;
+    }
+
+    if (snprintf(libdir, sizeof(libdir), "%s%s", dataDir, PKG_LIB_POSTFIX) != (ssize_t)libdirLen) {
+        LOGE("library dir not written successfully: %s\n", strerror(errno));
+        return -1;
+    }
+
+    if (stat(dataDir, &s) < 0) {
+        LOGE("couldn't state data dir");
+        return -1;
+    }
+
+    if (chown(dataDir, 0, 0) < 0) {
+        LOGE("failed to chown '%s': %s\n", dataDir, strerror(errno));
+        return -1;
+    }
+
+    if (chmod(dataDir, 0700) < 0) {
+        LOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno));
+        rc = -1;
+        goto out;
+    }
+
+    if (lstat(libdir, &libStat) < 0) {
+        LOGE("couldn't stat lib dir: %s\n", strerror(errno));
+        rc = -1;
+        goto out;
+    }
+
+    if (S_ISDIR(libStat.st_mode)) {
+        if (delete_dir_contents(libdir, 1, 0) < 0) {
+            rc = -1;
+            goto out;
+        }
+    } else if (S_ISLNK(libStat.st_mode)) {
+        if (unlink(libdir) < 0) {
+            rc = -1;
+            goto out;
+        }
+    }
+
+    if (mkdir(libdir, 0755) < 0) {
+        LOGE("cannot create dir '%s': %s\n", libdir, strerror(errno));
+        rc = -errno;
+        goto out;
+    }
+
+    if (chown(libdir, AID_SYSTEM, AID_SYSTEM) < 0) {
+        LOGE("cannot chown dir '%s': %s\n", libdir, strerror(errno));
+        unlink(libdir);
+        rc = -errno;
+        goto out;
+    }
+
+out:
+    if (chmod(dataDir, s.st_mode) < 0) {
+        LOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno));
+        return -1;
+    }
+
+    if (chown(dataDir, s.st_uid, s.st_gid) < 0) {
+        LOGE("failed to chown '%s' : %s\n", dataDir, strerror(errno));
+        return -1;
+    }
+
+    return rc;
+}
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index c991845..9ba6402 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -101,6 +101,16 @@
     return movefiles();
 }
 
+static int do_linklib(char **arg, char reply[REPLY_MAX])
+{
+    return linklib(arg[0], arg[1]);
+}
+
+static int do_unlinklib(char **arg, char reply[REPLY_MAX])
+{
+    return unlinklib(arg[0]);
+}
+
 struct cmdinfo {
     const char *name;
     unsigned numargs;
@@ -121,6 +131,8 @@
     { "getsize",              4, do_get_size },
     { "rmuserdata",           2, do_rm_user_data },
     { "movefiles",            0, do_movefiles },
+    { "linklib",              2, do_linklib },
+    { "unlinklib",            1, do_unlinklib },
 };
 
 static int readx(int s, void *_buf, int count)
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index 479e4b2..59475e9 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -111,3 +111,5 @@
 int free_cache(int64_t free_size);
 int dexopt(const char *apk_path, uid_t uid, int is_public);
 int movefiles();
+int linklib(const char* target, const char* source);
+int unlinklib(const char* libPath);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index e66f52a..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) {
@@ -2739,14 +2718,15 @@
         private final File mBackupFile;
         private final int mMode;
 
-        private Map<String, Object> mMap;  // guarded by 'this'
-        private long mTimestamp;  // guarded by 'this'
+        private Map<String, Object> mMap;     // guarded by 'this'
         private int mDiskWritesInFlight = 0;  // guarded by 'this'
-        private boolean mLoaded = false;  // guarded by 'this'
+        private boolean mLoaded = false;      // guarded by 'this'
+        private long mStatTimestamp;          // guarded by 'this'
+        private long mStatSize;               // guarded by 'this'
 
         private final Object mWritingToDiskLock = new Object();
         private static final Object mContent = new Object();
-        private WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners;
+        private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners;
 
         SharedPreferencesImpl(
             File file, int mode, Map initialContents) {
@@ -2757,7 +2737,7 @@
             mMap = initialContents != null ? initialContents : new HashMap<String, Object>();
             FileStatus stat = new FileStatus();
             if (FileUtils.getFileStatus(file.getPath(), stat)) {
-                mTimestamp = stat.mtime;
+                mStatTimestamp = stat.mtime;
             }
             mListeners = new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
         }
@@ -2784,7 +2764,7 @@
                 return true;
             }
             synchronized (this) {
-                return mTimestamp != stat.mtime;
+                return mStatTimestamp != stat.mtime || mStatSize != stat.size;
             }
         }
 
@@ -3165,7 +3145,8 @@
                 FileStatus stat = new FileStatus();
                 if (FileUtils.getFileStatus(mFile.getPath(), stat)) {
                     synchronized (this) {
-                        mTimestamp = stat.mtime;
+                        mStatTimestamp = stat.mtime;
+                        mStatSize = stat.size;
                     }
                 }
                 // Writing was successful, delete the backup file if there is one.
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index c476b8f..a25aa6f 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -53,6 +53,8 @@
  * download in a notification or from the downloads UI.
  */
 public class DownloadManager {
+    private static final String TAG = "DownloadManager";
+
     /**
      * An identifier for a particular download, unique across the system.  Clients use this ID to
      * make subsequent calls related to the download.
@@ -133,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.
@@ -263,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,
@@ -278,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,
@@ -567,18 +577,18 @@
          */
         public static final int ORDER_DESCENDING = 2;
 
-        private Long mId = null;
+        private long[] mIds = null;
         private Integer mStatusFlags = null;
         private String mOrderByColumn = Downloads.COLUMN_LAST_MODIFICATION;
         private int mOrderDirection = ORDER_DESCENDING;
         private boolean mOnlyIncludeVisibleInDownloadsUi = false;
 
         /**
-         * Include only the download with the given ID.
+         * Include only the downloads with the given IDs.
          * @return this object
          */
-        public Query setFilterById(long id) {
-            mId = id;
+        public Query setFilterById(long... ids) {
+            mIds = ids;
             return this;
         }
 
@@ -639,9 +649,11 @@
         Cursor runQuery(ContentResolver resolver, String[] projection, Uri baseUri) {
             Uri uri = baseUri;
             List<String> selectionParts = new ArrayList<String>();
+            String[] selectionArgs = null;
 
-            if (mId != null) {
-                uri = ContentUris.withAppendedId(uri, mId);
+            if (mIds != null) {
+                selectionParts.add(getWhereClauseForIds(mIds));
+                selectionArgs = getWhereArgsForIds(mIds);
             }
 
             if (mStatusFlags != null) {
@@ -672,11 +684,14 @@
                 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;
 
-            return resolver.query(uri, projection, selection, null, orderBy);
+            return resolver.query(uri, projection, selection, selectionArgs, orderBy);
         }
 
         private String joinStrings(String joiner, Iterable<String> parts) {
@@ -738,17 +753,39 @@
     }
 
     /**
-     * Cancel a download and remove it from the download manager.  The 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, it will not be deleted.
+     * 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 id the ID of the download
+     * @param ids the IDs of the downloads to be marked 'deleted'
+     * @return the number of downloads actually updated
+     * @hide
      */
-    public void remove(long id) {
-        int numDeleted = mResolver.delete(getDownloadUri(id), null, null);
-        if (numDeleted == 0) {
-            throw new IllegalArgumentException("Download " + id + " does not exist");
+    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.
+     *
+     * @param ids the IDs of the downloads to remove
+     * @return the number of downloads actually removed
+     */
+    public int remove(long... ids) {
+        if (ids == null || ids.length == 0) {
+            // called with nothing to remove!
+            throw new IllegalArgumentException("input param 'ids' can't be null");
+        }
+        return mResolver.delete(mBaseUri, getWhereClauseForIds(ids), getWhereArgsForIds(ids));
     }
 
     /**
@@ -776,20 +813,20 @@
     }
 
     /**
-     * Restart the given download, which must have already completed (successfully or not).  This
+     * Restart the given downloads, which must have already completed (successfully or not).  This
      * method will only work when called from within the download manager's process.
-     * @param id the ID of the download
+     * @param ids the IDs of the downloads
      * @hide
      */
-    public void restartDownload(long id) {
-        Cursor cursor = query(new Query().setFilterById(id));
+    public void restartDownload(long... ids) {
+        Cursor cursor = query(new Query().setFilterById(ids));
         try {
-            if (!cursor.moveToFirst()) {
-                throw new IllegalArgumentException("No download with id " + id);
-            }
-            int status = cursor.getInt(cursor.getColumnIndex(COLUMN_STATUS));
-            if (status != STATUS_SUCCESSFUL && status != STATUS_FAILED) {
-                throw new IllegalArgumentException("Cannot restart incomplete download: " + id);
+            for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
+                int status = cursor.getInt(cursor.getColumnIndex(COLUMN_STATUS));
+                if (status != STATUS_SUCCESSFUL && status != STATUS_FAILED) {
+                    throw new IllegalArgumentException("Cannot restart incomplete download: "
+                            + cursor.getLong(cursor.getColumnIndex(COLUMN_ID)));
+                }
             }
         } finally {
             cursor.close();
@@ -800,7 +837,7 @@
         values.put(Downloads.Impl.COLUMN_TOTAL_BYTES, -1);
         values.putNull(Downloads.Impl._DATA);
         values.put(Downloads.Impl.COLUMN_STATUS, Downloads.Impl.STATUS_PENDING);
-        mResolver.update(getDownloadUri(id), values, null, null);
+        mResolver.update(mBaseUri, values, getWhereClauseForIds(ids), getWhereArgsForIds(ids));
     }
 
     /**
@@ -811,6 +848,34 @@
     }
 
     /**
+     * Get a parameterized SQL WHERE clause to select a bunch of IDs.
+     */
+    static String getWhereClauseForIds(long[] ids) {
+        StringBuilder whereClause = new StringBuilder();
+        whereClause.append("(");
+        for (int i = 0; i < ids.length; i++) {
+            if (i > 0) {
+                whereClause.append("OR ");
+            }
+            whereClause.append(Downloads.Impl._ID);
+            whereClause.append(" = ? ");
+        }
+        whereClause.append(")");
+        return whereClause.toString();
+    }
+
+    /**
+     * Get the selection args for a clause returned by {@link #getWhereClauseForIds(long[])}.
+     */
+    static String[] getWhereArgsForIds(long[] ids) {
+        String[] whereArgs = new String[ids.length];
+        for (int i = 0; i < ids.length; i++) {
+            whereArgs[i] = Long.toString(ids[i]);
+        }
+        return whereArgs;
+    }
+
+    /**
      * This class wraps a cursor returned by DownloadProvider -- the "underlying cursor" -- and
      * presents a different set of columns, those defined in the DownloadManager.COLUMN_* constants.
      * Some columns correspond directly to underlying values while others are computed from
@@ -915,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 8e655e2..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;
@@ -67,10 +67,11 @@
     private static final int DISCONNECT_HFP_INCOMING = 6;
     public static final int DISCONNECT_A2DP_OUTGOING = 7;
     public static final int DISCONNECT_A2DP_INCOMING = 8;
+    public static final int DISCONNECT_PBAP_OUTGOING = 9;
 
-    public static final int UNPAIR = 9;
-    public static final int AUTO_CONNECT_PROFILES = 10;
-    public static final int TRANSITION_TO_STABLE = 11;
+    public static final int UNPAIR = 100;
+    public static final int AUTO_CONNECT_PROFILES = 101;
+    public static final int TRANSITION_TO_STABLE = 102;
 
     private static final int AUTO_CONNECT_DELAY = 6000; // 6 secs
 
@@ -84,7 +85,9 @@
     private BluetoothService mService;
     private BluetoothA2dpService mA2dpService;
     private BluetoothHeadset  mHeadsetService;
+    private BluetoothPbap     mPbapService;
     private boolean mHeadsetServiceConnected;
+    private boolean mPbapServiceConnected;
 
     private BluetoothDevice mDevice;
     private int mHeadsetState;
@@ -133,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);
             }
       }
     };
@@ -172,10 +179,12 @@
         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);
 
         HeadsetServiceListener l = new HeadsetServiceListener();
+        PbapServiceListener p = new PbapServiceListener();
     }
 
     private class HeadsetServiceListener implements BluetoothHeadset.ServiceListener {
@@ -194,10 +203,26 @@
         }
     }
 
+    private class PbapServiceListener implements BluetoothPbap.ServiceListener {
+        public PbapServiceListener() {
+            mPbapService = new BluetoothPbap(mContext, this);
+        }
+        public void onServiceConnected() {
+            synchronized(BluetoothDeviceProfileState.this) {
+                mPbapServiceConnected = true;
+            }
+        }
+        public void onServiceDisconnected() {
+            synchronized(BluetoothDeviceProfileState.this) {
+                mPbapServiceConnected = false;
+            }
+        }
+    }
+
     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);
@@ -224,6 +249,9 @@
                 case DISCONNECT_A2DP_INCOMING:
                     transitionTo(mIncomingA2dp);
                     break;
+                case DISCONNECT_PBAP_OUTGOING:
+                    processCommand(DISCONNECT_PBAP_OUTGOING);
+                    break;
                 case UNPAIR:
                     if (mHeadsetState != BluetoothHeadset.STATE_DISCONNECTED) {
                         sendMessage(DISCONNECT_HFP_OUTGOING);
@@ -272,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
@@ -342,6 +374,7 @@
                        deferMessage(deferMsg);
                     }
                     break;
+                case DISCONNECT_PBAP_OUTGOING:
                 case UNPAIR:
                 case AUTO_CONNECT_PROFILES:
                     deferMessage(message);
@@ -362,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
@@ -409,6 +446,7 @@
                     // If this causes incoming HFP to fail, it is more of a headset problem
                     // since both connections are incoming ones.
                     break;
+                case DISCONNECT_PBAP_OUTGOING:
                 case UNPAIR:
                 case AUTO_CONNECT_PROFILES:
                     deferMessage(message);
@@ -429,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
@@ -491,11 +533,12 @@
                     }
                     break;
                 case DISCONNECT_A2DP_OUTGOING:
-                    processCommand(DISCONNECT_A2DP_OUTGOING);
+                    deferMessage(message);
                     break;
                 case DISCONNECT_A2DP_INCOMING:
                     // Ignore, will be handled by Bluez
                     break;
+                case DISCONNECT_PBAP_OUTGOING:
                 case UNPAIR:
                 case AUTO_CONNECT_PROFILES:
                     deferMessage(message);
@@ -516,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
@@ -561,6 +608,7 @@
                 case DISCONNECT_A2DP_INCOMING:
                     // Ignore, will be handled by Bluez
                     break;
+                case DISCONNECT_PBAP_OUTGOING:
                 case UNPAIR:
                 case AUTO_CONNECT_PROFILES:
                     deferMessage(message);
@@ -588,14 +636,14 @@
         }
     }
 
-    synchronized void deferHeadsetMessage(int command) {
+    synchronized void deferProfileServiceMessage(int command) {
         Message msg = new Message();
         msg.what = command;
         deferMessage(msg);
     }
 
     synchronized boolean processCommand(int command) {
-        log("Processing command:" + command);
+        Log.i(TAG, "Processing command:" + command);
         switch(command) {
             case  CONNECT_HFP_OUTGOING:
                 if (mHeadsetService != null) {
@@ -604,7 +652,7 @@
                 break;
             case CONNECT_HFP_INCOMING:
                 if (!mHeadsetServiceConnected) {
-                    deferHeadsetMessage(command);
+                    deferProfileServiceMessage(command);
                 } else if (mHeadsetState == BluetoothHeadset.STATE_CONNECTING) {
                     return mHeadsetService.acceptIncomingConnect(mDevice);
                 } else if (mHeadsetState == BluetoothHeadset.STATE_DISCONNECTED) {
@@ -621,8 +669,13 @@
                 return true;
             case DISCONNECT_HFP_OUTGOING:
                 if (!mHeadsetServiceConnected) {
-                    deferHeadsetMessage(command);
+                    deferProfileServiceMessage(command);
                 } else {
+                    // Disconnect PBAP
+                    // TODO(): Add PBAP to the state machine.
+                    Message m = new Message();
+                    m.what = DISCONNECT_PBAP_OUTGOING;
+                    deferMessage(m);
                     if (mHeadsetService.getPriority(mDevice) ==
                         BluetoothHeadset.PRIORITY_AUTO_CONNECT) {
                         mHeadsetService.setPriority(mDevice, BluetoothHeadset.PRIORITY_ON);
@@ -645,6 +698,13 @@
                     return mA2dpService.disconnectSinkInternal(mDevice);
                 }
                 break;
+            case DISCONNECT_PBAP_OUTGOING:
+                if (!mPbapServiceConnected) {
+                    deferProfileServiceMessage(command);
+                } else {
+                    return mPbapService.disconnect();
+                }
+                break;
             case UNPAIR:
                 return mService.removeBondInternal(mDevice.getAddress());
             default:
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/SharedPreferences.java b/core/java/android/content/SharedPreferences.java
index 1484204..3221afa 100644
--- a/core/java/android/content/SharedPreferences.java
+++ b/core/java/android/content/SharedPreferences.java
@@ -186,9 +186,21 @@
          * {@link #commit} will block until all async commits are
          * completed as well as the commit itself.
          *
-         * <p>If you call this from an {@link android.app.Activity},
-         * the base class will wait for any async commits to finish in
-         * its {@link android.app.Activity#onPause}.</p>
+         * <p>As {@link SharedPreferences} instances are singletons within
+         * a process, it's safe to replace any instance of {@link #commit} with
+         * {@link #apply} if you were already ignoring the return value.
+         *
+         * <p>You don't need to worry about Android component
+         * lifecycles and their interaction with <code>apply()</code>
+         * writing to disk.  The framework makes sure in-flight disk
+         * writes from <code>apply()</code> complete before switching
+         * states.
+         *
+         * <p class='note'>The SharedPreferences.Editor interface
+         * isn't expected to be implemented directly.  However, if you
+         * previously did implement it and are now getting errors
+         * about missing <code>apply()</code>, you can simply call
+         * {@link #commit} from <code>apply()</code>.
          */
         void apply();
     }
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/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index af327c3..eb05d76 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -65,6 +65,18 @@
     public ApplicationInfo applicationInfo;
     
     /**
+     * The time at which the app was first installed.  Units are as
+     * per {@link System#currentTimeMillis()}.
+     */
+    public long firstInstallTime;
+
+    /**
+     * The time at which the app was last updated.  Units are as
+     * per {@link System#currentTimeMillis()}.
+     */
+    public long lastUpdateTime;
+
+    /**
      * All kernel group-IDs that have been assigned to this package.
      * This is only filled in if the flag {@link PackageManager#GET_GIDS} was set.
      */
@@ -207,6 +219,8 @@
         } else {
             dest.writeInt(0);
         }
+        dest.writeLong(firstInstallTime);
+        dest.writeLong(lastUpdateTime);
         dest.writeIntArray(gids);
         dest.writeTypedArray(activities, parcelableFlags);
         dest.writeTypedArray(receivers, parcelableFlags);
@@ -242,6 +256,8 @@
         if (hasApp != 0) {
             applicationInfo = ApplicationInfo.CREATOR.createFromParcel(source);
         }
+        firstInstallTime = source.readLong();
+        lastUpdateTime = source.readLong();
         gids = source.createIntArray();
         activities = source.createTypedArray(ActivityInfo.CREATOR);
         receivers = source.createTypedArray(ActivityInfo.CREATOR);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 7346561..b5d1653 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1891,7 +1891,7 @@
         if (pkg == null) {
             return null;
         }
-        return PackageParser.generatePackageInfo(pkg, null, flags);
+        return PackageParser.generatePackageInfo(pkg, null, flags, 0, 0);
     }
 
     /**
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 89839ce..51f4202 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -187,7 +187,7 @@
      * @param flags indicating which optional information is included.
      */
     public static PackageInfo generatePackageInfo(PackageParser.Package p,
-            int gids[], int flags) {
+            int gids[], int flags, long firstInstallTime, long lastUpdateTime) {
 
         PackageInfo pi = new PackageInfo();
         pi.packageName = p.packageName;
@@ -197,6 +197,8 @@
         pi.sharedUserLabel = p.mSharedUserLabel;
         pi.applicationInfo = p.applicationInfo;
         pi.installLocation = p.installLocation;
+        pi.firstInstallTime = firstInstallTime;
+        pi.lastUpdateTime = lastUpdateTime;
         if ((flags&PackageManager.GET_GIDS) != 0) {
             pi.gids = gids;
         }
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/android/inputmethodservice/ExtractEditText.java b/core/java/android/inputmethodservice/ExtractEditText.java
index 8a52e40..3447e76c 100644
--- a/core/java/android/inputmethodservice/ExtractEditText.java
+++ b/core/java/android/inputmethodservice/ExtractEditText.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
-import android.view.ContextMenu;
 import android.view.inputmethod.ExtractedText;
 import android.widget.EditText;
 
@@ -29,7 +28,6 @@
 public class ExtractEditText extends EditText {
     private InputMethodService mIME;
     private int mSettingExtractedText;
-    private boolean mContextMenuShouldBeHandledBySuper = false;
     
     public ExtractEditText(Context context) {
         super(context, null);
@@ -99,19 +97,13 @@
         return false;
     }
     
-    @Override
-    protected void onCreateContextMenu(ContextMenu menu) {
-        super.onCreateContextMenu(menu);
-        mContextMenuShouldBeHandledBySuper = true;
-    }
-
     @Override public boolean onTextContextMenuItem(int id) {
-        if (mIME != null && !mContextMenuShouldBeHandledBySuper) {
+        // Horrible hack: select word option has to be handled by original view to work.
+        if (mIME != null && id != android.R.id.startSelectingText) {
             if (mIME.onExtractTextContextMenuItem(id)) {
                 return true;
             }
         }
-        mContextMenuShouldBeHandledBySuper = false;
         return super.onTextContextMenuItem(id);
     }
     
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/BatteryStats.java b/core/java/android/os/BatteryStats.java
index d49c8be..d67e6f5 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -449,6 +449,10 @@
         public static final int STATE_WAKE_LOCK_FLAG = 1<<17;
         public static final int STATE_SENSOR_ON_FLAG = 1<<16;
         
+        public static final int MOST_INTERESTING_STATES =
+            STATE_BATTERY_PLUGGED_FLAG | STATE_SCREEN_ON_FLAG
+            | STATE_GPS_ON_FLAG | STATE_PHONE_IN_CALL_FLAG;
+
         public int states;
 
         public HistoryItem() {
diff --git a/core/java/android/os/DropBoxManager.java b/core/java/android/os/DropBoxManager.java
index fa23458..a47c66a 100644
--- a/core/java/android/os/DropBoxManager.java
+++ b/core/java/android/os/DropBoxManager.java
@@ -21,6 +21,7 @@
 import com.android.internal.os.IDropBoxManagerService;
 
 import java.io.ByteArrayInputStream;
+import java.io.Closeable;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
@@ -61,7 +62,7 @@
      * This may include a reference to a stream, so you must call
      * {@link #close()} when you are done using it.
      */
-    public static class Entry implements Parcelable {
+    public static class Entry implements Parcelable, Closeable {
         private final String mTag;
         private final long mTimeMillis;
 
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 9494a06..de5b7b9 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -38,7 +38,10 @@
  * network access on the application's main thread, where UI
  * operations are received and animations take place.  Keeping disk
  * and network operations off the main thread makes for much smoother,
- * more responsive applications.
+ * more responsive applications.  By keeping your application's main thread
+ * responsive, you also prevent
+ * <a href="{@docRoot}guide/practices/design/responsiveness.html">ANR dialogs</a>
+ * from being shown to users.
  *
  * <p class="note">Note that even though an Android device's disk is
  * often on flash memory, many devices run a filesystem on top of that
@@ -104,6 +107,10 @@
     // Only show an annoying dialog at most every 30 seconds
     private static final long MIN_DIALOG_INTERVAL_MS = 30000;
 
+    // How many offending stacks to keep track of (and time) per loop
+    // of the Looper.
+    private static final int MAX_OFFENSES_PER_LOOP = 10;
+
     // Thread-policy:
 
     /**
@@ -680,6 +687,17 @@
         }
     }
 
+    private static final ThreadLocal<ArrayList<ViolationInfo>> violationsBeingTimed =
+            new ThreadLocal<ArrayList<ViolationInfo>>() {
+        @Override protected ArrayList<ViolationInfo> initialValue() {
+            return new ArrayList<ViolationInfo>();
+        }
+    };
+
+    private static boolean tooManyViolationsThisLoop() {
+        return violationsBeingTimed.get().size() >= MAX_OFFENSES_PER_LOOP;
+    }
+
     private static class AndroidBlockGuardPolicy implements BlockGuard.Policy {
         private int mPolicyMask;
 
@@ -707,6 +725,9 @@
             if ((mPolicyMask & DETECT_DISK_WRITE) == 0) {
                 return;
             }
+            if (tooManyViolationsThisLoop()) {
+                return;
+            }
             BlockGuard.BlockGuardPolicyException e = new StrictModeDiskWriteViolation(mPolicyMask);
             e.fillInStackTrace();
             startHandlingViolationException(e);
@@ -717,6 +738,9 @@
             if ((mPolicyMask & DETECT_DISK_READ) == 0) {
                 return;
             }
+            if (tooManyViolationsThisLoop()) {
+                return;
+            }
             BlockGuard.BlockGuardPolicyException e = new StrictModeDiskReadViolation(mPolicyMask);
             e.fillInStackTrace();
             startHandlingViolationException(e);
@@ -727,6 +751,9 @@
             if ((mPolicyMask & DETECT_NETWORK) == 0) {
                 return;
             }
+            if (tooManyViolationsThisLoop()) {
+                return;
+            }
             BlockGuard.BlockGuardPolicyException e = new StrictModeNetworkViolation(mPolicyMask);
             e.fillInStackTrace();
             startHandlingViolationException(e);
@@ -747,13 +774,6 @@
             handleViolationWithTimingAttempt(info);
         }
 
-        private static final ThreadLocal<ArrayList<ViolationInfo>> violationsBeingTimed =
-                new ThreadLocal<ArrayList<ViolationInfo>>() {
-            @Override protected ArrayList<ViolationInfo> initialValue() {
-                return new ArrayList<ViolationInfo>();
-            }
-        };
-
         // Attempts to fill in the provided ViolationInfo's
         // durationMillis field if this thread has a Looper we can use
         // to measure with.  We measure from the time of violation
@@ -780,7 +800,7 @@
 
             MessageQueue queue = Looper.myQueue();
             final ArrayList<ViolationInfo> records = violationsBeingTimed.get();
-            if (records.size() >= 10) {
+            if (records.size() >= MAX_OFFENSES_PER_LOOP) {
                 // Not worth measuring.  Too many offenses in one loop.
                 return;
             }
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index 60ea95c..467a0ac 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -484,7 +484,7 @@
              * IObbActionListener to inform it of the terminal state of the
              * call.
              */
-            public void mountObb(String filename, String key, IObbActionListener token)
+            public void mountObb(String filename, String key, IObbActionListener token, int nonce)
                     throws RemoteException {
                 Parcel _data = Parcel.obtain();
                 Parcel _reply = Parcel.obtain();
@@ -493,6 +493,7 @@
                     _data.writeString(filename);
                     _data.writeString(key);
                     _data.writeStrongBinder((token != null ? token.asBinder() : null));
+                    _data.writeInt(nonce);
                     mRemote.transact(Stub.TRANSACTION_mountObb, _data, _reply, 0);
                     _reply.readException();
                 } finally {
@@ -508,8 +509,8 @@
              * IObbActionListener to inform it of the terminal state of the
              * call.
              */
-            public void unmountObb(String filename, boolean force, IObbActionListener token)
-                    throws RemoteException {
+            public void unmountObb(String filename, boolean force, IObbActionListener token,
+                    int nonce) throws RemoteException {
                 Parcel _data = Parcel.obtain();
                 Parcel _reply = Parcel.obtain();
                 try {
@@ -517,6 +518,7 @@
                     _data.writeString(filename);
                     _data.writeInt((force ? 1 : 0));
                     _data.writeStrongBinder((token != null ? token.asBinder() : null));
+                    _data.writeInt(nonce);
                     mRemote.transact(Stub.TRANSACTION_unmountObb, _data, _reply, 0);
                     _reply.readException();
                 } finally {
@@ -855,7 +857,9 @@
                     key = data.readString();
                     IObbActionListener observer;
                     observer = IObbActionListener.Stub.asInterface(data.readStrongBinder());
-                    mountObb(filename, key, observer);
+                    int nonce;
+                    nonce = data.readInt();
+                    mountObb(filename, key, observer, nonce);
                     reply.writeNoException();
                     return true;
                 }
@@ -867,7 +871,9 @@
                     force = 0 != data.readInt();
                     IObbActionListener observer;
                     observer = IObbActionListener.Stub.asInterface(data.readStrongBinder());
-                    unmountObb(filename, force, observer);
+                    int nonce;
+                    nonce = data.readInt();
+                    unmountObb(filename, force, observer, nonce);
                     reply.writeNoException();
                     return true;
                 }
@@ -979,7 +985,7 @@
      * MountService will call back to the supplied IObbActionListener to inform
      * it of the terminal state of the call.
      */
-    public void mountObb(String filename, String key, IObbActionListener token)
+    public void mountObb(String filename, String key, IObbActionListener token, int nonce)
             throws RemoteException;
 
     /*
@@ -1023,7 +1029,7 @@
      * MountService will call back to the supplied IObbActionListener to inform
      * it of the terminal state of the call.
      */
-    public void unmountObb(String filename, boolean force, IObbActionListener token)
+    public void unmountObb(String filename, boolean force, IObbActionListener token, int nonce)
             throws RemoteException;
 
     /*
diff --git a/core/java/android/os/storage/IObbActionListener.java b/core/java/android/os/storage/IObbActionListener.java
index 2c098ac..d6fa58a 100644
--- a/core/java/android/os/storage/IObbActionListener.java
+++ b/core/java/android/os/storage/IObbActionListener.java
@@ -69,9 +69,11 @@
                     data.enforceInterface(DESCRIPTOR);
                     String filename;
                     filename = data.readString();
-                    String status;
-                    status = data.readString();
-                    this.onObbResult(filename, status);
+                    int nonce;
+                    nonce = data.readInt();
+                    int status;
+                    status = data.readInt();
+                    this.onObbResult(filename, nonce, status);
                     reply.writeNoException();
                     return true;
                 }
@@ -101,13 +103,15 @@
              *            on
              * @param returnCode status of the operation
              */
-            public void onObbResult(String filename, String status) throws RemoteException {
+            public void onObbResult(String filename, int nonce, int status)
+                    throws RemoteException {
                 Parcel _data = Parcel.obtain();
                 Parcel _reply = Parcel.obtain();
                 try {
                     _data.writeInterfaceToken(DESCRIPTOR);
                     _data.writeString(filename);
-                    _data.writeString(status);
+                    _data.writeInt(nonce);
+                    _data.writeInt(status);
                     mRemote.transact(Stub.TRANSACTION_onObbResult, _data, _reply, 0);
                     _reply.readException();
                 } finally {
@@ -124,7 +128,8 @@
      * Return from an OBB action result.
      * 
      * @param filename the path to the OBB the operation was performed on
-     * @param returnCode status of the operation
+     * @param nonce identifier that is meaningful to the receiver
+     * @param status status code as defined in {@link OnObbStateChangeListener}
      */
-    public void onObbResult(String filename, String status) throws RemoteException;
+    public void onObbResult(String filename, int nonce, int status) throws RemoteException;
 }
diff --git a/core/java/android/os/storage/OnObbStateChangeListener.java b/core/java/android/os/storage/OnObbStateChangeListener.java
index a2d0a56..1fb1782 100644
--- a/core/java/android/os/storage/OnObbStateChangeListener.java
+++ b/core/java/android/os/storage/OnObbStateChangeListener.java
@@ -17,15 +17,69 @@
 package android.os.storage;
 
 /**
- * Used for receiving notifications from {@link StorageManager}.
+ * Used for receiving notifications from {@link StorageManager} about OBB file
+ * states.
  */
 public abstract class OnObbStateChangeListener {
+
+    /**
+     * The OBB container is now mounted and ready for use. Returned in status
+     * messages from calls made via {@link StorageManager}
+     */
+    public static final int MOUNTED = 1;
+
+    /**
+     * The OBB container is now unmounted and not usable. Returned in status
+     * messages from calls made via {@link StorageManager}
+     */
+    public static final int UNMOUNTED = 2;
+
+    /**
+     * There was an internal system error encountered while trying to mount the
+     * OBB. Returned in status messages from calls made via
+     * {@link StorageManager}
+     */
+    public static final int ERROR_INTERNAL = 20;
+
+    /**
+     * The OBB could not be mounted by the system. Returned in status messages
+     * from calls made via {@link StorageManager}
+     */
+    public static final int ERROR_COULD_NOT_MOUNT = 21;
+
+    /**
+     * The OBB could not be unmounted. This most likely indicates that a file is
+     * in use on the OBB. Returned in status messages from calls made via
+     * {@link StorageManager}
+     */
+    public static final int ERROR_COULD_NOT_UNMOUNT = 22;
+
+    /**
+     * A call was made to unmount the OBB when it was not mounted. Returned in
+     * status messages from calls made via {@link StorageManager}
+     */
+    public static final int ERROR_NOT_MOUNTED = 23;
+
+    /**
+     * The OBB has already been mounted. Returned in status messages from calls
+     * made via {@link StorageManager}
+     */
+    public static final int ERROR_ALREADY_MOUNTED = 24;
+
+    /**
+     * 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;
+
     /**
      * Called when an OBB has changed states.
      * 
      * @param path path to the OBB file the state change has happened on
      * @param state the current state of the OBB
      */
-    public void onObbStateChange(String path, String state) {
+    public void onObbStateChange(String path, int state) {
     }
 }
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 2ebd049..73ac79f 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -22,12 +22,13 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * StorageManager is the interface to the systems storage service. The storage
@@ -69,7 +70,12 @@
     /*
      * List of our listeners
      */
-    private ArrayList<ListenerDelegate> mListeners = new ArrayList<ListenerDelegate>();
+    private List<ListenerDelegate> mListeners = new ArrayList<ListenerDelegate>();
+
+    /*
+     * Next available nonce
+     */
+    final private AtomicInteger mNextNonce = new AtomicInteger(0);
 
     private class MountServiceBinderListener extends IMountServiceListener.Stub {
         public void onUsbMassStorageConnectionChanged(boolean available) {
@@ -93,57 +99,38 @@
     private final ObbActionListener mObbActionListener = new ObbActionListener();
 
     private class ObbActionListener extends IObbActionListener.Stub {
-        private List<WeakReference<ObbListenerDelegate>> mListeners = new LinkedList<WeakReference<ObbListenerDelegate>>();
+        private SparseArray<ObbListenerDelegate> mListeners = new SparseArray<ObbListenerDelegate>();
 
         @Override
-        public void onObbResult(String filename, String status) throws RemoteException {
+        public void onObbResult(String filename, int nonce, int status) throws RemoteException {
+            final ObbListenerDelegate delegate;
             synchronized (mListeners) {
-                final Iterator<WeakReference<ObbListenerDelegate>> iter = mListeners.iterator();
-                while (iter.hasNext()) {
-                    final WeakReference<ObbListenerDelegate> ref = iter.next();
-
-                    final ObbListenerDelegate delegate = (ref == null) ? null : ref.get();
-                    if (delegate == null) {
-                        iter.remove();
-                        continue;
-                    }
-
-                    delegate.sendObbStateChanged(filename, status);
+                delegate = mListeners.get(nonce);
+                if (delegate != null) {
+                    mListeners.remove(nonce);
                 }
             }
+
+            if (delegate != null) {
+                delegate.sendObbStateChanged(filename, status);
+            }
         }
 
-        public void addListener(OnObbStateChangeListener listener) {
-            if (listener == null) {
-                return;
-            }
+        public int addListener(OnObbStateChangeListener listener) {
+            final ObbListenerDelegate delegate = new ObbListenerDelegate(listener);
 
             synchronized (mListeners) {
-                final Iterator<WeakReference<ObbListenerDelegate>> iter = mListeners.iterator();
-                while (iter.hasNext()) {
-                    final WeakReference<ObbListenerDelegate> ref = iter.next();
-
-                    final ObbListenerDelegate delegate = (ref == null) ? null : ref.get();
-                    if (delegate == null) {
-                        iter.remove();
-                        continue;
-                    }
-
-                    /*
-                     * If we're already in the listeners, we don't need to be in
-                     * there again.
-                     */
-                    if (listener.equals(delegate.getListener())) {
-                        return;
-                    }
-                }
-
-                final ObbListenerDelegate delegate = new ObbListenerDelegate(listener);
-                mListeners.add(new WeakReference<ObbListenerDelegate>(delegate));
+                mListeners.put(delegate.nonce, delegate);
             }
+
+            return delegate.nonce;
         }
     }
 
+    private int getNextNonce() {
+        return mNextNonce.getAndIncrement();
+    }
+
     /**
      * Private class containing sender and receiver code for StorageEvents.
      */
@@ -151,7 +138,10 @@
         private final WeakReference<OnObbStateChangeListener> mObbEventListenerRef;
         private final Handler mHandler;
 
+        private final int nonce;
+
         ObbListenerDelegate(OnObbStateChangeListener listener) {
+            nonce = getNextNonce();
             mObbEventListenerRef = new WeakReference<OnObbStateChangeListener>(listener);
             mHandler = new Handler(mTgtLooper) {
                 @Override
@@ -180,7 +170,7 @@
             return mObbEventListenerRef.get();
         }
 
-        void sendObbStateChanged(String path, String state) {
+        void sendObbStateChanged(String path, int state) {
             ObbStateChangedStorageEvent e = new ObbStateChangedStorageEvent(path, state);
             mHandler.sendMessage(e.getMessage());
         }
@@ -191,9 +181,10 @@
      */
     private class ObbStateChangedStorageEvent extends StorageEvent {
         public final String path;
-        public final String state;
 
-        public ObbStateChangedStorageEvent(String path, String state) {
+        public final int state;
+
+        public ObbStateChangedStorageEvent(String path, int state) {
             super(EVENT_OBB_STATE_CHANGED);
             this.path = path;
             this.state = state;
@@ -420,10 +411,8 @@
      * <p>
      * The OBB will remain mounted for as long as the StorageManager reference
      * is held by the application. As soon as this reference is lost, the OBBs
-     * in use will be unmounted. The {@link OnObbStateChangeListener} registered with
-     * this call will receive all further OBB-related events until it goes out
-     * of scope. If the caller is not interested in whether the call succeeds,
-     * the <code>listener</code> may be specified as <code>null</code>.
+     * in use will be unmounted. The {@link OnObbStateChangeListener} registered
+     * with this call will receive the success or failure of this operation.
      * <p>
      * <em>Note:</em> you can only mount OBB files for which the OBB tag on the
      * file matches a package ID that is owned by the calling program's UID.
@@ -433,12 +422,21 @@
      * @param filename the path to the OBB file
      * @param key secret used to encrypt the OBB; may be <code>null</code> if no
      *            encryption was used on the OBB.
+     * @param listener will receive the success or failure of the operation
      * @return whether the mount call was successfully queued or not
      */
     public boolean mountObb(String filename, String key, OnObbStateChangeListener listener) {
+        if (filename == null) {
+            throw new IllegalArgumentException("filename cannot be null");
+        }
+
+        if (listener == null) {
+            throw new IllegalArgumentException("listener cannot be null");
+        }
+
         try {
-            mObbActionListener.addListener(listener);
-            mMountService.mountObb(filename, key, mObbActionListener);
+            final int nonce = mObbActionListener.addListener(listener);
+            mMountService.mountObb(filename, key, mObbActionListener, nonce);
             return true;
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to mount OBB", e);
@@ -452,10 +450,8 @@
      * <code>force</code> flag is true, it will kill any application needed to
      * unmount the given OBB (even the calling application).
      * <p>
-     * The {@link OnObbStateChangeListener} registered with this call will receive all
-     * further OBB-related events until it goes out of scope. If the caller is
-     * not interested in whether the call succeeded, the listener may be
-     * specified as <code>null</code>.
+     * The {@link OnObbStateChangeListener} registered with this call will
+     * receive the success or failure of this operation.
      * <p>
      * <em>Note:</em> you can only mount OBB files for which the OBB tag on the
      * file matches a package ID that is owned by the calling program's UID.
@@ -466,12 +462,21 @@
      * @param filename path to the OBB file
      * @param force whether to kill any programs using this in order to unmount
      *            it
+     * @param listener will receive the success or failure of the operation
      * @return whether the unmount call was successfully queued or not
      */
     public boolean unmountObb(String filename, boolean force, OnObbStateChangeListener listener) {
+        if (filename == null) {
+            throw new IllegalArgumentException("filename cannot be null");
+        }
+
+        if (listener == null) {
+            throw new IllegalArgumentException("listener cannot be null");
+        }
+
         try {
-            mObbActionListener.addListener(listener);
-            mMountService.unmountObb(filename, force, mObbActionListener);
+            final int nonce = mObbActionListener.addListener(listener);
+            mMountService.unmountObb(filename, force, mObbActionListener, nonce);
             return true;
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to mount OBB", e);
@@ -486,7 +491,11 @@
      * @param filename path to OBB image
      * @return true if OBB is mounted; false if not mounted or on error
      */
-    public boolean isObbMounted(String filename) throws IllegalArgumentException {
+    public boolean isObbMounted(String filename) {
+        if (filename == null) {
+            throw new IllegalArgumentException("filename cannot be null");
+        }
+
         try {
             return mMountService.isObbMounted(filename);
         } catch (RemoteException e) {
@@ -506,12 +515,14 @@
      *         not mounted or exception encountered trying to read status
      */
     public String getMountedObbPath(String filename) {
+        if (filename == null) {
+            throw new IllegalArgumentException("filename cannot be null");
+        }
+
         try {
             return mMountService.getMountedObbPath(filename);
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to find mounted path for OBB", e);
-        } catch (IllegalArgumentException e) {
-            Log.d(TAG, "Couldn't read OBB file", e);
         }
 
         return null;
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index dde6493..36d676a 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -1195,7 +1195,14 @@
 
     private void tryCommit(SharedPreferences.Editor editor) {
         if (mPreferenceManager.shouldCommit()) {
-            editor.apply();
+            try {
+                editor.apply();
+            } catch (AbstractMethodError unused) {
+                // The app injected its own pre-Gingerbread
+                // SharedPreferences.Editor implementation without
+                // an apply method.
+                editor.commit();
+            }
         }
     }
     
diff --git a/core/java/android/preference/PreferenceManager.java b/core/java/android/preference/PreferenceManager.java
index fa83897..e44a090 100644
--- a/core/java/android/preference/PreferenceManager.java
+++ b/core/java/android/preference/PreferenceManager.java
@@ -443,7 +443,16 @@
             pm.setSharedPreferencesMode(sharedPreferencesMode);
             pm.inflateFromResource(context, resId, null);
 
-            defaultValueSp.edit().putBoolean(KEY_HAS_SET_DEFAULT_VALUES, true).apply();
+            SharedPreferences.Editor editor =
+                    defaultValueSp.edit().putBoolean(KEY_HAS_SET_DEFAULT_VALUES, true);
+            try {
+                editor.apply();
+            } catch (AbstractMethodError unused) {
+                // The app injected its own pre-Gingerbread
+                // SharedPreferences.Editor implementation without
+                // an apply method.
+                editor.commit();
+            }
         }
     }
     
@@ -478,15 +487,21 @@
     boolean shouldCommit() {
         return !mNoCommit;
     }
-    
+
     private void setNoCommit(boolean noCommit) {
         if (!noCommit && mEditor != null) {
-            mEditor.apply();
+            try {
+                mEditor.apply();
+            } catch (AbstractMethodError unused) {
+                // The app injected its own pre-Gingerbread
+                // SharedPreferences.Editor implementation without
+                // an apply method.
+                mEditor.commit();
+            }
         }
-        
         mNoCommit = noCommit;
     }
-    
+
     /**
      * Returns the activity that shows the preferences. This is useful for doing
      * managed queries, but in most cases the use of {@link #getContext()} is
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 7484964..9138da2 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -5543,6 +5543,14 @@
         public static final int MODE_LARGE = 3;
 
         /**
+         * Extra used to specify the last selected tab index of the Contacts app.
+         * If this is not given or -1
+         * @hide
+         */
+        public static final String EXTRA_SELECTED_CONTACTS_APP_TAB_INDEX =
+                "SELECTED_TAB_INDEX";
+
+        /**
          * Trigger a dialog that lists the various methods of interacting with
          * the requested {@link Contacts} entry. This may be based on available
          * {@link ContactsContract.Data} rows under that contact, and may also
@@ -5567,6 +5575,16 @@
          */
         public static void showQuickContact(Context context, View target, Uri lookupUri, int mode,
                 String[] excludeMimes) {
+            context.startActivity(getQuickContactIntent(context, target, lookupUri, mode,
+                    excludeMimes));
+        }
+
+        /**
+         * Creates the Intent to launch Quick Contacts
+         * @hide
+         */
+        public static Intent getQuickContactIntent(Context context, View target, Uri lookupUri,
+                int mode, String[] excludeMimes) {
             // Find location and bounds of target view, adjusting based on the
             // assumed local density.
             final float appScale = context.getResources().getCompatibilityInfo().applicationScale;
@@ -5580,7 +5598,7 @@
             rect.bottom = (int) ((pos[1] + target.getHeight()) * appScale + 0.5f);
 
             // Trigger with obtained rectangle
-            showQuickContact(context, rect, lookupUri, mode, excludeMimes);
+            return getQuickContactIntent(context, rect, lookupUri, mode, excludeMimes);
         }
 
         /**
@@ -5611,6 +5629,16 @@
          */
         public static void showQuickContact(Context context, Rect target, Uri lookupUri, int mode,
                 String[] excludeMimes) {
+            context.startActivity(getQuickContactIntent(context, target, lookupUri, mode,
+                    excludeMimes));
+        }
+
+        /**
+         * Creates the Intent to launch Quick Contacts
+         * @hide
+         */
+        public static Intent getQuickContactIntent(Context context, Rect target, Uri lookupUri,
+                int mode, String[] excludeMimes) {
             // Launch pivot dialog through intent for now
             final Intent intent = new Intent(ACTION_QUICK_CONTACT);
             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP
@@ -5620,7 +5648,7 @@
             intent.setSourceBounds(target);
             intent.putExtra(EXTRA_MODE, mode);
             intent.putExtra(EXTRA_EXCLUDE_MIMES, excludeMimes);
-            context.startActivity(intent);
+            return intent;
         }
     }
 
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..6e221c8 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)) {
@@ -365,6 +367,11 @@
         int state = getSinkState(device);
         String path = mBluetoothService.getObjectPathFromAddress(device.getAddress());
 
+        switch (state) {
+            case BluetoothA2dp.STATE_DISCONNECTED:
+            case BluetoothA2dp.STATE_DISCONNECTING:
+                return false;
+        }
         // State is CONNECTING or CONNECTED or PLAYING
         handleSinkStateChange(device, state, BluetoothA2dp.STATE_DISCONNECTING);
         if (!disconnectSinkNative(path)) {
@@ -491,14 +498,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 +518,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/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 9e7eedf..0e5ece1 100755
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -46,10 +46,12 @@
  * with the special action {@link #ACTION_MULTIPLE} that either specifies
  * that single repeated key code or a sequence of characters to insert.
  * </p><p>
- * In general, the framework makes no guarantees that the key events delivered
- * to a view constitute a complete key press.  In particular, there is no
- * guarantee that a view will always receive a key event with {@link #ACTION_UP}
- * for each {@link #ACTION_DOWN} that was delivered.
+ * In general, the framework cannot guarantee that the key events it delivers
+ * to a view always constitute complete key sequences since some events may be dropped
+ * or modified by containing views before they are delivered.  The view implementation
+ * should be prepared to handle {@link #FLAG_CANCELED} and should tolerate anomalous
+ * situations such as receiving a new {@link #ACTION_DOWN} without first having
+ * received an {@link #ACTION_UP} for the prior key press.
  * </p><p>
  * Refer to {@link InputDevice} for more information about how different kinds of
  * input devices and sources represent keys and buttons.
@@ -195,7 +197,8 @@
     public static final int KEYCODE_TAB             = 61;
     /** Key code constant: Space key. */
     public static final int KEYCODE_SPACE           = 62;
-    /** Key code constant: Symbol modifier key. */
+    /** Key code constant: Symbol modifier key.
+     * Used to enter alternate symbols. */
     public static final int KEYCODE_SYM             = 63;
     /** Key code constant: Explorer special function key.
      * Used to launch a browser application. */
@@ -205,7 +208,8 @@
     public static final int KEYCODE_ENVELOPE        = 65;
     /** Key code constant: Enter key. */
     public static final int KEYCODE_ENTER           = 66;
-    /** Key code constant: Delete key. */
+    /** Key code constant: Backspace key.
+     * Deletes characters before the insertion point. */
     public static final int KEYCODE_DEL             = 67;
     /** Key code constant: '`' (backtick) key. */
     public static final int KEYCODE_GRAVE           = 68;
@@ -227,7 +231,10 @@
     public static final int KEYCODE_SLASH           = 76;
     /** Key code constant: '@' key. */
     public static final int KEYCODE_AT              = 77;
-    /** Key code constant: Number Lock modifier key. */
+    /** Key code constant: Number modifier key.
+     * Used to enter numeric symbols.
+     * This key is not Num Lock; it is more like {@link #KEYCODE_ALT_LEFT} and is
+     * interpreted as an ALT key by {@link android.text.method.MetaKeyKeyListener}. */
     public static final int KEYCODE_NUM             = 78;
     /** Key code constant: Headset Hook key.
      * Used to hang up calls and stop media. */
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 6705596..c2fec96 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -81,10 +81,12 @@
  *     }
  * }
  * </code></pre></p><p>
- * In general, the framework makes no guarantees that the motion events delivered
- * to a view constitute a complete gesture.  In particular, there is no
- * guarantee that a view will always receive a motion event with {@link #ACTION_UP}
- * for each {@link #ACTION_DOWN} that was delivered.
+ * In general, the framework cannot guarantee that the motion events it delivers
+ * to a view always constitute a complete motion sequences since some events may be dropped
+ * or modified by containing views before they are delivered.  The view implementation
+ * should be prepared to handle {@link #ACTION_CANCEL} and should tolerate anomalous
+ * situations such as receiving a new {@link #ACTION_DOWN} without first having
+ * received an {@link #ACTION_UP} for the prior gesture.
  * </p><p>
  * Refer to {@link InputDevice} for more information about how different kinds of
  * input devices and sources represent pointer coordinates.
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 954b3e7..1fd31a3 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -65,6 +65,7 @@
  * @hide
  */
 public interface WindowManagerPolicy {
+    // Policy flags.  These flags are also defined in frameworks/base/include/ui/Input.h.
     public final static int FLAG_WAKE = 0x00000001;
     public final static int FLAG_WAKE_DROPPED = 0x00000002;
     public final static int FLAG_SHIFT = 0x00000004;
@@ -76,9 +77,11 @@
     public final static int FLAG_VIRTUAL = 0x00000100;
 
     public final static int FLAG_INJECTED = 0x01000000;
+    public final static int FLAG_TRUSTED = 0x02000000;
 
     public final static int FLAG_WOKE_HERE = 0x10000000;
     public final static int FLAG_BRIGHT_HERE = 0x20000000;
+    public final static int FLAG_PASS_TO_USER = 0x40000000;
 
     public final static boolean WATCH_POINTER = false;
 
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index 19abec1..e82ed9f 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -519,6 +519,7 @@
             return false;
         case MotionEvent.ACTION_UP:
         case MotionEvent.ACTION_CANCEL:
+            super.onTouchEvent(event);
             if (mHasPerformedLongClick) {
                 mGotTouchDown = false;
                 return false;
@@ -684,9 +685,6 @@
         // webkit's drawing.
         setWillNotDraw(!inPassword);
         setBackgroundDrawable(inPassword ? mBackground : null);
-        // For non-password fields, avoid the invals from TextView's blinking
-        // cursor
-        setCursorVisible(inPassword);
     }
 
     /**
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/AbsListView.java b/core/java/android/widget/AbsListView.java
index ee57c6e..6260cdb 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2247,8 +2247,14 @@
                                 mTouchMode = TOUCH_MODE_OVERSCROLL;
                                 if (rawDeltaY > 0) {
                                     mEdgeGlowTop.onPull((float) overscroll / getHeight());
+                                    if (!mEdgeGlowBottom.isFinished()) {
+                                        mEdgeGlowBottom.onRelease();
+                                    }
                                 } else if (rawDeltaY < 0) {
                                     mEdgeGlowBottom.onPull((float) overscroll / getHeight());
+                                    if (!mEdgeGlowTop.isFinished()) {
+                                        mEdgeGlowTop.onRelease();
+                                    }
                                 }
                             }
                         }
@@ -2307,8 +2313,14 @@
                                         !contentFits())) {
                             if (rawDeltaY > 0) {
                                 mEdgeGlowTop.onPull((float) -incrementalDeltaY / getHeight());
+                                if (!mEdgeGlowBottom.isFinished()) {
+                                    mEdgeGlowBottom.onRelease();
+                                }
                             } else if (rawDeltaY < 0) {
                                 mEdgeGlowBottom.onPull((float) -incrementalDeltaY / getHeight());
+                                if (!mEdgeGlowTop.isFinished()) {
+                                    mEdgeGlowTop.onRelease();
+                                }
                             }
                             invalidate();
                         }
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index aa14c81..d3aa42f 100755
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -17,14 +17,14 @@
 package android.widget;
 
 import com.android.internal.R;
+
 import android.content.Context;
-import android.content.res.Resources;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageParser;
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.graphics.drawable.Drawable;
 import android.util.Log;
 import android.view.LayoutInflater;
@@ -329,11 +329,6 @@
 
         TextView permGrpView = (TextView) permView.findViewById(R.id.permission_group);
         TextView permDescView = (TextView) permView.findViewById(R.id.permission_list);
-        if (dangerous) {
-            final Resources resources = context.getResources();
-            permGrpView.setTextColor(resources.getColor(R.color.perms_dangerous_grp_color));
-            permDescView.setTextColor(resources.getColor(R.color.perms_dangerous_perm_color));
-        }
 
         ImageView imgView = (ImageView)permView.findViewById(R.id.perm_icon);
         imgView.setImageDrawable(icon);
diff --git a/core/java/android/widget/EdgeGlow.java b/core/java/android/widget/EdgeGlow.java
index 1f7daab..416be86 100644
--- a/core/java/android/widget/EdgeGlow.java
+++ b/core/java/android/widget/EdgeGlow.java
@@ -33,12 +33,12 @@
     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 = 1.f;
+    private static final float MAX_ALPHA = 0.8f;
     private static final float HELD_EDGE_ALPHA = 0.7f;
     private static final float HELD_EDGE_SCALE_Y = 0.5f;
     private static final float HELD_GLOW_ALPHA = 0.5f;
@@ -91,6 +91,7 @@
     // How much dragging should effect the height of the glow image.
     // Number determined by user testing.
     private static final int PULL_DISTANCE_GLOW_FACTOR = 5;
+    private static final float PULL_DISTANCE_ALPHA_GLOW_FACTOR = 0.8f;
 
     private static final int VELOCITY_EDGE_FACTOR = 8;
     private static final int VELOCITY_GLOW_FACTOR = 16;
@@ -144,8 +145,9 @@
         mEdgeScaleY = mEdgeScaleYStart = Math.max(
                 HELD_EDGE_SCALE_Y, Math.min(distance * PULL_DISTANCE_EDGE_FACTOR, 1.f));
 
-        mGlowAlpha = mGlowAlphaStart = Math.max(
-                0.5f, Math.min(mGlowAlpha + Math.abs(deltaDistance), MAX_ALPHA));
+        mGlowAlpha = mGlowAlphaStart = Math.min(MAX_ALPHA,
+                mGlowAlpha +
+                (Math.abs(deltaDistance) * PULL_DISTANCE_ALPHA_GLOW_FACTOR));
 
         float glowChange = Math.abs(deltaDistance);
         if (deltaDistance > 0 && mPullDistance < 0) {
@@ -154,8 +156,10 @@
         if (mPullDistance == 0) {
             mGlowScaleY = 0;
         }
-        mGlowScaleY = mGlowScaleYStart = Math.max(
-                0, mGlowScaleY + glowChange * PULL_DISTANCE_GLOW_FACTOR);
+
+        // Do not allow glow to get larger than MAX_GLOW_HEIGHT.
+        mGlowScaleY = mGlowScaleYStart = Math.min(MAX_GLOW_HEIGHT, Math.max(
+                0, mGlowScaleY + glowChange * PULL_DISTANCE_GLOW_FACTOR));
 
         mEdgeAlphaFinish = mEdgeAlpha;
         mEdgeScaleYFinish = mEdgeScaleY;
@@ -202,8 +206,8 @@
 
         // The edge should always be at least partially visible, regardless
         // of velocity.
-        mEdgeAlphaStart = 0.5f;
-        mEdgeScaleYStart = 0.2f;
+        mEdgeAlphaStart = 0.f;
+        mEdgeScaleY = mEdgeScaleYStart = 0.f;
         // The glow depends more on the velocity, and therefore starts out
         // nearly invisible.
         mGlowAlphaStart = 0.5f;
@@ -213,7 +217,8 @@
         // reflect the strength of the user's scrolling.
         mEdgeAlphaFinish = Math.max(0, Math.min(velocity * VELOCITY_EDGE_FACTOR, 1));
         // Edge should never get larger than the size of its asset.
-        mEdgeScaleYFinish = 1.f;
+        mEdgeScaleYFinish = Math.max(
+                HELD_EDGE_SCALE_Y, Math.min(velocity * VELOCITY_EDGE_FACTOR, 1.f));
 
         // Growth for the size of the glow should be quadratic to properly
         // respond
@@ -281,10 +286,11 @@
                     mGlowAlphaStart = mGlowAlpha;
                     mGlowScaleYStart = mGlowScaleY;
 
+                    // After absorb, the glow and edge should fade to nothing.
                     mEdgeAlphaFinish = 0.f;
-                    mEdgeScaleYFinish = mEdgeScaleY;
+                    mEdgeScaleYFinish = 0.f;
                     mGlowAlphaFinish = 0.f;
-                    mGlowScaleYFinish = mGlowScaleY;
+                    mGlowScaleYFinish = 0.f;
                     break;
                 case STATE_PULL:
                     mState = STATE_PULL_DECAY;
@@ -296,14 +302,21 @@
                     mGlowAlphaStart = mGlowAlpha;
                     mGlowScaleYStart = mGlowScaleY;
 
-                    // After a pull, the glow should fade to nothing.
+                    // After pull, the glow and edge should fade to nothing.
                     mEdgeAlphaFinish = 0.f;
                     mEdgeScaleYFinish = 0.f;
                     mGlowAlphaFinish = 0.f;
                     mGlowScaleYFinish = 0.f;
                     break;
                 case STATE_PULL_DECAY:
-                    // Do nothing; wait for release
+                    // When receding, we want edge to decrease more slowly
+                    // than the glow.
+                    float factor = mGlowScaleYFinish != 0 ? 1
+                            / (mGlowScaleYFinish * mGlowScaleYFinish)
+                            : Float.MAX_VALUE;
+                    mEdgeScaleY = mEdgeScaleYStart +
+                        (mEdgeScaleYFinish - mEdgeScaleYStart) *
+                            interp * factor;
                     break;
                 case STATE_RECEDE:
                     mState = STATE_IDLE;
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 6a52f75..d38eef3 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -542,8 +542,14 @@
                         final int pulledToX = oldX + deltaX;
                         if (pulledToX < 0) {
                             mEdgeGlowLeft.onPull((float) deltaX / getWidth());
+                            if (!mEdgeGlowRight.isFinished()) {
+                                mEdgeGlowRight.onRelease();
+                            }
                         } else if (pulledToX > range) {
                             mEdgeGlowRight.onPull((float) deltaX / getWidth());
+                            if (!mEdgeGlowLeft.isFinished()) {
+                                mEdgeGlowLeft.onRelease();
+                            }
                         }
                     }
                 }
diff --git a/core/java/android/widget/QuickContactBadge.java b/core/java/android/widget/QuickContactBadge.java
index 4bbb540..e7d44a0 100644
--- a/core/java/android/widget/QuickContactBadge.java
+++ b/core/java/android/widget/QuickContactBadge.java
@@ -48,6 +48,7 @@
     private QueryHandler mQueryHandler;
     private Drawable mBadgeBackground;
     private Drawable mNoBadgeBackground;
+    private int mSelectedContactsAppTabIndex = -1;
 
     protected String[] mExcludeMimes = null;
 
@@ -133,6 +134,15 @@
         onContactUriChanged();
     }
 
+    /**
+     * Sets the currently selected tab of the Contacts application. If not set, this is -1
+     * and therefore does not save a tab selection when a phone call is being made
+     * @hide
+     */
+    public void setSelectedContactsAppTabIndex(int value) {
+        mSelectedContactsAppTabIndex = value;
+    }
+
     private void onContactUriChanged() {
         if (mContactUri == null && mContactEmail == null && mContactPhone == null) {
             if (mNoBadgeBackground == null) {
@@ -215,7 +225,13 @@
     }
 
     private void trigger(Uri lookupUri) {
-        QuickContact.showQuickContact(getContext(), this, lookupUri, mMode, mExcludeMimes);
+        final Intent intent = QuickContact.getQuickContactIntent(getContext(), this, lookupUri,
+                mMode, mExcludeMimes);
+        if (mSelectedContactsAppTabIndex != -1) {
+            intent.putExtra(QuickContact.EXTRA_SELECTED_CONTACTS_APP_TAB_INDEX,
+                    mSelectedContactsAppTabIndex);
+        }
+        getContext().startActivity(intent);
     }
 
     private class QueryHandler extends AsyncQueryHandler {
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 0337b5c..1daf2ab 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -537,8 +537,14 @@
                         final int pulledToY = oldY + deltaY;
                         if (pulledToY < 0) {
                             mEdgeGlowTop.onPull((float) deltaY / getHeight());
+                            if (!mEdgeGlowBottom.isFinished()) {
+                                mEdgeGlowBottom.onRelease();
+                            }
                         } else if (pulledToY > range) {
                             mEdgeGlowBottom.onPull((float) deltaY / getHeight());
+                            if (!mEdgeGlowTop.isFinished()) {
+                                mEdgeGlowTop.onRelease();
+                            }
                         }
                     }
                 }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5dd3d6b..9080f96 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -92,11 +92,12 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewDebug;
-import android.view.WindowManager;
+import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 import android.view.ViewParent;
 import android.view.ViewRoot;
 import android.view.ViewTreeObserver;
+import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.view.animation.AnimationUtils;
@@ -4321,6 +4322,7 @@
 
         switch (keyCode) {
             case KeyEvent.KEYCODE_ENTER:
+                mEnterKeyIsDown = true;
                 // If ALT modifier is held, then we always insert a
                 // newline character.
                 if ((event.getMetaState()&KeyEvent.META_ALT_ON) == 0) {
@@ -4353,6 +4355,7 @@
                 break;
                 
             case KeyEvent.KEYCODE_DPAD_CENTER:
+                mDPadCenterIsDown = true;
                 if (shouldAdvanceFocusOnEnter()) {
                     return 0;
                 }
@@ -4444,9 +4447,11 @@
         }
 
         hideControllers();
+        stopTextSelectionMode();
 
         switch (keyCode) {
             case KeyEvent.KEYCODE_DPAD_CENTER:
+                mDPadCenterIsDown = false;
                 /*
                  * If there is a click listener, just call through to
                  * super, which will invoke it.
@@ -4467,6 +4472,7 @@
                 return super.onKeyUp(keyCode, event);
                 
             case KeyEvent.KEYCODE_ENTER:
+                mEnterKeyIsDown = false;
                 if (mInputContentType != null
                         && mInputContentType.onEditorActionListener != null
                         && mInputContentType.enterDown) {
@@ -6545,11 +6551,11 @@
             int selEnd = getSelectionEnd();
 
             if (!mFrozenWithFocus || (selStart < 0 || selEnd < 0)) {
+                // If a tap was used to give focus to that view, move cursor at tap position.
                 // Has to be done before onTakeFocus, which can be overloaded.
-                if (mLastTouchOffset >= 0) {
-                    // Can happen when a TextView is displayed after its content has been deleted.
-                    mLastTouchOffset = Math.min(mLastTouchOffset, mText.length());
-                    Selection.setSelection((Spannable) mText, mLastTouchOffset);
+                final int lastTapPosition = getLastTapPosition();
+                if (lastTapPosition >= 0) {
+                    Selection.setSelection((Spannable) mText, lastTapPosition);
                 }
 
                 if (mMovement != null) {
@@ -6610,7 +6616,9 @@
                 terminateTextSelectionMode();
             }
 
-            mLastTouchOffset = -1;
+            if (mSelectionModifierCursorController != null) {
+                ((SelectionModifierCursorController) mSelectionModifierCursorController).resetTouchOffsets();
+            }
         }
 
         startStopMarquee(focused);
@@ -6622,6 +6630,24 @@
         super.onFocusChanged(focused, direction, previouslyFocusedRect);
     }
 
+    private int getLastTapPosition() {
+        if (mSelectionModifierCursorController != null) {
+            int lastTapPosition = ((SelectionModifierCursorController)
+                    mSelectionModifierCursorController).getMinTouchOffset();
+            if (lastTapPosition >= 0) {
+                // Safety check, should not be possible.
+                if (lastTapPosition > mText.length()) {
+                    Log.e(LOG_TAG, "Invalid tap focus position (" + lastTapPosition + " vs "
+                            + mText.length() + ")");
+                    lastTapPosition = mText.length();
+                }
+                return lastTapPosition;
+            }
+        }
+
+        return -1;
+    }
+
     @Override
     public void onWindowFocusChanged(boolean hasWindowFocus) {
         super.onWindowFocusChanged(hasWindowFocus);
@@ -6644,10 +6670,7 @@
             if (mInputContentType != null) {
                 mInputContentType.enterDown = false;
             }
-            hideInsertionPointCursorController();
-            if (mSelectionModifierCursorController != null) {
-                mSelectionModifierCursorController.hide();
-            }
+            hideControllers();
         }
 
         startStopMarquee(hasWindowFocus);
@@ -6657,10 +6680,7 @@
     protected void onVisibilityChanged(View changedView, int visibility) {
         super.onVisibilityChanged(changedView, visibility);
         if (visibility != VISIBLE) {
-            hideInsertionPointCursorController();
-            if (mSelectionModifierCursorController != null) {
-                mSelectionModifierCursorController.hide();
-            }
+            hideControllers();
         }
     }
 
@@ -6713,7 +6733,7 @@
                 // Tapping outside stops selection mode, if any
                 stopTextSelectionMode();
 
-                if (mInsertionPointCursorController != null) {
+                if (mInsertionPointCursorController != null && mText.length() > 0) {
                     mInsertionPointCursorController.show();
                 }
             }
@@ -6834,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();
             }
@@ -6843,7 +6872,7 @@
             mInsertionPointCursorController = null;
         }
 
-        if (textCanBeSelected() && mLayout != null) {
+        if (windowSupportsHandles && textCanBeSelected() && mLayout != null) {
             if (mSelectionModifierCursorController == null) {
                 mSelectionModifierCursorController = new SelectionModifierCursorController();
             }
@@ -7227,9 +7256,21 @@
         }
 
         // Two ints packed in a long
-        return (((long) start) << 32) | end;
+        return packRangeInLong(start, end);
     }
     
+    private static long packRangeInLong(int start, int end) {
+        return (((long) start) << 32) | end;
+    }
+
+    private static int extractRangeStartFromLong(long range) {
+        return (int) (range >>> 32);
+    }
+
+    private static int extractRangeEndFromLong(long range) {
+        return (int) (range & 0x00000000FFFFFFFFL);
+    }
+
     private void selectCurrentWord() {
         // In case selection mode is started after an orientation change or after a select all,
         // use the current selection instead of creating one
@@ -7237,24 +7278,31 @@
             return;
         }
 
-        int selectionStart, selectionEnd;
+        int minOffset, maxOffset;
 
-        // selectionModifierCursorController is not null at that point
-        SelectionModifierCursorController selectionModifierCursorController =
-            ((SelectionModifierCursorController) mSelectionModifierCursorController);
-        int minOffset = selectionModifierCursorController.getMinTouchOffset();
-        int maxOffset = selectionModifierCursorController.getMaxTouchOffset();
+        if (mContextMenuTriggeredByKey) {
+            minOffset = getSelectionStart();
+            maxOffset = getSelectionEnd();
+        } else {
+            // selectionModifierCursorController is not null at that point
+            SelectionModifierCursorController selectionModifierCursorController =
+                ((SelectionModifierCursorController) mSelectionModifierCursorController);
+            minOffset = selectionModifierCursorController.getMinTouchOffset();
+            maxOffset = selectionModifierCursorController.getMaxTouchOffset();
+        }
+
+        int selectionStart, selectionEnd;
         
         long wordLimits = getWordLimitsAt(minOffset);
         if (wordLimits >= 0) {
-            selectionStart = (int) (wordLimits >>> 32);
+            selectionStart = extractRangeStartFromLong(wordLimits);
         } else {
             selectionStart = Math.max(minOffset - 5, 0);
         }
 
         wordLimits = getWordLimitsAt(maxOffset);
         if (wordLimits >= 0) {
-            selectionEnd = (int) (wordLimits & 0x00000000FFFFFFFFL);
+            selectionEnd = extractRangeEndFromLong(wordLimits);
         } else {
             selectionEnd = Math.min(maxOffset + 5, mText.length());
         }
@@ -7263,14 +7311,11 @@
     }
     
     private String getWordForDictionary() {
-        if (mLastTouchOffset < 0) {
-            return null;
-        }
-
-        long wordLimits = getWordLimitsAt(mLastTouchOffset);
+        int seedPosition = mContextMenuTriggeredByKey ? getSelectionStart() : getLastTapPosition();
+        long wordLimits = getWordLimitsAt(seedPosition);
         if (wordLimits >= 0) {
-            int start = (int) (wordLimits >>> 32);
-            int end = (int) (wordLimits & 0x00000000FFFFFFFFL);
+            int start = extractRangeStartFromLong(wordLimits);
+            int end = extractRangeEndFromLong(wordLimits);
             return mTransformed.subSequence(start, end).toString();
         } else {
             return null;
@@ -7317,6 +7362,14 @@
     protected void onCreateContextMenu(ContextMenu menu) {
         super.onCreateContextMenu(menu);
         boolean added = false;
+        mContextMenuTriggeredByKey = mDPadCenterIsDown || mEnterKeyIsDown;
+        // Problem with context menu on long press: the menu appears while the key in down and when
+        // the key is released, the view does not receive the key_up event. This ensures that the
+        // state is reset whenever the context menu action is displayed.
+        // mContextMenuTriggeredByKey saved that state so that it is available in
+        // onTextContextMenuItem. We cannot simply clear these flags in onTextContextMenuItem since
+        // it may not be called (if the user/ discards the context menu with the back key).
+        mDPadCenterIsDown = mEnterKeyIsDown = false;
 
         if (mIsInTextSelectionMode) {
             MenuHandler handler = new MenuHandler();
@@ -7342,21 +7395,6 @@
                 added = true;
             }
         } else {
-            /*
-            if (!isFocused()) {
-                if (isFocusable() && mInput != null) {
-                    if (canCopy()) {
-                        MenuHandler handler = new MenuHandler();
-                        menu.add(0, ID_COPY, 0, com.android.internal.R.string.copy).
-                             setOnMenuItemClickListener(handler).
-                             setAlphabeticShortcut('c');
-                        menu.setHeaderTitle(com.android.internal.R.string.editTextMenuTitle);
-                    }
-                }
-
-                //return;
-            }
-             */
             MenuHandler handler = new MenuHandler();
 
             if (canSelectText()) {
@@ -7485,43 +7523,9 @@
                 CharSequence paste = clip.getText();
 
                 if (paste != null && paste.length() > 0) {
-                    // Paste adds/removes spaces before or after insertion as needed.
-
-                    if (Character.isSpaceChar(paste.charAt(0))) {
-                        if (min > 0 && Character.isSpaceChar(mTransformed.charAt(min - 1))) {
-                            // Two spaces at beginning of paste: remove one
-                            final int originalLength = mText.length();
-                            ((Editable) mText).replace(min - 1, min, "");
-                            // Due to filters, there is no garantee that exactly one character was
-                            // removed. Count instead.
-                            final int delta = mText.length() - originalLength;
-                            min += delta;
-                            max += delta;
-                        }
-                    } else {
-                        if (min > 0 && !Character.isSpaceChar(mTransformed.charAt(min - 1))) {
-                            // No space at beginning of paste: add one
-                            final int originalLength = mText.length();
-                            ((Editable) mText).replace(min, min, " ");
-                            // Taking possible filters into account as above.
-                            final int delta = mText.length() - originalLength;
-                            min += delta;
-                            max += delta;
-                        }
-                    }
-
-                    if (Character.isSpaceChar(paste.charAt(paste.length() - 1))) {
-                        if (max < mText.length() && Character.isSpaceChar(mTransformed.charAt(max))) {
-                            // Two spaces at end of paste: remove one
-                            ((Editable) mText).replace(max, max + 1, "");
-                        }
-                    } else {
-                        if (max < mText.length() && !Character.isSpaceChar(mTransformed.charAt(max))) {
-                            // No space at end of paste: add one
-                            ((Editable) mText).replace(max, max, " ");
-                        }
-                    }
-
+                    long minMax = prepareSpacesAroundPaste(min, max, paste);
+                    min = extractRangeStartFromLong(minMax);
+                    max = extractRangeEndFromLong(minMax);
                     Selection.setSelection((Spannable) mText, max);
                     ((Editable) mText).replace(min, max, paste);
                     stopTextSelectionMode();
@@ -7544,7 +7548,6 @@
 
             case ID_ADD_TO_DICTIONARY:
                 String word = getWordForDictionary();
-
                 if (word != null) {
                     Intent i = new Intent("com.android.settings.USER_DICTIONARY_INSERT");
                     i.putExtra("word", word);
@@ -7557,6 +7560,49 @@
         return false;
     }
 
+    /**
+     * Prepare text so that there are not zero or two spaces at beginning and end of region defined
+     * by [min, max] when replacing this region by paste.
+     */
+    private long prepareSpacesAroundPaste(int min, int max, CharSequence paste) {
+        // Paste adds/removes spaces before or after insertion as needed.
+        if (Character.isSpaceChar(paste.charAt(0))) {
+            if (min > 0 && Character.isSpaceChar(mTransformed.charAt(min - 1))) {
+                // Two spaces at beginning of paste: remove one
+                final int originalLength = mText.length();
+                ((Editable) mText).replace(min - 1, min, "");
+                // Due to filters, there is no garantee that exactly one character was
+                // removed. Count instead.
+                final int delta = mText.length() - originalLength;
+                min += delta;
+                max += delta;
+            }
+        } else {
+            if (min > 0 && !Character.isSpaceChar(mTransformed.charAt(min - 1))) {
+                // No space at beginning of paste: add one
+                final int originalLength = mText.length();
+                ((Editable) mText).replace(min, min, " ");
+                // Taking possible filters into account as above.
+                final int delta = mText.length() - originalLength;
+                min += delta;
+                max += delta;
+            }
+        }
+
+        if (Character.isSpaceChar(paste.charAt(paste.length() - 1))) {
+            if (max < mText.length() && Character.isSpaceChar(mTransformed.charAt(max))) {
+                // Two spaces at end of paste: remove one
+                ((Editable) mText).replace(max, max + 1, "");
+            }
+        } else {
+            if (max < mText.length() && !Character.isSpaceChar(mTransformed.charAt(max))) {
+                // No space at end of paste: add one
+                ((Editable) mText).replace(max, max, " ");
+            }
+        }
+        return packRangeInLong(min, max);
+    }
+
     @Override
     public boolean performLongClick() {
         if (super.performLongClick()) {
@@ -7602,10 +7648,7 @@
     private void stopTextSelectionMode() {
         if (mIsInTextSelectionMode) {
             Selection.setSelection((Spannable) mText, getSelectionEnd());
-            if (mSelectionModifierCursorController != null) {
-                mSelectionModifierCursorController.hide();
-            }
-
+            hideSelectionModifierCursorController();
             mIsInTextSelectionMode = false;
         }
     }
@@ -7860,8 +7903,7 @@
                 final float newPosX = rawX - mTouchToWindowOffsetX + mHotspotX;
                 final float newPosY = rawY - mTouchToWindowOffsetY + mHotspotY + mTouchOffsetY;
 
-                mController.updatePosition(this, (int) Math.round(newPosX),
-                        (int) Math.round(newPosY));
+                mController.updatePosition(this, Math.round(newPosX), Math.round(newPosY));
 
                 break;
             }
@@ -7986,6 +8028,7 @@
         SelectionModifierCursorController() {
             mStartHandle = new HandleView(this, HandleView.LEFT);
             mEndHandle = new HandleView(this, HandleView.RIGHT);
+            resetTouchOffsets();
         }
 
         public void show() {
@@ -8068,14 +8111,16 @@
         }
 
         public boolean onTouchEvent(MotionEvent event) {
-            if (isFocused() && isTextEditable()) {
+            // This is done even when the View does not have focus, so that long presses can start
+            // selection and tap can move cursor from this tap position.
+            if (isTextEditable()) {
                 switch (event.getActionMasked()) {
                     case MotionEvent.ACTION_DOWN:
                         final int x = (int) event.getX();
                         final int y = (int) event.getY();
 
                         // Remember finger down position, to be able to start selection from there
-                        mMinTouchOffset = mMaxTouchOffset = mLastTouchOffset = getOffset(x, y);
+                        mMinTouchOffset = mMaxTouchOffset = getOffset(x, y);
 
                         break;
 
@@ -8115,6 +8160,10 @@
             return mMaxTouchOffset;
         }
 
+        public void resetTouchOffsets() {
+            mMinTouchOffset = mMaxTouchOffset = -1;
+        }
+
         /**
          * @return true iff this controller is currently used to move the selection start.
          */
@@ -8135,9 +8184,15 @@
         }
     }
 
+    private void hideSelectionModifierCursorController() {
+        if (mSelectionModifierCursorController != null) {
+            mSelectionModifierCursorController.hide();
+        }
+    }
+    
     private void hideControllers() {
         hideInsertionPointCursorController();
-        stopTextSelectionMode();
+        hideSelectionModifierCursorController();
     }
 
     private int getOffsetForHorizontal(int line, int x) {
@@ -8232,7 +8287,11 @@
     private CursorController        mInsertionPointCursorController;
     private CursorController        mSelectionModifierCursorController;
     private boolean                 mIsInTextSelectionMode = false;
-    private int                     mLastTouchOffset = -1;
+    // These are needed to desambiguate a long click. If the long click comes from ones of these, we
+    // select from the current cursor position. Otherwise, select from long pressed position.
+    private boolean                 mDPadCenterIsDown = false;
+    private boolean                 mEnterKeyIsDown = false;
+    private boolean                 mContextMenuTriggeredByKey = false;
     // Created once and shared by different CursorController helper methods.
     // Only one cursor controller is active at any time which prevent race conditions.
     private static Rect             sCursorControllerTempRect = new Rect();
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/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index b033fad..a9e5052 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -72,6 +72,9 @@
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
     
+    // No, really, THIS is the maximum number of items we will record in the history.
+    private static final int MAX_MAX_HISTORY_ITEMS = 3000;
+
     // The maximum number of names wakelocks we will keep track of
     // per uid; once the limit is reached, we batch the remaining wakelocks
     // in to one common name.
@@ -1169,15 +1172,20 @@
         mBtHeadset = headset;
     }
 
+    int mChangedStates = 0;
+
     void addHistoryRecordLocked(long curTime) {
         if (!mHaveBatteryLevel || !mRecordingHistory) {
             return;
         }
 
         // If the current time is basically the same as the last time,
-        // just collapse into one record.
+        // and no states have since the last recorded entry changed and
+        // are now resetting back to their original value, then just collapse
+        // into one record.
         if (mHistoryEnd != null && mHistoryEnd.cmd == HistoryItem.CMD_UPDATE
-                && (mHistoryBaseTime+curTime) < (mHistoryEnd.time+500)) {
+                && (mHistoryBaseTime+curTime) < (mHistoryEnd.time+2000)
+                && ((mHistoryEnd.states^mHistoryCur.states)&mChangedStates) == 0) {
             // If the current is the same as the one before, then we no
             // longer need the entry.
             if (mHistoryLastEnd != null && mHistoryLastEnd.cmd == HistoryItem.CMD_UPDATE
@@ -1188,20 +1196,29 @@
                 mHistoryEnd = mHistoryLastEnd;
                 mHistoryLastEnd = null;
             } else {
+                mChangedStates |= mHistoryEnd.states^mHistoryCur.states;
                 mHistoryEnd.setTo(mHistoryEnd.time, HistoryItem.CMD_UPDATE, mHistoryCur);
             }
             return;
         }
 
-        if (mNumHistoryItems == MAX_HISTORY_ITEMS) {
+        mChangedStates = 0;
+
+        if (mNumHistoryItems == MAX_HISTORY_ITEMS
+                || mNumHistoryItems == MAX_MAX_HISTORY_ITEMS) {
             addHistoryRecordLocked(curTime, HistoryItem.CMD_OVERFLOW);
         }
 
         if (mNumHistoryItems >= MAX_HISTORY_ITEMS) {
             // Once we've reached the maximum number of items, we only
+            // record changes to the battery level and the most interesting states.
+            // Once we've reached the maximum maximum number of items, we only
             // record changes to the battery level.
             if (mHistoryEnd != null && mHistoryEnd.batteryLevel
-                    == mHistoryCur.batteryLevel) {
+                    == mHistoryCur.batteryLevel &&
+                    (mNumHistoryItems >= MAX_MAX_HISTORY_ITEMS
+                            || ((mHistoryEnd.states^mHistoryCur.states)
+                                    & HistoryItem.MOST_INTERESTING_STATES) == 0)) {
                 return;
             }
         }
@@ -4450,10 +4467,13 @@
     }
 
     public void commitPendingDataToDisk() {
-        Parcel next;
+        final Parcel next;
         synchronized (this) {
             next = mPendingWrite;
             mPendingWrite = null;
+            if (next == null) {
+                return;
+            }
 
             mWriteLock.lock();
         }
diff --git a/core/java/com/android/internal/widget/ContactHeaderWidget.java b/core/java/com/android/internal/widget/ContactHeaderWidget.java
index f421466..4392113 100644
--- a/core/java/com/android/internal/widget/ContactHeaderWidget.java
+++ b/core/java/com/android/internal/widget/ContactHeaderWidget.java
@@ -332,6 +332,13 @@
     }
 
     /**
+     * @hide
+     */
+    public void setSelectedContactsAppTabIndex(int value) {
+        mPhotoView.setSelectedContactsAppTabIndex(value);
+    }
+
+    /**
      * Turn on/off showing of the aggregate badge element.
      */
     public void showAggregateBadge(boolean showBagde) {
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 2f5a0f09..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 b9eb5d6..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 -->
@@ -364,6 +365,13 @@
         android:description="@string/permdesc_nfcLlcp"
         android:label="@string/permlab_nfcLlcp" />
 
+    <!-- Allows an application to use SIP service -->
+    <permission android:name="android.permission.USE_SIP"
+        android:permissionGroup="android.permission-group.NETWORK"
+        android:protectionLevel="dangerous"
+        android:description="@string/permdesc_use_sip"
+        android:label="@string/permlab_use_sip" />
+
     <!-- Allows applications to call into AccountAuthenticators. Only
     the system can get this permission. -->
     <permission android:name="android.permission.ACCOUNT_MANAGER"
@@ -1325,10 +1333,6 @@
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
         </activity>
-        <activity android:name="com.android.internal.app.ExternalMediaFormatActivity"
-                android:theme="@style/Theme.Dialog.Alert"
-                android:excludeFromRecents="true">
-        </activity>
 
         <activity android:name="android.accounts.ChooseAccountActivity"
                 android:excludeFromRecents="true"
diff --git a/core/res/res/drawable-hdpi/btn_code_lock_touched.png b/core/res/res/drawable-hdpi/btn_code_lock_touched.png
index b90508c..0410dd3 100644
--- a/core/res/res/drawable-hdpi/btn_code_lock_touched.png
+++ b/core/res/res/drawable-hdpi/btn_code_lock_touched.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_media_player.9.png b/core/res/res/drawable-hdpi/btn_media_player.9.png
index bf16315..c23cfb6e 100644
--- a/core/res/res/drawable-hdpi/btn_media_player.9.png
+++ b/core/res/res/drawable-hdpi/btn_media_player.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_media_player_disabled.9.png b/core/res/res/drawable-hdpi/btn_media_player_disabled.9.png
index d7b8ed5..45228f1 100644
--- a/core/res/res/drawable-hdpi/btn_media_player_disabled.9.png
+++ b/core/res/res/drawable-hdpi/btn_media_player_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_media_player_disabled_selected.9.png b/core/res/res/drawable-hdpi/btn_media_player_disabled_selected.9.png
index 1a35c31..27e4e1d 100644
--- a/core/res/res/drawable-hdpi/btn_media_player_disabled_selected.9.png
+++ b/core/res/res/drawable-hdpi/btn_media_player_disabled_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_media_player_pressed.9.png b/core/res/res/drawable-hdpi/btn_media_player_pressed.9.png
index 17dd3fc..0b98507 100644
--- a/core/res/res/drawable-hdpi/btn_media_player_pressed.9.png
+++ b/core/res/res/drawable-hdpi/btn_media_player_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_media_player_selected.9.png b/core/res/res/drawable-hdpi/btn_media_player_selected.9.png
index a146d8f..e43fa8a 100644
--- a/core/res/res/drawable-hdpi/btn_media_player_selected.9.png
+++ b/core/res/res/drawable-hdpi/btn_media_player_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/checkbox_off_background.png b/core/res/res/drawable-hdpi/checkbox_off_background.png
index a8e4785..275cba6 100644
--- a/core/res/res/drawable-hdpi/checkbox_off_background.png
+++ b/core/res/res/drawable-hdpi/checkbox_off_background.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/checkbox_on_background.png b/core/res/res/drawable-hdpi/checkbox_on_background.png
index 800d3d5..a390814 100644
--- a/core/res/res/drawable-hdpi/checkbox_on_background.png
+++ b/core/res/res/drawable-hdpi/checkbox_on_background.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_bullet_key_permission.png b/core/res/res/drawable-hdpi/ic_bullet_key_permission.png
index 98d95dc..b6b840a 100644
--- a/core/res/res/drawable-hdpi/ic_bullet_key_permission.png
+++ b/core/res/res/drawable-hdpi/ic_bullet_key_permission.png
Binary files differ
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_default.png b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_default.png
index 467a013..c45b956 100644
--- a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_default.png
+++ b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_default.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 c21b24e..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 87007a3..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/jog_tab_bar_left_end_normal.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_normal.9.png
index 109be42..b9ec237 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_normal.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_normal.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_normal.9.png
index 030c9e9..30fcda5 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_normal.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_left_normal.png b/core/res/res/drawable-hdpi/jog_tab_left_normal.png
old mode 100755
new mode 100644
index 8b89538..d43c5e2
--- a/core/res/res/drawable-hdpi/jog_tab_left_normal.png
+++ b/core/res/res/drawable-hdpi/jog_tab_left_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_right_normal.png b/core/res/res/drawable-hdpi/jog_tab_right_normal.png
old mode 100755
new mode 100644
index 01bba0b..1eb4234
--- a/core/res/res/drawable-hdpi/jog_tab_right_normal.png
+++ b/core/res/res/drawable-hdpi/jog_tab_right_normal.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/panel_background.9.png b/core/res/res/drawable-hdpi/panel_background.9.png
index bfe5713..03175d4 100644
--- a/core/res/res/drawable-hdpi/panel_background.9.png
+++ b/core/res/res/drawable-hdpi/panel_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_bottom_bright.9.png b/core/res/res/drawable-hdpi/popup_bottom_bright.9.png
old mode 100755
new mode 100644
index eaae624..6e5fbb5
--- a/core/res/res/drawable-hdpi/popup_bottom_bright.9.png
+++ b/core/res/res/drawable-hdpi/popup_bottom_bright.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
old mode 100755
new mode 100644
index 8b5d3d5..3434b2d
--- 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_bottom_medium.9.png b/core/res/res/drawable-hdpi/popup_bottom_medium.9.png
old mode 100755
new mode 100644
index 26ede44..673a509
--- a/core/res/res/drawable-hdpi/popup_bottom_medium.9.png
+++ b/core/res/res/drawable-hdpi/popup_bottom_medium.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_center_bright.9.png b/core/res/res/drawable-hdpi/popup_center_bright.9.png
old mode 100755
new mode 100644
index e0ea9c0fa..c2a739c
--- a/core/res/res/drawable-hdpi/popup_center_bright.9.png
+++ b/core/res/res/drawable-hdpi/popup_center_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_center_dark.9.png b/core/res/res/drawable-hdpi/popup_center_dark.9.png
old mode 100755
new mode 100644
index ac1f92df..9d2bfb1
--- a/core/res/res/drawable-hdpi/popup_center_dark.9.png
+++ b/core/res/res/drawable-hdpi/popup_center_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
old mode 100755
new mode 100644
index 1ce2a6d..4375bf2d
--- 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_bright.9.png b/core/res/res/drawable-hdpi/popup_full_bright.9.png
old mode 100755
new mode 100644
index e5b1b46..6b8aa9d
--- a/core/res/res/drawable-hdpi/popup_full_bright.9.png
+++ b/core/res/res/drawable-hdpi/popup_full_bright.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
old mode 100755
new mode 100644
index 8f2fdf0..2884abe
--- 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_bright.9.png b/core/res/res/drawable-hdpi/popup_top_bright.9.png
old mode 100755
new mode 100644
index 766a658..76c35ec
--- a/core/res/res/drawable-hdpi/popup_top_bright.9.png
+++ b/core/res/res/drawable-hdpi/popup_top_bright.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
old mode 100755
new mode 100644
index 1108909..f317330
--- 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_notify_call_mute.png b/core/res/res/drawable-hdpi/stat_notify_call_mute.png
index 0cf5ef5..b0f7990 100755
--- a/core/res/res/drawable-hdpi/stat_notify_call_mute.png
+++ b/core/res/res/drawable-hdpi/stat_notify_call_mute.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png b/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png
index 0458124..76034e5 100644
--- a/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png
+++ b/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_0.png b/core/res/res/drawable-hdpi/stat_sys_battery_0.png
index 3ed0105..82f2509 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_0.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_0.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..2ed6082 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/btn_media_player.9.png b/core/res/res/drawable-mdpi/btn_media_player.9.png
index 3ec3f683..c479e33 100755
--- a/core/res/res/drawable-mdpi/btn_media_player.9.png
+++ b/core/res/res/drawable-mdpi/btn_media_player.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_media_player_disabled.9.png b/core/res/res/drawable-mdpi/btn_media_player_disabled.9.png
index e74335b..8f9d8b4 100755
--- a/core/res/res/drawable-mdpi/btn_media_player_disabled.9.png
+++ b/core/res/res/drawable-mdpi/btn_media_player_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_media_player_disabled_selected.9.png b/core/res/res/drawable-mdpi/btn_media_player_disabled_selected.9.png
index 2c6517f..0ba6794 100755
--- a/core/res/res/drawable-mdpi/btn_media_player_disabled_selected.9.png
+++ b/core/res/res/drawable-mdpi/btn_media_player_disabled_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_media_player_pressed.9.png b/core/res/res/drawable-mdpi/btn_media_player_pressed.9.png
index 40bee47..f341470 100755
--- a/core/res/res/drawable-mdpi/btn_media_player_pressed.9.png
+++ b/core/res/res/drawable-mdpi/btn_media_player_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_media_player_selected.9.png b/core/res/res/drawable-mdpi/btn_media_player_selected.9.png
index 28d809f..09f4c992 100755
--- a/core/res/res/drawable-mdpi/btn_media_player_selected.9.png
+++ b/core/res/res/drawable-mdpi/btn_media_player_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/checkbox_off_background.png b/core/res/res/drawable-mdpi/checkbox_off_background.png
index 6b2124f..e9471e5 100644
--- a/core/res/res/drawable-mdpi/checkbox_off_background.png
+++ b/core/res/res/drawable-mdpi/checkbox_off_background.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/checkbox_on_background.png b/core/res/res/drawable-mdpi/checkbox_on_background.png
index 56495fc..c247069 100644
--- a/core/res/res/drawable-mdpi/checkbox_on_background.png
+++ b/core/res/res/drawable-mdpi/checkbox_on_background.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_emergency.png b/core/res/res/drawable-mdpi/ic_emergency.png
index 45d0f21..c6faf1e 100755
--- a/core/res/res/drawable-mdpi/ic_emergency.png
+++ b/core/res/res/drawable-mdpi/ic_emergency.png
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/panel_background.9.png b/core/res/res/drawable-mdpi/panel_background.9.png
index 2305be4..822b6c6 100644
--- a/core/res/res/drawable-mdpi/panel_background.9.png
+++ b/core/res/res/drawable-mdpi/panel_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_bottom_bright.9.png b/core/res/res/drawable-mdpi/popup_bottom_bright.9.png
index e8e203b3..e7b713d 100644
--- a/core/res/res/drawable-mdpi/popup_bottom_bright.9.png
+++ b/core/res/res/drawable-mdpi/popup_bottom_bright.9.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..88ce336 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
old mode 100755
new mode 100644
index dee6d6b..e5aaad0
--- 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_center_bright.9.png b/core/res/res/drawable-mdpi/popup_center_bright.9.png
index c817338db..a259356 100644
--- a/core/res/res/drawable-mdpi/popup_center_bright.9.png
+++ b/core/res/res/drawable-mdpi/popup_center_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_center_dark.9.png b/core/res/res/drawable-mdpi/popup_center_dark.9.png
index 79ffdaa..9378dbf 100644
--- a/core/res/res/drawable-mdpi/popup_center_dark.9.png
+++ b/core/res/res/drawable-mdpi/popup_center_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_center_medium.9.png b/core/res/res/drawable-mdpi/popup_center_medium.9.png
old mode 100755
new mode 100644
index ba2e9bf..885403c
--- a/core/res/res/drawable-mdpi/popup_center_medium.9.png
+++ b/core/res/res/drawable-mdpi/popup_center_medium.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_full_bright.9.png b/core/res/res/drawable-mdpi/popup_full_bright.9.png
index d33ff2b9..d7fb3db 100644
--- a/core/res/res/drawable-mdpi/popup_full_bright.9.png
+++ b/core/res/res/drawable-mdpi/popup_full_bright.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..7b9f291 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_bright.9.png b/core/res/res/drawable-mdpi/popup_top_bright.9.png
index 727a948..72d82f0 100644
--- a/core/res/res/drawable-mdpi/popup_top_bright.9.png
+++ b/core/res/res/drawable-mdpi/popup_top_bright.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..616d80f 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_notify_call_mute.png b/core/res/res/drawable-mdpi/stat_notify_call_mute.png
index 6da8313..4a3b057 100644
--- a/core/res/res/drawable-mdpi/stat_notify_call_mute.png
+++ b/core/res/res/drawable-mdpi/stat_notify_call_mute.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_0.png b/core/res/res/drawable-mdpi/stat_sys_battery_0.png
index 4a5e99e..a7068b2 100644
--- a/core/res/res/drawable-mdpi/stat_sys_battery_0.png
+++ b/core/res/res/drawable-mdpi/stat_sys_battery_0.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/layout/app_perms_summary.xml b/core/res/res/layout/app_perms_summary.xml
index 7160743..bdbbfcb 100755
--- a/core/res/res/layout/app_perms_summary.xml
+++ b/core/res/res/layout/app_perms_summary.xml
@@ -65,21 +65,23 @@
             android:layout_marginLeft="16dip"
             android:duplicateParentState="true">
 
-            <ImageView
-                android:id="@+id/show_more_icon"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content" />
-
             <TextView
                 android:id="@+id/show_more_text"
                 android:textAppearance="?android:attr/textAppearanceMedium"
                 android:duplicateParentState="true"
-                android:layout_alignTop="@id/show_more_icon"
+                android:layout_alignTop="@+id/show_more_icon"
                 android:layout_gravity="center_vertical"
-                android:paddingLeft="6dip"
-                android:layout_width="match_parent"
+                android:paddingLeft="36dip"
+                android:layout_weight="1"
+                android:layout_width="wrap_content"
                 android:layout_height="wrap_content" />
 
+            <ImageView
+                android:id="@id/show_more_icon"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginRight="12dip" />
+
         </LinearLayout>
 
         <View
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 9029ab3..a58e92b 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -169,7 +169,7 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Nástroje pro vývojáře"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Funkce pouze pro vývojáře aplikací"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Úložiště"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Přístup ke kartě SD."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Přístup ke sdílenému úložišti"</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Přístup ke kartě SD."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"zakázání či změny stavového řádku"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Umožňuje aplikaci zakázat stavový řádek nebo přidat či odebrat systémové ikony."</string>
@@ -403,22 +403,14 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Umožňuje aplikaci konfigurovat místní telefon s rozhraním Bluetooth a vyhledávat a párovat vzdálená zařízení."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"vytvoření připojení Bluetooth"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Umožňuje aplikaci zobrazit konfiguraci místního telefonu s rozhraním Bluetooth, vytvářet připojení ke spárovaným zařízením a přijímat tato připojení."</string>
-    <!-- no translation found for permlab_nfcAdmin (2251302233012250056) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcAdmin (1935842611464895785) -->
-    <skip />
-    <!-- no translation found for permlab_nfcRaw (4423471711114325708) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcRaw (5533022736559385665) -->
-    <skip />
-    <!-- no translation found for permlab_nfcNotify (478470360082792358) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcNotify (2990053517962070617) -->
-    <skip />
-    <!-- no translation found for permlab_nfcLlcp (4972051461007030426) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcLlcp (91592127786004640) -->
-    <skip />
+    <string name="permlab_nfcAdmin" msgid="2251302233012250056">"Správa NFC"</string>
+    <string name="permdesc_nfcAdmin" msgid="1935842611464895785">"Umožňuje aplikaci nakonfigurovat místní telefon NFC."</string>
+    <string name="permlab_nfcRaw" msgid="4423471711114325708">"Úplný přístup NFC ke vzdálenému zařízení"</string>
+    <string name="permdesc_nfcRaw" msgid="5533022736559385665">"Umožňuje aplikaci přístup ke vzdáleným zařízením NFC."</string>
+    <string name="permlab_nfcNotify" msgid="478470360082792358">"Oznámení NFC ze vzdáleného zařízení"</string>
+    <string name="permdesc_nfcNotify" msgid="2990053517962070617">"Umožňuje aplikaci přijímat oznámení o operacích souvisejících se vzdálenými zařízeními NFC."</string>
+    <string name="permlab_nfcLlcp" msgid="4972051461007030426">"Oznámení NFC ze vzdáleného zařízení LLCP"</string>
+    <string name="permdesc_nfcLlcp" msgid="91592127786004640">"Umožňuje aplikaci přijímat oznámení o operacích LLCP souvisejících se vzdálenými zařízeními NFC."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"vypnutí zámku kláves"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Umožňuje aplikaci vypnout zámek kláves a související zabezpečení heslem. Příkladem oprávněného použití této funkce je vypnutí zámku klávesnice při příchozím hovoru a jeho opětovné zapnutí po skončení hovoru."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"čtení nastavení synchronizace"</string>
@@ -435,22 +427,26 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Umožní aplikaci číst soukromá slova, jména a fráze, která uživatel mohl uložit do svého slovníku."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"zápis do slovníku definovaného uživatelem"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Umožní aplikaci zapisovat nová slova do uživatelského slovníku."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"změna/smazání obsahu karty SD"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"úpravy/mazání obsahu sdíl. úložiště"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"změna/smazání obsahu karty SD"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Umožní aplikaci zápis na kartu SD."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Umožní zápis do sdíl. úlož."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Umožní aplikaci zápis na kartu SD."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"přistupovat do souborového systému mezipaměti"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Umožňuje aplikaci číst a zapisovat do souborového systému mezipaměti."</string>
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Omezení hesla"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Omezuje typ hesel, která lze použít."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Sledování pokusů o přihlášení"</string>
-    <!-- outdated translation 1961251179624843483 -->     <string name="policydesc_watchLogin" msgid="7227578260165172673">"Sleduje nezdařené pokusy o přihlášení do zařízení a umožňuje provedení určité akce."</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Obnovení hesla"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Vynutí nastavení hesla na novou hodnotu, kterou vám před přihlášením musí sdělit správce."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Vynucení uzamčení"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Určuje, kdy dojde k uzamčení zařízení a bude požadováno opětovné zadání hesla."</string>
+    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+    <skip />
+    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
+    <skip />
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavit pravidla pro heslo"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Ovládat délku hesel pro odemčení obrazovky a v nich používané znaky"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Sledovat pokusy o odemčení obrazovky"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Sledovat počet nesprávných hesel zadaných při odemykání obrazovky a uzamknout telefon nebo odstranit veškerá data telefonu, pokud dojde k příliš mnoha neplatným pokusům o zadání hesla"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Změnit heslo pro odemknutí obrazovky"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Změnit heslo pro odemknutí obrazovky"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Uzamknout obrazovku"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Ovládat, jak a kdy se obrazovka uzamkne"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Vymazání všech dat"</string>
-    <!-- outdated translation 2314060933796396205 -->     <string name="policydesc_wipeData" msgid="7669895333814222586">"Bez dalšího potvrzení obnoví výchozí nastavení z výroby a smaže všechna data."</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Bez upozornění smazat všechna data telefonu obnovením továrních dat"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Domů"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -610,10 +606,8 @@
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Umožňuje aplikaci číst všechny navštívené adresy URL a záložky Prohlížeče."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"zápis do historie a záložek Prohlížeče"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Umožní aplikaci změnit historii či záložky prohlížeče uložené v telefonu. Škodlivé aplikace mohou pomocí tohoto nastavení vymazat či pozměnit data Prohlížeče."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"nastavit budík v budíku"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Dovoluje aplikaci nastavit budík v nainstalované aplikaci budíku. Některé budíkové aplikace nemusí tuto funkci implementovat."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Změnit oprávnění prohlížeče poskytovat informace o zeměpisné poloze"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Umožňuje aplikaci změnit oprávnění prohlížeče poskytovat informace o zeměpisné poloze. Škodlivé aplikace mohou toto nastavení použít k odesílání informací o umístění na libovolné webové stránky."</string>
     <string name="save_password_message" msgid="767344687139195790">"Chcete, aby si prohlížeč zapamatoval toto heslo?"</string>
@@ -808,17 +802,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Zobrazit vše"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"Úložiště USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB připojeno"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Připojili jste svůj telefon k počítači pomocí USB. Chcete-li kopírovat soubory z počítače na kartu SD v zařízení Android či obráceně, vyberte následující tlačítko."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Připojili jste telefon k počítači pomocí rozhraní USB. Chcete-li kopírovat soubory z počítače do sdíleného úložiště zařízení Android či obráceně, vyberte následující tlačítko."</string>
     <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Připojili jste svůj telefon k počítači pomocí USB. Chcete-li kopírovat soubory z počítače na kartu SD v zařízení Android či obráceně, vyberte následující tlačítko."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Zapnout úložiště USB"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Při používání vaší karty SD jako úložiště USB došlo k problému."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Při používání sdíleného úložiště jako úložiště USB došlo k problému."</string>
     <string name="usb_storage_error_message" product="default" msgid="2534784751603345363">"Při používání vaší karty SD jako úložiště USB došlo k problému."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB připojeno"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Vyberte, chcete-li kopírovat soubory do nebo z počítače."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Vypnout úložiště USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Vyberte, chcete-li vypnout úložiště USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"Úložiště USB je používáno"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Před vypnutím úložiště USB zkontrolujte, zda jste odpojili (vyjmuli) kartu SD zařízení Android z počítače."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Před vypnutím úložiště USB zkontrolujte, zda jste odpojili (vyňali) sdílené úložiště zařízení Android z počítače."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Před vypnutím úložiště USB zkontrolujte, zda jste odpojili (vyjmuli) kartu SD zařízení Android z počítače."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Vypnout úložiště USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Při vypínání úložiště USB došlo k problémům. Zkontrolujte, zda byl hostitel USB odpojen, a zkuste to znovu."</string>
@@ -826,9 +820,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Pokud zapnete úložiště USB, dojde k zastavení některých používaných aplikací. Tyto aplikace pravděpodobně nebudou k dispozici až do vypnutí úložiště USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Chyba operace na rozhraní USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Formátovat kartu SD"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Formátovat sdíl. úl."</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formátovat kartu SD"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Opravdu chcete kartu SD naformátovat? Všechna data na kartě budou ztracena."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Chcete sdílené úložiště formátovat, a smazat tak všechny soubory, které jsou v něm uložené? Tuto akci nelze vrátit zpět."</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Opravdu chcete kartu SD naformátovat? Všechna data na kartě budou ztracena."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formátovat"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Ladění přes rozhraní USB připojeno"</string>
@@ -837,28 +831,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AÁBCČDĎEÉĚFGHCHIÍJKLMNŇOÓPQRŘSŠTŤUÚVWXYÝZŽ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AÁBCČDĎEÉĚFGHCHIÍJKLMNŇOÓPQRŘSŠTŤUÚVWXYÝZŽ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidáti"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Příprava karty SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Příprava sdíleného úložiště"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Příprava karty SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Kontrola chyb."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Prázdná karta SD"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Prázdné sdílené úložiště"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Prázdná karta SD"</string>
-    <!-- outdated translation 1312266820092958014 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"Karta SD je prázdná nebo používá nepodporovaný systém souborů."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"Sdílené úložiště je prázdné nebo obsahuje nepodporovaný systém souborů."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Karta SD je prázdná nebo obsahuje nepodporovaný systém souborů."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Poškozená karta SD"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Poškozené sdílené úložiště"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Poškozená karta SD"</string>
-    <!-- outdated translation 2679412884290061775 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"Karta SD je poškozena. Pravděpodobně ji bude nutné znovu formátovat."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"Sdílené úložiště je poškozené. Bude pravděpodobně nutné je přeformátovat."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Karta SD je poškozená. Bude pravděpodobně nutné ji přeformátovat."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Karta SD byla neočekávaně odebrána"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Sdíl. úlož. nečekaně odebráno"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Karta SD byla neočekávaně odebrána"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Chcete-li zabránit ztrátě dat, kartu SD před odebráním odpojte."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Před odebráním sdíleného úložiště ho nejprve odpojte, abyste zabránili ztrátě dat."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Chcete-li zabránit ztrátě dat, kartu SD před odebráním odpojte."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"Kartu SD je možné bezpečně odebrat"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"Sdílené úložiště lze odebrat"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Kartu SD je možné bezpečně odebrat"</string>
-    <!-- outdated translation 7613960686747592770 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"Kartu SD lze nyní bezpečně vyjmout."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"Sdílené úložiště lze bezpečně odebrat."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Kartu SD lze bezpečně odebrat."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Karta SD byla odstraněna"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Sdílené úložiště bylo odebráno"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Karta SD byla odstraněna"</string>
-    <!-- outdated translation 4205117227342822275 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"Karta SD byla odebrána. Chcete-li zvětšit úložiště svého zařízení, vložte kartu SD."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"Sdílené úložiště je odebráno. Vložte nové médium."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Karta SD byla odebrána. Vložte novou kartu."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Nebyly nalezeny žádné odpovídající aktivity."</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"aktualizovat statistiku použití součástí"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index a74b9b7..05a45fc 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -169,7 +169,7 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Udviklingsværktøjer"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Funktioner kun til programudviklere."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Lagring"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Få adgang til SD-kortet."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Få adgang til delt hukommelse."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Få adgang til SD-kortet."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"deaktiver eller rediger statuslinje"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Tillader, at et program deaktiverer statuslinjen eller tilføjer eller fjerner systemikoner."</string>
@@ -403,22 +403,14 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Tillader, at et program konfigurerer den lokale Bluetooth-telefon samt opdager og parrer med fjerne enheder."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"opret Bluetooth-forbindelser"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Tillader, at et program viser konfigurationen af den lokale Bluetooth-telefon samt opretter og accepterer forbindelse med parrede enheder."</string>
-    <!-- no translation found for permlab_nfcAdmin (2251302233012250056) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcAdmin (1935842611464895785) -->
-    <skip />
-    <!-- no translation found for permlab_nfcRaw (4423471711114325708) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcRaw (5533022736559385665) -->
-    <skip />
-    <!-- no translation found for permlab_nfcNotify (478470360082792358) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcNotify (2990053517962070617) -->
-    <skip />
-    <!-- no translation found for permlab_nfcLlcp (4972051461007030426) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcLlcp (91592127786004640) -->
-    <skip />
+    <string name="permlab_nfcAdmin" msgid="2251302233012250056">"NFC-administration"</string>
+    <string name="permdesc_nfcAdmin" msgid="1935842611464895785">"Tillader, at et program konfigurerer den lokale NFC-telefon."</string>
+    <string name="permlab_nfcRaw" msgid="4423471711114325708">"NFC har fuld adgang til fjernenhed"</string>
+    <string name="permdesc_nfcRaw" msgid="5533022736559385665">"Tillader, at et program har adgang til NFC-fjernenheder."</string>
+    <string name="permlab_nfcNotify" msgid="478470360082792358">"NFC-meddelelse fra fjernenhed"</string>
+    <string name="permdesc_nfcNotify" msgid="2990053517962070617">"Tillader, at et program meddeles om handlinger, som er relateret til NFC-fjernenheder."</string>
+    <string name="permlab_nfcLlcp" msgid="4972051461007030426">"NFC-meddelelse fra LLCP-fjernenhed"</string>
+    <string name="permdesc_nfcLlcp" msgid="91592127786004640">"Tillader, at et program meddeles om LLCP-handlinger, som er relateret til NFC-fjernenheder."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"deaktiver tastaturlås"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Tillader, at et program deaktiverer tastaturlåsen og al associeret adgangskodesikkerhed. Et legitimt eksempel på dette er, at telefonen deaktiverer tastaturlåsen, når der modtages et indgående telefonopkald, og genaktiverer tastaturlåsen, når opkaldet er afsluttet."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"læs indstillinger for synkronisering"</string>
@@ -435,22 +427,26 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Tillader, at et program læser alle private ord, navne og sætninger, som brugeren eventuelt har gemt i brugerordbogen."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"skriv til den brugerdefinerede ordbog"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Tillader, at et program skriver nye ord i brugerordbogen."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"ret/slet indholdet på SD-kortet"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"ret/slet indholdet i delt hukommelse"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"ret/slet indholdet på SD-kortet"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Tillader, at et program skriver til SD-kortet."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Til. prog. at sk. t. delt huk."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Tillader, at et program skriver til SD-kortet."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"få adgang til cache-filsystemet"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Tillader, at et program læser og skriver til cache-filsystemet."</string>
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Begræns adgangskode"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Begræns de adgangskodetyper, du har tilladelse til at bruge."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Vis forsøg på at logge ind"</string>
-    <!-- outdated translation 1961251179624843483 -->     <string name="policydesc_watchLogin" msgid="7227578260165172673">"Overvåg mislykkede forsøg på at logge ind på enheden for at foretage en handling."</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Nulstil adgangskode"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Tving din adgangskode til en ny værdi. Dette kræver, at administratoren giver den til dig, før du kan kogge ind."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Tvangslås"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Kontrol når enheden låses, så du skal indtaste adgangskoden igen."</string>
+    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+    <skip />
+    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
+    <skip />
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Indstil regler for adgangskode"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Kontroller længden samt tilladte tegn i adgangskoder til oplåsning af skærm"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Overvåg forsøg på oplåsning af skærm"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Overvåg antallet af forkerte adgangskoder, som indtastes ved oplåsning af skærmen, og lås telefonen, eller slet alle telefonens data, hvis der er for mange forkerte forsøg"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Skift adgangskode til oplåsning af skærm"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Skift adgangskode til oplåsning af skærm"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Lås skærmen"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Bestem, hvordan og hvornår skærmen låses"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Slet alle data"</string>
-    <!-- outdated translation 2314060933796396205 -->     <string name="policydesc_wipeData" msgid="7669895333814222586">"Foretag en fabriksnulstilling, der sletter alle dine data uden bekræftelse."</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Slet telefonens data uden varsel ved at gendanne fabriksindstillinger"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Hjem"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -610,10 +606,8 @@
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Tillader, at programmet læser alle de webadresser, browseren har besøgt, og alle browserens bogmærker."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"skriv browserens oversigt og bogmærker"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Tillader, at et program ændrer browseroversigten eller bogmærker, der er gemt på din telefon. Ondsindede programmer kan bruge dette til at slette eller ændre din browsers data."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"angiv alarm i alarmprogram"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Tillader, at programmet angiver en alarm i et installeret alarmprogram. Nogle alarmprogrammer kan ikke implementere denne funktion."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Skift browsertilladelser for geografisk placering"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Giver et program tilladelse til at ændre browserens tilladelser for geografisk placering. Skadelige programmer kan bruge dette til at tillade, at placeringsoplysninger sendes til vilkårlige websteder."</string>
     <string name="save_password_message" msgid="767344687139195790">"Ønsker du, at browseren skal huske denne adgangskode?"</string>
@@ -808,17 +802,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Vis alle"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB-masselagring"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB er tilsluttet"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Du har forbundet din telefon til din computer via USB. Vælg knappen nedenfor, hvis du ønsker at kopiere filer mellem din computer og din Androids SD-kort."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Du har forbundet din telefon til din computer via USB. Vælg knappen nedenfor, hvis du ønsker at kopiere filer mellem din computer og din Androids delte hukommelse."</string>
     <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Du har forbundet din telefon til din computer via USB. Vælg knappen nedenfor, hvis du ønsker at kopiere filer mellem din computer og din Androids SD-kort."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Slå USB-lagringen til"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Der opstod et problem med at bruge dit SD-kort til USB-lagring."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Der opstod et problem med at bruge den delte hukommelse til USB-lagring."</string>
     <string name="usb_storage_error_message" product="default" msgid="2534784751603345363">"Der opstod et problem med at bruge dit SD-kort til USB-lagring."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB er tilsluttet"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Vælg for at kopiere filer til/fra din computer."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Slå USB-lagringen fra"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Vælg for at slå USB-lagring fra."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB-lager i brug"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Sørg for, at du har demonteret (\"udskubbet\") din Androids SD-kort fra computeren, før du slår USB-lagring fra."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Sørg for, at du har demonteret (\"udskubbet\") din Androids delte hukommelse fra computeren, før du slår USB-lagring fra."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Sørg for, at du har demonteret (\"udskubbet\") din Androids SD-kort fra computeren, før du slår USB-lagring fra."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Slå USB-lagring fra"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Der opstod et problem med at slå USB-lagringen fra. Sørg for, at du har demonteret USB-værten, og prøv så igen."</string>
@@ -826,9 +820,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Hvis du slår USB-lagring til, vil nogle af de programmer, som du bruger, stoppe, og de kan være utilgængelige, indtil du slår USB-lagring til igen."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB-handlingen mislykkedes"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Formater SD-kort"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Formater delt hukom."</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formater SD-kort"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Er du sikker på, du ønsker at formatere SD-kortet? Alle data på kortet mistes."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Vil du formatere den delte hukommelse og slette alle filer, som er gemt der? Handlingen kan ikke fortydes!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Er du sikker på, du ønsker at formatere SD-kortet? Alle data på kortet mistes."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formater"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-fejlretning er tilsluttet"</string>
@@ -837,28 +831,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidater"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Forbereder SD-kortet"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Forbereder delt hukommelse"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Forbereder SD-kortet"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Kontrollerer for fejl."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Tomt SD-kort"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Tom delt hukommelse"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Tomt SD-kort"</string>
-    <!-- outdated translation 1312266820092958014 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"SD-kortet er tomt eller bruger et ikke understøttet filsystem."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"Delt hukommelse er tom eller har et ikke-understøttet filsystem."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD-kortet er tomt eller har et ikke understøttet filsystem."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Beskadiget SD-kort"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Beskadiget delt hukommelse"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Beskadiget SD-kort"</string>
-    <!-- outdated translation 2679412884290061775 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"SD-kortet er beskadiget. Du skal muligvis omformatere dit kort."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"Delt hukommelse er beskadiget. Du bliver muligvis nødt til at formatere den igen."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD-kortet er beskadiget. Du bliver muligvis nødt til at formatere det igen."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"SD-kortet blev fjernet uventet"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Delt huk. blev fjernet uventet"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD-kortet blev fjernet uventet"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Demonter SD-kortet inden fjernelse for at undgå tab af data."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Demonter delt hukommelse inden fjernelse for at undgå tab af data."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Demonter SD-kortet inden fjernelse for at undgå tab af data."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"SD-kortet kan fjernes sikkert"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"Sikkert at fjerne delt hukom."</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"SD-kortet kan fjernes sikkert"</string>
-    <!-- outdated translation 7613960686747592770 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"SD-kortet kan nu fjernes sikkert."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"Du kan nu fjerne den delte hukommelse."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Du kan nu fjerne SD-kortet."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"SD-kortet er fjernet"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Fjernet delt hukommelse"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"SD-kortet er fjernet"</string>
-    <!-- outdated translation 4205117227342822275 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"SD er fjernet. Indsæt et nyt SD-kort for at øge din enheds lagerplads."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"Delt hukommelse fjernet. Indsæt nyt medie."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD-kortet er fjernet. Indsæt et nyt."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Der blev ikke fundet nogen matchende aktiviteter"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"opdater brugerstatistikker for komponenter"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 2f4013f..eb3178c 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -122,8 +122,8 @@
     <string name="httpErrorFileNotFound" msgid="5588380756326017105">"Die angeforderte Datei wurde nicht gefunden."</string>
     <string name="httpErrorTooManyRequests" msgid="1235396927087188253">"Es werden zurzeit zu viele Anfragen verarbeitet. Versuchen Sie es später erneut."</string>
     <string name="notification_title" msgid="1259940370369187045">"Fehler bei Anmeldung für <xliff:g id="ACCOUNT">%1$s</xliff:g>"</string>
-    <string name="contentServiceSync" msgid="8353523060269335667">"Synchronisieren"</string>
-    <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synchronisieren"</string>
+    <string name="contentServiceSync" msgid="8353523060269335667">"Synchronisierung"</string>
+    <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synchronisierung"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Zu viele <xliff:g id="CONTENT_TYPE">%s</xliff:g> gelöscht."</string>
     <string name="low_memory" msgid="6632412458436461203">"Telefonspeicher ist voll! Löschen Sie Dateien, um Speicherplatz freizugeben."</string>
     <string name="me" msgid="6545696007631404292">"Eigene"</string>
@@ -169,7 +169,7 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Entwickler-Tools"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Funktionen nur für Anwendungsentwickler vorgesehen."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Speicher"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Greift auf die SD-Karte zu."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Zugriff auf gem. Speicher"</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Greift auf die SD-Karte zu."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"Statusleiste deaktivieren oder ändern"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Ermöglicht der Anwendung, die Statusanzeige zu deaktivieren oder Systemsymbole hinzuzufügen oder zu entfernen."</string>
@@ -184,7 +184,7 @@
     <string name="permlab_receiveMms" msgid="8894700916188083287">"MMS empfangen"</string>
     <string name="permdesc_receiveMms" msgid="4563346832000174373">"Ermöglicht der Anwendung, MMS-Mitteilungen zu empfangen und zu verarbeiten. Schädliche Anwendungen können Ihre Nachrichten möglicherweise überwachen oder löschen, bevor sie angezeigt werden."</string>
     <string name="permlab_sendSms" msgid="5600830612147671529">"Kurznachrichten senden"</string>
-    <string name="permdesc_sendSms" msgid="1946540351763502120">"Ermöglicht Anwendungen das Senden von SMS-Nachrichten. Bei schädlichen Anwendungen können Kosten entstehen, wenn diese Nachrichten ohne Ihre Zustimmung versenden."</string>
+    <string name="permdesc_sendSms" msgid="1946540351763502120">"Ermöglicht der Anwendung das Senden von SMS-Nachrichten. Bei schädlichen Anwendungen können Kosten entstehen, wenn diese Nachrichten ohne Ihre Zustimmung versenden."</string>
     <string name="permlab_readSms" msgid="4085333708122372256">"SMS oder MMS lesen"</string>
     <string name="permdesc_readSms" msgid="3002170087197294591">"Ermöglicht einer Anwendung, auf Ihrem Telefon oder Ihrer SIM-Karte gespeicherte Kurznachrichten zu lesen. Schädliche Anwendungen lesen so möglicherweise Ihre  vertraulichen Nachrichten."</string>
     <string name="permlab_writeSms" msgid="6881122575154940744">"SMS oder MMS bearbeiten"</string>
@@ -312,7 +312,7 @@
     <string name="permlab_recordAudio" msgid="3876049771427466323">"Audio aufnehmen"</string>
     <string name="permdesc_recordAudio" msgid="6493228261176552356">"Ermöglicht der Anwendung, auf den Pfad für Audioaufzeichnungen zuzugreifen."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"Bilder und Videos aufnehmen"</string>
-    <string name="permdesc_camera" msgid="6004878235852154239">"Ermöglicht der Anwendung, Fotos und Videos mit der Kamera aufzunehmen. So kann die Anwendung jederzeit Bilder zusammentragen, die von der Kamera erfasst werden."</string>
+    <string name="permdesc_camera" msgid="6004878235852154239">"Ermöglicht der Anwendung, Fotos und Videos mit der Kamera aufzunehmen. So kann die Anwendung jederzeit Bilder aus dem Sichtfeld der Kamera erfassen."</string>
     <string name="permlab_brick" msgid="8337817093326370537">"Telefon dauerhaft deaktivieren."</string>
     <string name="permdesc_brick" msgid="5569526552607599221">"Ermöglicht der Anwendung, das gesamte Telefon dauerhaft zu deaktivieren. Dies birgt hohe Risiken."</string>
     <string name="permlab_reboot" msgid="2898560872462638242">"Neustart des Telefons erzwingen"</string>
@@ -403,22 +403,14 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Ermöglicht einer Anwendung, das lokale Bluetooth-Telefon zu konfigurieren, Remote-Geräte zu erkennen und eine Verbindung zu diesen herzustellen."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"Bluetooth-Verbindungen herstellen"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Ermöglicht einer Anwendung, die Konfiguration des lokalen Bluetooth-Telefons einzusehen und Verbindungen mit Partnergeräten herzustellen und zu akzeptieren."</string>
-    <!-- no translation found for permlab_nfcAdmin (2251302233012250056) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcAdmin (1935842611464895785) -->
-    <skip />
-    <!-- no translation found for permlab_nfcRaw (4423471711114325708) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcRaw (5533022736559385665) -->
-    <skip />
-    <!-- no translation found for permlab_nfcNotify (478470360082792358) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcNotify (2990053517962070617) -->
-    <skip />
-    <!-- no translation found for permlab_nfcLlcp (4972051461007030426) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcLlcp (91592127786004640) -->
-    <skip />
+    <string name="permlab_nfcAdmin" msgid="2251302233012250056">"NFC-Verwaltung"</string>
+    <string name="permdesc_nfcAdmin" msgid="1935842611464895785">"Ermöglicht einer Anwendung, das lokale NFC-Telefon zu konfigurieren"</string>
+    <string name="permlab_nfcRaw" msgid="4423471711114325708">"NFC-Vollzugriff auf Remote-Gerät"</string>
+    <string name="permdesc_nfcRaw" msgid="5533022736559385665">"Ermöglicht einer Anwendung den Zugriff auf Remote-NFC-Geräte"</string>
+    <string name="permlab_nfcNotify" msgid="478470360082792358">"NFC-Benachrichtigung von Remote-Gerät"</string>
+    <string name="permdesc_nfcNotify" msgid="2990053517962070617">"Hiermit wird eine Anwendung über Operationen im Zusammenhang mit Remote-NFC-Geräten benachrichtigt."</string>
+    <string name="permlab_nfcLlcp" msgid="4972051461007030426">"NFC-Benachrichtigung von Remote-LLCP-Gerät"</string>
+    <string name="permdesc_nfcLlcp" msgid="91592127786004640">"Hiermit wird eine Anwendung über LLCP-Operationen im Zusammenhang mit NFC-Remote-Geräten benachrichtigt."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"Tastensperre deaktivieren"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Ermöglicht einer Anwendung, die Tastensperre sowie den damit verbundenen Passwortschutz zu deaktivieren. So wird die Tastensperre vom Telefon deaktiviert, wenn ein Anruf eingeht, und nach Beendigung des Anrufs wieder aktiviert."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"Synchronisierungseinstellungen lesen"</string>
@@ -432,56 +424,60 @@
     <string name="permlab_subscribedFeedsWrite" msgid="9015246325408209296">"abonnierte Feeds schreiben"</string>
     <string name="permdesc_subscribedFeedsWrite" msgid="8121607099326533878">"Ermöglicht einer Anwendung, Änderungen an den kürzlich synchronisierten Feeds vorzunehmen. Schädliche Anwendungen könnten so Ihre synchronisierten Feeds ändern."</string>
     <string name="permlab_readDictionary" msgid="432535716804748781">"nutzerdefiniertes Wörterbuch lesen"</string>
-    <string name="permdesc_readDictionary" msgid="1082972603576360690">"Erlaubt einer Anwendung, alle privaten Wörter, Namen und Ausdrücke zu lesen, die ein Nutzer in seinem Wörterbuch gespeichert hat."</string>
+    <string name="permdesc_readDictionary" msgid="1082972603576360690">"Ermöglicht einer Anwendung, alle privaten Wörter, Namen und Ausdrücke zu lesen, die ein Nutzer in seinem Wörterbuch gespeichert hat."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"in nutzerdefiniertes Wörterbuch schreiben"</string>
-    <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Ermöglicht einer Anwendung, neue Wörter in das Wörterbuch des Nutzers zu schreiben."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"SD-Karten-Inhalt ändern/löschen"</string>
+    <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Ermöglicht einer Anwendung, Ihrem Wörterbuch neue Einträge hinzuzufügen."</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"Speicherinhalt ändern/löschen"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"SD-Karten-Inhalt ändern/löschen"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Ermöglicht einer Anwendung, auf die SD-Karte zu schreiben"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Schreiben in gem. Speicher"</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Ermöglicht einer Anwendung, auf die SD-Karte zu schreiben"</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"Zugriff auf das Cache-Dateisystem"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Gewährt einer Anwendung Lese- und Schreibzugriff auf das Cache-Dateisystem."</string>
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Passwort beschränken"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Beschränken der erlaubten Passworttypen"</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Anmeldeversuche überwachen"</string>
-    <!-- outdated translation 1961251179624843483 -->     <string name="policydesc_watchLogin" msgid="7227578260165172673">"Fehlgeschlagene Versuche·zum Anmelden/Durchführen einer Aktion überwachen"</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Passwort zurücksetzen"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Festlegen eines neuen Werts für Ihr Passwort, sodass der Administrator es Ihnen vor dem Anmelden übermitteln muss."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Sperren erzwingen"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Steuerung der Gerätesperre; erfordert die erneute Passworteingabe"</string>
+    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+    <skip />
+    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
+    <skip />
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Passwortregeln festlegen"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Zulässige Länge und Zeichen für Passwörter zum Entsperren des Displays festlegen"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Versuche zum Entsperren des Displays überwachen"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Anzahl der falsch eingegebenen Passwörter beim Entsperren des Displays überwachen und Telefon sperren oder alle Daten auf dem Telefon löschen, wenn zu häufig ein falsches Passwort eingegeben wird"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Passwort zum Entsperren des Displays ändern"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Passwort zum Entsperren des Displays ändern"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Display sperren"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Steuern Sie, wie und wann das Display gesperrt wird."</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Alle Daten löschen"</string>
-    <!-- outdated translation 2314060933796396205 -->     <string name="policydesc_wipeData" msgid="7669895333814222586">"Zurücksetzen auf die Werkseinstellungen. Dabei werden alle Ihre Daten ohne Nachfrage gelöscht."</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Auf Werkseinstellungen zurücksetzen und Daten auf dem Telefon ohne Warnung löschen"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Privat"</item>
     <item msgid="869923650527136615">"Mobil"</item>
-    <item msgid="7897544654242874543">"Arbeit"</item>
-    <item msgid="1103601433382158155">"Fax (Arbeit)"</item>
+    <item msgid="7897544654242874543">"Geschäftlich"</item>
+    <item msgid="1103601433382158155">"Fax (geschäftl.)"</item>
     <item msgid="1735177144948329370">"Fax (privat)"</item>
     <item msgid="603878674477207394">"Pager"</item>
-    <item msgid="1650824275177931637">"Andere"</item>
+    <item msgid="1650824275177931637">"Sonstige"</item>
     <item msgid="9192514806975898961">"Benutzerdefiniert"</item>
   </string-array>
   <string-array name="emailAddressTypes">
     <item msgid="8073994352956129127">"Privat"</item>
-    <item msgid="7084237356602625604">"Arbeit"</item>
-    <item msgid="1112044410659011023">"Andere"</item>
+    <item msgid="7084237356602625604">"Geschäftlich"</item>
+    <item msgid="1112044410659011023">"Sonstige"</item>
     <item msgid="2374913952870110618">"Benutzerdefiniert"</item>
   </string-array>
   <string-array name="postalAddressTypes">
     <item msgid="6880257626740047286">"Privat"</item>
-    <item msgid="5629153956045109251">"Arbeit"</item>
-    <item msgid="4966604264500343469">"Andere"</item>
+    <item msgid="5629153956045109251">"Geschäftlich"</item>
+    <item msgid="4966604264500343469">"Sonstige"</item>
     <item msgid="4932682847595299369">"Benutzerdefiniert"</item>
   </string-array>
   <string-array name="imAddressTypes">
     <item msgid="1738585194601476694">"Privat"</item>
-    <item msgid="1359644565647383708">"Arbeit"</item>
+    <item msgid="1359644565647383708">"Geschäftlich"</item>
     <item msgid="7868549401053615677">"Andere"</item>
     <item msgid="3145118944639869809">"Benutzerdefiniert"</item>
   </string-array>
   <string-array name="organizationTypes">
-    <item msgid="7546335612189115615">"Arbeit"</item>
-    <item msgid="4378074129049520373">"Andere"</item>
+    <item msgid="7546335612189115615">"Geschäftlich"</item>
+    <item msgid="4378074129049520373">"Sonstige"</item>
     <item msgid="3455047468583965104">"Benutzerdefiniert"</item>
   </string-array>
   <string-array name="imProtocols">
@@ -497,11 +493,11 @@
     <string name="phoneTypeCustom" msgid="1644738059053355820">"Benutzerdefiniert"</string>
     <string name="phoneTypeHome" msgid="2570923463033985887">"Privat"</string>
     <string name="phoneTypeMobile" msgid="6501463557754751037">"Mobil"</string>
-    <string name="phoneTypeWork" msgid="8863939667059911633">"Arbeit"</string>
-    <string name="phoneTypeFaxWork" msgid="3517792160008890912">"Fax (Beruflich)"</string>
+    <string name="phoneTypeWork" msgid="8863939667059911633">"Geschäftlich"</string>
+    <string name="phoneTypeFaxWork" msgid="3517792160008890912">"Fax (geschäftl.)"</string>
     <string name="phoneTypeFaxHome" msgid="2067265972322971467">"Fax (privat)"</string>
     <string name="phoneTypePager" msgid="7582359955394921732">"Pager"</string>
-    <string name="phoneTypeOther" msgid="1544425847868765990">"Andere"</string>
+    <string name="phoneTypeOther" msgid="1544425847868765990">"Sonstige"</string>
     <string name="phoneTypeCallback" msgid="2712175203065678206">"Rückruf"</string>
     <string name="phoneTypeCar" msgid="8738360689616716982">"Auto"</string>
     <string name="phoneTypeCompanyMain" msgid="540434356461478916">"Firma (Hauptnummer)"</string>
@@ -511,8 +507,8 @@
     <string name="phoneTypeRadio" msgid="4093738079908667513">"Radio"</string>
     <string name="phoneTypeTelex" msgid="3367879952476250512">"Telex"</string>
     <string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY/TDD"</string>
-    <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"Handy (geschäftlich)"</string>
-    <string name="phoneTypeWorkPager" msgid="649938731231157056">"Pager (beruflich)"</string>
+    <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"Handy (geschäftl.)"</string>
+    <string name="phoneTypeWorkPager" msgid="649938731231157056">"Pager (geschäftl.)"</string>
     <string name="phoneTypeAssistant" msgid="5596772636128562884">"Zweite Nummer"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
     <string name="eventTypeBirthday" msgid="2813379844211390740">"Geburtstag"</string>
@@ -520,17 +516,17 @@
     <string name="eventTypeOther" msgid="5834288791948564594">"Termin"</string>
     <string name="emailTypeCustom" msgid="8525960257804213846">"Benutzerdefiniert"</string>
     <string name="emailTypeHome" msgid="449227236140433919">"Privat"</string>
-    <string name="emailTypeWork" msgid="3548058059601149973">"Beruflich"</string>
-    <string name="emailTypeOther" msgid="2923008695272639549">"Andere"</string>
+    <string name="emailTypeWork" msgid="3548058059601149973">"Geschäftlich"</string>
+    <string name="emailTypeOther" msgid="2923008695272639549">"Sonstige"</string>
     <string name="emailTypeMobile" msgid="119919005321166205">"Mobil"</string>
     <string name="postalTypeCustom" msgid="8903206903060479902">"Benutzerdefiniert"</string>
     <string name="postalTypeHome" msgid="8165756977184483097">"Privat"</string>
-    <string name="postalTypeWork" msgid="5268172772387694495">"Beruflich"</string>
-    <string name="postalTypeOther" msgid="2726111966623584341">"Andere"</string>
+    <string name="postalTypeWork" msgid="5268172772387694495">"Geschäftlich"</string>
+    <string name="postalTypeOther" msgid="2726111966623584341">"Sonstige"</string>
     <string name="imTypeCustom" msgid="2074028755527826046">"Benutzerdefiniert"</string>
     <string name="imTypeHome" msgid="6241181032954263892">"Privat"</string>
-    <string name="imTypeWork" msgid="1371489290242433090">"Beruflich"</string>
-    <string name="imTypeOther" msgid="5377007495735915478">"Andere"</string>
+    <string name="imTypeWork" msgid="1371489290242433090">"Geschäftlich"</string>
+    <string name="imTypeOther" msgid="5377007495735915478">"Sonstige"</string>
     <string name="imProtocolCustom" msgid="6919453836618749992">"Benutzerdefiniert"</string>
     <string name="imProtocolAim" msgid="7050360612368383417">"AIM"</string>
     <string name="imProtocolMsn" msgid="144556545420769442">"Windows Live"</string>
@@ -541,13 +537,13 @@
     <string name="imProtocolIcq" msgid="1574870433606517315">"ICQ"</string>
     <string name="imProtocolJabber" msgid="2279917630875771722">"Jabber"</string>
     <string name="imProtocolNetMeeting" msgid="8287625655986827971">"NetMeeting"</string>
-    <string name="orgTypeWork" msgid="29268870505363872">"Beruflich"</string>
-    <string name="orgTypeOther" msgid="3951781131570124082">"Andere"</string>
+    <string name="orgTypeWork" msgid="29268870505363872">"Geschäftlich"</string>
+    <string name="orgTypeOther" msgid="3951781131570124082">"Sonstige"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Benutzerdefiniert"</string>
     <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Benutzerdefiniert"</string>
     <string name="sipAddressTypeHome" msgid="6093598181069359295">"Privat"</string>
     <string name="sipAddressTypeWork" msgid="6920725730797099047">"Geschäftlich"</string>
-    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Andere"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Sonstige"</string>
     <string name="contact_status_update_attribution" msgid="5112589886094402795">"über <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="contact_status_update_attribution_with_date" msgid="5945386376369979909">"<xliff:g id="DATE">%1$s</xliff:g> über <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"PIN-Code eingeben"</string>
@@ -563,7 +559,7 @@
     <string name="lockscreen_emergency_call" msgid="5347633784401285225">"Notruf"</string>
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Zurück zum Anruf"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Korrekt!"</string>
-    <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Tut uns leid. Versuchen Sie es noch einmal."</string>
+    <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Bitte versuchen Sie es erneut."</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Wird geladen (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Aufgeladen"</string>
     <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
@@ -610,10 +606,8 @@
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Ermöglicht der Anwendung, alle URLs, die mit dem Browser besucht wurden, sowie alle Lesezeichen des Browsers zu lesen."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"Browserverlauf und Lesezeichen schreiben"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Ermöglicht einer Anwendung, den auf Ihrem Telefon gespeicherten Browserverlauf und die Lesezeichen zu ändern. Schädliche Anwendungen können so Ihre Browserdaten löschen oder ändern."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"Alarm im Wecker festlegen"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Ermöglicht dieser Anwendung, einen Alarm mithilfe eines installierten Weckers festzulegen. Einige Weckeranwendungen verfügen möglicherweise nicht über diese Funktion."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Geolokalisierungsberechtigungen des Browsers ändern"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Ermöglicht einer Anwendung, die Geolokalisierungsberechtigungen des Browsers zu ändern. Schädliche Anwendungen können dies nutzen, um das Senden von Standortinformationen an willkürliche Websites zuzulassen."</string>
     <string name="save_password_message" msgid="767344687139195790">"Möchten Sie, dass der Browser dieses Passwort speichert?"</string>
@@ -745,7 +739,7 @@
     <string name="capital_off" msgid="6815870386972805832">"AUS"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Aktion durchführen mit"</string>
     <string name="alwaysUse" msgid="4583018368000610438">"Standardmäßig für diese Aktion verwenden."</string>
-    <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Löschen Sie die Standardeinstellungen unter \"Starteinstellungen &gt; Anwendungen &gt; Anwendungen verwalten\"."</string>
+    <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Standardeinstellung zurücksetzen unter \"Einstellungen &gt; Anwendungen &gt; Anwendungen verwalten\"."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Aktion auswählen"</string>
     <string name="noApplications" msgid="1691104391758345586">"Diese Aktion kann von keiner Anwendung ausgeführt werden."</string>
     <string name="aerr_title" msgid="653922989522758100">"Tut uns leid!"</string>
@@ -808,17 +802,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Alle anzeigen"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB-Massenspeicher"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB-Verbindung"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Sie haben Ihr Telefon über USB mit Ihrem Computer verbunden. Wählen Sie die Schaltfläche unten aus, wenn Sie Dateien auf Ihren Computer oder die SD-Karte Ihres Android-Geräts kopieren möchten."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Sie haben Ihr Telefon über USB mit Ihrem Computer verbunden. Wählen Sie die Schaltfläche unten aus, wenn Sie Dateien von Ihrem Computer in den gemeinsamen Speicher Ihres Android-Geräts und umgekehrt kopieren möchten."</string>
     <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Sie haben Ihr Telefon über USB mit Ihrem Computer verbunden. Wählen Sie die Schaltfläche unten aus, wenn Sie Dateien auf Ihren Computer oder die SD-Karte Ihres Android-Geräts kopieren möchten."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"USB-Speicher aktivieren"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Bei der Verwendung Ihrer SD-Karte als USB-Speicher ist ein Problem aufgetreten."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Bei der Verwendung Ihres gemeinsamen Speichers als USB-Speicher ist ein Problem aufgetreten."</string>
     <string name="usb_storage_error_message" product="default" msgid="2534784751603345363">"Bei der Verwendung Ihrer SD-Karte als USB-Speicher ist ein Problem aufgetreten."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB-Verbindung"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Zum Kopieren von Dateien zum/vom Computer"</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"USB-Speicher deaktivieren"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Auswählen, um USB-Speicher zu deaktivieren."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB-Speicher in Verwendung"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Stellen Sie vor dem Deaktivieren des USB-Speichers sicher, dass Sie Ihre Android-SD-Karte von Ihrem Computer getrennt (\"ausgeworfen\") haben."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Stellen Sie vor dem Deaktivieren des USB-Speichers sicher, dass Sie den gemeinsamen Android-Speicher von Ihrem Computer getrennt (\"ausgeworfen\") haben."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Stellen Sie vor dem Deaktivieren des USB-Speichers sicher, dass Sie Ihre Android-SD-Karte von Ihrem Computer getrennt (\"ausgeworfen\") haben."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"USB-Speicher deaktivieren"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Beim Deaktivieren des USB-Speichers ist ein Problem aufgetreten. Überprüfen Sie, ob Sie den USB-Host getrennt haben, und versuchen Sie es erneut."</string>
@@ -826,9 +820,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Wenn Sie den USB-Speicher aktivieren, werden einige von Ihnen verwendete Anwendungen angehalten und sind möglicherweise nicht verfügbar, bis Sie den USB-Speicher wieder deaktivieren."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB-Vorgang fehlgeschlagen"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"SD-Karte formatieren"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Speicher formatieren"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD-Karte formatieren"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Möchten Sie die SD-Karte wirklich formatieren? Alle Daten auf Ihrer Karte gehen dann verloren."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Gemeinsamen Speicher formatieren und alle darauf gespeicherten Dateien löschen? Diese Aktion kann nicht rückgängig gemacht werden!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Möchten Sie die SD-Karte wirklich formatieren? Alle Daten auf Ihrer Karte gehen dann verloren."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Format"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-Debugging verbunden"</string>
@@ -837,28 +831,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"Kandidaten"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"SD-Karte wird vorbereitet"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Gem. Speicher vorbereiten"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"SD-Karte wird vorbereitet"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Suche nach Fehlern"</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"SD-Karte leer"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Gemeinsamer Speicher leer"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"SD-Karte leer"</string>
-    <!-- outdated translation 1312266820092958014 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"Die SD-Karte ist leer oder verwendet ein Dateisystem, das nicht unterstützt wird."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"Gemeinsamer Speicher ist leer oder verfügt über ein nicht unterstütztes Dateisystem"</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD-Karte ist leer oder verfügt über ein nicht unterstütztes Dateisystem."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Beschädigte SD-Karte"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Gem. Speicher beschädigt"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Beschädigte SD-Karte"</string>
-    <!-- outdated translation 2679412884290061775 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"Die SD-Karte ist beschädigt. Sie müssen Ihre Karte eventuell neu formatieren."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"Gemeinsamer Speicher ist beschädigt. Sie müssen ihn neu formatieren."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Die SD-Karte ist beschädigt. Sie müssen Ihre Karte eventuell neu formatieren."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"SD-Karte unerwartet entfernt"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Gem. Speicher entfernt"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD-Karte unerwartet entfernt"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"SD-Karte vor dem Entnehmen trennen, um Datenverlust zu vermeiden."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Trennen Sie den gemeinsamen Speicher vor dem Entfernen, um Datenverlust zu vermeiden."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"SD-Karte vor dem Entnehmen trennen, um Datenverlust zu vermeiden."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"SD-Karte kann entfernt werden."</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"Speicher kann entfernt werden."</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"SD-Karte kann entfernt werden."</string>
-    <!-- outdated translation 7613960686747592770 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"Die SD-Karte kann jetzt entfernt werden."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"Gemeinsamer Speicher kann entfernt werden."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Die SD-Karte kann entfernt werden."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"SD-Karte entfernt"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Gemeinsamer Speicher entfernt"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"SD-Karte entfernt"</string>
-    <!-- outdated translation 4205117227342822275 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"Die SD-Karte wurde entfernt. Legen Sie eine neue SD-Karte ein, um den Speicherplatz Ihres Geräts zu erweitern."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"Gemeinsamer Speicher entfernt. Neuen Datenträger einlegen"</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD-Karte entfernt. Legen Sie eine neue ein."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Keine passenden Aktivitäten gefunden"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"Nutzungsstatistik der Komponente aktualisieren"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 7128ad7..bd60ad4 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -169,7 +169,7 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Εργαλεία ανάπτυξης"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Δυνατότητες που είναι απαραίτητες μόνο σε προγραμματιστές εφαρμογών."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Αποθηκευτικός χώρος"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Πρόσβαση στην κάρτα SD."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Πρόσβ. σε κοινόχρ. αποθ. χώρο."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Πρόσβαση στην κάρτα SD."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"απενεργοποίηση ή τροποποίηση γραμμής κατάστασης"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Επιτρέπει στην εφαρμογή να απενεργοποιεί τη γραμμή κατάστασης ή να προσθέτει και να αφαιρεί εικονίδια συστήματος."</string>
@@ -403,22 +403,14 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Επιτρέπει σε μια εφαρμογή τη διαμόρφωση του τοπικού τηλεφώνου Bluetooth και την ανακάλυψη και σύζευξη με απομακρυσμένες συσκευές."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"δημιουργία συνδέσεων Bluetooth"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Επιτρέπει σε μια εφαρμογή να προβάλει τη διαμόρφωση του τοπικού τηλεφώνου Bluetooth και επίσης να πραγματοποιεί και να αποδέχεται συνδέσεις με συζευγμένες συσκευές."</string>
-    <!-- no translation found for permlab_nfcAdmin (2251302233012250056) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcAdmin (1935842611464895785) -->
-    <skip />
-    <!-- no translation found for permlab_nfcRaw (4423471711114325708) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcRaw (5533022736559385665) -->
-    <skip />
-    <!-- no translation found for permlab_nfcNotify (478470360082792358) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcNotify (2990053517962070617) -->
-    <skip />
-    <!-- no translation found for permlab_nfcLlcp (4972051461007030426) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcLlcp (91592127786004640) -->
-    <skip />
+    <string name="permlab_nfcAdmin" msgid="2251302233012250056">"Διαχείριση NFC"</string>
+    <string name="permdesc_nfcAdmin" msgid="1935842611464895785">"Επιτρέπει σε κάποια εφαρμογή τη διαμόρφωση του τοπικού τηλεφώνου NFC."</string>
+    <string name="permlab_nfcRaw" msgid="4423471711114325708">"Πλήρης πρόσβαση NFC σε απομακρυσμένη συσκευή"</string>
+    <string name="permdesc_nfcRaw" msgid="5533022736559385665">"Επιτρέπει σε κάποια εφαρμογή την πρόσβαση στις απομακρυσμένες συσκευές NFC."</string>
+    <string name="permlab_nfcNotify" msgid="478470360082792358">"Ειδοποίηση NFC από την απομακρυσμένη συσκευή"</string>
+    <string name="permdesc_nfcNotify" msgid="2990053517962070617">"Επιτρέπει την ενημέρωση της εφαρμογής σχετικά με λειτουργίες που σχετίζονται με απομακρυσμένες συσκευές NFC."</string>
+    <string name="permlab_nfcLlcp" msgid="4972051461007030426">"Ειδοποίηση NFC από την απομακρυσμένη συσκευή LLCP"</string>
+    <string name="permdesc_nfcLlcp" msgid="91592127786004640">"Επιτρέπει την ενημέρωση της εφαρμογής σχετικά με λειτουργίες LLCP που σχετίζονται με απομακρυσμένες συσκευές NFC."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"απενεργοποίηση κλειδώματος πληκτρολογίου"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Επιτρέπει σε μια εφαρμογή την απενεργοποίηση του κλειδώματος πληκτρολογίου και άλλης σχετικής ασφάλειας με κωδικό πρόσβασης. Για παράδειγμα, η απενεργοποίηση του κλειδώματος πληκτρολογίου όταν λαμβάνεται εισερχόμενη τηλεφωνική κλήση και η επανενεργοποίηση του κλειδώματος πληκτρολογίου όταν η κλήση τερματιστεί."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ανάγνωση ρυθμίσεων συγχρονισμού"</string>
@@ -435,22 +427,26 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Επιτρέπει σε μια εφαρμογή να αναγνώσει ιδιωτικές λέξεις και φράσεις και ιδιωτικά ονόματα, τα οποία ο χρήστης ενδέχεται να έχει αποθηκεύσει στο λεξικό χρήστη."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"εγγραφή σε καθορισμένο από τον χρήστη λεξικό"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Επιτρέπει σε μια εφαρμογή την εγγραφή νέων λέξεων στο λεξικό χρήστη."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"τροποποίηση/διαγραφή περιεχομένων κάρτας SD"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"τροπ./διαγ. περ. κοιν. απ. χώρ."</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"τροποποίηση/διαγραφή περιεχομένων κάρτας SD"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Επιτρέπει στην εφαρμογή την εγγραφή στην κάρτα SD."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Επιτρ. εγγρ. εφ. σε κοιν. απ. χώρ."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Επιτρέπει στην εφαρμογή την εγγραφή στην κάρτα SD."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"πρόσβαση στο σύστημα αρχείων προσωρινής μνήμης"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Επιτρέπει σε μια εφαρμογή την ανάγνωση και την εγγραφή του συστήματος αρχείων προσωρινής μνήμης."</string>
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Περιορισμός επιλογών κωδικού πρόσβασης"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Περιορισμός των τύπων κωδικού πρόσβασης που επιτρέπεται να χρησιμοποιείτε."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Παρακολούθηση προσπαθειών σύνδεσης"</string>
-    <!-- outdated translation 1961251179624843483 -->     <string name="policydesc_watchLogin" msgid="7227578260165172673">"Παρακολούθηση αποτυχημένων προσπαθειών σύνδεσης με τη συσκευή, για την εκτέλεσης κάποιας ενέργειας."</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Επαναφορά κωδικού πρόσβασης"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Εφαρμογή του κωδικού πρόσβασής σας σε μια νέα τιμή, με την προϋπόθεση ότι σας παρέχεται από τον διαχειριστή για να μπορείτε να συνδεθείτε."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Εφαρμογή κλειδώματος"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Ελέγχει πότε κλειδώνει η συσκευή, απαιτώντας κωδικό πρόσβασης για επανείσοδο."</string>
+    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+    <skip />
+    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
+    <skip />
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Ορισμός κανόνων κωδικού πρόσβασης"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Έλεγχος του μεγέθους και των χαρακτήρων που επιτρέπονται στους κωδικούς πρόσβασης ξεκλειδώματος οθόνης"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Παρακολούθηση προσπαθειών ξεκλειδώματος οθόνης"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Παρακολούθηση του αριθμού των εσφαλμένων κωδικών πρόσβασης που έχουν εισαχθεί κατά το ξεκλείδωμα της οθόνης και κλείδωμα του τηλεφώνου ή διαγραφή όλων των δεδομένων του τηλεφώνου σε περίπτωση που έχουν εισαχθεί πάρα πολλοί εσφαλμένοι κωδικοί πρόσβασης"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Αλλαγή κωδικού πρόσβασης ξεκλειδώματος οθόνης"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Αλλαγή κωδικού πρόσβασης ξεκλειδώματος οθόνης"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Κλείδωμα οθόνης"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Έλεγχος του τρόπου και του χρόνου κλειδώματος της οθόνης"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Διαγραφή όλων των δεδομένων"</string>
-    <!-- outdated translation 2314060933796396205 -->     <string name="policydesc_wipeData" msgid="7669895333814222586">"Πραγματοποιείται επαναφορά εργοστασιακών ρυθμίσεων, με τη διαγραφή όλων των δεδομένων σας χωρίς επιβεβαίωση."</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Διαγραφή των δεδομένων του τηλεφώνου χωρίς προειδοποίηση με επαναφορά των εργοστασιακών δεδομένων"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Οικία"</item>
     <item msgid="869923650527136615">"Κινητό"</item>
@@ -610,10 +606,8 @@
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Επιτρέπει στην εφαρμογή την ανάγνωση όλων των διευθύνσεων URL που το πρόγραμμα περιήγησης έχει επισκεφθεί και όλων των σελιδοδεικτών του προγράμματος περιήγησης."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"εγγραφή ιστορικού και σελιδοδεικτών προγράμματος περιήγησης"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Επιτρέπει σε μια εφαρμογή να τροποποιήσει το ιστορικό ή τους σελιδοδείκτες του προγράμματος περιήγησης που βρίσκονται αποθηκευμένα στο τηλέφωνό σας. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να διαγράψουν ή να τροποποιήσουν τα δεδομένα του προγράμματος περιήγησης."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"ρύθμιση ειδοποίησης σε ξυπνητήρι"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Επιτρέπει στην εφαρμογή να ρυθμίσει μια ειδοποίηση σε μια εγκατεστημένη εφαρμογή ξυπνητηριού. Κάποιες εφαρμογές ξυπνητηριού ενδέχεται να μην περιλαμβάνουν αυτή τη λειτουργία."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Τροποποίηση δικαιωμάτων γεωγραφικής θέσης προγράμματος περιήγησης"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Επιτρέπει σε μια εφαρμογή την τροποποίηση των δικαιωμάτων γεωγραφικής θέσης του προγράμματος περιήγησης. Οι κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να επιτρέψουν την αποστολή στοιχείων τοποθεσίας σε αυθαίρετους ιστότοπους."</string>
     <string name="save_password_message" msgid="767344687139195790">"Θέλετε το πρόγραμμα περιήγησης να διατηρήσει αυτόν τον κωδικό πρόσβασης;"</string>
@@ -808,17 +802,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Εμφάνιση όλων"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"Μαζική αποθήκευση USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Το USB είναι συνδεδεμένο"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Συνδέσατε το τηλέφωνό σας στον υπολογιστή μέσω USB. Επιλέξτε το παρακάτω κουμπί αν θέλετε να αντιγράψετε αρχεία μεταξύ του υπολογιστή και της κάρτας SD του Android."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Συνδέσατε το τηλέφωνό σας στον υπολογιστή μέσω USB. Επιλέξτε το παρακάτω κουμπί αν θέλετε να αντιγράψετε αρχεία μεταξύ του υπολογιστή και του κοινόχρηστου χώρου αποθήκευσης του Android."</string>
     <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Συνδέσατε το τηλέφωνό σας στον υπολογιστή μέσω USB. Επιλέξτε το παρακάτω κουμπί αν θέλετε να αντιγράψετε αρχεία μεταξύ του υπολογιστή και της κάρτας SD του Android."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Ενεργοποίηση αποθηκευτικού χώρου USB"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Παρουσιάστηκε ένα πρόβλημα στη χρήση της κάρτας SD ως αποθηκευτικό χώρο USB."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Παρουσιάστηκε ένα πρόβλημα στη χρήση του κοινόχρηστου αποθηκευτικού χώρου ως αποθηκευτικό χώρο USB."</string>
     <string name="usb_storage_error_message" product="default" msgid="2534784751603345363">"Παρουσιάστηκε ένα πρόβλημα στη χρήση της κάρτας SD ως αποθηκευτικό χώρο USB."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"Το USB είναι συνδεδεμένο"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Επιλέξτε για αντιγραφή προς/από τον υπολογιστή σας."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Απενεργοποίηση αποθηκευτικού χώρου USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Επιλογή για απενεργοποίηση αποθηκευτικού χώρου USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"Χώρος αποθήκευσης USB σε χρήση"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Προτού απενεργοποιήσετε το χώρο αποθήκευσης USB, βεβαιωθείτε ότι έχετε αποσυνδέσει (“αφαιρέσει”) την κάρτα SD του Android από τον υπολογιστή σας."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Προτού απενεργοποιήσετε τον χώρο αποθήκευσης USB, βεβαιωθείτε ότι έχετε αποπροσαρτήσει (\"αφαιρέσει\") τον κοινόχρηστο αποθηκευτικό χώρο του Android από τον υπολογιστή σας."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Προτού απενεργοποιήσετε το χώρο αποθήκευσης USB, βεβαιωθείτε ότι έχετε αποσυνδέσει (“αφαιρέσει”) την κάρτα SD του Android από τον υπολογιστή σας."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Απενεργοποίηση χώρου αποθήκευσης USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Παρουσιάστηκε πρόβλημα κατά την απενεργοποίηση του αποθηκευτικού χώρου USB. Βεβαιωθείτε ότι έχετε αφαιρέσει την υποδοχή USB και προσπαθήστε ξανά."</string>
@@ -826,9 +820,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Εάν ενεργοποιήσετε τον αποθηκευτικό χώρο USB, ορισμένες από τις εφαρμογές που χρησιμοποιείτε θα σταματήσουν και ενδέχεται να μην είναι διαθέσιμες μέχρι να απενεργοποιήσετε τον αποθηκευτικό χώρο USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Απέτυχε η λειτουργία USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"ΟΚ"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Διαμόρφωση κάρτας SD"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Διαγ. κοιν. απ. χώρ."</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Διαμόρφωση κάρτας SD"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Είστε βέβαιοι ότι θέλετε να διαμορφώσετε την κάρτα SD; Όλα τα δεδομένα στην κάρτα σας θα χαθούν."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Να γίνει διαγραφή του κοινόχρηστου αποθηκευτικού χώρου, η οποία θα διαγράψει όλα τα αρχεία που έχετε αποθηκεύσει εκεί; Η ενέργεια είναι μη αναστρέψιμη!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Είστε βέβαιοι ότι θέλετε να διαμορφώσετε την κάρτα SD; Όλα τα δεδομένα στην κάρτα σας θα χαθούν."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Διαμόρφωση"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Συνδέθηκε ο εντοπισμός σφαλμάτων USB"</string>
@@ -837,28 +831,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"υποψήφιοι"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Προετοιμασία κάρτας SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Προετοιμ. κοινόχρ. αποθ. χώρ."</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Προετοιμασία κάρτας SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Έλεγχος για σφάλματα."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Κενή κάρτα SD"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Κενός κοινόχρ. αποθηκ. χώρος"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Κενή κάρτα SD"</string>
-    <!-- outdated translation 1312266820092958014 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"Η κάρτα SD είναι κενή ή χρησιμοποιεί σύστημα αρχείων που δεν υποστηρίζεται."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"Ο κοινόχρηστος αποθηκευτικός χώρος είναι κενός ή έχει κάποιο σύστημα αρχείων το οποίο δεν υποστηρίζεται."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Η κάρτα SD είναι κενή ή έχει μη υποστηριζόμενο σύστημα αρχείων."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Κατεστραμμένη κάρτα SD"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Κατεστρ. κοινόχρ. αποθ. χώρος"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Κατεστραμμένη κάρτα SD"</string>
-    <!-- outdated translation 2679412884290061775 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"Η κάρτα SD έχει υποστεί βλάβη. Ενδέχεται να χρειαστεί αναδιαμόρφωση της κάρτας σας."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"Ο κοινόχρηστος αποθηκευτικός χώρος παρουσιάζει βλάβη. Ενδεχομένως θα πρέπει να προβείτε σε διαμόρφωσή του."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Η κάρτα SD παρουσιάζει βλάβη. Ενδεχομένως θα πρέπει να προβείτε σε διαμόρφωσή της."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Μη αναμενόμενη αφαίρεση κάρτας SD"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Μη αναμενόμενη κατάργηση κοινόχρηστου αποθηκευτικού χώρου"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Μη αναμενόμενη αφαίρεση κάρτας SD"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Αποπροσαρτήστε την κάρτα SD πριν την αφαιρέσετε για την αποφυγή απώλειας δεδομένων."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Αποπροσαρτήστε τον κοινόχρηστο αποθηκευτικό χώρο πριν τον αφαιρέσετε για την αποφυγή απώλειας δεδομένων."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Αποπροσαρτήστε την κάρτα SD πριν την αφαιρέσετε για την αποφυγή απώλειας δεδομένων."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"Η κάρτα SD μπορεί να αφαιρεθεί με ασφάλεια"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"Ασφ. κατάργ. κοιν. αποθ. χώρ."</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Η κάρτα SD μπορεί να αφαιρεθεί με ασφάλεια"</string>
-    <!-- outdated translation 7613960686747592770 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"Τώρα μπορείτε να αφαιρέσετε με ασφάλεια την κάρτα SD."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"Μπορείτε να καταργήσετε τον κοινόχρηστο αποθηκευτικό χώρο εύκολα."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Μπορείτε να αφαιρέσετε με ασφάλεια της κάρτα SD."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Η κάρτα SD αφαιρέθηκε"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Κοιν. απ. χώρ. που έχει καταρ."</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Η κάρτα SD αφαιρέθηκε"</string>
-    <!-- outdated translation 4205117227342822275 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"Η κάρτα SD αφαιρέθηκε. Εισαγάγετε μια νέα κάρτα SD για να αυξήσετε τον αποθηκευτικό χώρο της συσκευής σας."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"Ο κοινόχρηστος αποθηκευτικός χώρος καταργήθηκε. Εισαγάγετε νέα πολυμέσα."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Αφαιρέθηκε η κάρτα SD. Τοποθετήστε μια νέα κάρτα."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Δεν βρέθηκαν δραστηριότητες που να αντιστοιχούν"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"ενημέρωση στατιστικών χρήσης στοιχείου"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 406d335..7cc057b 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -169,7 +169,7 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Herramientas de desarrollo"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Las funciones sólo son necesarias para los desarrolladores de aplicaciones."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Espacio de almacenamiento"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Acceder a la tarjeta SD."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Accede al almacenamiento comp."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Acceder a la tarjeta SD."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"desactivar o modificar la barra de estado"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Admite que la aplicación desactive la barra de estado, o agregue y elimine íconos del sistema."</string>
@@ -403,22 +403,14 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Admite una aplicación que configura el teléfono Bluetooth local y descubre y se vincula con dispositivos remotos."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"crear conexiones de Bluetooth"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Admite una aplicación que ve la configuración del teléfono Bluetooth local, y realiza y acepta conexiones con dispositivos vinculados."</string>
-    <!-- no translation found for permlab_nfcAdmin (2251302233012250056) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcAdmin (1935842611464895785) -->
-    <skip />
-    <!-- no translation found for permlab_nfcRaw (4423471711114325708) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcRaw (5533022736559385665) -->
-    <skip />
-    <!-- no translation found for permlab_nfcNotify (478470360082792358) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcNotify (2990053517962070617) -->
-    <skip />
-    <!-- no translation found for permlab_nfcLlcp (4972051461007030426) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcLlcp (91592127786004640) -->
-    <skip />
+    <string name="permlab_nfcAdmin" msgid="2251302233012250056">"Administración NFC"</string>
+    <string name="permdesc_nfcAdmin" msgid="1935842611464895785">"Permite a una aplicación configurar el teléfono NFC local."</string>
+    <string name="permlab_nfcRaw" msgid="4423471711114325708">"Acceso completo NFC a dispositivo remoto"</string>
+    <string name="permdesc_nfcRaw" msgid="5533022736559385665">"Permite a una aplicación acceder a dispositivos remotos NFC."</string>
+    <string name="permlab_nfcNotify" msgid="478470360082792358">"Notificación NFC de dispositivo remoto"</string>
+    <string name="permdesc_nfcNotify" msgid="2990053517962070617">"Permite a una aplicación ser notificada sobre las operaciones relacionadas a los dispositivos remotos NFC."</string>
+    <string name="permlab_nfcLlcp" msgid="4972051461007030426">"Notificación NFC de dispositivo remoto LLCP."</string>
+    <string name="permdesc_nfcLlcp" msgid="91592127786004640">"Permite a una aplicación que se le notifique sobre las operaciones LLCP relacionadas con los dispositivos remotos NFC."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"desactivar el bloqueo"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Admite una aplicación que desactiva el bloqueo y cualquier seguridad con contraseña relacionada. Un ejemplo legítimo de esto es el bloqueo desactivado por el teléfono cuando recibe una llamada telefónica entrante, y luego la reactivación del bloqueo cuando finaliza la llamada."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"leer la configuración de sincronización"</string>
@@ -435,22 +427,26 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Admite una aplicación para leer palabras, nombres y frases privadas que posiblemente el usuario haya almacenado en el diccionario del usuario."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"escribir al diccionario definido por el usuario"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Admite una aplicación que escribe palabras nuevas en el diccionario del usuario."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"modificar/suprimir el contenido de la tarjeta SD"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"modificar/elimin cont alm comp"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"modificar/suprimir el contenido de la tarjeta SD"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Admite que una aplicación escriba en la tarjeta SD."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Perm apl. escribir en alm comp"</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Admite que una aplicación escriba en la tarjeta SD."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"Acceder al sistema de archivos caché"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permite que una aplicación lea y escriba el sistema de archivos caché."</string>
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Limitar la contraseña"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Restringe los tipos de contraseñas que puedes utilizar."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Observar los intentos de acceso"</string>
-    <!-- outdated translation 1961251179624843483 -->     <string name="policydesc_watchLogin" msgid="7227578260165172673">"Intentos fallidos del control para acceder al dispositivo para realizar alguna acción."</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Restablecer contraseña"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Forzar un nuevo valor para tu contraseña, el administrador deberá enviártelo antes de poder acceder."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Provocar el bloqueo"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Controlar cuando se bloquee el dispositivo, requiere que vuelvas a ingresar tu contraseña."</string>
+    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+    <skip />
+    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
+    <skip />
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Establecer reglas de contraseña"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Controlar la longitud y los caracteres permitidos en las contraseñas para desbloquear la pantalla"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Supervisa los intentos para desbloquear la pantalla"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Supervisa el número de contraseñas incorrectas ingresadas al desbloquear la pantalla, y bloquee el teléfono o elimine todos los datos del teléfono si se ingresan demasiadas contraseñas incorrectas."</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Cambiar la contraseña para desbloquear la pantalla"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Cambiar la contraseña para desbloquear la pantalla"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Bloquear la pantalla"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Controlar cómo y cuándo se bloquea la pantalla"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Borrar todos los datos"</string>
-    <!-- outdated translation 2314060933796396205 -->     <string name="policydesc_wipeData" msgid="7669895333814222586">"Realizar un reestablecimiento de fábrica y borrar todos tus datos sin ninguna confirmación."</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Borrar los datos del teléfono sin advertencias al restablecer la configuración original"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Casa"</item>
     <item msgid="869923650527136615">"Celular"</item>
@@ -610,10 +606,8 @@
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permite a la aplicación leer todas las URL que ha visitado el navegador y todos los marcadores del navegador."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"escribir historial y marcadores del navegador"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Permite a una aplicación modificar el historial y los marcadores del navegador almacenados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para borrar o modificar tus datos."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"configurar alarma en reloj alarma"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Permite que la aplicación configure una alarma en una aplicación instalada de reloj alarma. Es posible que algunas aplicaciones de reloj alarma no implementen esta función."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modificar los permisos de ubicación geográfica del navegador"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permite que una aplicación modifique los permisos de ubicación geográfica del navegador. Las aplicaciones maliciosas pueden utilizarlos para permitir el envío de información sobre la ubicación a sitos web de forma arbitraria."</string>
     <string name="save_password_message" msgid="767344687139195790">"¿Quieres recordar esta contraseña en el navegador?"</string>
@@ -808,17 +802,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Mostrar todos"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"Almacenamiento masivo USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"conectado al USB"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Has conectado tu teléfono a tu computadora mediante USB. Selecciona el botón a continuación si deseas copiar los archivos entre tu computadora y la tarjeta SD de Android."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Has conectado tu teléfono a tu computadora mediante USB. Selecciona el botón a continuación si deseas copiar los archivos entre tu computadora y el almacenamiento compartido de Android."</string>
     <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Has conectado tu teléfono a tu computadora mediante USB. Selecciona el botón a continuación si deseas copiar los archivos entre tu computadora y la tarjeta SD de Android."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Activar el almacenamiento USB"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Hay un problema para utilizar tu tarjeta SD en el almacenamiento USB."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Hay un problema para utilizar el almacenamiento compartido en el almacenamiento USB."</string>
     <string name="usb_storage_error_message" product="default" msgid="2534784751603345363">"Hay un problema para utilizar tu tarjeta SD en el almacenamiento USB."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"conectado al USB"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Seleccionar para copiar archivos desde o hacia tu computadora."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Apagar el almacenamiento USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Seleccionar para desactivar el almacenamiento USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"Almacenamiento USB en uso"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Antes de desactivar el almacenamiento USB, asegúrate de haber desmontado (\"expulsado\") la tarjeta SD de Android de tu computadora."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Antes de desactivar el almacenamiento USB, asegúrate de haber desmontado (\"expulsado\") el almacenamiento compartido de Android de tu computadora."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Antes de desactivar el almacenamiento USB, asegúrate de haber desmontado (\"expulsado\") la tarjeta SD de Android de tu computadora."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Desactivar el almacenamiento USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Se ha producido un problema al desactivar el almacenamiento USB. Asegúrate de haber desmontado el host USB, luego vuelve a intentarlo."</string>
@@ -826,9 +820,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Si activas el almacenamiento USB, algunas aplicaciones que estás usando se detendrán y es posible que no estén disponibles hasta que desactives el almacenamiento USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Error en el funcionamiento del USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"Aceptar"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Formatear tarjeta SD"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Formatear almacenamiento compartido"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatear tarjeta SD"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"¿Estás seguro de que quieres formatear la tarjeta SD? Se perderán todos los datos de tu tarjeta."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"¿Deseas formatear el almacenamiento compartido y borrar todos los archivos almacenados aquí? ¡Esta acción no se puede cambiar!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"¿Estás seguro de que quieres formatear la tarjeta SD? Se perderán todos los datos de tu tarjeta."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formato"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuración de USB conectada"</string>
@@ -837,28 +831,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Preparación de la tarjeta SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Preparando el alm. compartido"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Preparación de la tarjeta SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Verificando errores"</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Tarjeta SD vacía"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Alm. comp. en blanco"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Tarjeta SD vacía"</string>
-    <!-- outdated translation 1312266820092958014 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"La tarjeta SD está vacía o utiliza un filesystem no admitido."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"Almacenamiento compartido en blanco o sistema de archivos no compatible."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Tarjeta SD en blanco o el sistema de archivos no es compatible."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Tarjeta SD dañada"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Alm. compartido dañado"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Tarjeta SD dañada"</string>
-    <!-- outdated translation 2679412884290061775 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"La tarjeta SD está dañada. Es posible que debas reformatear tu tarjeta."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"Almacenamiento compartido dañado. Es posible que debas reformatearlo."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Tarjeta SD dañada. Es posible que debas reformatearla."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Tarjeta SD extraída de forma imprevista"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Alm. comp. eliminado inesp."</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Tarjeta SD extraída de forma imprevista"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Desmontar la tarjeta SD antes de extraerla para evitar la pérdida de datos."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Desmontar almacenamiento compartido antes de extraerlo para evitar la pérdida de datos."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Desmontar la tarjeta SD antes de extraerla para evitar la pérdida de datos."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"Tarjeta SD fácil de extraer"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"Es seguro eliminar alm comp."</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Tarjeta SD fácil de extraer"</string>
-    <!-- outdated translation 7613960686747592770 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"La tarjeta SD ahora se puede extraer de manera segura."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"Puede eliminar de forma segura el almacenamiento compartido."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Puedes eliminar la tarjeta SD sin riesgos."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Tarjeta SD extraída"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Alm. comp. eliminado"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Tarjeta SD extraída"</string>
-    <!-- outdated translation 4205117227342822275 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"Se extrajo la SD. Inserta una nva. tarjeta SD para aumentar el espacio de almac. de tu disposit."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"Almacenamiento compartido eliminado. Insertar nuevos medios."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Tarjeta SD eliminada. Inserta una nueva."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"No se encontraron actividades coincidentes"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"actualizar la estadística de uso de los componentes"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 1cf971a..d3560ac 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -169,7 +169,7 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Herramientas de desarrollo"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Funciones necesarias solo para desarrolladores de aplicaciones"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Almacenamiento"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Acceder a la tarjeta SD"</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Acceso almacenamiento compartido"</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Acceder a la tarjeta SD"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"inhabilitar o modificar la barra de estado"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Permite que las aplicaciones inhabiliten la barra de estado, o añadan y eliminen iconos del sistema."</string>
@@ -403,22 +403,14 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Permite que una aplicación configure el teléfono Bluetooth local, y vea dispositivos remotos y sincronice el teléfono con ellos."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"crear conexiones de Bluetooth"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Permite que una aplicación vea la configuración del teléfono Bluetooth local, y cree y acepte conexiones con los dispositivos sincronizados."</string>
-    <!-- no translation found for permlab_nfcAdmin (2251302233012250056) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcAdmin (1935842611464895785) -->
-    <skip />
-    <!-- no translation found for permlab_nfcRaw (4423471711114325708) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcRaw (5533022736559385665) -->
-    <skip />
-    <!-- no translation found for permlab_nfcNotify (478470360082792358) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcNotify (2990053517962070617) -->
-    <skip />
-    <!-- no translation found for permlab_nfcLlcp (4972051461007030426) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcLlcp (91592127786004640) -->
-    <skip />
+    <string name="permlab_nfcAdmin" msgid="2251302233012250056">"Administración de NFC"</string>
+    <string name="permdesc_nfcAdmin" msgid="1935842611464895785">"Permite que una aplicación configure el teléfono NFC local."</string>
+    <string name="permlab_nfcRaw" msgid="4423471711114325708">"Acceso completo NFC a dispositivo remoto"</string>
+    <string name="permdesc_nfcRaw" msgid="5533022736559385665">"Permite que una aplicación acceda a los dispositivos NFC remotos."</string>
+    <string name="permlab_nfcNotify" msgid="478470360082792358">"Notificación NFC de dispositivo remoto"</string>
+    <string name="permdesc_nfcNotify" msgid="2990053517962070617">"Permite que una aplicación reciba notificaciones sobre las operaciones relacionadas con dispositivos NFC remotos."</string>
+    <string name="permlab_nfcLlcp" msgid="4972051461007030426">"Notificación NFC de dispositivo LLCP remoto"</string>
+    <string name="permdesc_nfcLlcp" msgid="91592127786004640">"Permite que una aplicación reciba notificaciones de operaciones LLCP relacionadas con dispositivos NFC remotos."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"inhabilitar bloqueo del teclado"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Permite que una aplicación inhabilite el bloqueo del teclado y cualquier protección con contraseña asociada. Un ejemplo legítimo de este permiso es la inhabilitación por parte del teléfono del bloqueo del teclado cuando recibe una llamada telefónica entrante y su posterior habilitación cuando finaliza la llamada."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"leer la configuración de sincronización"</string>
@@ -435,22 +427,26 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Permite a una aplicación leer cualquier frase, palabra o nombre privado que el usuario haya almacenado en su diccionario."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"escribir en el diccionario definido por el usuario"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Permite a una aplicación escribir palabras nuevas en el diccionario de usuario."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"modificar/eliminar contenido de la tarjeta SD"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"modificar/suprimir contenido"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"modificar/eliminar contenido de la tarjeta SD"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Permite que una aplicación escriba en la tarjeta SD."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Permit esc aplic en almac comp"</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Permite que una aplicación escriba en la tarjeta SD."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"acceder al sistema de archivos almacenado en caché"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permite que una aplicación lea y escriba el sistema de archivos almacenado en caché."</string>
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Limitar opciones de contraseña"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Permite restringir los tipos de contraseñas que puede utilizar el usuario."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Controlar intentos de acceso"</string>
-    <!-- outdated translation 1961251179624843483 -->     <string name="policydesc_watchLogin" msgid="7227578260165172673">"Se ha producido un error al intentar controlar el acceso al dispositivo para realizar una acción."</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Restablecer contraseña"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Permite forzar la contraseña para establecer un valor nuevo que el administrador deberá proporcionar al usuario para poder acceder."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Forzar bloqueo"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Permite controlar el momento de bloqueo del dispositivo solicitando al usuario que vuelva a introducir la contraseña."</string>
+    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+    <skip />
+    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
+    <skip />
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Establecimiento de reglas de contraseña"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Control de la longitud y de los caracteres permitidos en las contraseñas de bloqueo de pantalla"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Control de intentos de bloqueo de pantalla"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Control del número de contraseñas incorrectas introducidas al desbloquear la pantalla, así como bloqueo del teléfono o borrado de todos los datos si se introducen demasiadas contraseñas incorrectas"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Modificación de contraseña de bloqueo de pantalla"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Modificación de contraseña de bloqueo de pantalla"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Bloqueo de pantalla"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Control de la forma en que se bloquea la pantalla y del momento en que se bloquea"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Borrar todos los datos"</string>
-    <!-- outdated translation 2314060933796396205 -->     <string name="policydesc_wipeData" msgid="7669895333814222586">"Permite realizar un restablecimiento de fábrica eliminando todos los datos sin confirmación."</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Borrado de los datos del teléfono sin avisar restableciendo datos de fábrica"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Casa"</item>
     <item msgid="869923650527136615">"Móvil"</item>
@@ -610,10 +606,8 @@
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permite que la aplicación lea todas las URL que ha visitado el navegador y todos sus marcadores."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"escribir en marcadores y en el historial del navegador"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Permite que una aplicación modifique la información de los marcadores o del historial del navegador almacenada en el teléfono. Las aplicaciones malintencionadas pueden utilizar este permiso para borrar o modificar los datos del navegador."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"establecer alarma en un reloj"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Permite a la aplicación establecer una alarma en una aplicación de reloj instalada. Es posible que algunas aplicaciones de reloj no incluyan esta función."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modificar los permisos de ubicación geográfica del navegador"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permite que una aplicación modifique los permisos de ubicación geográfica del navegador. Las aplicaciones malintencionadas pueden utilizar este permiso para permitir el envío de información sobre la ubicación a sitios web arbitrarios."</string>
     <string name="save_password_message" msgid="767344687139195790">"¿Deseas que el navegador recuerde esta contraseña?"</string>
@@ -808,17 +802,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Mostrar todos"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"Almacenamiento USB masivo"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Conectado por USB"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Has conectado el teléfono al equipo mediante USB. Selecciona el botón situado debajo si deseas copiar archivos entre el equipo y la tarjeta SD del teléfono con Android."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Has conectado el teléfono al equipo mediante USB. Selecciona el botón situado debajo si deseas copiar archivos entre el equipo y el almacenamiento compartido del teléfono con Android."</string>
     <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Has conectado el teléfono al equipo mediante USB. Selecciona el botón situado debajo si deseas copiar archivos entre el equipo y la tarjeta SD del teléfono con Android."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Activar almacenamiento USB"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Se ha producido un problema al intentar utilizar la tarjeta SD para el almacenamiento USB."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Se ha producido un problema al intentar utilizar el almacenamiento compartido para el almacenamiento USB."</string>
     <string name="usb_storage_error_message" product="default" msgid="2534784751603345363">"Se ha producido un problema al intentar utilizar la tarjeta SD para el almacenamiento USB."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"Conectado por USB"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Para copiar archivos al/desde el equipo"</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Desactivar almacenamiento USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Seleccionar para desactivar USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"El almacenamiento USB está en uso."</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Antes de desactivar el almacenamiento USB, asegúrate de haber desmontado (\"retirado\") la tarjeta SD del teléfono con Android del equipo."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Antes de desactivar el almacenamiento USB, asegúrate de haber desactivado (\"extraído\") el almacenamiento compartido del teléfono con Android del equipo."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Antes de desactivar el almacenamiento USB, asegúrate de haber desmontado (\"retirado\") la tarjeta SD del teléfono con Android del equipo."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Desactivar almacenamiento USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Se ha producido un problema al desactivar el almacenamiento USB. Asegúrate de haber desactivado el host USB y, a continuación, vuelve a intentarlo."</string>
@@ -826,9 +820,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Si activas el almacenamiento USB, se detendrán algunas aplicaciones que estás utilizando y estas no estarán disponibles hasta que lo desactives."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"No se ha podido realizar la operación USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"Aceptar"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Formatear tarjeta SD"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Formateo almacenamiento compart"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatear tarjeta SD"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"¿Estás seguro de que quieres formatear la tarjeta SD? Se perderán todos los datos de la tarjeta."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"¿Quieres formatear el almacenamiento compartido y borrar todos los archivos? Esta acción no se puede deshacer."</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"¿Estás seguro de que quieres formatear la tarjeta SD? Se perderán todos los datos de la tarjeta."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formato"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Dispositivo de depuración USB conectado"</string>
@@ -837,28 +831,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Preparando tarjeta SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Preparando almacenam compart"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Preparando tarjeta SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Comprobando errores..."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Tarjeta SD vacía"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Almacenamiento compartido vacío"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Tarjeta SD vacía"</string>
-    <!-- outdated translation 1312266820092958014 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"La tarjeta SD está vacía o utiliza un sistema de archivos incompatible."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"Almacenamiento compartido vacío o con sistema de archivos no admitido"</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"La tarjeta SD está vacía o su sistema de archivos es incompatible."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Tarjeta SD dañada"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Almacenamiento compartido dañado"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Tarjeta SD dañada"</string>
-    <!-- outdated translation 2679412884290061775 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"La tarjeta SD está dañada. Es posible que sea necesario volver a formatearla."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"El almacenamiento compartido está dañado. Es posible que sea necesario volver a formatearlo."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"La tarjeta SD está dañada. Es posible que sea necesario volver a formatearla."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"La tarjeta SD se ha extraído inesperadamente."</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Almacenam comp extraído inesp"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"La tarjeta SD se ha extraído inesperadamente."</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Desactiva la tarjeta SD antes de extraerla para evitar la pérdida de datos."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Desactiva el almacenamiento compartido antes de extraerlo para evitar pérdidas de datos."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Desactiva la tarjeta SD antes de extraerla para evitar la pérdida de datos."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"Es seguro extraer la tarjeta SD."</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"Almac extraíble forma segura"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Es seguro extraer la tarjeta SD."</string>
-    <!-- outdated translation 7613960686747592770 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"Ya puedes extraer la tarjeta SD."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"Puedes extraer el almacenamiento compartido de forma segura."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Puedes extraer la tarjeta SD de forma segura."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Tarjeta SD extraída"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Almacenam compartido extraído"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Tarjeta SD extraída"</string>
-    <!-- outdated translation 4205117227342822275 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"La tarjeta SD se ha extraído. Inserta una nueva tarjeta SD para aumentar la capacidad de almacenamiento de tu dispositivo."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"Se ha extraído el almacenamiento compartido. Inserta un nuevo medio."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"La tarjeta SD se ha extraído. Inserta una nueva."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"No se ha encontrado ninguna actividad coincidente."</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"actualizar estadísticas de uso de componentes"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 3c567f4..cfa52ba 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -169,7 +169,7 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Outils de développement"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Ces fonctionnalités sont réservées aux développeurs d\'applications."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Stockage"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Accès à la carte SD"</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Accéder au stockage partagé"</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Accès à la carte SD"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"Désactivation ou modification de la barre d\'état"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Permet à une application de désactiver la barre d\'état ou d\'ajouter/supprimer des icônes système."</string>
@@ -403,22 +403,14 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Permet à une application de configurer le téléphone Bluetooth local, d\'identifier des périphériques distants et de les associer au téléphone."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"Création de connexions Bluetooth"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Permet à une application d\'obtenir la configuration du téléphone Bluetooth local et de créer et accepter des connexions à des appareils associés."</string>
-    <!-- no translation found for permlab_nfcAdmin (2251302233012250056) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcAdmin (1935842611464895785) -->
-    <skip />
-    <!-- no translation found for permlab_nfcRaw (4423471711114325708) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcRaw (5533022736559385665) -->
-    <skip />
-    <!-- no translation found for permlab_nfcNotify (478470360082792358) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcNotify (2990053517962070617) -->
-    <skip />
-    <!-- no translation found for permlab_nfcLlcp (4972051461007030426) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcLlcp (91592127786004640) -->
-    <skip />
+    <string name="permlab_nfcAdmin" msgid="2251302233012250056">"Administration NFC"</string>
+    <string name="permdesc_nfcAdmin" msgid="1935842611464895785">"Permet à une application de configurer le téléphone NFC local."</string>
+    <string name="permlab_nfcRaw" msgid="4423471711114325708">"Accès NFC complet à l\'appareil distant"</string>
+    <string name="permdesc_nfcRaw" msgid="5533022736559385665">"Permet à une application d\'accéder à des appareils NFC distants."</string>
+    <string name="permlab_nfcNotify" msgid="478470360082792358">"Notification NFC depuis un appareil distant"</string>
+    <string name="permdesc_nfcNotify" msgid="2990053517962070617">"Permet à une application d\'être avertie en cas d\'opérations sur des appareils NFC distants."</string>
+    <string name="permlab_nfcLlcp" msgid="4972051461007030426">"Notification NFC depuis un appareil distant LLCP"</string>
+    <string name="permdesc_nfcLlcp" msgid="91592127786004640">"Permet à une application d\'être avertie en cas d\'opérations LLCP sur des appareils NFC distants."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"Désactivation du verrouillage des touches"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Permet à une application de désactiver le verrouillage des touches et toute sécurité par mot de passe. Exemple : Votre téléphone désactive le verrouillage du clavier lorsque vous recevez un appel, puis le réactive lorsque vous raccrochez."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"Lecture des paramètres de synchronisation"</string>
@@ -435,22 +427,26 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Permet à une application de lire tous les mots, noms et expressions que l\'utilisateur a pu enregistrer dans son dictionnaire personnel."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"Enregistrement dans le dictionnaire défini par l\'utilisateur"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Permet à une application d\'enregistrer de nouveaux mots dans le dictionnaire personnel de l\'utilisateur."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"Modifier/supprimer le contenu de la carte SD"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"modifier/supprimer le contenu du stockage partagé"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"Modifier/supprimer le contenu de la carte SD"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Autorise une application à écrire sur la carte SD."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Autorise une application à écrire sur le stockage partagé."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Autorise une application à écrire sur la carte SD."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"accéder au système de fichiers en cache"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permet à une application de lire et d\'écrire dans le système de fichiers en cache."</string>
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Limiter le mot de passe"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Restreint les types de mots de passe que vous êtes autorisé à utiliser."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Surveiller les tentatives de connexion"</string>
-    <!-- outdated translation 1961251179624843483 -->     <string name="policydesc_watchLogin" msgid="7227578260165172673">"Surveille les échecs de connexion au périphérique pour effectuer une action."</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Réinitialiser le mot de passe"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Force l\'utilisation d\'un nouveau mot de passe, qui doit vous être communiqué par l\'administrateur pour que vous puissiez vous connecter."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Forcer le verrouillage"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Contrôle le verrouillage du périphérique, avec obligation de saisir à nouveau le mot de passe."</string>
+    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+    <skip />
+    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
+    <skip />
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Définir les règles du mot de passe"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Gérer le nombre et le type de caractères autorisés dans les mots de passe de déverrouillage de l\'écran"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Gérer les tentatives de déverrouillage de l\'écran"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Gérer le nombre de mots de passe incorrects saisis lors du déverrouillage de l\'écran et verrouiller le téléphone ou effacer toutes ses données après un certain nombre de tentatives"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Modifier le mot de passe de déverrouillage de l\'écran"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Modifier le mot de passe de déverrouillage de l\'écran"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Verrouiller l\'écran"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Gérer le mode et les conditions de verrouillage de l\'écran"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Effacer toutes les données"</string>
-    <!-- outdated translation 2314060933796396205 -->     <string name="policydesc_wipeData" msgid="7669895333814222586">"Rétablit les paramètres d\'usine, supprimant toutes vos données sans demande de confirmation."</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Effacer les données du téléphone sans avertissement, en restaurant les valeurs d\'usine"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Domicile"</item>
     <item msgid="869923650527136615">"Mobile"</item>
@@ -610,10 +606,8 @@
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Autorise l\'application à lire toutes les URL auxquelles le navigateur a accédé et tous ses favoris."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"écrire dans l\'historique et les favoris du navigateur"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Autorise une application à modifier l\'historique du navigateur ou les favoris enregistrés sur votre téléphone. Des applications malveillantes peuvent utiliser cette fonction pour effacer ou modifier les données de votre navigateur."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"régler le réveil"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Permet à l\'application de définir une alarme dans un utilitaire faisant office de réveil. Certains réveils risquent ne pas prendre en charge cette fonctionnalité."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modifier les autorisations de géolocalisation du navigateur"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permet à une application de modifier les autorisations de géolocalisation du navigateur. Les applications malveillantes peuvent se servir de cette fonctionnalité pour envoyer des informations de lieu à des sites Web arbitraires."</string>
     <string name="save_password_message" msgid="767344687139195790">"Voulez-vous que le navigateur se souvienne de ce mot de passe ?"</string>
@@ -808,17 +802,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Tout afficher"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"Stockage de masse USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Connecté à l\'aide d\'un câble USB"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Vous avez connecté votre téléphone à votre ordinateur à l\'aide d\'un câble USB. Sélectionnez le bouton ci-dessous pour copier des fichiers de votre ordinateur vers la carte SD de votre Android, ou inversement."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Vous avez connecté votre téléphone à votre ordinateur à l\'aide d\'un câble USB. Sélectionnez le bouton ci-dessous pour copier des fichiers de votre ordinateur vers le stockage partagé de votre Android, ou inversement."</string>
     <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Vous avez connecté votre téléphone à votre ordinateur à l\'aide d\'un câble USB. Sélectionnez le bouton ci-dessous pour copier des fichiers de votre ordinateur vers la carte SD de votre Android, ou inversement."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Activer le périphérique de stockage USB"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Un problème est survenu lors de l\'utilisation de votre carte SD en tant que périphérique de stockage USB."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Un problème est survenu lors de l\'utilisation de votre stockage partagé en tant que périphérique de stockage USB."</string>
     <string name="usb_storage_error_message" product="default" msgid="2534784751603345363">"Un problème est survenu lors de l\'utilisation de votre carte SD en tant que périphérique de stockage USB."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"Connecté avec un câble USB"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Activez pour copier des fichiers vers/de votre ordinateur."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Éteindre le périphérique de stockage USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Sélectionner pour éteindre le périphérique de stockage USB"</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"Stockage USB en cours d\'utilisation"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Avant de mettre hors tension le stockage USB, assurez-vous d\'avoir désactivé (\"éjecté\") la carte SD de votre téléphone Android à partir de votre ordinateur."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Avant de mettre hors tension le stockage USB, assurez-vous d\'avoir démonté (\"éjecté\") le stockage partagé de votre téléphone Android à partir de votre ordinateur."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Avant de mettre hors tension le stockage USB, assurez-vous d\'avoir désactivé (\"éjecté\") la carte SD de votre téléphone Android à partir de votre ordinateur."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Désactiver le périphérique de stockage USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Un problème est survenu lors de la mise hors tension du périphérique de stockage USB. Assurez-vous que l\'hôte USB a bien été désactivé, puis essayez à nouveau."</string>
@@ -826,9 +820,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Si vous activez le périphérique de stockage USB, certaines applications que vous utilisez se fermeront et risquent de n\'être de nouveau disponibles qu\'après la désactivation du périphérique."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Échec du fonctionnement USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Formater la carte SD"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Formater le stockage partagé"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formater la carte SD"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Voulez-vous vraiment formater la carte SD ? Toutes les données de cette carte seront perdues."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Formater le stockage partagé en effaçant tout le contenu ? Cette action est irréversible !"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Voulez-vous vraiment formater la carte SD ? Toutes les données de cette carte seront perdues."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Format"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Débogage USB connecté"</string>
@@ -837,28 +831,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidats"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Préparation de la carte SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Préparation du stockage partagé"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Préparation de la carte SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Recherche d\'erreurs"</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Carte SD vide"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Stockage partagé vide"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Carte SD vide"</string>
-    <!-- outdated translation 1312266820092958014 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"La carte SD est vide ou utilise un système de fichiers non pris en charge."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"Le stockage partagé est vide ou son système de fichiers n\'est pas pris en charge."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"La carte SD est vide ou son système de fichiers n\'est pas pris en charge."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Carte SD endommagée"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Stockage partagé endommagé"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Carte SD endommagée"</string>
-    <!-- outdated translation 2679412884290061775 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"La carte SD est endommagée. Vous devrez peut-être reformater votre carte."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"Le stockage partagé est endommagé. Vous devrez peut-être le reformater."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"La carte SD est endommagée. Vous devrez peut-être la reformater."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Carte SD retirée inopinément"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Stockage partagé retiré inopinément"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Carte SD retirée inopinément"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Désactiver la carte SD avant de la retirer pour éviter toute perte de données."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Démonter le stockage partagé avant de le retirer pour éviter toute perte de données."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Désactiver la carte SD avant de la retirer pour éviter toute perte de données."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"La carte SD peut être retirée en toute sécurité"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"Le stockage partagé peut être retiré en toute sécurité"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"La carte SD peut être retirée en toute sécurité"</string>
-    <!-- outdated translation 7613960686747592770 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"Vous pouvez désormais retirer la carte SD en toute sécurité."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"Vous pouvez retirer le stockage partagé en toute sécurité."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Vous pouvez retirer la carte SD en toute sécurité."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Carte SD manquante"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Stockage partagé retiré"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Carte SD manquante"</string>
-    <!-- outdated translation 4205117227342822275 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"Carte SD manquante. Insérez une autre carte pour augmenter la capacité de stockage."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"Stockage partagé retiré. Insérez un nouveau support."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"La carte SD a été retirée. Insérez-en une autre."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Aucune activité correspondante trouvée"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"mettre à jour les données statistiques du composant"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 4e8d19a..2e164bb8 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -169,7 +169,7 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Strumenti di sviluppo"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Funzionalità necessarie soltanto agli sviluppatori di applicazioni."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Archiviazione"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Accesso alla scheda SD."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Accesso all\'archivio condiviso."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Accesso alla scheda SD."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"disattivare o modificare la barra di stato"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Consente all\'applicazione di disattivare la barra di stato o di aggiungere e rimuovere icone di sistema."</string>
@@ -403,22 +403,14 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Consente a un\'applicazione di configurare il telefono Bluetooth locale e di rilevare e abbinare dispositivi remoti."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"creazione connessioni Bluetooth"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Consente a un\'applicazione di visualizzare la configurazione del telefono Bluetooth locale e di stabilire e accettare connessioni con dispositivi associati."</string>
-    <!-- no translation found for permlab_nfcAdmin (2251302233012250056) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcAdmin (1935842611464895785) -->
-    <skip />
-    <!-- no translation found for permlab_nfcRaw (4423471711114325708) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcRaw (5533022736559385665) -->
-    <skip />
-    <!-- no translation found for permlab_nfcNotify (478470360082792358) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcNotify (2990053517962070617) -->
-    <skip />
-    <!-- no translation found for permlab_nfcLlcp (4972051461007030426) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcLlcp (91592127786004640) -->
-    <skip />
+    <string name="permlab_nfcAdmin" msgid="2251302233012250056">"Gestione NFC"</string>
+    <string name="permdesc_nfcAdmin" msgid="1935842611464895785">"Consente a un\'applicazione di configurare il telefono NFC locale."</string>
+    <string name="permlab_nfcRaw" msgid="4423471711114325708">"Accesso completo NFC a dispositivo remoto"</string>
+    <string name="permdesc_nfcRaw" msgid="5533022736559385665">"Consente a un\'applicazione di accedere ai dispositivi NFC remoti."</string>
+    <string name="permlab_nfcNotify" msgid="478470360082792358">"Notifica NFC da dispositivo remoto"</string>
+    <string name="permdesc_nfcNotify" msgid="2990053517962070617">"Consente a un\'applicazione di ricevere notifiche su operazioni correlate ai dispositivi NFC."</string>
+    <string name="permlab_nfcLlcp" msgid="4972051461007030426">"Notifica NFC da dispositivo LLCP remoto"</string>
+    <string name="permdesc_nfcLlcp" msgid="91592127786004640">"Consente a un\'applicazione di ricevere notifiche su operazioni LLCP correlate ai dispositivi NFC."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"disattivazione blocco tastiera"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Consente la disattivazione da parte di un\'applicazione del blocco tastiera e di eventuali protezioni tramite password associate. Un valido esempio è la disattivazione da parte del telefono del blocco tastiera quando riceve una telefonata in entrata, e la successiva riattivazione del blocco al termine della chiamata."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"lettura impostazioni di sincronizz."</string>
@@ -435,22 +427,26 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Consente a un\'applicazione di leggere parole, nomi e frasi private che l\'utente potrebbe aver memorizzato nel dizionario utente."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"scrittura nel dizionario definito dall\'utente"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Consente a un\'applicazione di scrivere nuove parole nel dizionario utente."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"modificare/eliminare i contenuti della scheda SD"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"modifica/eliminaz. contenuti arch. cond."</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"modificare/eliminare i contenuti della scheda SD"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Consente a un\'applicazione di scrivere sulla scheda SD."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Consente a un\'applicazione di scrivere nell\'arch. cond."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Consente a un\'applicazione di scrivere sulla scheda SD."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"accesso al filesystem nella cache"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Consente a un\'applicazione di leggere e scrivere il filesystem nella cache."</string>
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Limita password"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Limita i tipi di password che sei autorizzato a utilizzare."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Controlla i tentativi di accesso"</string>
-    <!-- outdated translation 1961251179624843483 -->     <string name="policydesc_watchLogin" msgid="7227578260165172673">"Monitora i tentativi non riusciti di accedere al dispositivo per eseguire un\'azione."</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Reimposta password"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Forza un nuovo valore per la password, chiedendo all\'amministratore di concedertelo prima di poter eseguire l\'accesso."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Forza blocco"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Controlla quando il dispositivo si blocca, chiedendoti di reinserire la password."</string>
+    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+    <skip />
+    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
+    <skip />
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Imposta regole password"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Controlla la lunghezza e i caratteri ammessi nelle password di sblocco dello schermo"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Monitora tentativi di sblocco dello schermo"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Monitora il numero di password errate inserite durante lo sblocco dello schermo e blocca il telefono o cancella tutti i dati del telefono se vengono inserite troppe password errate"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Cambia la password di sblocco dello schermo"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Cambia la password di sblocco dello schermo"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Blocca lo schermo"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Controlla come e quando si blocca lo schermo"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Cancella tutti i dati"</string>
-    <!-- outdated translation 2314060933796396205 -->     <string name="policydesc_wipeData" msgid="7669895333814222586">"Esegui un ripristino di fabbrica, eliminando tutti i tuoi dati senza conferma."</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Cancella i dati del telefono senza preavviso eseguendo un ripristino dati di fabbrica"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Casa"</item>
     <item msgid="869923650527136615">"Cellulare"</item>
@@ -610,10 +606,8 @@
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Consente all\'applicazione di leggere tutti gli URL visitati e tutti i segnalibri del browser."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"creazione cronologia e segnalibri del browser"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Consente a un\'applicazione di modificare la cronologia o i segnalibri del browser memorizzati sul telefono. Le applicazioni dannose possono sfruttare questa possibilità per cancellare o modificare i dati del browser."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"impostazione allarmi nella sveglia"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Consente all\'applicazione di impostare un allarme in un\'applicazione sveglia installata. Alcune applicazioni sveglia potrebbero non supportare questa funzione."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modifica le autorizzazioni di localizzazione geografica del browser"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Consente a un\'applicazione di modificare le autorizzazioni di localizzazione geografica del browser. Le applicazioni dannose possono utilizzare questa autorizzazione per consentire l\'invio di informazioni sulla posizione a siti web arbitrari."</string>
     <string name="save_password_message" msgid="767344687139195790">"Memorizzare la password nel browser?"</string>
@@ -808,17 +802,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Mostra tutto"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"Archiviazione di massa USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB collegata"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Il telefono è stato collegato al computer tramite USB. Seleziona il pulsante sottostante se desideri copiare file tra il computer e la scheda SD di Android."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Il telefono è stato collegato al computer tramite USB. Seleziona il pulsante sottostante se desideri copiare file tra il computer e l\'archivio condiviso di Android."</string>
     <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Il telefono è stato collegato al computer tramite USB. Seleziona il pulsante sottostante se desideri copiare file tra il computer e la scheda SD di Android."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Attiva archivio USB"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Problema di utilizzo della scheda SD per l\'archiviazione USB."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Problema di utilizzo dell\'archivio condiviso per l\'archiviazione USB."</string>
     <string name="usb_storage_error_message" product="default" msgid="2534784751603345363">"Problema di utilizzo della scheda SD per l\'archiviazione USB."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB collegata"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Seleziona per copiare file sul/dal tuo computer."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Disattiva archivio USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Seleziona per disattivare archivio USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"Archiviazione USB in uso"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Prima di disattivare l\'archiviazione USB, assicurati di avere smontato (\"espulso\") la scheda SD di Android dal computer."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Prima di disattivare l\'archiviazione USB, assicurati di avere smontato (\"espulso\") l\'archivio condiviso di Android dal computer."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Prima di disattivare l\'archiviazione USB, assicurati di avere smontato (\"espulso\") la scheda SD di Android dal computer."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Disattiva archiviazione USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Si è verificato un problema durante la disattivazione dell\'archiviazione USB. Verifica di avere smontato l\'host USB e riprova."</string>
@@ -826,9 +820,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Se attivi l\'archivio USB, alcune applicazioni in uso si bloccheranno e potrebbero risultare non disponibili finché non disattiverai l\'archivio USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Operazione USB non riuscita"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Formatta scheda SD"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Formatta archivio cond."</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatta scheda SD"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Formattare la scheda SD? Tutti i dati sulla scheda verranno persi."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Formattare l\'archivio condiviso cancellando tutti i file memorizzati al suo interno? Questa azione è irreversibile."</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Formattare la scheda SD? Tutti i dati sulla scheda verranno persi."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formatta"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Debug USB collegato"</string>
@@ -837,28 +831,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidati"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Preparazione scheda SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Preparazione archivio condiviso"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Preparazione scheda SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Ricerca errori."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Scheda SD vuota"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Archivio condiviso vuoto"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Scheda SD vuota"</string>
-    <!-- outdated translation 1312266820092958014 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"La scheda SD è vuota o utilizza un file system non supportato."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"Archivio condiviso vuoto o con filesystem non supportato."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Scheda SD vuota o con filesystem non supportato."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Scheda SD danneggiata"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Archivio condiviso danneggiato"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Scheda SD danneggiata"</string>
-    <!-- outdated translation 2679412884290061775 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"La scheda SD è danneggiata. Potrebbe essere necessario riformattarla."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"Archivio condiviso danneggiato. Potrebbe essere necessario riformattarlo."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Scheda SD danneggiata. Potrebbe essere necessario riformattarla."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Rimozione imprevista della scheda SD"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Rimozione inaspettata archivio cond."</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Rimozione imprevista della scheda SD"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Smonta scheda SD prima della rimozione per evitare la perdita di dati."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Smonta l\'archivio condiviso prima della rimozione per evitare la perdita di dati."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Smonta scheda SD prima della rimozione per evitare la perdita di dati."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"È possibile rimuovere la scheda SD"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"Puoi rimuovere l\'archivio cond."</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"È possibile rimuovere la scheda SD"</string>
-    <!-- outdated translation 7613960686747592770 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"È ora possibile rimuovere la scheda SD in modo sicuro."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"Puoi rimuovere l\'archivio condiviso in tutta sicurezza."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Puoi rimuovere la scheda SD in tutta sicurezza."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Scheda SD rimossa"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Archivio condiviso rimosso"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Scheda SD rimossa"</string>
-    <!-- outdated translation 4205117227342822275 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"Inserisci una nuova scheda SD per aumentare la memoria del dispositivo."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"Archivio condiviso rimosso. Inserisci un nuovo supporto."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Scheda SD rimossa. Inseriscine un\'altra."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Nessuna attività corrispondente trovata"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"aggiornare le statistiche di utilizzo dei componenti"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index a4d07a8..ee6fcc1 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -169,7 +169,7 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"開発ツール"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"アプリケーションのデベロッパーにのみ必要な機能です。"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"ストレージ"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"SDカードにアクセスします。"</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"共有ストレージへのアクセス"</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"SDカードにアクセスします。"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"ステータスバーの無効化や変更"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"ステータスバーの無効化やシステムアイコンの追加や削除をアプリケーションに許可します。"</string>
@@ -403,22 +403,14 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"このBluetooth端末の設定、およびリモート端末を検出してペアに設定することをアプリケーションに許可します。"</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"Bluetooth接続の作成"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"このBluetooth端末の設定表示、および別の端末をペアとして設定し接続を承認することをアプリケーションに許可します。"</string>
-    <!-- no translation found for permlab_nfcAdmin (2251302233012250056) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcAdmin (1935842611464895785) -->
-    <skip />
-    <!-- no translation found for permlab_nfcRaw (4423471711114325708) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcRaw (5533022736559385665) -->
-    <skip />
-    <!-- no translation found for permlab_nfcNotify (478470360082792358) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcNotify (2990053517962070617) -->
-    <skip />
-    <!-- no translation found for permlab_nfcLlcp (4972051461007030426) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcLlcp (91592127786004640) -->
-    <skip />
+    <string name="permlab_nfcAdmin" msgid="2251302233012250056">"NFCの管理"</string>
+    <string name="permdesc_nfcAdmin" msgid="1935842611464895785">"ローカルNFC端末の設定をアプリケーションに許可します。"</string>
+    <string name="permlab_nfcRaw" msgid="4423471711114325708">"リモートデバイスへのNFCフルアクセス"</string>
+    <string name="permdesc_nfcRaw" msgid="5533022736559385665">"リモートNFCデバイスへのアクセスをアプリケーションに許可します。"</string>
+    <string name="permlab_nfcNotify" msgid="478470360082792358">"リモートデバイスからのNFC通知"</string>
+    <string name="permdesc_nfcNotify" msgid="2990053517962070617">"リモートNFCデバイスに関連する処理の通知を受けることをアプリケーションに許可します。"</string>
+    <string name="permlab_nfcLlcp" msgid="4972051461007030426">"リモートLLCPデバイスからのNFC通知"</string>
+    <string name="permdesc_nfcLlcp" msgid="91592127786004640">"リモートNFCデバイスに関連するLLCP処理の通知を受けることをアプリケーションに許可します。"</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"キーロックを無効にする"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"キーロックや関連するパスワードセキュリティを無効にすることをアプリケーションに許可します。正当な利用の例では、かかってきた電話を受信する際にキーロックを無効にし、通話の終了時にキーロックを有効にし直します。"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"同期設定の読み取り"</string>
@@ -435,22 +427,26 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"アプリケーションが単語リストに登録されている個人的な語句や名前を読み込むことを許可します。"</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"単語リストへの書き込み"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"アプリケーションが単語リストに新しい語句を書き込むことを許可します。"</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"SDカードのコンテンツを修正/削除する"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"共有ストレージのコンテンツの変更/削除"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"SDカードのコンテンツを修正/削除する"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"SDカードへの書き込みをアプリケーションに許可します。"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"共有ストレージへの書き込みをアプリケーションに許可します。"</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"SDカードへの書き込みをアプリケーションに許可します。"</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"キャッシュファイルシステムにアクセス"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"キャッシュファイルシステムへの読み書きをアプリケーションに許可します。"</string>
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"パスワードの制限"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"使用できるパスワードの種類を制限します。"</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"ログインの監視"</string>
-    <!-- outdated translation 1961251179624843483 -->     <string name="policydesc_watchLogin" msgid="7227578260165172673">"携帯電話へのログインの失敗を監視し、何らかの処置をとります。"</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"パスワードのリセット"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"パスワードを強制的に新しい値に変更します。ログインするには管理者からその値を通知してもらう必要があります。"</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"強制ロック"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"携帯電話のロック時を管理します。パスワードの再入力が必要となります。"</string>
+    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+    <skip />
+    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
+    <skip />
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"パスワードルールの設定"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"画面ロック解除パスワードの長さと使用できる文字数を制御する"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"画面ロック解除試行の監視"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"画面ロック解除のために入力されたパスワードが間違っていた回数を監視し、回数が多すぎる場合は端末をロックするか、端末内のデータをすべて削除します。"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"画面ロック解除パスワードの変更"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"画面ロック解除パスワードの変更"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"画面のロック"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"画面をロックする方法とタイミングを制御する"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"すべてのデータを消去"</string>
-    <!-- outdated translation 2314060933796396205 -->     <string name="policydesc_wipeData" msgid="7669895333814222586">"出荷時設定にリセットします。確認なしでデータがすべて削除されます。"</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"警告せずにデータの初期化を実行して端末内のデータを消去します。"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"自宅"</item>
     <item msgid="869923650527136615">"携帯"</item>
@@ -610,10 +606,8 @@
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"ブラウザでアクセスしたすべてのURLおよびブラウザのすべてのブックマークの読み取りをアプリケーションに許可します。"</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"ブラウザの履歴とブックマークを書き込む"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"携帯電話に保存されているブラウザの履歴やブックマークの修正をアプリケーショに許可します。これにより悪意のあるアプリケーションが、ブラウザのデータを消去または変更する恐れがあります。"</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"アラームの設定"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"インストール済みアラームアプリケーションのアラーム設定をアプリケーションに許可します。この機能が実装されていないアラームアプリケーションもあります。"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"ブラウザの位置情報へのアクセス権を変更"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"ブラウザの位置情報に対するアクセス権の変更をアプリケーションに許可します。この設定では、悪意のあるアプリケーションが任意のウェブサイトに位置情報を送信する可能性があります。"</string>
     <string name="save_password_message" msgid="767344687139195790">"このパスワードをブラウザで保存しますか?"</string>
@@ -808,17 +802,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"すべて表示"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USBマスストレージ"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB接続"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"携帯電話をUSBでパソコンに接続しています。パソコンとAndroidのSDカード間でファイルをコピーするには、下のボタンを選択します。"</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"携帯端末をUSBでパソコンに接続しています。パソコンとAndroidの共有ストレージ間でファイルをコピーするには、下のボタンを選択します。"</string>
     <string name="usb_storage_message" product="default" msgid="4796759646167247178">"携帯電話をUSBでパソコンに接続しています。パソコンとAndroidのSDカード間でファイルをコピーするには、下のボタンを選択します。"</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"USBストレージをONにする"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"USBメモリにSDカードを使用する際に問題が発生しました。"</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"共有ストレージをUSBストレージとして使用する際に問題が発生しました。"</string>
     <string name="usb_storage_error_message" product="default" msgid="2534784751603345363">"USBメモリにSDカードを使用する際に問題が発生しました。"</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB接続"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"パソコンとの間でファイルをコピーします。"</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"USBストレージをOFFにする"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"USBストレージをOFFにする場合に選択します。"</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USBストレージを使用中"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"USBストレージをOFFにする前に、パソコンで必ずAndroidのSDカードのマウントを解除して(カードを取り出して)ください。"</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"USBストレージをOFFにする前に、パソコンで必ずAndroidの共有ストレージのマウントを解除して(ストレージを取り出して)ください。"</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"USBストレージをOFFにする前に、パソコンで必ずAndroidのSDカードのマウントを解除して(カードを取り出して)ください。"</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"USBストレージをOFFにする"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"USBストレージをOFFにする際に問題が発生しました。USBホストのマウントが解除されていることを確認してからもう一度お試しください。"</string>
@@ -826,9 +820,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"USBストレージをONにすると、使用中のアプリケーションの一部が停止し、USBストレージをOFFにするまで使用できなくなる場合があります。"</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB操作に失敗しました"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"SDカードをフォーマット"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"共有ストレージのフォーマット"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SDカードをフォーマット"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"SDカードをフォーマットしてもよろしいですか?カード内のすべてのデータが失われます。"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"共有ストレージをフォーマットして、保存されているすべてのファイルを消去しますか?この操作は元に戻せません。"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"SDカードをフォーマットしてもよろしいですか?カード内のすべてのデータが失われます。"</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"フォーマット"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USBデバッグが接続されました"</string>
@@ -837,28 +831,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"候補"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"SDカードの準備中"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"共有ストレージの準備中"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"SDカードの準備中"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"エラーを確認しています。"</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"空のSDカード"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"共有ストレージが空です"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"空のSDカード"</string>
-    <!-- outdated translation 1312266820092958014 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"SDカードが空か、サポート対象外のファイルシステムを使用しています。"</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"共有ストレージが空であるか、サポートされていないファイルシステムを使用しています。"</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SDカードが空か、サポート対象外のファイルシステムを使用しています。"</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"破損したSDカード"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"共有ストレージが破損しています"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"破損したSDカード"</string>
-    <!-- outdated translation 2679412884290061775 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"SDカードが破損しています。カードのフォーマットが必要な可能性があります。"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"共有ストレージが破損しています。ストレージの再フォーマットが必要な可能性があります。"</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SDカードが破損しています。カードのフォーマットが必要な可能性があります。"</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"SDカードが予期せず取り外されました"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"共有ストレージが不適切に取り外されました"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SDカードが予期せず取り外されました"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"データの喪失を防ぐためSDカードを取り外す前にマウントを解除してください。"</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"データの喪失を防ぐため共有ストレージを取り外す前にマウントを解除してください。"</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"データの喪失を防ぐためSDカードを取り外す前にマウントを解除してください。"</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"SDカードを安全に取り外しました"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"共有ストレージの安全な取り外し"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"SDカードを安全に取り外しました"</string>
-    <!-- outdated translation 7613960686747592770 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"SDカードを安全に取り外せます。"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"共有ストレージを安全に取り外せます。"</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"SDカードは安全に取り外せます。"</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"SDカードが取り外されています"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"共有ストレージが取り外されています"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"SDカードが取り外されています"</string>
-    <!-- outdated translation 4205117227342822275 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"SDカードがありません。メモリを使用する際はカードを挿入してください。"</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"共有ストレージが取り外されています。新しいメディアを挿入してください。"</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SDカードが取り外されました。新しいカードを挿入してください。"</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"一致するアクティビティが見つかりません"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"コンポーネント使用状況に関する統計情報の更新"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 56495d6f..48098bc 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -169,7 +169,7 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"개발 도구"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"애플리케이션 개발자에게만 필요한 기능입니다."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"저장"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"SD 카드에 액세스합니다."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"공유 저장용량에 액세스합니다."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"SD 카드에 액세스합니다."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"상태 표시줄 사용 중지 또는 수정"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"애플리케이션이 상태 표시줄을 사용 중지하거나 시스템 아이콘을 추가 및 제거할 수 있도록 합니다."</string>
@@ -403,22 +403,14 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"애플리케이션이 로컬 Bluetooth 휴대전화를 구성한 다음 원격 장치를 검색하여 페어링할 수 있도록 합니다."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"Bluetooth 연결 만들기"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"애플리케이션이 로컬 Bluetooth 전화의 구성을 보고 페어링된 장치에 연결하며 연결을 수락할 수 있도록 합니다."</string>
-    <!-- no translation found for permlab_nfcAdmin (2251302233012250056) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcAdmin (1935842611464895785) -->
-    <skip />
-    <!-- no translation found for permlab_nfcRaw (4423471711114325708) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcRaw (5533022736559385665) -->
-    <skip />
-    <!-- no translation found for permlab_nfcNotify (478470360082792358) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcNotify (2990053517962070617) -->
-    <skip />
-    <!-- no translation found for permlab_nfcLlcp (4972051461007030426) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcLlcp (91592127786004640) -->
-    <skip />
+    <string name="permlab_nfcAdmin" msgid="2251302233012250056">"NFC 관리"</string>
+    <string name="permdesc_nfcAdmin" msgid="1935842611464895785">"애플리케이션이 로컬 NFC 휴대전화를 구성할 수 있도록 합니다."</string>
+    <string name="permlab_nfcRaw" msgid="4423471711114325708">"원격 기기에 대한 NFC 전체 액세스 권한"</string>
+    <string name="permdesc_nfcRaw" msgid="5533022736559385665">"애플리케이션이 원격 NFC 기기에 액세스할 수 있도록 합니다."</string>
+    <string name="permlab_nfcNotify" msgid="478470360082792358">"원격 기기의 NFC 알림"</string>
+    <string name="permdesc_nfcNotify" msgid="2990053517962070617">"원격 NFC 기기 관련 작업에 대한 알림이 애플리케이션에 전달되도록 합니다."</string>
+    <string name="permlab_nfcLlcp" msgid="4972051461007030426">"원격 LLCP 기기의 NFC 알림"</string>
+    <string name="permdesc_nfcLlcp" msgid="91592127786004640">"원격 NFC 기기 관련 LLCP 작업에 대한 알림이 애플리케이션에 전달되도록 합니다."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"키 잠금 사용 중지"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"애플리케이션이 키 잠금 및 관련 비밀번호 보안을 사용 중지할 수 있도록 합니다. 예를 들어, 휴대전화가 수신전화를 받을 때 키 잠금을 사용 중지했다가 통화가 끝나면 키 잠금을 다시 사용할 수 있습니다."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"동기화 설정 읽기"</string>
@@ -435,22 +427,26 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"애플리케이션이 사용자 사전에 보관되어 있는 비공개 단어, 이름 및 구문을 읽도록 합니다."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"사용자정의 사전에 작성"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"애플리케이션이 사용자 사전에 새 단어를 입력할 수 있도록 합니다."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"SD 카드 콘텐츠 수정/삭제"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"공유 저장용량 콘텐츠 수정/삭제"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"SD 카드 콘텐츠 수정/삭제"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"애플리케이션이 SD 카드에 쓸 수 있도록 합니다."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"애플리케이션이 공유 저장용량에 쓸 수 있도록 합니다."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"애플리케이션이 SD 카드에 쓸 수 있도록 합니다."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"캐시 파일시스템 액세스"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"애플리케이션이 캐시 파일시스템을 읽고 쓸 수 있도록 합니다."</string>
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"비밀번호 제한"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"사용할 수 있는 비밀번호 유형을 제한합니다."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"로그인 시도 보기"</string>
-    <!-- outdated translation 1961251179624843483 -->     <string name="policydesc_watchLogin" msgid="7227578260165172673">"몇 가지 작업을 수행하기 위해 기기에 대해 실패한 로그인 시도를 모니터링합니다."</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"비밀번호 재설정"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"비밀번호를 새 값으로 강제 설정합니다. 이를 수행하려면 로그인하기 전에 관리자에게 새로 지정할 비밀번호 값을 요청해야 합니다."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"강제 잠금"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"기기가 잠겨 있을 때 작동하려면 비밀번호를 다시 입력해야 합니다."</string>
+    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+    <skip />
+    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
+    <skip />
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"비밀번호 규칙 설정"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"화면 잠금해제 비밀번호에 허용되는 길이 및 문자 수를 제어합니다."</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"화면 잠금해제 시도 모니터링"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"화면 잠금해제 시 비밀번호를 잘못 입력한 횟수를 모니터링하고, 잘못된 비밀번호 입력 횟수가 너무 많은 경우 휴대전화를 잠그거나 휴대전화에 있는 데이터를 모두 지웁니다."</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"화면 잠금해제 비밀번호를 변경합니다."</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"화면 잠금해제 비밀번호를 변경합니다."</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"화면 잠금"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"화면을 잠그는 방법과 시기를 제어합니다."</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"모든 데이터 삭제"</string>
-    <!-- outdated translation 2314060933796396205 -->     <string name="policydesc_wipeData" msgid="7669895333814222586">"초기화를 수행하여 모든 데이터를 확인하지 않고 삭제합니다."</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"초기화를 수행하여 경고 없이 휴대전화 데이터를 지웁니다."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"집"</item>
     <item msgid="869923650527136615">"모바일"</item>
@@ -610,10 +606,8 @@
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"애플리케이션이 브라우저로 방문한 모든 URL과 브라우저의 모든 북마크를 읽도록 허용합니다."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"브라우저의 기록 및 북마크 쓰기"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"애플리케이션이 휴대전화에 저장된 브라우저 기록 또는 북마크를 수정할 수 있도록 허용합니다. 이 경우 악성 애플리케이션이 브라우저의 데이터를 지우거나 수정할 수 있습니다."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"알람 시계에 알람 설정"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"실치된 알람 시계 애플리케이션에 알람을 설정하도록 허용합니다. 일부 알람 시계 애플리케이션은 이 기능을 구현하지 않을 수 있습니다."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"브라우저 위치 정보 수정 권한"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"애플리케이션이 브라우저의 위치 정보 권한을 수정할 수 있도록 합니다. 악성 애플리케이션이 이를 사용하여 임의의 웹사이트에 위치 정보를 보낼 수도 있습니다."</string>
     <string name="save_password_message" msgid="767344687139195790">"브라우저에 이 비밀번호를 저장하시겠습니까?"</string>
@@ -808,17 +802,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"모두 표시"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB 대용량 저장소"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB 연결됨"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"USB를 통해 휴대전화를 컴퓨터에 연결했습니다. 컴퓨터와 Android의 SD 카드 간에 파일을 복사하려면 아래의 버튼을 선택하세요."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"USB를 통해 휴대전화를 컴퓨터에 연결했습니다. 컴퓨터와 Android의 공유 저장용량 간에 파일을 복사하려면 아래의 버튼을 선택하세요."</string>
     <string name="usb_storage_message" product="default" msgid="4796759646167247178">"USB를 통해 휴대전화를 컴퓨터에 연결했습니다. 컴퓨터와 Android의 SD 카드 간에 파일을 복사하려면 아래의 버튼을 선택하세요."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"USB 저장소 사용"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"USB 저장소로 SD 카드를 사용하는 동안 문제가 발생했습니다."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"USB 저장소로 공유 저장용량을 사용하는 동안 문제가 발생했습니다."</string>
     <string name="usb_storage_error_message" product="default" msgid="2534784751603345363">"USB 저장소로 SD 카드를 사용하는 동안 문제가 발생했습니다."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB 연결됨"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"컴퓨터에 파일을 복사하거나 컴퓨터의 파일을 복사하려면 선택합니다."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"USB 저장소 끄기"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"USB 저장소 끄기를 선택하세요."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB 저장소 사용 중"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"USB 저장소를 사용하지 않도록 설정하기 전에 컴퓨터에서 Android의 SD 카드를 마운트 해제했는지(꺼냈는지) 확인하시기 바랍니다."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"USB 저장소를 사용하지 않도록 설정하기 전에 컴퓨터에서 Android의 공유 저장용량을 마운트 해제했는지(꺼냈는지) 확인하시기 바랍니다."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"USB 저장소를 사용하지 않도록 설정하기 전에 컴퓨터에서 Android의 SD 카드를 마운트 해제했는지(꺼냈는지) 확인하시기 바랍니다."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"USB 저장소 사용 안함"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"USB 저장소를 사용하지 않도록 설정하는 동안 문제가 발생했습니다. USB 호스트와 연결을 해제했는지 확인한 다음 다시 시도하세요."</string>
@@ -826,9 +820,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"USB 저장소를 사용 설정하면 사용 중인 일부 애플리케이션이 중지되고 USB 저장소를 사용 중지할 때까지 사용할 수 없게 됩니다."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB 작업 실패"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"확인"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"SD 카드 포맷"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"공유 저장용량 포맷"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD 카드 포맷"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"SD 카드를 포맷하시겠습니까? 포맷하면 카드의 모든 데이터를 잃게 됩니다."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"공유 저장용량을 포맷하여 저장된 파일을 모두 지우시겠습니까? 실행취소할 수 없는 작업입니다."</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"SD 카드를 포맷하시겠습니까? 포맷하면 카드의 모든 데이터를 잃게 됩니다."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"포맷"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB 디버깅 연결됨"</string>
@@ -837,28 +831,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"가능한 원인"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"SD 카드 준비 중"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"공유 저장용량 준비 중"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"SD 카드 준비 중"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"오류 확인 중입니다."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"빈 SD 카드"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"공유 저장용량 비어 있음"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"빈 SD 카드"</string>
-    <!-- outdated translation 1312266820092958014 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"SD 카드가 비어 있거나 지원되지 않는 파일시스템을 사용 중입니다."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"공유 저장용량이 비어 있거나 지원되지 않는 파일 시스템을 사용합니다."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD 카드가 비어 있거나 지원되지 않는 파일 시스템을 사용합니다."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"손상된 SD 카드"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"공유 저장용량 손상됨"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"손상된 SD 카드"</string>
-    <!-- outdated translation 2679412884290061775 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"SD 카드가 손상되었습니다. 카드를 다시 포맷하시기 바랍니다."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"공유 저장용량이 손상되었습니다. 다시 포맷해야 할 수도 있습니다."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD 카드가 손상되었습니다. 카드를 다시 포맷해야 할 수 있습니다."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"SD 카드가 예상치 않게 제거되었습니다."</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"공유 저장용량이 예기치 못하게 제거됨"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD 카드가 예상치 않게 제거되었습니다."</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"데이터 손실을 피하려면 SD 카드를 제거하기 전에 마운트 해제합니다."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"데이터 손실을 피하려면 공유 저장용량을 제거하기 전에 마운트 해제합니다."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"데이터 손실을 피하려면 SD 카드를 제거하기 전에 마운트 해제합니다."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"SD 카드 제거 가능"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"공유 저장용량 안전하게 제거"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"SD 카드 제거 가능"</string>
-    <!-- outdated translation 7613960686747592770 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"이제 SD 카드를 안전하게 제거할 수 있습니다."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"공유 저장용량을 안전하게 제거할 수 있습니다."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"안전하게 SD 카드를 제거할 수 있습니다."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"SD 카드 없음"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"공유 저장용량 분리함"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"SD 카드 없음"</string>
-    <!-- outdated translation 4205117227342822275 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"SD가 제거되었습니다. 기기의 저장 용량을 늘리려면 새 SD 카드를 삽입하세요."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"공유 저장용량을 제거했습니다. 새 미디어를 삽입하세요."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD 카드가 없습니다.  SD 카드를 넣으세요."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"일치하는 활동이 없습니다."</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"구성 요소 사용 통계 업데이트"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 375e592..7529cc4 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -169,7 +169,7 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Utviklingsverktøy"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Funksjonalitet kun utviklere trenger."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Lagring"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Tilgang til minnekortet."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Tilgang til delt lagring."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Tilgang til minnekortet."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"deaktivere eller endre statusfeltet"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Lar applikasjonen deaktivere statusfeltet, samt legge til og fjerne systemikoner."</string>
@@ -403,22 +403,14 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Lar applikasjonen konfigurere den lokale Bluetooth-telefonen, og å oppdage og pare med andre enheter."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"opprette Bluetooth-tilkoblinger"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Lar applikasjonen se konfigurasjonen til den lokale Bluetooth-telefonen, og å opprette og godta tilkoblinger med parede enheter."</string>
-    <!-- no translation found for permlab_nfcAdmin (2251302233012250056) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcAdmin (1935842611464895785) -->
-    <skip />
-    <!-- no translation found for permlab_nfcRaw (4423471711114325708) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcRaw (5533022736559385665) -->
-    <skip />
-    <!-- no translation found for permlab_nfcNotify (478470360082792358) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcNotify (2990053517962070617) -->
-    <skip />
-    <!-- no translation found for permlab_nfcLlcp (4972051461007030426) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcLlcp (91592127786004640) -->
-    <skip />
+    <string name="permlab_nfcAdmin" msgid="2251302233012250056">"NFC-administrasjon"</string>
+    <string name="permdesc_nfcAdmin" msgid="1935842611464895785">"Tillater et program å konfigurere lokal NFC-telefon."</string>
+    <string name="permlab_nfcRaw" msgid="4423471711114325708">"NFC full tilgang til ekstern enhet"</string>
+    <string name="permdesc_nfcRaw" msgid="5533022736559385665">"Tillater et program å få tilgang til eksterne NFC-enheter."</string>
+    <string name="permlab_nfcNotify" msgid="478470360082792358">"NFC varsel fra ekstern enhet"</string>
+    <string name="permdesc_nfcNotify" msgid="2990053517962070617">"Tillater et program å bli varslet om operasjoner knyttet til eksterne NFC-enheter."</string>
+    <string name="permlab_nfcLlcp" msgid="4972051461007030426">"NFC varsel fra ekstern LLCP-enhet"</string>
+    <string name="permdesc_nfcLlcp" msgid="91592127786004640">"Tillater et program å bli varslet om LLCP-operasjoner knyttet til eksterne NFC-enheter."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"slå av tastaturlås"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Lar applikasjonen slå av tastaturlåsen og enhver tilknyttet passordsikkerhet. Et legitimt eksempel på dette er at telefonen slår av tastaturlåsen når den mottar et innkommende anrop, og så slår den på igjen når samtalen er over."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"lese synkroniseringsinnstillinger"</string>
@@ -435,22 +427,26 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Lar applikasjonen lese private ord, navn og uttrykk som brukeren har lagret i den brukerdefinerte ordlisten."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"skrive til brukerdefinert ordliste"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Lar applikasjonen skrive nye ord til den brukerdefinerte ordlisten."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"redigere/slette innhold på minnekort"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"endre/slette innh. i delt lagr."</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"redigere/slette innhold på minnekort"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Lar applikasjonen skrive til minnekortet."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Prog. skriver til delt lagr."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Lar applikasjonen skrive til minnekortet."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"tilgang til bufrede filer"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Tillater et program å lese og skrive til bufrede filer."</string>
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Begrens passord"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Begrense typene passord du kan bruke."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Overvåk påloggingsforsøk"</string>
-    <!-- outdated translation 1961251179624843483 -->     <string name="policydesc_watchLogin" msgid="7227578260165172673">"Overvåk mislykkede påloggingsforsøk eller forsøk på handlinger på enheten."</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Tilbakestill passordet"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Fremtving tilbakestilling av passord, slik at administratoren må gi deg et nytt passord når du skal logge deg på."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Obligatorisk låsing"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Kontrollerer når enheten låses. Du må skrive inn passordet på nytt for å låse den opp."</string>
+    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+    <skip />
+    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
+    <skip />
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Angi passordregler"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Kontroller tillatt lengde og tegn i passord for opplåsing av skjerm"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Overvåk forsøk på opplåsing av skjerm"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Overvåk antall feil passordforsøk ved opplåsing av skjerm. Lås telefonen eller slett alle data ved for mange feil passordforsøk"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Endre passord for opplåsing av skjerm"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Endre passord for opplåsing av skjerm"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Lås skjermen"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Kontroller hvordan og når skjermen låses"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Slett alle data"</string>
-    <!-- outdated translation 2314060933796396205 -->     <string name="policydesc_wipeData" msgid="7669895333814222586">"Utfører tilbakestilling til fabrikkstandard. Alle data slettes uten varsel."</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Tilbakestill telefonens data uten advarsel ved å utføre tilbakestilling til fabrikkstandard"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Hjemmenummer"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -610,10 +606,8 @@
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Lar applikasjonen lese alle adresser nettleseren har besøkt, og alle nettleserens bokmerker."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"skrive til nettleserens logg og bokmerker"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Lar applikasjonen endre nettleserens logg og bokmerker lagret på telefonen. Ondsinnede applikasjoner kan bruke dette til å fjerne eller redigere nettleserens data."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"angi alarm i alarmklokke"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Lar programmet angi en alarm i et installert alarmklokkeprogram. Det kan hende at enkelte alarmklokkeprogrammer ikke implementerer denne funksjonen."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Endre nettleserens tillatelser for geografisk posisjonering"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Tillater programmet å endre nettleserens tillatelser for geografisk posisjonering. Skadelige programmer kan bruke denne funksjonen til å sende posisjonsopplysninger til vilkårlige nettsteder."</string>
     <string name="save_password_message" msgid="767344687139195790">"Ønsker du at nettleseren skal huske dette passordet?"</string>
@@ -808,17 +802,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Vis alle"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB-masselagring"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB koblet til"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Du har koblet telefonen til datamaskinen via USB. Velg knappen nedenfor hvis du vil kopiere filer mellom datamaskinen og minnekortet i telefonen."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Du har koblet telefonen til datamaskinen via USB. Velg knappen nedenfor hvis du vil kopiere filer mellom datamaskinen og delt lagring for Android."</string>
     <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Du har koblet telefonen til datamaskinen via USB. Velg knappen nedenfor hvis du vil kopiere filer mellom datamaskinen og minnekortet i telefonen."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Slå på USB-lagring"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Det oppsto et problem med å bruke minnekortet ditt for USB-lagring."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Det oppstod et problem under delt lagring for USB-enheten."</string>
     <string name="usb_storage_error_message" product="default" msgid="2534784751603345363">"Det oppsto et problem med å bruke minnekortet ditt for USB-lagring."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB tilkoblet"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Velg om du ønsker å kopiere filer til/fra en datamaskin."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Slå av USB-lagring"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Velg for å slå av USB-lagring."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB-lagring er i bruk"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Før du slår av USB-lagring, sjekk at du har avmontert telefonen på datamaskinen."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Før du slår av USB-lagring, må du kontrollere at du har koblet fra den delte lagringsenheten for Android fra datamaskinen."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Før du slår av USB-lagring, sjekk at du har avmontert telefonen på datamaskinen."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Slå av USB-lagring"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Det oppstod et problem ved deaktivering av USB-lagring. Kontroller at du har demontert USB-verten, og prøv på nytt."</string>
@@ -826,9 +820,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Hvis du aktiverer USB-lagring, virker ikke lenger enkelte av programmene du bruker, og de kan være utilgjengelige inntil du deaktiverer USB-lagringen."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB-operasjonen mislyktes"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Formatere minnekort"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Formatér delt lagr."</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatere minnekort"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Er du sikker på at du ønsker å formatere minnekortet? Alle data på kortet vil gå tapt."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Vil du formatere delt lagring og slette alle lagrede filer? Handlingen kan ikke angres!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Er du sikker på at du ønsker å formatere minnekortet? Alle data på kortet vil gå tapt."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formatér"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-debugging tilkoblet"</string>
@@ -837,28 +831,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"</string>
     <string name="candidates_style" msgid="4333913089637062257">"TAG_FONT"<u>"kandidater"</u>"CLOSE_FONT"</string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Forbereder minnekort"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Forbereder delt lagring"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Forbereder minnekort"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Sjekker for feil."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Tomt minnekort"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Delt lagring er tom"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Tomt minnekort"</string>
-    <!-- outdated translation 1312266820092958014 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"Minnekortet er tomt eller bruker et ustøttet filsystem."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"Delt lagring er tom eller har et filsystem som ikke håndteres."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Minnekortet er tomt eller har et ikke-støttet filsystem."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Skadet minnekort"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Delt lagring skadet"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Skadet minnekort"</string>
-    <!-- outdated translation 2679412884290061775 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"Minnekortet er skadet. Det kan være du må formatere kortet."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"Delt lagring er skadet. Det kan være nødvendig å formatere enheten."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Minnekortet er skadet. Du må kanskje formatere det."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Minnekortet ble tatt ut uventet"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Delt lagring fjernet uventet"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Minnekortet ble tatt ut uventet"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Avmonter minnekortet før det tas ut, for å unngå datatap."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Koble fra delt lagring før enheten tas ut av maskinen for å unngå tap av data."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Avmonter minnekortet før det tas ut, for å unngå datatap."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"Trygt å ta ut minnekort"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"Delt lagring kan trygt fjernes"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Trygt å ta ut minnekort"</string>
-    <!-- outdated translation 7613960686747592770 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"Minnekortet kan nå trygt tas ut."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"Det er trygt å ta ut enheten for delt lagring."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Det er trygt å ta ut minnekortet."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Minnekortet ble tatt ut"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Fjernet delt lagring"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Minnekortet ble tatt ut"</string>
-    <!-- outdated translation 4205117227342822275 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"Minnekortet ble tatt ut. Sett inn et nytt minnekort for å øke lagringsplassen."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"Delt lagring fjernet. Sett inn et nytt medium."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Minnekortet ble fjernet. Sett inn et nytt."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Fant ingen tilsvarende aktiviteter"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"oppdater statistikk over komponentbruk"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 2dedd7b..93dd560 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -169,7 +169,7 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Ontwikkelingshulpprogramma\'s"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Functies die alleen door toepassingsontwikkelaars worden gebruikt."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Opslagruimte"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Toegang tot de SD-kaart."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Toegang krijgen tot de gedeelde opslag."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Toegang tot de SD-kaart."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"statusbalk uitschakelen of wijzigen"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Hiermee kan een toepassing de statusbalk uitschakelen of systeempictogrammen toevoegen en verwijderen."</string>
@@ -403,22 +403,14 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Hiermee kan een toepassing de lokale Bluetooth-telefoon configureren en externe apparaten zoeken en aansluiten."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"Bluetooth-verbindingen maken"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Hiermee kan een toepassing de configuratie van een lokale Bluetooth-telefoon bekijken en verbindingen met gekoppelde apparaten maken en accepteren."</string>
-    <!-- no translation found for permlab_nfcAdmin (2251302233012250056) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcAdmin (1935842611464895785) -->
-    <skip />
-    <!-- no translation found for permlab_nfcRaw (4423471711114325708) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcRaw (5533022736559385665) -->
-    <skip />
-    <!-- no translation found for permlab_nfcNotify (478470360082792358) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcNotify (2990053517962070617) -->
-    <skip />
-    <!-- no translation found for permlab_nfcLlcp (4972051461007030426) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcLlcp (91592127786004640) -->
-    <skip />
+    <string name="permlab_nfcAdmin" msgid="2251302233012250056">"NFC-beheer"</string>
+    <string name="permdesc_nfcAdmin" msgid="1935842611464895785">"Hiermee kan een toepassing de lokale NFC-telefoon configureren."</string>
+    <string name="permlab_nfcRaw" msgid="4423471711114325708">"NFC volledige toegang tot extern apparaat"</string>
+    <string name="permdesc_nfcRaw" msgid="5533022736559385665">"Hiermee kan een toepassing toegang krijgen tot externe NFC-apparaten."</string>
+    <string name="permlab_nfcNotify" msgid="478470360082792358">"NFC-melding van extern apparaat"</string>
+    <string name="permdesc_nfcNotify" msgid="2990053517962070617">"Hiermee kan een toepassing op de hoogte worden gesteld van bewerkingen gerelateerd aan externe NFC-apparaten."</string>
+    <string name="permlab_nfcLlcp" msgid="4972051461007030426">"NFC-melding van extern LLCP-apparaat"</string>
+    <string name="permdesc_nfcLlcp" msgid="91592127786004640">"Hiermee kan een toepassing op de hoogte worden gesteld van LLCP-bewerkingen gerelateerd aan externe NFC-apparaten."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"toetsvergrendeling uitschakelen"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Hiermee kan een toepassing de toetsvergrendeling en bijbehorende wachtwoordbeveiliging uitschakelen. Een voorbeeld: de telefoon schakelt de toetsvergrendeling uit als er een oproep binnenkomt en schakelt de toetsvergrendeling weer in als de oproep is beëindigd."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"synchronisatie-instellingen lezen"</string>
@@ -435,22 +427,26 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Hiermee kan een toepassing privéwoorden, namen en woordcombinaties lezen die de gebruiker heeft opgeslagen in het gebruikerswoordenboek."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"schrijven naar door gebruiker gedefinieerd woordenboek"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Hiermee kan een toepassing nieuwe woorden schrijven naar het gebruikerswoordenboek."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"inhoud op de SD-kaart aanpassen/verwijderen"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"inhoud van gedeelde opslag aanpassen/verwijderen"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"inhoud op de SD-kaart aanpassen/verwijderen"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Hiermee kan een toepassing schrijven naar de SD-kaart."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Hiermee kan een toepassing schrijven naar de gedeelde opslag."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Hiermee kan een toepassing schrijven naar de SD-kaart."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"het cachebestandssysteem openen"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Staat een toepassing toe het cachebestandssysteem te lezen en te schrijven."</string>
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Wachtwoord beperken"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"De typen wachtwoorden beperken die u mag gebruiken."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Aanmeldingspogingen controleren"</string>
-    <!-- outdated translation 1961251179624843483 -->     <string name="policydesc_watchLogin" msgid="7227578260165172673">"Mislukte pogingen controleren voor aanmelding bij het apparaat om een bepaalde actie uit te voeren."</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Wachtwoord opnieuw instellen"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Uw wachtwoord gedwongen wijzigen in een nieuwe waarde, wat vereist dat de beheerder u het wachtwoord geeft voordat u zich kunt aanmelden."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Gedwongen vergrendelen"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Beheren wanneer het apparaat wordt vergrendeld, wat vereist dat u het wachtwoord opnieuw invoert."</string>
+    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+    <skip />
+    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
+    <skip />
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Wachtwoordregels instellen"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"De lengte en tekens beheren die zijn toegestaan in wachtwoorden voor schermontgrendeling"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Pogingen voor schermontgrendeling bijhouden"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Bijhouden hoe vaak onjuiste wachtwoorden worden ingevoerd wanneer het scherm wordt ontgrendeld en de telefoon vergrendelen of alle gegevens op de telefoon wissen als er te veel onjuiste wachtwoorden worden ingevoerd"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Het wachtwoord voor schermontgrendeling wijzigen"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Het wachtwoord voor schermontgrendeling wijzigen"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Het scherm vergrendelen"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Beheren hoe en wanneer het scherm wordt vergrendeld"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Alle gegevens wissen"</string>
-    <!-- outdated translation 2314060933796396205 -->     <string name="policydesc_wipeData" msgid="7669895333814222586">"De fabrieksinstellingen herstellen, waarbij alle gegevens worden verwijderd zonder bevestiging."</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"De gegevens van de telefoon zonder waarschuwing wissen door de fabrieksinstellingen te herstellen"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Thuis"</item>
     <item msgid="869923650527136615">"Mobiel"</item>
@@ -610,10 +606,8 @@
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Hiermee kan een toepassing de URL\'s lezen die u via de browser heeft bezocht, evenals alle bladwijzers van de browser."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"browsergeschiedenis en bladwijzers schrijven"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Hiermee kan een toepassing de op uw telefoon opgeslagen browsergeschiedenis of bladwijzers wijzigen. Schadelijke toepassingen kunnen hiermee uw browsergegevens verwijderen of wijzigen."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"alarm instellen in wekker"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Hiermee kan de toepassing een alarm instellen in een geïnstalleerde wekkertoepassing. Deze functie wordt door sommige wekkertoepassingen niet geïmplementeerd."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Geolocatierechten voor browser aanpassen"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Staat een toepassing toe de geolocatierechten van de browser aan te passen. Schadelijke toepassingen kunnen dit gebruiken om locatiegegevens te verzenden naar willekeurige websites."</string>
     <string name="save_password_message" msgid="767344687139195790">"Wilt u dat de browser dit wachtwoord onthoudt?"</string>
@@ -808,17 +802,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Alles weergeven"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB-massaopslag"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB-verbinding"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"U heeft uw telefoon via USB op uw computer aangesloten. Selecteer de onderstaande knop als u bestanden tussen uw computer en de SD-kaart van uw Android wilt kopiëren."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"U heeft uw telefoon via USB op uw computer aangesloten. Selecteer de onderstaande knop als u bestanden tussen uw computer en de gedeelde opslag van uw Android wilt kopiëren."</string>
     <string name="usb_storage_message" product="default" msgid="4796759646167247178">"U heeft uw telefoon via USB op uw computer aangesloten. Selecteer de onderstaande knop als u bestanden tussen uw computer en de SD-kaart van uw Android wilt kopiëren."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"USB-opslag inschakelen"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Er is een probleem bij het gebruik van uw SD-kaart voor USB-opslag."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Er is een probleem bij het gebruik van uw gedeelde opslag voor USB-opslag."</string>
     <string name="usb_storage_error_message" product="default" msgid="2534784751603345363">"Er is een probleem bij het gebruik van uw SD-kaart voor USB-opslag."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB-verbinding"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Selecteer dit om bestanden naar/van uw computer te kopiëren."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"USB-opslag uitschakelen"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Selecteer dit om USB-opslag uit te schakelen."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB-opslag in gebruik"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Voordat u USB-opslag uitschakelt, moet u de SD-kaart van uw Android hebben ontkoppeld (\'uitgeworpen\') van uw computer."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Voordat u USB-opslag uitschakelt, moet u de gedeelde opslag van uw Android hebben ontkoppeld (\'uitgeworpen\') van uw computer."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Voordat u USB-opslag uitschakelt, moet u de SD-kaart van uw Android hebben ontkoppeld (\'uitgeworpen\') van uw computer."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"USB-opslag uitschakelen"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Er is een probleem opgetreden tijdens het uitschakelen van de USB-opslag. Controleer of u de USB-host heeft losgekoppeld en probeer het opnieuw."</string>
@@ -826,9 +820,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Als u USB-opslag inschakelt, worden bepaalde toepassingen die u gebruikt, gestopt en worden deze mogelijk pas weer beschikbaar wanneer u USB-opslag uitschakelt."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB-bewerking mislukt"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"SD-kaart formatteren"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Gedeelde opslag formatteren"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD-kaart formatteren"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Weet u zeker dat u de SD-kaart wilt formatteren? Alle gegevens op uw kaart gaan dan verloren."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Gedeelde opslag formatteren en alle opgeslagen bestanden wissen? Actie kan niet ongedaan worden gemaakt."</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Weet u zeker dat u de SD-kaart wilt formatteren? Alle gegevens op uw kaart gaan dan verloren."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formatteren"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-foutopsporing verbonden"</string>
@@ -837,28 +831,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidaten"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"SD-kaart voorbereiden"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Gedeelde opslag voorbereiden"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"SD-kaart voorbereiden"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Controleren op fouten."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Lege SD-kaart"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Lege gedeelde opslag"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Lege SD-kaart"</string>
-    <!-- outdated translation 1312266820092958014 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"De SD-kaart is leeg of gebruikt een niet-ondersteund bestandssysteem."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"Gedeelde opslag leeg of heeft een niet-ondersteund bestandssysteem."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD-kaart is leeg of heeft een niet-ondersteund bestandssysteem."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Beschadigde SD-kaart"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Gedeelde opslag beschadigd"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Beschadigde SD-kaart"</string>
-    <!-- outdated translation 2679412884290061775 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"De SD-kaart is beschadigd. U moet de kaart mogelijk opnieuw formatteren."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"Gedeelde opslag beschadigd. U moet de opslag mogelijk opnieuw formatteren."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD-kaart beschadigd. U moet de kaart mogelijk opnieuw formatteren."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"SD-kaart onverwachts verwijderd"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Gedeelde opslag onverwachts verwijderd"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD-kaart onverwachts verwijderd"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Ontkoppel de SD-kaart voordat u deze verwijdert om gegevensverlies te voorkomen."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Ontkoppel de gedeelde opslag voordat u deze verwijdert om gegevensverlies te voorkomen."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Ontkoppel de SD-kaart voordat u deze verwijdert om gegevensverlies te voorkomen."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"De SD-kaart kan veilig worden verwijderd"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"Gedeelde opslag kan veilig worden verwijderd"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"De SD-kaart kan veilig worden verwijderd"</string>
-    <!-- outdated translation 7613960686747592770 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"De SD-kaart kan nu veilig worden verwijderd."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"U kunt de gedeelde opslag veilig verwijderen."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"U kunt de SD-kaart veilig verwijderen."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"SD-kaart is verwijderd"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Gedeelde opslag verwijderen"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"SD-kaart is verwijderd"</string>
-    <!-- outdated translation 4205117227342822275 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"De SD-kaart is verwijderd. Plaats een nieuwe SD-kaart om de opslagcapaciteit van uw apparaat te vergroten."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"Gedeelde opslag verwijderd. Plaats nieuw medium."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD-kaart verwijderd. Plaats een nieuwe."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Geen overeenkomende activiteiten gevonden"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"gebruiksstatistieken van component bijwerken"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 4e5256f..5ae94ff 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -169,7 +169,7 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Narzędzia programistyczne"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Funkcje potrzebne jedynie programistom"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Pamięć"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Dostęp do karty SD."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Dostęp do pamięci udostępnionej."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Dostęp do karty SD."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"wyłączanie lub zmienianie paska stanu"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Pozwala aplikacjom na wyłączenie paska stanu lub dodawanie i usuwanie ikon systemowych."</string>
@@ -403,22 +403,14 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Pozwala aplikacji na konfigurowanie lokalnego telefonu Bluetooth, wyszukiwanie urządzeń zdalnych i łączenie się z nimi."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"tworzenie połączeń Bluetooth"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Pozwala aplikacji na wyświetlanie konfiguracji lokalnego telefonu Bluetooth oraz na tworzenie i akceptowanie połączeń ze sparowanymi urządzeniami."</string>
-    <!-- no translation found for permlab_nfcAdmin (2251302233012250056) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcAdmin (1935842611464895785) -->
-    <skip />
-    <!-- no translation found for permlab_nfcRaw (4423471711114325708) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcRaw (5533022736559385665) -->
-    <skip />
-    <!-- no translation found for permlab_nfcNotify (478470360082792358) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcNotify (2990053517962070617) -->
-    <skip />
-    <!-- no translation found for permlab_nfcLlcp (4972051461007030426) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcLlcp (91592127786004640) -->
-    <skip />
+    <string name="permlab_nfcAdmin" msgid="2251302233012250056">"Administracja komunikacją NFC"</string>
+    <string name="permdesc_nfcAdmin" msgid="1935842611464895785">"Zezwala aplikacji na konfigurowanie obsługi komunikacji NFC w tym telefonie."</string>
+    <string name="permlab_nfcRaw" msgid="4423471711114325708">"Pełny dostęp do urządzenia zdalnego za pomocą komunikacji NFC"</string>
+    <string name="permdesc_nfcRaw" msgid="5533022736559385665">"Zezwala aplikacji na uzyskiwanie dostępu do zdalnych urządzeń obsługujących komunikację NFC."</string>
+    <string name="permlab_nfcNotify" msgid="478470360082792358">"Powiadomienie w ramach komunikacji NFC z urządzenia zdalnego"</string>
+    <string name="permdesc_nfcNotify" msgid="2990053517962070617">"Zezwala aplikacji na otrzymywanie powiadomień o operacjach związanych ze zdalnymi urządzeniami obsługującymi komunikację NFC."</string>
+    <string name="permlab_nfcLlcp" msgid="4972051461007030426">"Powiadomienie w ramach komunikacji NFC z urządzenia obsługującego protokół LLCP"</string>
+    <string name="permdesc_nfcLlcp" msgid="91592127786004640">"Zezwala aplikacji na otrzymywanie powiadomień o operacjach LLCP związanych ze zdalnymi urządzeniami obsługującymi komunikację NFC."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"wyłączanie blokady klawiatury"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Pozwala aplikacji na wyłączenie blokady klawiatury i wszystkich związanych z tym haseł zabezpieczających. Typowym przykładem takiego działania jest wyłączanie blokady klawiatury, gdy pojawia się połączenie przychodzące, a następnie ponowne jej włączanie po zakończeniu połączenia."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"czytanie ustawień synchronizowania"</string>
@@ -435,22 +427,26 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Zezwala aplikacji na odczytywanie wszelkich prywatnych słów, nazw i wyrażeń zapisanych przez użytkownika w swoim słowniku."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"zapisywanie w słowniku zdefiniowanym przez użytkownika"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Zezwala aplikacjom na zapisywanie nowych słów w słowniku użytkownika."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"modyfikowanie/usuwanie zawartości karty SD"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"modyfikowanie/usuwanie zawartości pamięci udostępnionej"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"modyfikowanie/usuwanie zawartości karty SD"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Umożliwia aplikacji zapis na karcie SD."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Zezwala aplikacji na zapis w pamięci udostępnionej."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Umożliwia aplikacji zapis na karcie SD."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"dostęp do systemu plików pamięci podręcznej"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Zezwala aplikacji na odczyt i zapis w systemie plików pamięci podręcznej."</string>
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Ogranicz liczbę prób wprowadzenia hasła"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Ogranicza dozwolone typy haseł użytkownika."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitoruj próby logowania"</string>
-    <!-- outdated translation 1961251179624843483 -->     <string name="policydesc_watchLogin" msgid="7227578260165172673">"Monitoruje nieudane próby zalogowania do urządzenia w celu wykonania określonego działania."</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Resetuj hasło"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Wymusza podanie nowej wartości hasła, wymagając przekazania go użytkownikowi przez administratora przed zalogowaniem."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Wymuś zablokowanie"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Kontroluje, kiedy urządzenie jest blokowane, wymagając ponownego wprowadzenia hasła."</string>
+    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+    <skip />
+    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
+    <skip />
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Określ reguły hasła"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Kontrolowanie długości haseł odblokowania ekranu i dozwolonych w nich znaków"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Monitoruj próby odblokowania ekranu"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Monitorowanie liczby przypadków wprowadzenia nieprawidłowego hasła podczas odblokowywania ekranu oraz blokowanie telefonu lub wymazywanie z niego wszystkich danych po wprowadzeniu zbyt wielu nieprawidłowych haseł"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Zmień hasło odblokowania ekranu"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Zmień hasło odblokowania ekranu"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Zablokuj ekran"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Kontrolowanie sposobu i warunków blokowania ekranu"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Usuń wszystkie dane"</string>
-    <!-- outdated translation 2314060933796396205 -->     <string name="policydesc_wipeData" msgid="7669895333814222586">"Wykonuje reset fabryczny, usuwając wszystkie dane użytkownika bez żadnego potwierdzenia."</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Wymazywanie danych z telefonu bez ostrzeżenia, przez przywrócenie danych fabrycznych"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Dom"</item>
     <item msgid="869923650527136615">"Komórka"</item>
@@ -610,10 +606,8 @@
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Umożliwia aplikacji odczyt wszystkich adresów URL odwiedzonych przez przeglądarkę, a także wszystkich zakładek przeglądarki."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"zapis historii i zakładek przeglądarki"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Umożliwia aplikacji modyfikowanie historii lub zakładek przeglądarki zapisanych w telefonie. Złośliwe aplikacje mogą używać tej opcji do usuwania lub modyfikowania danych przeglądarki."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"ustaw alarm w budziku"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Umożliwia aplikacji ustawienie alarmu w zainstalowanej aplikacji budzika. W niektórych aplikacjach budzika funkcja ta może nie być zaimplementowana."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modyfikowanie uprawnień przeglądarki dotyczących lokalizacji geograficznej"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Zezwala aplikacji na modyfikowanie uprawnień przeglądarki dotyczących lokalizacji geograficznej. Złośliwe aplikacje mogą używać tej opcji do wysyłania informacji o lokalizacji do dowolnych witryn internetowych."</string>
     <string name="save_password_message" msgid="767344687139195790">"Czy chcesz, aby zapamiętać to hasło w przeglądarce?"</string>
@@ -808,17 +802,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Pokaż wszystko"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"Pamięć masowa USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Połączenie przez USB"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Telefon został połączony z komputerem za pośrednictwem USB. Wybierz poniższy przycisk, aby skopiować pliki między komputerem a kartą SD systemu Android."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Telefon został połączony z komputerem za pośrednictwem USB. Wybierz poniższy przycisk, aby skopiować pliki między komputerem a pamięcią udostępnioną systemu Android."</string>
     <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Telefon został połączony z komputerem za pośrednictwem USB. Wybierz poniższy przycisk, aby skopiować pliki między komputerem a kartą SD systemu Android."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Włącz nośnik USB"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Wystąpił problem z wykorzystaniem karty SD dla pamięci USB."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Wystąpił problem z użyciem pamięci udostępnionej jako nośnika USB."</string>
     <string name="usb_storage_error_message" product="default" msgid="2534784751603345363">"Wystąpił problem z wykorzystaniem karty SD dla pamięci USB."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"Połączenie przez USB"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Wybierz, aby skopiować pliki do/z komputera"</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Wyłącz nośnik USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Wybierz, aby wyłączyć nośnik USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"Nośnik USB w użyciu"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Przed wyłączeniem nośnika USB upewnij się, że karta SD systemu Android została odłączona („wyjęta”) od komputera."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Przed wyłączeniem nośnika USB upewnij się, że pamięć udostępniona systemu Android została odłączona od komputera („wyjęta”)."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Przed wyłączeniem nośnika USB upewnij się, że karta SD systemu Android została odłączona („wyjęta”) od komputera."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Wyłącz nośnik USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Wystąpił problem podczas wyłączania nośnika USB. Upewnij się, że host USB został odłączony, a następnie spróbuj ponownie."</string>
@@ -826,9 +820,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Po włączeniu nośnika USB niektóre używane aplikacje zostaną zatrzymane i mogą być niedostępne do chwili wyłączenia nośnika USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Operacja USB nie powiodła się"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Formatuj kartę SD"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Formatuj pamięć udostępnioną"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatuj kartę SD"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Czy na pewno sformatować kartę SD? Wszystkie dane na karcie zostaną utracone."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Czy sformatować pamięć udostępnioną i wymazać wszystkie zapisane tam pliki? Tej czynności nie można cofnąć."</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Czy na pewno sformatować kartę SD? Wszystkie dane na karcie zostaną utracone."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formatuj"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Podłączono moduł debugowania USB"</string>
@@ -837,28 +831,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĄBCĆDEĘFGHIJKLŁMNŃOÓPQRSŚTUVWXYZŹŻ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandydaci"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Przygotowywanie karty SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Przygotowywanie pamięci udostępnionej"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Przygotowywanie karty SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Sprawdzanie w poszukiwaniu błędów."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Pusta karta SD"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Pusta pamięć udostępniona"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Pusta karta SD"</string>
-    <!-- outdated translation 1312266820092958014 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"Karta SD jest pusta lub używa nieobsługiwanego systemu plików."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"Pamięć udostępniona jest pusta lub zawiera nieobsługiwany system plików."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Karta SD jest pusta lub zawiera nieobsługiwany system plików."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Uszkodzona karta SD"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Uszkodzona pamięć udostępniona"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Uszkodzona karta SD"</string>
-    <!-- outdated translation 2679412884290061775 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"Karta SD jest uszkodzona. Konieczne może być przeformatowanie karty."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"Pamięć udostępniona jest uszkodzona. Konieczne może być ponowne sformatowanie."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Karta SD jest uszkodzona. Konieczne może być ponowne sformatowanie."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Karta SD została nieoczekiwanie wyjęta"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Nośnik pamięci udostępnionej został wyjęty"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Karta SD została nieoczekiwanie wyjęta"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Odłącz kartę SD przed jej wyjęciem, aby uniknąć utraty danych."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Odłącz pamięć udostępnioną przed wyjęciem jej nośnika, aby uniknąć utraty danych."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Odłącz kartę SD przed jej wyjęciem, aby uniknąć utraty danych."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"Można bezpiecznie usunąć kartę SD"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"Można wyjąć nośnik pamięci udostępnionej"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Można bezpiecznie usunąć kartę SD"</string>
-    <!-- outdated translation 7613960686747592770 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"Można teraz bezpiecznie usunąć kartę SD."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"Możesz bezpiecznie wyjąć nośnik pamięci udostępnionej."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Możesz bezpiecznie wyjąć kartę SD."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Usunięta karta SD"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Brak pamięci udostępnionej"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Usunięta karta SD"</string>
-    <!-- outdated translation 4205117227342822275 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"Karta SD została usunięta. Włóż nową kartę SD, aby zwiększyć pamięć urządzenia."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"Nośnik pamięci udostępnionej został wyjęty. Włóż nowy nośnik."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Karta SD została wyjęta. Włóż nową kartę."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Nie znaleziono pasujących działań"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"aktualizowanie statystyk użycia komponentu"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 55fdd18..c495012 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -169,7 +169,7 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Ferramentas de desenvolvimento"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Funcionalidades apenas necessárias para programadores de aplicações."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Armazenamento"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Aceder ao cartão SD."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Aceder ao armaz. partilhado."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Aceder ao cartão SD."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"desactivar ou modificar barra de estado"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Permite à aplicação desactivar a barra de estado ou adicionar e remover ícones do sistema."</string>
@@ -403,22 +403,14 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Permite a uma aplicação configurar o telefone Bluetooth local, bem como descobrir e emparelhar com dispositivos remotos."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"criar ligações Bluetooth"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Permite a uma aplicação ver a configuração do telefone Bluetooth local, bem como efectuar e aceitar ligações com dispositivos emparelhados."</string>
-    <!-- no translation found for permlab_nfcAdmin (2251302233012250056) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcAdmin (1935842611464895785) -->
-    <skip />
-    <!-- no translation found for permlab_nfcRaw (4423471711114325708) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcRaw (5533022736559385665) -->
-    <skip />
-    <!-- no translation found for permlab_nfcNotify (478470360082792358) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcNotify (2990053517962070617) -->
-    <skip />
-    <!-- no translation found for permlab_nfcLlcp (4972051461007030426) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcLlcp (91592127786004640) -->
-    <skip />
+    <string name="permlab_nfcAdmin" msgid="2251302233012250056">"Administração de NFC"</string>
+    <string name="permdesc_nfcAdmin" msgid="1935842611464895785">"Permite que uma aplicação configure o telefone NFC local."</string>
+    <string name="permlab_nfcRaw" msgid="4423471711114325708">"Acesso total de NFC ao dispositivo remoto"</string>
+    <string name="permdesc_nfcRaw" msgid="5533022736559385665">"Permite que uma aplicação aceda a dispositivos NFC remotos."</string>
+    <string name="permlab_nfcNotify" msgid="478470360082792358">"Notificação NFC a partir do dispositivo remoto"</string>
+    <string name="permdesc_nfcNotify" msgid="2990053517962070617">"Permite que uma aplicação seja notificada sobre operações relacionadas com dispositivos NFC remotos."</string>
+    <string name="permlab_nfcLlcp" msgid="4972051461007030426">"Notificação NFC a partir do dispositivo LLCP remoto"</string>
+    <string name="permdesc_nfcLlcp" msgid="91592127786004640">"Permite que uma aplicação seja notificada sobre operações LLCP relacionadas com dispositivos NFC remotos."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"desactivar bloqueio de teclas"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Permite a uma aplicação desactivar o bloqueio de teclas e qualquer segurança por palavra-passe associada. Um exemplo legítimo é a desactivação do bloqueio de teclas pelo telefone ao receber uma chamada, reactivando, em seguida, o bloqueio de teclas ao terminar a chamada."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ler definições de sincronização"</string>
@@ -435,22 +427,26 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Permite a uma aplicação ler quaisquer palavras, nomes e expressões privadas que o utilizador possa ter armazenado no dicionário do utilizador."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"escrever no dicionário definido pelo utilizador"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Permite a uma aplicação escrever novas palavras no dicionário do utilizador."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"modificar/eliminar conteúdo do cartão SD"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"modif./elim. conteúdo do armaz. part."</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"modificar/eliminar conteúdo do cartão SD"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Permite que uma aplicação escreva no cartão SD."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Permite que uma aplicação escreva no armaz. partilhado."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Permite que uma aplicação escreva no cartão SD."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"aceder ao sistema de ficheiros da cache"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permite a uma aplicação ler e escrever no sistema de ficheiros da cache."</string>
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Limitar palavra-passe"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Restrinja os tipos de palavras-passe que está autorizado a utilizar."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Ver tentativas de início de sessão"</string>
-    <!-- outdated translation 1961251179624843483 -->     <string name="policydesc_watchLogin" msgid="7227578260165172673">"O monitor falhou as tentativas de iniciar sessão no dispositivo para efectuar algumas acções."</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Repor palavra-passe"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Force a palavra-passe para um novo valor, sendo necessário que o administrador lho forneça antes de poder iniciar sessão."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Forçar bloqueio"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Controle quando o dispositivo é bloqueado, sendo necessário reintroduzir a respectiva palavra-passe."</string>
+    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+    <skip />
+    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
+    <skip />
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras de palavra-passe"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Controlar o comprimento e os caracteres permitidos nas palavras-passe de desbloqueio do ecrã"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Monitorizar tentativas de desbloqueio do ecrã"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Monitorize o número de palavras-passe incorrectas introduzidas ao desbloquear o ecrã e bloqueie o telefone ou apague todos os dados do telefone se forem introduzidas demasiadas palavras-passe incorrectas"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Alterar a palavra-passe de desbloqueio do ecrã"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Alterar a palavra-passe de desbloqueio do ecrã"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Bloquear o ecrã"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Controlar como e quando ocorre o bloqueio do ecrã"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Apagar todos os dados"</string>
-    <!-- outdated translation 2314060933796396205 -->     <string name="policydesc_wipeData" msgid="7669895333814222586">"Efectue uma reposição de fábrica, eliminando todos os dados sem qualquer confirmação."</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Apagar os dados do telefone sem avisar, ao efectuar uma reposição de dados de fábrica"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Residência"</item>
     <item msgid="869923650527136615">"Móvel"</item>
@@ -610,10 +606,8 @@
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permite que a aplicação leia todos os URLs visitados pelo browser e todos os marcadores do browser."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"gravar histórico e marcadores do browser"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Permite que uma aplicação modifique o histórico e os marcadores do browser armazenados no telefone. As aplicações maliciosas podem utilizar esta permissão para apagar ou modificar os dados do browser."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"definir alarme no despertador"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Permite que a aplicação defina um alarme numa aplicação de despertador instalada. Algumas aplicações de despertador podem não integrar esta funcionalidade."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modificar permissões de localização geográfica do Navegador"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permite a uma aplicação modificar as permissões de localização geográfica do Navegador. As aplicações mal intencionadas podem utilizar isto para enviar informações de localização para Web sites arbitrários."</string>
     <string name="save_password_message" msgid="767344687139195790">"Quer que o browser memorize esta palavra-passe?"</string>
@@ -808,17 +802,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Mostrar tudo"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"Armazenamento em massa USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Ligado através de USB"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Ligou o telefone ao computador através de USB. Seleccione o botão abaixo se pretender copiar ficheiros entre o computador e o cartão SD do Android."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Ligou o telefone ao computador através de USB. Seleccione o botão abaixo se pretender copiar ficheiros entre o computador e o armazenamento partilhado do Android."</string>
     <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Ligou o telefone ao computador através de USB. Seleccione o botão abaixo se pretender copiar ficheiros entre o computador e o cartão SD do Android."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Activar armazenamento USB"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Existe um problema ao utilizar o cartão SD para armazenamento USB."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Existe um problema ao utilizar o armazenamento partilhado para o armazenamento USB."</string>
     <string name="usb_storage_error_message" product="default" msgid="2534784751603345363">"Existe um problema ao utilizar o cartão SD para armazenamento USB."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"Ligado através de USB"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Seleccione para copiar ficheiro para/do seu computador."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Desactivar armazenamento USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Opte por desactivar o armazenamento USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"O armazenamento USB está a ser utilizado"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Antes de desactivar o armazenamento USB, certifique-se de que desinstalou (\"ejectou\") o cartão SD do Android do computador."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Antes de desactivar o armazenamento USB, certifique-se de que desmontou (\"ejectou\") o armazenamento partilhado do Android do computador."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Antes de desactivar o armazenamento USB, certifique-se de que desinstalou (\"ejectou\") o cartão SD do Android do computador."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Desactivar armazenamento USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Ocorreu um problema ao desactivar o armazenamento USB. Confirme se desinstalou o anfitrião USB e, em seguida, tente novamente."</string>
@@ -826,9 +820,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Se activar o armazenamento USB, algumas aplicações que estiver a utilizar serão paradas e poderão ficar indisponíveis até desactivar o armazenamento USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Falha na operação USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Formatar cartão SD"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Formatar armaz. part."</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatar cartão SD"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Tem a certeza de que pretende formatar o cartão SD? Perder-se-ão todos os dados no cartão."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Formatar armazenamento partilhado e apagar todos os ficheiros armazenados? Não é possível reverter a acção!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Tem a certeza de que pretende formatar o cartão SD? Perder-se-ão todos os dados no cartão."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formatar"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuração USB ligada"</string>
@@ -837,28 +831,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"A preparar cartão SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"A preparar armaz. partilhado"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"A preparar cartão SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"A verificar a presença de erros."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Cartão SD vazio"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Armazenamento partilhado vazio"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Cartão SD vazio"</string>
-    <!-- outdated translation 1312266820092958014 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"O cartão SD está vazio ou a utilizar um sistema de ficheiros não suportado."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"O armazenamento partilhado está vazio ou tem um sistema de ficheiros não suportado."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Cartão SD vazio ou sistema de ficheiros não suportado."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Cartão SD danificado"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Armazen. partilhado danificado"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Cartão SD danificado"</string>
-    <!-- outdated translation 2679412884290061775 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"O cartão SD está danificado. Poderá ser necessário reformatar o cartão."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"O armazenamento partilhado está danificado. Poderá ser necessário reformatá-lo."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Cartão SD danificado. Poderá ser necessário reformatá-lo."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Cartão SD removido de forma inesperada"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Armaz. part. remov. forma inesperada"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Cartão SD removido de forma inesperada"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Desmonte o cartão SD antes de retirá-lo para evitar a perda de dados."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Desmonte o armazenamento partilhado antes de removê-lo para evitar a perda de dados."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Desmonte o cartão SD antes de retirá-lo para evitar a perda de dados."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"É seguro retirar o cartão SD"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"Seguro remover arm. partilhado"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"É seguro retirar o cartão SD"</string>
-    <!-- outdated translation 7613960686747592770 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"É possível remover agora o cartão SD em segurança."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"Pode remover o armazenamento partilhado com segurança."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Pode remover o cartão SD com segurança."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Cartão SD removido"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Armazen. partilhado removido"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Cartão SD removido"</string>
-    <!-- outdated translation 4205117227342822275 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"O cartão SD foi removido. Introduza um novo cartão SD para aumentar a capacidade de armazenamento do dispositivo."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"O armazenamento partilhado foi removido. Insira um novo suporte de dados."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Cartão SD removido. Insira um novo cartão."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Nenhuma actividade correspondente encontrada"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"actualizar estatísticas de utilização de componentes"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index d5e1ca0..b768356 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -169,7 +169,7 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Ferramentas de desenvolvimento"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Recursos necessários apenas para desenvolvedores de aplicativo."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Armazenamento"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Acessar o cartão SD."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Acessa o armazenamento comp."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Acessar o cartão SD."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"desativar ou modificar a barra de status"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Permite que o aplicativo desative a barra de status ou adicione e remova ícones do sistema."</string>
@@ -403,22 +403,14 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Permite que um aplicativo configure o telefone Bluetooth local, descubra e pareie com dispositivos remotos."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"criar conexões Bluetooth"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Permite que um aplicativo veja a configuração do telefone Bluetooth local e que possa fazer e aceitar conexões com dispositivos pareados."</string>
-    <!-- no translation found for permlab_nfcAdmin (2251302233012250056) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcAdmin (1935842611464895785) -->
-    <skip />
-    <!-- no translation found for permlab_nfcRaw (4423471711114325708) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcRaw (5533022736559385665) -->
-    <skip />
-    <!-- no translation found for permlab_nfcNotify (478470360082792358) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcNotify (2990053517962070617) -->
-    <skip />
-    <!-- no translation found for permlab_nfcLlcp (4972051461007030426) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcLlcp (91592127786004640) -->
-    <skip />
+    <string name="permlab_nfcAdmin" msgid="2251302233012250056">"Administração do NFC"</string>
+    <string name="permdesc_nfcAdmin" msgid="1935842611464895785">"Permite que um aplicativo configure o telefone NFC local."</string>
+    <string name="permlab_nfcRaw" msgid="4423471711114325708">"Acesso completo do NFC ao aparelho remoto"</string>
+    <string name="permdesc_nfcRaw" msgid="5533022736559385665">"Permite que um aplicativo acesse aparelhos NFC remotos"</string>
+    <string name="permlab_nfcNotify" msgid="478470360082792358">"Notificação NFC do aparelho remoto"</string>
+    <string name="permdesc_nfcNotify" msgid="2990053517962070617">"Permite que um aplicativo seja notificado sobre operações relacionadas a aparelhos NFC remotos."</string>
+    <string name="permlab_nfcLlcp" msgid="4972051461007030426">"Notificação NFC do aparelho LLCP remoto"</string>
+    <string name="permdesc_nfcLlcp" msgid="91592127786004640">"Permite que um aplicativo seja notificado sobre operações LLCP relacionadas a aparelhos NFC remotos."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"desativar o bloqueio de teclas"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Permite que um aplicativo desative o bloqueio de teclas e qualquer segurança por senha associada. Um exemplo legítimo disso é a desativação do bloqueio de teclas pelo telefone ao receber uma chamada e a reativação do bloqueio quando a chamada é finalizada."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ler as configurações de sincronização"</string>
@@ -435,22 +427,26 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Permite que um aplicativo leia quaisquer palavras, nomes e frases particulares armazenados pelo usuário no dicionário do usuário."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"gravar no dicionário definido pelo usuário"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Permite que um aplicativo grave novas palavras no dicionário do usuário."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"modificar/excluir conteúdo do cartão SD"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"modificar/excluir cont. armaz."</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"modificar/excluir conteúdo do cartão SD"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Permite que um aplicativo grave no cartão SD."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Perm. aplic. grave arm. comp."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Permite que um aplicativo grave no cartão SD."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"acessar o sistema de arquivos de cache"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permite que um aplicativo leia e grave no sistema de arquivos de cache."</string>
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Limitar senha"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Restringe os tipos de senha que você tem permissão de usar."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Exibir tentativas de login"</string>
-    <!-- outdated translation 1961251179624843483 -->     <string name="policydesc_watchLogin" msgid="7227578260165172673">"Monitora as tentativas malsucedidas de login no aparelho para executar alguma ação."</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Redefinir senha"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Força a sua senha para um novo valor, exigindo que o administrador a forneça antes que você possa fazer login."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Forçar bloqueio"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Controla o bloqueio do aparelho, exigindo que a senha seja digitada novamente."</string>
+    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+    <skip />
+    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
+    <skip />
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras para senha"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Controla o tamanho e os caracteres permitidos nas senhas de desbloqueio de tela"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Monitorar tentativas de desbloqueio da tela"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Monitora o número de senhas incorretas inseridas ao desbloquear a tela e bloqueia o telefone ou apaga todos os dados do telefone se muitas senhas incorretas forem inseridas"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Alterar a senha para desbloqueio da tela"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Altera a senha para desbloqueio da tela"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Bloquear a tela"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Controla como e quando a tela é bloqueada"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Apagar todos os dados"</string>
-    <!-- outdated translation 2314060933796396205 -->     <string name="policydesc_wipeData" msgid="7669895333814222586">"Execute uma redefinição de fábrica, excluindo todos os seus dados sem qualquer confirmação."</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Apaga os dados do telefone sem aviso, executando uma redefinição da configuração original"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Residencial"</item>
     <item msgid="869923650527136615">"Celular"</item>
@@ -610,10 +606,8 @@
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permite que o aplicativo leia todos os URLs visitados pelo Navegador e todos os favoritos do Navegador."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"gravar histórico e favoritos do Navegador"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Permite que um aplicativo modifique o histórico ou os favoritos do Navegador armazenados no seu telefone. Aplicativos maliciosos podem usar isso para apagar ou modificar os dados do seu Navegador."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"definir alarme no despertador"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Permite que o aplicativo defina um alarme em um aplicativo de despertador instalado. Talvez alguns aplicativos de despertador não implementem esse recurso."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modifique as permissões de geolocalização do seu navegador"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permite que um aplicativo modifique as permissões de geolocalização do navegador. Aplicativos maliciosos podem usar isso para permitir o envio de informações de localização a sites arbitrários."</string>
     <string name="save_password_message" msgid="767344687139195790">"Deseja que o navegador lembre desta senha?"</string>
@@ -808,17 +802,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Mostrar todas"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"Armazenamento USB em massa"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Conectado por USB"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Você conectou o telefone ao computador via USB. Selecione o botão abaixo se quiser copiar arquivos entre o computador e o cartão SD do seu Android."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Você conectou o telefone ao computador via USB. Selecione o botão abaixo se quiser copiar arquivos entre seu computador e o armazenamento compartilhado do Android."</string>
     <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Você conectou o telefone ao computador via USB. Selecione o botão abaixo se quiser copiar arquivos entre o computador e o cartão SD do seu Android."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Ativar o armazenamento USB"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Há um problema com o uso do seu cartão SD para armazenamento USB."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Há um problema com o uso do seu armazenamento compartilhado para armazenamento USB."</string>
     <string name="usb_storage_error_message" product="default" msgid="2534784751603345363">"Há um problema com o uso do seu cartão SD para armazenamento USB."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"Conectado por USB"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Selecione para copiar arquivos para/do seu computador."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Desativar o armazenamento USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Selecione para desativar o armazenamento USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"Armazenamento USB em uso"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Antes de desativar o armazenamento USB, verifique se desconectou (“ejetou”) o cartão SD do Android do computador."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Antes de desativar o armazenamento USB, verifique se desconectou (“ejetou”) o armazenamento compartilhado do Android do computador."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Antes de desativar o armazenamento USB, verifique se desconectou (“ejetou”) o cartão SD do Android do computador."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Desativar o armazenamento USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Houve um problema ao desativar o armazenamento USB. Verifique se desconectou o host USB e tente novamente."</string>
@@ -826,9 +820,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Se você ativar o armazenamento USB, alguns aplicativos que estão em uso serão interrompidos e poderão não estar disponíveis até você desativar o armazenamento USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Falha de operação de USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Formatar cartão SD"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Formatar arm. comp."</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatar cartão SD"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Tem certeza de que deseja formatar o cartão SD? Todos os dados no seu cartão serão perdidos."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Formatar o armazenamento compartilhado, apagando todos os arquivos armazenados? A ação não pode ser revertida!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Tem certeza de que deseja formatar o cartão SD? Todos os dados no seu cartão serão perdidos."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formatar"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuração USB conectada"</string>
@@ -837,28 +831,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Preparando o cartão SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Preparando armazen. compart."</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Preparando o cartão SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Procurando erros."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Cartão SD em branco"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Armazenamento compart. vazio"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Cartão SD em branco"</string>
-    <!-- outdated translation 1312266820092958014 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"O cartão SD está em branco ou está usando um sistema de arquivos não suportado."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"O armazenamento compartilhado está vazio ou possui sistema de arquivos incompatível."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Cartão SD vazio ou com sistema de arquivos incompatível."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Cartão SD danificado"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Armaz. compart. danificado"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Cartão SD danificado"</string>
-    <!-- outdated translation 2679412884290061775 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"O cartão SD está danificado. Talvez seja necessário reformatar o seu cartão."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"O armazenamento compartilhado está danificado. Talvez seja necessário reformatá-lo."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"O cartão SD está danificado. Talvez seja necessário reformatá-lo."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Cartão SD removido inesperadamente."</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Armaz. comp. remov. inesperad."</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Cartão SD removido inesperadamente."</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Desmonte o cartão SD antes da remoção para evitar a perda de dados."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Desconecte o armazenamento compartilhado antes da remoção para evitar a perda de dados."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Desmonte o cartão SD antes da remoção para evitar a perda de dados."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"O cartão SD já pode ser removido com segurança."</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"É seguro remover armaz. comp."</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"O cartão SD já pode ser removido com segurança."</string>
-    <!-- outdated translation 7613960686747592770 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"O cartão SD já pode ser removido com segurança."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"Você pode remover com segurança o armazenamento compartilhado."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Você pode remover o cartão SD com segurança."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Cartão SD removido"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Armazen. compart. removido"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Cartão SD removido"</string>
-    <!-- outdated translation 4205117227342822275 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"O SD foi removido. Insira um novo cartão SD para aumentar o armazenamento do seu dispositivo."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"Armazenamento compartilhado removido. Insira nova mídia."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Cartão SD removido. Insira um novo."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Nenhum atividade correspondente foi encontrada"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"atualizar estatísticas de uso do componente"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index b61635f..27651f8 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -169,7 +169,7 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Инструменты разработки"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Функции, необходимые только разработчикам приложений."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Память"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Доступ к SD-карте."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Доступ к общему накопителю."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Доступ к SD-карте."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"отключать или изменять строку состояния"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Позволяет приложению отключать строку состояния или добавлять/удалять системные значки."</string>
@@ -403,22 +403,14 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Позволяет приложению настраивать локальный телефон Bluetooth, обнаруживать и выполнять сопряжение удаленных устройств."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"создавать подключения Bluetooth"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Позволяет приложению просматривать конфигурацию локального телефона Bluetooth, создавать подключения с сопряженными устройствами."</string>
-    <!-- no translation found for permlab_nfcAdmin (2251302233012250056) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcAdmin (1935842611464895785) -->
-    <skip />
-    <!-- no translation found for permlab_nfcRaw (4423471711114325708) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcRaw (5533022736559385665) -->
-    <skip />
-    <!-- no translation found for permlab_nfcNotify (478470360082792358) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcNotify (2990053517962070617) -->
-    <skip />
-    <!-- no translation found for permlab_nfcLlcp (4972051461007030426) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcLlcp (91592127786004640) -->
-    <skip />
+    <string name="permlab_nfcAdmin" msgid="2251302233012250056">"Администрировать NFC"</string>
+    <string name="permdesc_nfcAdmin" msgid="1935842611464895785">"Разрешает приложению настраивать локальный телефон NFC."</string>
+    <string name="permlab_nfcRaw" msgid="4423471711114325708">"Разрешает полный доступ к удаленному устройству с NFC"</string>
+    <string name="permdesc_nfcRaw" msgid="5533022736559385665">"Разрешает приложению доступ к удаленным устройствам NFC."</string>
+    <string name="permlab_nfcNotify" msgid="478470360082792358">"Присылать оповещения с удаленных устройств на NFC"</string>
+    <string name="permdesc_nfcNotify" msgid="2990053517962070617">"Разрешает приложению получать оповещения об операциях с удаленными устройствами NFC."</string>
+    <string name="permlab_nfcLlcp" msgid="4972051461007030426">"Присылать оповещения с удаленных устройств LLCP на NFC"</string>
+    <string name="permdesc_nfcLlcp" msgid="91592127786004640">"Разрешает приложению получать оповещения об операциях LLCP с удаленными устройствами NFC."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"отключать блокировку клавиатуры"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Позволяет приложению отключить блокировку клавиатуры и другие функции защиты паролем. Примером допустимого использования этой функции является отключение блокировки клавиатуры при получении входящего вызова и включение блокировки после завершения разговора."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"считывать настройки синхронизации"</string>
@@ -435,22 +427,26 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Позволяет приложению считывать любые слова, имена и фразы личного пользования, которые могут храниться в пользовательском словаре."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"записывать в словарь пользователя"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Позволяет приложению записывать новые слова в словарь пользователя."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"изменять/удалять содержимое SD-карты"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"изменять и удалять содержимое общего накопителя"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"изменять/удалять содержимое SD-карты"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Разрешает приложению запись на SD-карту"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Разрешает приложению запись на общий накопитель."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Разрешает приложению запись на SD-карту"</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"получать доступ к кэшу файловой системы"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Разрешает программам доступ для записи и чтения к кэшу файловой системы."</string>
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Ограничить пароль"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Ограничить типы паролей, доступных для использования."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Просмотр попыток входа"</string>
-    <!-- outdated translation 1961251179624843483 -->     <string name="policydesc_watchLogin" msgid="7227578260165172673">"Мониторинг неудачных попыток подключения к устройству для выполнения определенных действий."</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Сбросить пароль"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Принудительно изменить пароль, который администратор должен будет сообщить вам, чтобы вы смогли выполнить вход."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Принудительная блокировка"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Управление блокировкой устройства, требующей ввода пароля."</string>
+    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+    <skip />
+    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
+    <skip />
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Правила задания паролей"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Контролирует длину и символы при вводе паролей снятия блокировки экрана"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Отслеживать попытки снятия блокировки экрана"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Отслеживать количество неверно введенных паролей для снятия блокировки экрана и блокировать телефон либо уничтожить все данные на нем, если было введено слишком много неверных паролей"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Изменять пароль блокировки экрана"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Изменять пароль блокировки экрана"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Блокировать экран"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Контролирует способ и время блокировки экрана"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Удалить все данные"</string>
-    <!-- outdated translation 2314060933796396205 -->     <string name="policydesc_wipeData" msgid="7669895333814222586">"Выполнить сброс к начальным настройкам с удалением всех данных без запроса подтверждения."</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Уничтожить все данные на телефоне без предупреждения путем сброса настроек"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Домашний"</item>
     <item msgid="869923650527136615">"Мобильный"</item>
@@ -610,10 +606,8 @@
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Разрешает приложению считывать все URL, посещенные браузером, и все его закладки."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"записывать историю и закладки браузера"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Разрешает приложению изменять историю и закладки браузера, сохраненные в вашем телефоне. Вредоносное ПО может пользоваться этим, чтобы стирать или изменять данные вашего браузера."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"настраивать сигнал будильника"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Позволяет настраивать сигнал установленного приложения будильника. Для некоторых приложений будильника эта функция может быть недоступна."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Изменить разрешения браузера для доступа к географическому местоположению"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Позволяет программе изменять разрешения браузера для доступа к географическому положению. Вредоносные программы могут пользоваться этим для отправки информации о местоположении на некоторые сайты."</string>
     <string name="save_password_message" msgid="767344687139195790">"Вы хотите, чтобы браузер запомнил этот пароль?"</string>
@@ -808,17 +802,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Показать все"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"Запоминающее устройство USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB-подключение установлено"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Телефон подключен к компьютеру через порт USB. Нажмите кнопку ниже, если необходимо копировать файлы с компьютера на SD-карту устройства Android (или наоборот)."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Телефон подключен к компьютеру через порт USB. Для копирования файлов между компьютером и общим накопителем Android нажмите кнопку ниже."</string>
     <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Телефон подключен к компьютеру через порт USB. Нажмите кнопку ниже, если необходимо копировать файлы с компьютера на SD-карту устройства Android (или наоборот)."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Включить USB-накопитель"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"При использовании SD-карты как USB-накопителя возникла неполадка."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"При использовании общего накопителя как USB-накопителя возникла ошибка."</string>
     <string name="usb_storage_error_message" product="default" msgid="2534784751603345363">"При использовании SD-карты как USB-накопителя возникла неполадка."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB-подключение установлено"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Выберите копирование файлов на компьютер или с компьютера."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Выключить USB-накопитель"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Выберите, чтобы выключить USB-накопитель."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB-накопитель используется"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Перед отключением USB-накопителя убедитесь, что SD-карта устройства Android была отключена от компьютера."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Перед отключением USB-накопителя убедитесь, что общий накопитель Android был отключен от компьютера."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Перед отключением USB-накопителя убедитесь, что SD-карта устройства Android была отключена от компьютера."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Выключить USB-накопитель"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"При выключении USB-накопителя произошла неполадка. Убедитесь, что USB-хост отключен, и повторите попытку."</string>
@@ -826,9 +820,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"При включении USB-накопителя некоторые используемые приложения могут прекратить работу и оставаться недоступными до отключения USB-накопителя."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Сбой операции USB-подключения"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"ОК"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Очистить SD-карту"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Форматировать"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Очистить SD-карту"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Отформатировать карту SD? Все данные, находящиеся на карте, будут уничтожены."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Форматирование общего накопителя безвозвратно удалит все файлы на нем! Продолжить?"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Отформатировать карту SD? Все данные, находящиеся на карте, будут уничтожены."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Формат"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Отладка по USB разрешена"</string>
@@ -837,28 +831,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"варианты"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Подготовка карты SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Подготавливается общий накопитель"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Подготовка карты SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Проверка ошибок."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Пустая карта SD"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Нет данных на общем накопителе"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Пустая карта SD"</string>
-    <!-- outdated translation 1312266820092958014 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"Карта SD пуста или использует неподдерживаемую файловую систему."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"На общем накопителе нет данных или его файловая система не поддерживается."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD-карта пуста или использует неподдерживаемую файловую систему"</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Поврежденная карта SD"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Общий накопитель поврежден"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Поврежденная карта SD"</string>
-    <!-- outdated translation 2679412884290061775 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"Карта SD повреждена. Возможно, потребуется отформатировать ее."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"Общий накопитель поврежден. Попробуйте отформатировать его."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD-карта повреждена. Попробуйте отформатировать ее."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Карта SD неожиданно извлечена"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Общий накопитель неожиданно отключен"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Карта SD неожиданно извлечена"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Перед извлечением карты SD отключите ее во избежание потери данных."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Перед извлечением общего накопителя отключите его во избежание потери данных."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Перед извлечением карты SD отключите ее во избежание потери данных."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"Безопасное удаление карты SD"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"Общий накопитель безопасно отключен"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Безопасное удаление карты SD"</string>
-    <!-- outdated translation 7613960686747592770 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"Теперь карту SD можно безопасно удалить."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"Теперь общий накопитель может быть безопасно отключен."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Можно безопасно извлечь SD-карту."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Отсутствует карта SD"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Общий накопитель удален"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Отсутствует карта SD"</string>
-    <!-- outdated translation 4205117227342822275 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"Карта SD отсутствует. Для увеличения емкости устройства вставьте новую карту SD."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"Общий накопитель отключен. Вставьте другой накопитель."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD-карта извлечена. Вставьте новую карту."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Подходящих действий не найдено"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"обновлять статистику использования компонентов"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 8bc598d..7c11471 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -169,7 +169,7 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Utvecklingsverktyg"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Funktioner som endast behövs för programutvecklare."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Lagring"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Få åtkomst till SD-kortet."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Få åtkomst till SD-kortet."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Få åtkomst till SD-kortet."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"inaktivera eller ändra statusfält"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Tillåter att programmet inaktiverar statusfältet eller lägger till och tar bort systemikoner."</string>
@@ -403,22 +403,14 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Tillåter att ett program konfigurerar den lokala Bluetooth-telefonen samt upptäcker och parkopplar den med fjärranslutna enheter."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"skapa Bluetooth-anslutningar"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Tillåter att ett program ser den lokala Bluetooth-telefonens konfiguration, och skapar och accepterar anslutningar med parkopplade enheter."</string>
-    <!-- no translation found for permlab_nfcAdmin (2251302233012250056) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcAdmin (1935842611464895785) -->
-    <skip />
-    <!-- no translation found for permlab_nfcRaw (4423471711114325708) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcRaw (5533022736559385665) -->
-    <skip />
-    <!-- no translation found for permlab_nfcNotify (478470360082792358) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcNotify (2990053517962070617) -->
-    <skip />
-    <!-- no translation found for permlab_nfcLlcp (4972051461007030426) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcLlcp (91592127786004640) -->
-    <skip />
+    <string name="permlab_nfcAdmin" msgid="2251302233012250056">"Administrera NFC"</string>
+    <string name="permdesc_nfcAdmin" msgid="1935842611464895785">"Tillåter att ett program konfigurerar den lokala NFC-telefonen."</string>
+    <string name="permlab_nfcRaw" msgid="4423471711114325708">"NFC har fullständig åtkomst till fjärrenhet"</string>
+    <string name="permdesc_nfcRaw" msgid="5533022736559385665">"Tillåter att ett program får åtkomst till NFC-fjärrenheter."</string>
+    <string name="permlab_nfcNotify" msgid="478470360082792358">"NFC-avisering från fjärrenhet"</string>
+    <string name="permdesc_nfcNotify" msgid="2990053517962070617">"Tillåter att ett program får information om åtgärder relaterade till NFC-fjärrenheter."</string>
+    <string name="permlab_nfcLlcp" msgid="4972051461007030426">"NFC-avisering från LLCP-fjärrenhet"</string>
+    <string name="permdesc_nfcLlcp" msgid="91592127786004640">"Tillåter att ett program får information om LLCP-åtgärder relaterade till NFC-fjärrenheter."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"inaktivera tangentlås"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Tillåter att ett program inaktiverar tangentlåset och tillhörande lösenordsskydd. Ett exempel på detta är att telefonen inaktiverar tangentlåset vid inkommande samtal och sedan aktiverar det igen när samtalet är avslutat."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"läsa synkroniseringsinställningar"</string>
@@ -435,22 +427,26 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Tillåt att ett program läser alla privata ord, namn och fraser som användaren lagrar i sin ordlista."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"skriva till användardefinierad ordlista"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Tillåter att ett program skriver in nya ord i användarordlistan."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"ändra/ta bort innehåll på SD-kortet"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"ändra/ta bort innehåll på SD-kortet"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"ändra/ta bort innehåll på SD-kortet"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Tillåter att ett program skriver till SD-kortet."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Program får skriva t. SD-kort."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Tillåter att ett program skriver till SD-kortet."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"åtkomst till cachefilsystemet"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Tillåter att ett program läser och skriver till cachefilsystemet."</string>
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Begränsa lösenord"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Begränsar vilka typer av lösenord som får användas."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Visa inloggningsförsök"</string>
-    <!-- outdated translation 1961251179624843483 -->     <string name="policydesc_watchLogin" msgid="7227578260165172673">"Övervaka misslyckade inloggningsförsök på enheten för att utföra åtgärder."</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Återställ lösenord"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Framtvinga ett nytt värde för ditt lösenord. Kräver att administratören tillhandahåller det innan du kan logga in."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Framtvinga låsning"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Kontrollera när enheten låses, vilket kräver att du anger lösenordet igen."</string>
+    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+    <skip />
+    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
+    <skip />
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Ange lösenordsregler"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Bestäm längdbegränsning och vilka tecken som är tillåtna i skärmlåsets lösenord"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Övervaka försök att låsa upp skärmen"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Övervaka antalet felaktiga lösenord som angivits för skärmlåset och lås telefonen eller ta bort alla data från telefonen om för många felaktiga försök görs"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Ändra skärmlåsets lösenord"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Ändra skärmlåsets lösenord"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Lås skärmen"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Kontrollera hur och när skärmlåset aktiveras"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Radera alla data"</string>
-    <!-- outdated translation 2314060933796396205 -->     <string name="policydesc_wipeData" msgid="7669895333814222586">"Återställ fabriksinställningarna och ta bort alla data utan någon bekräftelse."</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Ta bort data på telefonen utan förvarning genom att återställa standardinställningarna"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Hem"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -610,10 +606,8 @@
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Tillåter att program läser alla webbadresser som webbläsaren har öppnat och alla webbläsarens bokmärken."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"skriva webbläsarhistorik och bokmärken"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Tillåter att ett program ändrar webbläsarhistoriken och bokmärkena i din telefon. Skadliga program kan använda detta för att ta bort eller ändra data i webbläsaren."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"ställa in alarm i alarmklocka"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Tillåter att programmet ställer in ett alarm i ett installerat alarmprogram. Vissa alarmprogram har inte den här funktionen."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Ändra geografisk plats för webbläsaren"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Tillåter att ett program ändrar webbläsarens behörigheter för geografisk plats. Skadliga program kan använda detta för att tillåta att platsinformation skickas till godtyckliga webbplatser."</string>
     <string name="save_password_message" msgid="767344687139195790">"Vill du att webbläsaren ska komma ihåg lösenordet?"</string>
@@ -808,17 +802,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Visa alla"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB-masslagring"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB-ansluten"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Du har anslutit telefonen till datorn via USB. Välj knappen nedan om du vill kopiera filer mellan datorn och SD-kortet i din Android."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Du har anslutit telefonen till datorn via USB. Välj knappen nedan om du vill kopiera filer mellan datorn och SD-kortet i din Android."</string>
     <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Du har anslutit telefonen till datorn via USB. Välj knappen nedan om du vill kopiera filer mellan datorn och SD-kortet i din Android."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Aktivera USB-lagring"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Det gick inte att använda ditt SD-kort för USB-lagring."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Det gick inte att använda ditt SD-kort för USB-lagring."</string>
     <string name="usb_storage_error_message" product="default" msgid="2534784751603345363">"Det gick inte att använda ditt SD-kort för USB-lagring."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB-ansluten"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Välj om du vill kopiera filer till/från din dator."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Inaktivera USB-lagring"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Välj om USB-lagring ska inaktiveras."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB-lagret används"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Kontrollera att du har demonterat (\"matat ut\") Android-telefonens SD-kort från datorn, innan du inaktiverar USB-lagring."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"Kontrollera att du har monterat bort (\"matat ut\") Android-telefonens SD-kort från datorn innan du inaktiverar USB-lagring."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Kontrollera att du har demonterat (\"matat ut\") Android-telefonens SD-kort från datorn, innan du inaktiverar USB-lagring."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Inaktivera USB-lagring"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Ett problem uppstod när USB-lagringsplatsen skulle inaktiveras. Kontrollera att USB-värden har demonterats och försök igen."</string>
@@ -826,9 +820,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Om du aktiverar USB-lagring avbryts några av de program som körs och de kanske inte blir tillgängliga igen förrän du inaktiverar USB-lagring."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB-åtgärd misslyckades"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Formatera SD-kort"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Formatera SD-kort"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatera SD-kort"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Vill du formatera SD-kortet? Alla data på ditt kort kommer att gå förlorade."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Formatera SD-kort, radera alla filer? Åtgärden kan inte ångras!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Vill du formatera SD-kortet? Alla data på ditt kort kommer att gå förlorade."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Format"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-felsökning ansluten"</string>
@@ -837,28 +831,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidater"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Förbereder SD-kort"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Förbereder SD-kort"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Förbereder SD-kort"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Söker efter fel."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Tomt SD-kort"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Tomt SD-kort"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Tomt SD-kort"</string>
-    <!-- outdated translation 1312266820092958014 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"SD-kortet är tomt eller så använder det ett filsystem som inte stöds."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"SD-kortet är tomt eller så har det ett filsystem som inte stöds."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD-kortet är tomt eller så har det ett filsystem som inte stöds."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Skadat SD-kort"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Skadat SD-kort"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Skadat SD-kort"</string>
-    <!-- outdated translation 2679412884290061775 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"SD-kortet är skadat. Du måste eventuellt formatera om ditt kort."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"SD-kortet är skadat. Du måste eventuellt formatera om det."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD-kortet är skadat. Du måste eventuellt formatera om det."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"SD-kort togs oväntat bort"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"SD-kort togs oväntat bort"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD-kort togs oväntat bort"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Demontera SD-kort innan borttagning för att undvika dataförlust."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Montera bort SD-kortet före borttagning för att undvika dataförlust."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Demontera SD-kort innan borttagning för att undvika dataförlust."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"Säkert att ta bort SD-kort"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"Säkert att ta bort SD-kort"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Säkert att ta bort SD-kort"</string>
-    <!-- outdated translation 7613960686747592770 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"SD-kortet kan nu tas bort."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"Det är nu säkert att ta bort SD-kortet."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Det är nu säkert att ta bort SD-kortet."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Borttaget SD-kort"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"SD-kortet har tagits bort"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Borttaget SD-kort"</string>
-    <!-- outdated translation 4205117227342822275 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"SD har tagits bort. Sätt i ett nytt SD-kort för att öka enhetens lagringsutrymme."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"SD-kortet har tagits bort. Sätt i ett nytt."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD-kortet har tagits bort. Sätt i ett nytt."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Inga matchande aktiviteter hittades"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"uppdatera statistik över användning av komponenter"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 58eb42a..d108232 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -169,7 +169,7 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Geliştirme araçları"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Yalnızca uygulama geliştiriciler için gerekli özellikler."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Depolama"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"SD karta erişin."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"Payl depolama birimine erişin."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"SD karta erişin."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"durum çubuğunu devre dışı bırak veya değiştir"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Uygulamanın durum çubuğunu devre dışı bırakmasına veya sistem simgeleri ekleyip kaldırmasına izin verir."</string>
@@ -403,22 +403,14 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"Uygulamaların yerel Bluetooth telefonunu yapılandırmasına ve uzak cihazları keşfedip bunlar ile eşleşmesine izin verir."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"Bluetooth bağlantıları oluştur"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"Uygulamaların yerel Bluetooth telefonunun yapılandırmasını görüntülemesine ve eşleşilmiş cihazlar ile bağlantı kurup kabul etmesine izin verir."</string>
-    <!-- no translation found for permlab_nfcAdmin (2251302233012250056) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcAdmin (1935842611464895785) -->
-    <skip />
-    <!-- no translation found for permlab_nfcRaw (4423471711114325708) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcRaw (5533022736559385665) -->
-    <skip />
-    <!-- no translation found for permlab_nfcNotify (478470360082792358) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcNotify (2990053517962070617) -->
-    <skip />
-    <!-- no translation found for permlab_nfcLlcp (4972051461007030426) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcLlcp (91592127786004640) -->
-    <skip />
+    <string name="permlab_nfcAdmin" msgid="2251302233012250056">"NFC yönetimi"</string>
+    <string name="permdesc_nfcAdmin" msgid="1935842611464895785">"Uygulamanın, yerel NFC telefonunu yapılandırmasına izin verir."</string>
+    <string name="permlab_nfcRaw" msgid="4423471711114325708">"Uzak cihaza tam NFC erişimi"</string>
+    <string name="permdesc_nfcRaw" msgid="5533022736559385665">"Uygulamaya, uzak NFC cihazlarına erişme izni verir."</string>
+    <string name="permlab_nfcNotify" msgid="478470360082792358">"Uzak cihazdan NFC bildirimi"</string>
+    <string name="permdesc_nfcNotify" msgid="2990053517962070617">"Uygulamaya, uzak NFC cihazlarıyla ilgili işlemlerin bildirilmesine izin verir."</string>
+    <string name="permlab_nfcLlcp" msgid="4972051461007030426">"Uzak LLCP cihazından NFC bildirimi"</string>
+    <string name="permdesc_nfcLlcp" msgid="91592127786004640">"Uygulamaya, uzak NFC cihazlarıyla ilgili LLCP işlemlerinin bildirilmesine izin verir."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"tuş kilidini devre dışı bırak"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Uygulamaların tuş kilidini ve ilgili şifreli güvenlik önlemini devre dışı bırakmasına izin verir. Bunun geçerli bir örneği gelen bir çağrı alındığında tuş kilidinin devre dışı bırakılması, sonra çağrı bittiğinde kilidin yeniden devreye sokulmasıdır."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"senk. ayarlarını oku"</string>
@@ -435,22 +427,26 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Kullanıcının kullanıcı sözlüğünde depolamış olabileceği kişisel kelimeleri, adları ve kelime öbeklerini uygulamaların okumasına izin verir."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"kullanıcı tanımlı sözlüğe yaz"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Uygulamaların kullanıcı sözlüğüne yeni kelimeler yazmasına izin verir."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"SD kart içeriklerini değiştir/sil"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"payl deplm birm içeriğini değiştr/sil"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"SD kart içeriklerini değiştir/sil"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Bir uygulamaya SD karta yazma izni verir."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"Uygulamaya, payl deplolama birimine yazma izni verir."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Bir uygulamaya SD karta yazma izni verir."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"önbellek dosya sistemine eriş"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Bir uygulamanın önbellek dosya sisteminde okuma yazma yapmasına izin verir."</string>
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Şifreyi sınırla"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Kullanmanıza izin verilen şifre türlerini sınırlayın."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Oturum açma denemelerini izle"</string>
-    <!-- outdated translation 1961251179624843483 -->     <string name="policydesc_watchLogin" msgid="7227578260165172673">"Bir işlem gerçekleştirmek için cihazdaki başarısız oturum açma girişimlerini izleyin."</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Şifre sıfırlama"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Şifrenizi yeni bir değer alması için zorlayın. Giriş yapabilmeniz için yöneticinin size yeni bir değer sağlamasını gerekecektir."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Kilitlemeye zorlama"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Cihaz kilitlendiğinde, şifresini yeniden girmenizi gerektiren denetim."</string>
+    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+    <skip />
+    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
+    <skip />
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Şifre kuralları ayarla"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Ekran kilidini açma şifrelerinde izin verilen uzunluğu ve karakterleri kontrol edin"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Ekran kilidini açma denemelerini izle"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"Ekran kilidi açılırken girilen yanlış şifre sayısını izler ve çok fazla sayıda yanlış şifre girilirse telefonu kilitler veya telefondaki tüm verileri siler"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Ekran kilidini açma şifresini değiştir"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Ekran kilidini açma şifresini değiştirin"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Ekranı kilitle"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Ekranın nasıl ve ne zaman kilitlendiğini kontrol edin"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Tüm verileri sil"</string>
-    <!-- outdated translation 2314060933796396205 -->     <string name="policydesc_wipeData" msgid="7669895333814222586">"Tüm verilerinizi onay olmadan silmek için fabrika ayarlarına sıfırlayın."</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"Fabrika verilerine sıfırlama işlemi gerçekleştirerek telefondaki verileri uyarıda bulunmadan silin"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Ev"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -610,10 +606,8 @@
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Uygulamaya Tarayıcının ziyaret etmiş olduğu tüm URL\'leri ve Tarayıcının tüm favorilerini okuma izni verir."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"Tarayıcı geçmişini ve favorileri yaz"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"Uygulamaya telefonunuzda depolanan Tarayıcı geçmişini veya favorileri değiştirme izni verir. Kötü amaçlı uygulamalar bunu Tarayıcı verilerinizi silmek veya değiştirmek için kullanabilir."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"çalar saatte alarm ayarla"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Uygulamanın yüklü bir çalar saat uygulamasında bir alarm ayarlamasına izin verir. Bazı çalar saat uygulamaları bu özelliği kullanmayabilir."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Tarayıcı\'nın coğrafi konum izinlerini değiştir"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Bir uygulamanın, Tarayıcı\'nın coğrafi konum izinlerini değiştirmesine izin verir. Kötü amaçlı uygulamalar, bu özelliği konum bilgilerini rastgele web sitelerine göndermek için kullanabilir."</string>
     <string name="save_password_message" msgid="767344687139195790">"Tarayıcının bu şifreyi anımsamasını istiyor musunuz?"</string>
@@ -808,17 +802,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Tümünü göster"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB Yığın Depolama"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB bağlandı"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Telefonunuzu USB ile bilgisayarınıza bağladınız. Bilgisayarınız ile Android\'inizin SD kartı arasında dosya kopyalamak istiyorsanız aşağıdaki düğmeyi seçin."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"Telefonunuzu USB ile bilgisayarınıza bağladınız. Bilgisayarınız ile Android\'inizin paylaşılan depolama birimi arasında dosya kopyalamak istiyorsanız aşağıdaki düğmeyi seçin."</string>
     <string name="usb_storage_message" product="default" msgid="4796759646167247178">"Telefonunuzu USB ile bilgisayarınıza bağladınız. Bilgisayarınız ile Android\'inizin SD kartı arasında dosya kopyalamak istiyorsanız aşağıdaki düğmeyi seçin."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"USB depolama birimini aç"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"SD kartınızı USB depolama birimi için kullanmada bir sorun var."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"Paylaşılan depolama biriminizi USB depolama amaçlı kullanmayla ilgili bir sorun var."</string>
     <string name="usb_storage_error_message" product="default" msgid="2534784751603345363">"SD kartınızı USB depolama birimi için kullanmada bir sorun var."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB bağlandı"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Bilgisayarınıza/bilgisayarınızdan dosya kopyalamak için seçin."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"USB depolama birimini kapat"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"USB depolama birimini kapatmak için seçin."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB depolama birimi kullanılıyor"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"USB depolama birimini kapatmadan önce Android SD kartını bilgisayarınızdan kaldırdığınızdan (\"çıkardığınızdan\") emin olun."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"USB depolama birimini kapatmadan önce Android\'inizin paylaşılan depolama biriminin bilgisayarınızla olan bağlantısını kestiğinizden (\"çıkardığınızdan\") emin olun."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"USB depolama birimini kapatmadan önce Android SD kartını bilgisayarınızdan kaldırdığınızdan (\"çıkardığınızdan\") emin olun."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"USB depolama birimini kapat"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"USB depolama birimini kapatırken bir sorun oluştu. USB ana makinesini kaldırdığınızdan emin olun ve daha sonra tekrar deneyin."</string>
@@ -826,9 +820,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"USB depolama birimini açarsanız, kullanmakta olduğunuz bazı uygulamalar durur ve USB depolama birimi kapatılıncaya kadar kullanılamayabilir."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB işlemi başarısız oldu"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"Tamam"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"SD kartı biçimlendir"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"Pay dep birm biçmlndr"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD kartı biçimlendir"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"SD kartı biçimlendirmek istediğinizden emin misiniz? Kartınızdaki tüm veriler yok olacak."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"Paylaşılan depolama birimi biçimlendirilsin mi? Depolama biriminde saklanan tüm dosyalar silinir. İşlem geri alınamaz!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"SD kartı biçimlendirmek istediğinizden emin misiniz? Kartınızdaki tüm veriler yok olacak."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Biçimlendir"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB hata ayıklaması bağlandı"</string>
@@ -837,28 +831,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"adaylar"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"SD kart hazırlanıyor"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"Payl depl birimi hazırlanıyor"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"SD kart hazırlanıyor"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Hatalar denetleniyor."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Boş SD kart"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"Boş paylaşılan depolama birimi"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Boş SD kart"</string>
-    <!-- outdated translation 1312266820092958014 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"SD kart boş veya desteklenmeyen bir dosya sistemi kullanıyor."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"Paylaşılan depolama birimi boş veya desteklenmeyen bir dosya sistemine sahip."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD kart boş veya desteklenmeyen dosya sistemi içeriyor"</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Hasarlı SD kart"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"Paylş deplm birimi zarar gördü"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Hasarlı SD kart"</string>
-    <!-- outdated translation 2679412884290061775 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"SD kart hasarlı. Kartınızı yeniden biçimlendirmeniz gerekebilir."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"Paylaşılan depolama birimi zarar gördü. Yeniden biçimlendirmeniz gerekebilir."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD kart zarar gördü. Yeniden biçimlendirmeniz gerekebilir."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"SD kart beklenmedik biçimde çıkarıldı"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"Payl depl brm beklnmdk şekl çıkarld"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD kart beklenmedik biçimde çıkarıldı"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Veri kaybından kaçınmak için SD kartı çıkarmadan önce bağlantısını kesin."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"Veri kaybı olmaması için paylaşılan depolama birimini çıkarmadan önce bağlantısını kesin."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Veri kaybından kaçınmak için SD kartı çıkarmadan önce bağlantısını kesin."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"SD kart güvenle çıkarılabilir"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"Payl dep birm güvenle çıkrlblr"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"SD kart güvenle çıkarılabilir"</string>
-    <!-- outdated translation 7613960686747592770 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"SD kart şimdi güvenli bir şekilde çıkarılabilir."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"Paylaşılan depolama birimini güvenli bir şekilde çıkarabilirsiniz."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"SD kartı güvenle kaldırabilirsiniz."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"SD kart çıkarılmış"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"Payl depolama birimi çıkarıldı"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"SD kart çıkarılmış"</string>
-    <!-- outdated translation 4205117227342822275 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"SD kart çıkarılmış. Cihazınızın depolama alanını artırmak için yeni bir SD kart takın."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"Paylaşılan depolama birimi çıkarıldı. Yeni ortamı takın."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD kart çıkarıldı. Yeni bir SD kart takın."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Eşleşen hiçbir etkinlik bulunamadı"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"bileşen kullanım istatistiklerini güncelle"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index aad56fd..abf118f 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -169,7 +169,7 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"开发工具"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"只有应用程序开发人员才会用到的功能。"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"存储"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"访问 SD 卡。"</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"访问共享存储设备。"</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"访问 SD 卡。"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"停用或修改状态栏"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"允许应用程序停用状态栏或者增删系统图标。"</string>
@@ -403,22 +403,14 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"允许应用程序配置本地蓝牙手机,以及发现远程设备并与其配对。"</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"创建蓝牙连接"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"允许应用程序查看本地蓝牙手机的配置,以及建立或接受与配对设备的连接。"</string>
-    <!-- no translation found for permlab_nfcAdmin (2251302233012250056) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcAdmin (1935842611464895785) -->
-    <skip />
-    <!-- no translation found for permlab_nfcRaw (4423471711114325708) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcRaw (5533022736559385665) -->
-    <skip />
-    <!-- no translation found for permlab_nfcNotify (478470360082792358) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcNotify (2990053517962070617) -->
-    <skip />
-    <!-- no translation found for permlab_nfcLlcp (4972051461007030426) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcLlcp (91592127786004640) -->
-    <skip />
+    <string name="permlab_nfcAdmin" msgid="2251302233012250056">"NFC 管理"</string>
+    <string name="permdesc_nfcAdmin" msgid="1935842611464895785">"允许应用程序配置本地 NFC 手机。"</string>
+    <string name="permlab_nfcRaw" msgid="4423471711114325708">"NFC 可完全访问线控设备"</string>
+    <string name="permdesc_nfcRaw" msgid="5533022736559385665">"允许应用程序访问线控 NFC 设备。"</string>
+    <string name="permlab_nfcNotify" msgid="478470360082792358">"来自线控设备的 NFC 通知"</string>
+    <string name="permdesc_nfcNotify" msgid="2990053517962070617">"当线控 NFC 设备发生操作时,允许通知应用程序。"</string>
+    <string name="permlab_nfcLlcp" msgid="4972051461007030426">"来自线控 LLCP 设备的 NFC 通知"</string>
+    <string name="permdesc_nfcLlcp" msgid="91592127786004640">"当线控 NFC 设备发生 LLCP 操作时,允许通知应用程序。"</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"停用键锁"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"允许应用程序停用键锁和任何关联的密码安全设置。例如,在手机上接听电话时停用键锁,在通话结束后重新启用键锁。"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"读取同步设置"</string>
@@ -435,22 +427,26 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"允许应用程序读取用户在用户词典中存储的任意私有字词、名称和短语。"</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"写入用户定义的词典"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"允许应用程序向用户词典中写入新词。"</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"修改/删除 SD 卡中的内容"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"修改/删除共享存储设备内容"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"修改/删除 SD 卡中的内容"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"允许应用程序写入 SD 卡。"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"允许应用程序写入共享存储设备。"</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"允许应用程序写入 SD 卡。"</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"访问缓存文件系统"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"允许应用程序读取和写入缓存文件系统。"</string>
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"限制密码选择"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"限制您能够使用的密码类型。"</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"监控登录尝试"</string>
-    <!-- outdated translation 1961251179624843483 -->     <string name="policydesc_watchLogin" msgid="7227578260165172673">"监控对于登录设备和执行某项操作的失败尝试。"</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"重置密码"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"强行更新密码,您需要获得管理员提供的新密码才能登录。"</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"强行锁定"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"控制何时锁定设备,这需要您重新输入密码。"</string>
+    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+    <skip />
+    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
+    <skip />
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"设置密码规则"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"控制屏幕解锁密码允许的长度和字符数"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"监视屏幕解锁尝试次数"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"监视锁定屏幕前密码输入错误的次数;如果密码输入错误次数太多,则会锁定手机或擦除手机上的所有数据。"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"更改屏幕解锁密码"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"更改屏幕解锁密码"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"锁定屏幕"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"控制锁定屏幕的方式和时间"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"清除所有数据"</string>
-    <!-- outdated translation 2314060933796396205 -->     <string name="policydesc_wipeData" msgid="7669895333814222586">"恢复出厂设置,这会在不提示确认的情况下删除您的所有数据。"</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"恢复出厂设置时,将擦除手机上的数据而不发送警告"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"住宅"</item>
     <item msgid="869923650527136615">"手机"</item>
@@ -610,10 +606,8 @@
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"允许应用程序读取用浏览器访问过的所有网址,以及浏览器的所有书签。"</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"写入浏览器的历史记录和书签"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"允许应用程序修改存储在手机中的浏览器历史记录或书签。恶意应用程序可借此清除或修改浏览器数据。"</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"在闹钟中设置警报"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"允许应用程序在安装的闹钟应用程序中设置警报。某些闹钟应用程序没有实现此功能。"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"修改浏览器的地理位置权限"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"允许应用程序修改浏览器的地理位置权限。恶意应用程序会利用这一点将位置信息发送到任意网站。"</string>
     <string name="save_password_message" msgid="767344687139195790">"是否希望浏览器记住此密码?"</string>
@@ -808,17 +802,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"全部显示"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB 大容量存储"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB 已连接"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"您已通过 USB 将手机连接至计算机。如果您要在计算机和 Android 手机的 SD 卡之间复制文件,请点击下面的按钮。"</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"您已通过 USB 将手机连接至计算机。如果您要在计算机和 Android 手机的共享存储设备之间复制文件,请选择下面的按钮。"</string>
     <string name="usb_storage_message" product="default" msgid="4796759646167247178">"您已通过 USB 将手机连接至计算机。如果您要在计算机和 Android 手机的 SD 卡之间复制文件,请点击下面的按钮。"</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"打开 USB 存储设备"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"使用 SD 卡进行 USB 存储时出现问题。"</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"使用共享存储设备作为 USB 存储时出现问题。"</string>
     <string name="usb_storage_error_message" product="default" msgid="2534784751603345363">"使用 SD 卡进行 USB 存储时出现问题。"</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB 已连接"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"选择将文件复制到计算机或从计算机复制到存储设备。"</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"关闭 USB 存储设备"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"选中以关闭 USB 存储设备。"</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"使用中的 USB 存储设备"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"在关闭 USB 存储设备前,请确保您已从计算机中卸载(“弹出”)Android 手机的 SD 卡。"</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"在关闭 USB 存储前,请确保您已从计算机中卸载(“弹出”)Android 手机的共享存储设备。"</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"在关闭 USB 存储设备前,请确保您已从计算机中卸载(“弹出”)Android 手机的 SD 卡。"</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"关闭 USB 存储设备"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"关闭 USB 存储设备时遇到问题。请检查并确保已卸载了 USB 主设备,然后重试。"</string>
@@ -826,9 +820,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"如果您打开了 USB 存储设备,则您当前使用的某些应用程序会停止,而且在您关闭 USB 存储设备前可能都无法使用。"</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB 操作失败"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"确定"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"格式化 SD 卡"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"格式化共享存储设备"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"格式化 SD 卡"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"确定要将 SD 卡格式化吗?该卡上的所有数据都将丢失。"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"确定要格式化共享存储设备,擦除其存储的所有文件吗?该操作将无法撤消!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"确定要将 SD 卡格式化吗?该卡上的所有数据都将丢失。"</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"格式化"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"已连接 USB 调试"</string>
@@ -837,28 +831,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"候选"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"正在准备 SD 卡"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"正在准备共享存储设备"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"正在准备 SD 卡"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"正在检查是否有错误。"</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"空 SD 卡"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"共享存储设备中无文件"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"空 SD 卡"</string>
-    <!-- outdated translation 1312266820092958014 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"SD 卡为空或使用不支持的文件系统。"</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"共享存储设备中无文件或使用了不受支持的文件系统。"</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD 卡无文件系统,或文件系统不受支持。"</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"SD 卡受损"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"共享存储设备已损坏"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"SD 卡受损"</string>
-    <!-- outdated translation 2679412884290061775 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"SD 卡受损。您可能需要重新格式化您的卡。"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"共享存储设备已损坏。您可能必须将其重新格式化。"</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD 卡已损坏。您可能必须将其重新格式化。"</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"SD 卡未正常移除"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"共享存储设备被意外移除"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD 卡未正常移除"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"请先卸载 SD 卡,再将其移除,以防数据丢失。"</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"请先卸载共享存储设备,再将其移除,以防数据丢失。"</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"请先卸载 SD 卡,再将其移除,以防数据丢失。"</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"SD 卡已安全移除"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"共享存储设备可安全移除"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"SD 卡已安全移除"</string>
-    <!-- outdated translation 7613960686747592770 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"现在可以安全移除 SD 卡。"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"可以安全移除共享存储设备。"</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"您现在可以安全移除 SD 卡。"</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"已移除 SD 卡"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"共享存储设备已移除"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"已移除 SD 卡"</string>
-    <!-- outdated translation 4205117227342822275 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"SD 卡已移除。请插入新 SD 卡来增加您的设备存储空间。"</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"共享存储设备已移除。请插入新媒体。"</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD 卡已移除。请插入新的 SD 卡。"</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"找不到匹配的活动"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"更新组件使用情况统计"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 6490c55..ec23c4d 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -169,7 +169,7 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"開發工具"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"只有開發者需要此功能。"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"儲存"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"存取 SD 卡。"</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="5455804353220581312">"存取共用儲存裝置。"</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"存取 SD 卡。"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"停用或變更狀態列"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"允許應用程式停用狀態列或新增、移除系統圖示。"</string>
@@ -403,22 +403,14 @@
     <string name="permdesc_bluetoothAdmin" msgid="7256289774667054555">"允許應用程式設定本機藍牙電話,以及偵測與配對其他遠端裝置。"</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"建立藍牙連線"</string>
     <string name="permdesc_bluetooth" msgid="762515380679392945">"允許應用程式檢視本機藍牙電話設定,並與其他配對裝置連線。"</string>
-    <!-- no translation found for permlab_nfcAdmin (2251302233012250056) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcAdmin (1935842611464895785) -->
-    <skip />
-    <!-- no translation found for permlab_nfcRaw (4423471711114325708) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcRaw (5533022736559385665) -->
-    <skip />
-    <!-- no translation found for permlab_nfcNotify (478470360082792358) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcNotify (2990053517962070617) -->
-    <skip />
-    <!-- no translation found for permlab_nfcLlcp (4972051461007030426) -->
-    <skip />
-    <!-- no translation found for permdesc_nfcLlcp (91592127786004640) -->
-    <skip />
+    <string name="permlab_nfcAdmin" msgid="2251302233012250056">"NFC 管理"</string>
+    <string name="permdesc_nfcAdmin" msgid="1935842611464895785">"允許應用程式設定本機 NFC 手機。"</string>
+    <string name="permlab_nfcRaw" msgid="4423471711114325708">"NFC 可完整存取遠端裝置"</string>
+    <string name="permdesc_nfcRaw" msgid="5533022736559385665">"允許應用程式存取遠端 NFC 裝置。"</string>
+    <string name="permlab_nfcNotify" msgid="478470360082792358">"來自遠端裝置的 NFC 通知"</string>
+    <string name="permdesc_nfcNotify" msgid="2990053517962070617">"執行與遠端 NFC 裝置相關的作業時,允許應用程式收到通知。"</string>
+    <string name="permlab_nfcLlcp" msgid="4972051461007030426">"來自遠端 LLCP 裝置的 NFC 通知"</string>
+    <string name="permdesc_nfcLlcp" msgid="91592127786004640">"執行與遠端 NFC 裝置相關的 LLCP 作業時,允許應用程式收到通知。"</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"停用按鍵鎖定"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"允許應用程式停用按鍵鎖定以及其他相關的密碼安全性。例如:收到來電時解除按鍵鎖定,通話結束後重新啟動按鍵鎖定。"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"讀取同步處理設定"</string>
@@ -435,22 +427,26 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"允許應用程式讀取使用者儲存在使用者字典內的任何私人字詞、名稱和詞組。"</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"寫入使用者定義的字典"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"允許應用程式將新字詞寫入使用者的字典。"</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"修改/刪除 SD 卡的內容"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="993707436941016913">"修改/刪除共用儲存裝置內容"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"修改/刪除 SD 卡的內容"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"允許應用程式寫入 SD 卡。"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="4131871541127211526">"允許應用程式寫入共用儲存裝置。"</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"允許應用程式寫入 SD 卡。"</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"存取快取檔案系統"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"允許應用程式讀取及寫入快取檔案系統。"</string>
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"限制密碼設定規則"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"限制允許使用的密碼類型。"</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"查看登入嘗試記錄"</string>
-    <!-- outdated translation 1961251179624843483 -->     <string name="policydesc_watchLogin" msgid="7227578260165172673">"監視者無法登入裝置執行部分動作。"</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"重設密碼"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"強制重新設定密碼。您必須取得以管理員提供的新密碼,才能登入。"</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"強制鎖定"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"裝置鎖定時可取得控制,但必須重新輸入密碼。"</string>
+    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+    <skip />
+    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
+    <skip />
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"設定密碼規則"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"控制螢幕解鎖密碼所允許的長度和字元"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"監視螢幕解鎖嘗試次數"</string>
+    <string name="policydesc_watchLogin" msgid="7227578260165172673">"監視螢幕解鎖時密碼輸入錯誤的次數,如果密碼輸入錯誤的次數過多,則會鎖定手機或清除手機的所有資料"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"變更螢幕解鎖密碼"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"變更螢幕解鎖密碼"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"鎖定螢幕"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"控制鎖定螢幕的方式和時間"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"清除所有資料"</string>
-    <!-- outdated translation 2314060933796396205 -->     <string name="policydesc_wipeData" msgid="7669895333814222586">"重設為原廠設定 (系統會刪除所有資料,且不會向您進行確認)。"</string>
+    <string name="policydesc_wipeData" msgid="7669895333814222586">"執行重設為原廠設定時,系統會直接清除手機資料而不提出警告"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"住家電話"</item>
     <item msgid="869923650527136615">"行動電話"</item>
@@ -610,10 +606,8 @@
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"允許應用程式讀取瀏覽器曾經造訪過的所有網址,以及瀏覽器的所有書籤。"</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"寫入瀏覽器的記錄與書籤"</string>
     <string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"允許應用程式修改儲存在電話上的瀏覽記錄或書籤。請注意:惡意應用程式可能會使用此選項來清除或修改您瀏覽器的資料。"</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"在鬧鐘應用程式中設定鬧鈴"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"允許應用程式設定您所安裝的鬧鐘應用程式執行鬧鈴功能 (有些鬧鐘應用程式並不支援此功能)。"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"修改瀏覽器地理資訊的權限"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"允許應用程式修改瀏覽器的地理位置權限,惡意應用程式可能會透過此方式允許將您的位置資訊任意傳送給某些網站。"</string>
     <string name="save_password_message" msgid="767344687139195790">"是否記住此密碼?"</string>
@@ -808,17 +802,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"顯示全部"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB 大量儲存裝置"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB 已連接"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"已透過 USB 連接手機與電腦。如要從電腦或 Android 系統的 SD 卡複製檔案,請選取下方按鈕。"</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="8231462750010066896">"已透過 USB 連接手機與電腦。如要在電腦和 Android 的共用儲存裝置之間複製檔案,請選取下方按鈕。"</string>
     <string name="usb_storage_message" product="default" msgid="4796759646167247178">"已透過 USB 連接手機與電腦。如要從電腦或 Android 系統的 SD 卡複製檔案,請選取下方按鈕。"</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"開啟 USB 儲存裝置"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"把 SD 卡當成 USB 儲存裝置時發生問題。"</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="4818347756402740261">"使用 USB 儲存裝置的共用儲存空間時發生問題。"</string>
     <string name="usb_storage_error_message" product="default" msgid="2534784751603345363">"把 SD 卡當成 USB 儲存裝置時發生問題。"</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB 已連接"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"選取此項將檔案複製到電腦,或從電腦複製。"</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"關閉 USB 儲存裝置"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"選取此處關閉 USB 儲存裝置。"</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB 儲存空間使用中"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"關閉 USB 儲存裝置前,請務必先將 Android 系統的 SD 卡從電腦上卸下 (退出)。"</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="8745345260780267185">"關閉 USB 儲存裝置前,請務必先從電腦卸載 (退出) Android 手機的共用儲存裝置。"</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"關閉 USB 儲存裝置前,請務必先將 Android 系統的 SD 卡從電腦上卸下 (退出)。"</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"關閉 USB 儲存裝置"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"關閉 USB 儲存裝置時發生問題。請檢查您是否已卸載 USB Host,然後再試一次。"</string>
@@ -826,9 +820,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"如果您開啟 USB 儲存裝置,則您正在使用的某些應用程式會停止運作,而且可能無法使用,待您將 USB 儲存裝置關閉才會恢復正常。"</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB 操作失敗"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"確定"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"將 SD 卡格式化"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="6577908006949742217">"格式化共用儲存裝置"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"將 SD 卡格式化"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"確定要將 SD 卡格式化嗎?該 SD 卡中的所有資料將會遺失。"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="3470815140068502824">"格式化共用儲存裝置時,是否清除其中儲存的所有檔案?這項動作無法復原!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"確定要將 SD 卡格式化嗎?該 SD 卡中的所有資料將會遺失。"</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"格式化"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB 偵錯模式已啟用"</string>
@@ -837,28 +831,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"待選項目"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"正在準備 SD 卡"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="4239516675028438997">"正在準備共用儲存裝置"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"正在準備 SD 卡"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"正在檢查錯誤。"</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"SD 卡為空白"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="3937345577983730873">"共用儲存裝置沒有內容"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"SD 卡為空白"</string>
-    <!-- outdated translation 1312266820092958014 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"SD 卡為空白或使用不支援的檔案系統。"</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="1606660756124629708">"共用儲存裝置無內容或使用不受支援的檔案系統。"</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD 卡內無檔案系統,或檔案系統不受支援。"</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"SD 卡已損壞"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="1724619902076528889">"共用儲存裝置已損壞"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"SD 卡已損壞"</string>
-    <!-- outdated translation 2679412884290061775 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"SD 卡已損壞。您可能需要將 SD 卡重新格式化。"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="6460311835130671194">"共用儲存裝置已損壞,您可能必須重新格式化。"</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD 卡已毀損,您可能必須予以重新格式化。"</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"SD 卡未正常移除"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="2582175016060432034">"共用儲存裝置已意外移除"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD 卡未正常移除"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"請先卸載 SD 卡,再將其移除,以免資料遺失。"</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="2005396464494648937">"請先卸載共用儲存裝置,再將其移除,以免資料遺失。"</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"請先卸載 SD 卡,再將其移除,以免資料遺失。"</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"可安全移除 SD 卡"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="36525881018679515">"共用儲存裝置已可安全移除"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"可安全移除 SD 卡"</string>
-    <!-- outdated translation 7613960686747592770 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"現在可以安全移除 SD 卡。"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="7503769106285188703">"您可安全移除共用儲存裝置了。"</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"您現在可以安全地移除 SD 卡。"</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"已移除 SD 卡"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="1874889764367085562">"共用儲存裝置已移除"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"已移除 SD 卡"</string>
-    <!-- outdated translation 4205117227342822275 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"已移除 SD 卡。請插入新的 SD 卡來增加裝置的儲存容量。"</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="2730890441331344776">"共用儲存裝置已移除。請插入新媒體。"</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD 卡已移除,請插入新的 SD 卡。"</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"找不到符合的活動"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"更新元件使用統計資料"</string>
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 340e23c..99fc5c2 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -148,6 +148,15 @@
     <!-- Flag indicating whether the we should enable the automatic brightness in Settings.
          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 -->
 
@@ -351,7 +360,7 @@
     <integer name="config_datause_notification_type">2</integer>
 
     <!-- Enables SIP on WIFI only -->
-    <bool name="config_sip_wifi_only">false</bool>
+    <bool name="config_sip_wifi_only">true</bool>
 
     <!-- Boolean indicating if restoring network selection should be skipped -->
     <!-- The restoring is handled by modem if it is true-->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index d9177e7..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>
 
@@ -1240,6 +1240,11 @@
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_cache_filesystem">Allows an application to read and write the cache filesystem.</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_use_sip">make/receive Internet calls</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_use_sip">Allows an application to use the SIP service to make/receive Internet calls.</string>
+
     <!-- Policy administration -->
 
     <!-- Title of policy access to limiting the user's password choices -->
@@ -2086,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. -->
@@ -2110,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. -->
@@ -2130,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. -->
@@ -2162,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/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index 276e281c..d5f385b 100755
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -45,6 +45,7 @@
 import android.util.Log;
 
 import java.io.File;
+import java.io.IOException;
 import java.io.InputStream;
 
 public class PackageManagerTests extends AndroidTestCase {
@@ -378,6 +379,18 @@
                     assertEquals(publicSrcPath, appInstallPath);
                     assertFalse((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
                     assertTrue(info.nativeLibraryDir.startsWith(dataDir.getPath()));
+
+                    // Make sure the native library dir is not a symlink
+                    final File nativeLibDir = new File(info.nativeLibraryDir);
+                    assertTrue("Native library dir should exist at " + info.nativeLibraryDir,
+                            nativeLibDir.exists());
+                    try {
+                        assertEquals("Native library dir should not be a symlink",
+                                info.nativeLibraryDir,
+                                nativeLibDir.getCanonicalPath());
+                    } catch (IOException e) {
+                        fail("Can't read " + nativeLibDir.getPath());
+                    }
                 } else if (rLoc == INSTALL_LOC_SD){
                     assertTrue("Application flags (" + info.flags
                             + ") should contain FLAG_EXTERNAL_STORAGE",
@@ -391,6 +404,19 @@
                     assertTrue("The native library path (" + info.nativeLibraryDir
                             + ") should start with " + SECURE_CONTAINERS_PREFIX,
                             info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX));
+
+                    // Make sure the native library in /data/data/<app>/lib is a
+                    // symlink to the ASEC
+                    final File nativeLibSymLink = new File(info.dataDir, "lib");
+                    assertTrue("Native library symlink should exist at " + nativeLibSymLink.getPath(),
+                            nativeLibSymLink.exists());
+                    try {
+                        assertEquals(nativeLibSymLink.getPath() + " should be a symlink to "
+                                + info.nativeLibraryDir, info.nativeLibraryDir, nativeLibSymLink
+                                .getCanonicalPath());
+                    } catch (IOException e) {
+                        fail("Can't read " + nativeLibSymLink.getPath());
+                    }
                 } else {
                     // TODO handle error. Install should have failed.
                     fail("Install should have failed");
@@ -1406,13 +1432,21 @@
                         receiver);
                 assertTrue(retCode);
                 ApplicationInfo info = getPm().getApplicationInfo(ip.pkg.packageName, 0);
-                assertNotNull(info);
+                assertNotNull("ApplicationInfo for recently installed application should exist",
+                        info);
                 if ((moveFlags & PackageManager.MOVE_INTERNAL) != 0) {
-                    assertTrue((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0);
-                    assertTrue(info.nativeLibraryDir.startsWith(info.dataDir));
+                    assertTrue("ApplicationInfo.FLAG_EXTERNAL_STORAGE flag should NOT be set",
+                            (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0);
+                    assertTrue("ApplicationInfo.nativeLibraryDir should start with " + info.dataDir,
+                            info.nativeLibraryDir.startsWith(info.dataDir));
                 } else if ((moveFlags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0){
-                    assertTrue((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
-                    assertTrue(info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX));
+                    assertTrue("ApplicationInfo.FLAG_EXTERNAL_STORAGE flag should be set",
+                            (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
+                    assertTrue("ApplicationInfo.nativeLibraryDir should start with " + SECURE_CONTAINERS_PREFIX,
+                            info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX));
+                    final File nativeLibSymLink = new File(info.dataDir, "lib");
+                    assertTrue("The data directory should have a 'lib' symlink that points to the ASEC container",
+                            nativeLibSymLink.getCanonicalPath().startsWith(SECURE_CONTAINERS_PREFIX));
                 }
             }
         } catch (NameNotFoundException e) {
diff --git a/core/tests/coretests/src/android/net/http/CookiesTest.java b/core/tests/coretests/src/android/net/http/CookiesTest.java
new file mode 100644
index 0000000..c9eca03
--- /dev/null
+++ b/core/tests/coretests/src/android/net/http/CookiesTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.net.http;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.logging.Logger;
+import java.util.logging.SimpleFormatter;
+import java.util.logging.StreamHandler;
+import junit.framework.TestCase;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.DefaultHttpClient;
+import tests.http.MockResponse;
+import tests.http.MockWebServer;
+
+public final class CookiesTest extends TestCase {
+
+    private MockWebServer server = new MockWebServer();
+
+    @Override protected void tearDown() throws Exception {
+        server.shutdown();
+        super.tearDown();
+    }
+
+    /**
+     * Test that we don't log potentially sensitive cookie values.
+     * http://b/3095990
+     */
+    public void testCookiesAreNotLogged() throws IOException, URISyntaxException {
+        // enqueue an HTTP response with a cookie that will be rejected
+        server.enqueue(new MockResponse()
+                .addHeader("Set-Cookie: password=secret; Domain=fake.domain"));
+        server.play();
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        Logger logger = Logger.getLogger("org.apache.http");
+        StreamHandler handler = new StreamHandler(out, new SimpleFormatter());
+        logger.addHandler(handler);
+        try {
+            HttpClient client = new DefaultHttpClient();
+            client.execute(new HttpGet(server.getUrl("/").toURI()));
+            handler.close();
+
+            String log = out.toString("UTF-8");
+            assertTrue(log, log.contains("password"));
+            assertTrue(log, log.contains("fake.domain"));
+            assertFalse(log, log.contains("secret"));
+
+        } finally {
+            logger.removeHandler(handler);
+        }
+    }
+}
diff --git a/core/tests/coretests/src/com/android/server/MountServiceTests.java b/core/tests/coretests/src/com/android/server/MountServiceTests.java
index 83e9d18..1f8c92e 100644
--- a/core/tests/coretests/src/com/android/server/MountServiceTests.java
+++ b/core/tests/coretests/src/com/android/server/MountServiceTests.java
@@ -21,7 +21,6 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
-import android.os.Environment;
 import android.os.FileUtils;
 import android.os.storage.OnObbStateChangeListener;
 import android.os.storage.StorageManager;
@@ -57,17 +56,15 @@
         }
     }
 
-    private interface CompletableTask {
-        public boolean isDone();
-    }
+    private static class ObbObserver extends OnObbStateChangeListener {
+        private String path;
 
-    private static class ObbObserver extends OnObbStateChangeListener implements CompletableTask {
-        public String path;
-        public String state;
+        public int state = -1;
         boolean done = false;
 
         @Override
-        public void onObbStateChange(String path, String state) {
+        public void onObbStateChange(String path, int state) {
+            Log.d(TAG, "Received message.  path=" + path + ", state=" + state);
             synchronized (this) {
                 this.path = path;
                 this.state = state;
@@ -76,32 +73,43 @@
             }
         }
 
+        public String getPath() {
+            assertTrue("Expected ObbObserver to have received a state change.", done);
+            return path;
+        }
+
+        public int getState() {
+            assertTrue("Expected ObbObserver to have received a state change.", done);
+            return state;
+        }
+
         public void reset() {
             this.path = null;
-            this.state = null;
+            this.state = -1;
             done = false;
         }
 
         public boolean isDone() {
             return done;
         }
-    }
 
-    private boolean waitForCompletion(CompletableTask task) {
-        long waitTime = 0;
-        synchronized (task) {
-            while (!task.isDone() && waitTime < MAX_WAIT_TIME) {
-                try {
-                    task.wait(WAIT_TIME_INCR);
-                    waitTime += WAIT_TIME_INCR;
-                } catch (InterruptedException e) {
-                    Log.i(TAG, "Interrupted during sleep", e);
+        public boolean waitForCompletion() {
+            long waitTime = 0;
+            synchronized (this) {
+                while (!isDone() && waitTime < MAX_WAIT_TIME) {
+                    try {
+                        wait(WAIT_TIME_INCR);
+                        waitTime += WAIT_TIME_INCR;
+                    } catch (InterruptedException e) {
+                        Log.i(TAG, "Interrupted during sleep", e);
+                    }
                 }
             }
-        }
 
-        return task.isDone();
+            return isDone();
+        }
     }
+
     private File getFilePath(String name) {
         final File filesDir = mContext.getFilesDir();
         final File outFile = new File(filesDir, name);
@@ -128,23 +136,52 @@
     }
 
     private void mountObb(StorageManager sm, final int resource, final File file,
-            String expectedState) {
+            int expectedState) {
         copyRawToFile(resource, file);
 
-        ObbObserver observer = new ObbObserver();
+        final ObbObserver observer = new ObbObserver();
         assertTrue("mountObb call on " + file.getPath() + " should succeed",
                 sm.mountObb(file.getPath(), null, observer));
 
         assertTrue("Mount should have completed",
-                waitForCompletion(observer));
+                observer.waitForCompletion());
+
+        if (expectedState == OnObbStateChangeListener.MOUNTED) {
+            assertTrue("OBB should be mounted", sm.isObbMounted(file.getPath()));
+        }
 
         assertEquals("Actual file and resolved file should be the same",
-                file.getPath(), observer.path);
+                file.getPath(), observer.getPath());
 
-        assertEquals(expectedState, observer.state);
+        assertEquals(expectedState, observer.getState());
     }
 
-    private String checkMountedPath(StorageManager sm, File file) {
+    private ObbObserver mountObbWithoutWait(final StorageManager sm, final int resource,
+            final File file) {
+        copyRawToFile(resource, file);
+
+        final ObbObserver observer = new ObbObserver();
+        assertTrue("mountObb call on " + file.getPath() + " should succeed", sm.mountObb(file
+                .getPath(), null, observer));
+
+        return observer;
+    }
+
+    private void waitForObbActionCompletion(final StorageManager sm, final File file,
+            final ObbObserver observer, int expectedState, boolean checkPath) {
+        assertTrue("Mount should have completed", observer.waitForCompletion());
+
+        assertTrue("OBB should be mounted", sm.isObbMounted(file.getPath()));
+
+        if (checkPath) {
+            assertEquals("Actual file and resolved file should be the same", file.getPath(),
+                    observer.getPath());
+        }
+
+        assertEquals(expectedState, observer.getState());
+    }
+
+    private String checkMountedPath(final StorageManager sm, final File file) {
         final String mountPath = sm.getMountedObbPath(file.getPath());
         assertStartsWith("Path should be in " + OBB_MOUNT_PREFIX,
                 OBB_MOUNT_PREFIX,
@@ -152,13 +189,21 @@
         return mountPath;
     }
 
-    private void unmountObb(StorageManager sm, final File outFile) {
-        ObbObserver observer = new ObbObserver();
+    private void unmountObb(final StorageManager sm, final File file, int expectedState) {
+        final ObbObserver observer = new ObbObserver();
+
         assertTrue("unmountObb call on test1.obb should succeed",
-                sm.unmountObb(outFile.getPath(), false, observer));
+ sm.unmountObb(file.getPath(),
+                false, observer));
 
         assertTrue("Unmount should have completed",
-                waitForCompletion(observer));
+                observer.waitForCompletion());
+
+        assertEquals(expectedState, observer.getState());
+
+        if (expectedState == OnObbStateChangeListener.UNMOUNTED) {
+            assertFalse("OBB should not be mounted", sm.isObbMounted(file.getPath()));
+        }
     }
 
     @LargeTest
@@ -167,7 +212,9 @@
 
         final File outFile = getFilePath("test1.obb");
 
-        mountObb(sm, R.raw.test1, outFile, Environment.MEDIA_MOUNTED);
+        mountObb(sm, R.raw.test1, outFile, OnObbStateChangeListener.MOUNTED);
+
+        mountObb(sm, R.raw.test1, outFile, OnObbStateChangeListener.ERROR_ALREADY_MOUNTED);
 
         final String mountPath = checkMountedPath(sm, outFile);
         final File mountDir = new File(mountPath);
@@ -175,7 +222,7 @@
         assertTrue("OBB mounted path should be a directory",
                 mountDir.isDirectory());
 
-        unmountObb(sm, outFile);
+        unmountObb(sm, outFile, OnObbStateChangeListener.UNMOUNTED);
     }
 
     @LargeTest
@@ -184,7 +231,7 @@
 
         final File outFile = getFilePath("test1_nosig.obb");
 
-        mountObb(sm, R.raw.test1_nosig, outFile, Environment.MEDIA_BAD_REMOVAL);
+        mountObb(sm, R.raw.test1_nosig, outFile, OnObbStateChangeListener.ERROR_INTERNAL);
 
         assertFalse("OBB should not be mounted",
                 sm.isObbMounted(outFile.getPath()));
@@ -199,7 +246,8 @@
 
         final File outFile = getFilePath("test1_wrongpackage.obb");
 
-        mountObb(sm, R.raw.test1_wrongpackage, outFile, Environment.MEDIA_BAD_REMOVAL);
+        mountObb(sm, R.raw.test1_wrongpackage, outFile,
+                OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
 
         assertFalse("OBB should not be mounted",
                 sm.isObbMounted(outFile.getPath()));
@@ -207,4 +255,31 @@
         assertNull("OBB's mounted path should be null",
                 sm.getMountedObbPath(outFile.getPath()));
     }
+
+    @LargeTest
+    public void testMountAndUnmountTwoObbs() {
+        StorageManager sm = getStorageManager();
+
+        final File file1 = getFilePath("test1.obb");
+        final File file2 = getFilePath("test2.obb");
+
+        ObbObserver oo1 = mountObbWithoutWait(sm, R.raw.test1, file1);
+        ObbObserver oo2 = mountObbWithoutWait(sm, R.raw.test1, file2);
+
+        Log.d(TAG, "Waiting for OBB #1 to complete mount");
+        waitForObbActionCompletion(sm, file1, oo1, OnObbStateChangeListener.MOUNTED, false);
+        Log.d(TAG, "Waiting for OBB #2 to complete mount");
+        waitForObbActionCompletion(sm, file2, oo2, OnObbStateChangeListener.MOUNTED, false);
+
+        final String mountPath1 = checkMountedPath(sm, file1);
+        final File mountDir1 = new File(mountPath1);
+        assertTrue("OBB mounted path should be a directory", mountDir1.isDirectory());
+
+        final String mountPath2 = checkMountedPath(sm, file2);
+        final File mountDir2 = new File(mountPath2);
+        assertTrue("OBB mounted path should be a directory", mountDir2.isDirectory());
+
+        unmountObb(sm, file1, OnObbStateChangeListener.UNMOUNTED);
+        unmountObb(sm, file2, OnObbStateChangeListener.UNMOUNTED);
+    }
 }
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/debug-tasks.jd b/docs/html/guide/developing/debug-tasks.jd
index 500ef58..f0bf84c 100644
--- a/docs/html/guide/developing/debug-tasks.jd
+++ b/docs/html/guide/developing/debug-tasks.jd
@@ -40,10 +40,13 @@
   your application, which can help you profile the performance of your application.</dd>
   <dt><strong><a href="{@docRoot}guide/developing/tools/ddms.html#logcat">logcat</a></strong></dt>
   <dd>Dumps a log of system
-      messages. The messages include a stack trace when the emulator throws an error,
+      messages. The messages include a stack trace when the device throws an error,
       as well as {@link android.util.Log} messages you've written from your application. To run
-      logcat, execute <code>adb logcat</code> or, from DDMS, select <strong>Device > Run
-      logcat</strong>.
+      logcat, execute <code>adb logcat</code> from your Android SDK {@code tools/} directory or,
+from DDMS, select <strong>Device > Run
+      logcat</strong>. When using the <a href="{@docRoot}sdk/eclipse-adt.html">ADT plugin for
+Eclipse</a>, you can also view logcat messages by opening the Logcat view, available from
+<strong>Window > Show View > Other > Android > Logcat</strong>.
       <p>{@link android.util.Log} is a logging
       class you can use to print out messages to the logcat. You can read messages
       in real time if you run logcat on DDMS (covered next). Common logging methods include:
@@ -148,72 +151,7 @@
 
 <h2 id="DebuggingWebPages">Debugging Web Pages</h2>
 
-<p>If you're developing a web application for Android devices, you can debug your JavaScript in the
-Android Browser using the Console APIs, which will output messages to logcat. If you're familiar
-debugging web pages with Firefox's FireBug or WebKit's Web Inspector, then you're probably familiar
-with the Console APIs. The Android Browser (and the {@link android.webkit.WebChromeClient}) supports
-most of the same APIs.</p>
-
-<p>When you call a function from the Console APIs (in the DOM's {@code window.console} object),
-you will see the output in logcat as a warning. For example, if your web page
-executes the following JavaScript:</p>
-<pre class="no-pretty-print">
-console.log("Hello World");
-</pre>
-<p>Then the logcat output from the Android Browser will look like this:</p>
-<pre class="no-pretty-print">
-W/browser ( 202): Console: Hello World http://www.example.com/hello.html :82
-</pre>
-
-<p>All Console messages from the Android Browser are tagged with the name "browser" on Android
-platforms running API Level 7 or higher. On platforms running API Level 6 or lower, Browser
-messages are tagged with the name "WebCore". The Android Browser also formats console messages
-with the log message
-preceded by "Console:" and then followed by the address and line number where the
-message occurred. (The format for the address and line number will appear different from the example
-above on platforms running API Level 6 or lower.)</p>
-
-<p>The Android Browser (and {@link android.webkit.WebChromeClient}) does not implement all of the
-Console APIs provided by Firefox or other WebKit-based browsers. Primarily, you need to depend
-on the basic text logging functions:</p>
-<ul>
-  <li>{@code console.log(String)}</li>
-  <li>{@code console.info(String)}</li>
-  <li>{@code console.warn(String)}</li>
-  <li>{@code console.error(String)}</li>
-</ul>
-<p>Although the Android Browser may not fully implement other Console functions, they will not raise
-run-time errors, but may not behave the same as they do on other desktop browsers.</p>
-
-<p>If you've implemented a custom {@link android.webkit.WebView} in your application, then in order
-to receive messages that are sent through the Console APIs, you must provide a {@link
-android.webkit.WebChromeClient} that implements the {@link
-android.webkit.WebChromeClient#onConsoleMessage(String,int,String) onConsoleMessage()} callback
-method. For example, assuming that the {@code myWebView} field references the {@link
-android.webkit.WebView} in your application, you can log debug messages like this:</p>
-<pre>
-myWebView.setWebChromeClient(new WebChromeClient() {
-  public void onConsoleMessage(String message, int lineNumber, String sourceID) {
-    Log.d("MyApplication", message + " -- From line " + lineNumber + " of " + sourceID);
-  }
-});
-</pre>
-<p>The {@link android.webkit.WebChromeClient#onConsoleMessage(String,int,String)
-onConsoleMessage()} method will be called each time one of the Console methods is called from
-within your {@link android.webkit.WebView}.</p>
-<p>When the "Hello World" log is executed through your {@link android.webkit.WebView}, it will
-now look like this:</p>
-<pre class="no-pretty-print">
-D/MyApplication ( 430): Hello World -- From line 82 of http://www.example.com/hello.html
-</pre>
-
-<p class="note"><strong>Note:</strong> The {@link
-android.webkit.WebChromeClient#onConsoleMessage(String,int,String) onConsoleMessage()} callback
-method was added with API Level 7. If you are using a custom {@link
-android.webkit.WebView} on a platform running API Level 6 or lower, then your Console messages will
-automatically be sent to logcat with the "WebCore" logging tag.</p>
-
-
+<p>See the <a href="{@docRoot}guide/webapps/debugging.html">Debugging Web Apps</a> document.</p>
 
 
 <h2 id="toptips">Top Debugging Tips</h2>
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 43a5e8d..2b803424 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -110,7 +110,7 @@
       <li class="toggle-list">
         <div><a href="<?cs var:toroot ?>guide/topics/resources/index.html">
                <span class="en">Application Resources</span>
-             </a> <span class="new">new!</span></div>
+             </a></div>
         <ul>
           <li><a href="<?cs var:toroot ?>guide/topics/resources/providing-resources.html">
                 <span class="en">Providing Resources</span>
@@ -120,14 +120,14 @@
               </a></li>
           <li><a href="<?cs var:toroot ?>guide/topics/resources/runtime-changes.html">
                 <span class="en">Handling Runtime Changes</span>
-              </a> <span class="new">new!</span></li>
+              </a></li>
           <li><a href="<?cs var:toroot ?>guide/topics/resources/localization.html">
                 <span class="en">Localization</span>
               </a></li>
           <li class="toggle-list">
             <div><a href="<?cs var:toroot ?>guide/topics/resources/available-resources.html">
               <span class="en">Resource Types</span>
-            </a> <span class="new">new!</span></div>
+            </a></div>
             <ul>
               <li><a href="<?cs var:toroot ?>guide/topics/resources/animation-resource.html">Animation</a></li>
               <li><a href="<?cs var:toroot ?>guide/topics/resources/color-list-resource.html">Color State List</a></li>
@@ -147,11 +147,11 @@
       <li class="toggle-list">
         <div><a href="<?cs var:toroot ?>guide/topics/data/data-storage.html">
             <span class="en">Data Storage</span>
-          </a> <span class="new">new!</span></div>
+          </a></div>
           <ul>
             <li><a href="<?cs var:toroot ?>guide/topics/data/backup.html">
                 <span class="en">Data Backup</span>
-              </a> <span class="new">new!</span>
+              </a>
             </li>
           </ul>
       </li>
@@ -227,7 +227,7 @@
         <ul>
           <li><a href="<?cs var:toroot ?>guide/topics/location/obtaining-user-location.html">
                 <span class="en">Obtaining User Location</span>
-              </a> <span class="new">new!</span></li>
+              </a></li>
         </ul>
       </li>
   <!--<li class="toggle-list">
@@ -246,7 +246,7 @@
       <li class="toggle-list">
         <div><a href="<?cs var:toroot?>guide/topics/search/index.html">
             <span class="en">Search</span>
-          </a> <span class="new">new!</span></div>
+          </a></div>
           <ul>
             <li><a href="<?cs var:toroot?>guide/topics/search/search-dialog.html">Using the Android Search Dialog</a></li>
             <li><a href="<?cs var:toroot?>guide/topics/search/adding-recent-query-suggestions.html">Adding Recent Query Suggestions</a></li>
@@ -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>
-            <span class="new">new!</span></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></li>
+            <span class="en">Device Administration</span>
+         </a> <span class="new">new!</span>
+    </li>
     </ul>
   </li>
 
@@ -306,18 +328,18 @@
            <div>
                 <a href="<?cs var:toroot ?>guide/developing/testing/index.html">
                    <span class="en">Testing</span>
-               </a> <span class="new">new!</span>
+               </a>
            </div>
            <ul>
               <li>
                 <a href="<?cs var:toroot ?>guide/developing/testing/testing_eclipse.html">
                   <span class="en">Testing in Eclipse, with ADT</span>
-                </a> <span class="new">new!</span>
+                </a>
               </li>
               <li>
                 <a href="<?cs var:toroot ?>guide/developing/testing/testing_otheride.html">
                   <span class="en">Testing in Other IDEs</span>
-                </a> <span class="new">new!</span>
+                </a>
               </li>
            </ul>
          </li>
@@ -332,8 +354,7 @@
       <!--<li><a href="<?cs var:toroot ?>guide/developing/tools/adt.html">ADT Plugin</a></li>-->
               <li><a href="<?cs var:toroot ?>guide/developing/tools/aidl.html">aidl</a></li>
               <li><a href="<?cs var:toroot ?>guide/developing/tools/avd.html">AVDs</a></li>
-              <li><a href="<?cs var:toroot ?>guide/developing/tools/bmgr.html">bmgr</a>
-            <span class="new">new!</span></li>
+              <li><a href="<?cs var:toroot ?>guide/developing/tools/bmgr.html">bmgr</a></li>
               <li><a href="<?cs var:toroot ?>guide/developing/tools/ddms.html">ddms</a></li>
               <li><a href="<?cs var:toroot ?>guide/developing/tools/othertools.html#dx">dx</a></li>
               <li><a href="<?cs var:toroot ?>guide/developing/tools/draw9patch.html">Draw 9-Patch</a></li>
@@ -413,7 +434,7 @@
     <ul>
       <li><a href="<?cs var:toroot ?>guide/practices/compatibility.html">
             <span class="en">Compatibility</span>
-          </a><span class="new">new!</span></li>
+          </a></li>
       <li><a href="<?cs var:toroot ?>guide/practices/screens_support.html">
             <span class="en">Supporting Multiple Screens</span>
           </a></li>
@@ -451,6 +472,25 @@
   </li>
 
   <li>
+    <h2><span class="en">Web Applications</span>
+    </h2>
+    <ul>
+      <li><a href="<?cs var:toroot ?>guide/webapps/targetting.html">
+            <span class="en">Targetting Android Devices</span>
+          </a> <span class="new">new!</span><!-- 10/8/10 --></li>
+      <li><a href="<?cs var:toroot ?>guide/webapps/webview.html">
+            <span class="en">Building Web Apps in WebView</span>
+          </a> <span class="new">new!</span><!-- 10/8/10 --></li>
+      <li><a href="<?cs var:toroot ?>guide/webapps/debugging.html">
+            <span class="en">Debugging Web Apps</span>
+          </a> <span class="new">new!</span><!-- 10/8/10 --></li>
+      <li><a href="<?cs var:toroot ?>guide/webapps/best-practices.html">
+            <span class="en">Best Practices for Web Apps</span>
+          </a> <span class="new">new!</span><!-- 10/8/10 --></li>
+    </ul>
+  </li>
+
+  <li>
     <h2><span class="en">Appendix</span>
                <span class="de" style="display:none">Anhang</span>
                <span class="es" style="display:none">Apéndice</span>
@@ -466,10 +506,10 @@
           </a></li>
       <li><a href="<?cs var:toroot ?>guide/appendix/market-filters.html">
             <span class="en">Market Filters</span>
-           </a> <span class="new">new!</span></li>
+           </a></li>
       <li><a href="<?cs var:toroot ?>guide/appendix/install-location.html">
             <span class="en">App Install Location</span>
-          </a> <span class="new">new!</span></li>
+          </a></li>
       <li><a href="<?cs var:toroot ?>guide/appendix/media-formats.html">
             <span class="en">Supported Media Formats</span>
           </a></li>
diff --git a/docs/html/guide/practices/design/responsiveness.jd b/docs/html/guide/practices/design/responsiveness.jd
index b811d1b..a00e3aa 100644
--- a/docs/html/guide/practices/design/responsiveness.jd
+++ b/docs/html/guide/practices/design/responsiveness.jd
@@ -99,6 +99,10 @@
 event timeout. These same practices should be followed for any other threads
 that display UI, as they are also subject to the same timeouts.</p>
 
+<p>You can use {@link android.os.StrictMode} to help find potentially
+long running operations such as network or database operations that
+you might accidentally be doing your main thread.</p>
+
 <p>The specific constraint on IntentReceiver execution time emphasizes what
 they were meant to do: small, discrete amounts of work in the background such
 as saving a setting or registering a Notification. So as with other methods
diff --git a/docs/html/guide/topics/admin/device-admin.jd b/docs/html/guide/topics/admin/device-admin.jd
index 4d9a14f..fda716a 100644
--- a/docs/html/guide/topics/admin/device-admin.jd
+++ b/docs/html/guide/topics/admin/device-admin.jd
@@ -1,24 +1,33 @@
-page.title=Android Device Administration API
+page.title=Device Administration
 @jd:body
+
 <div id="qv-wrapper">
 <div id="qv">
     <h2>In this document</h2>
     <ol>
 <li><a href="#overview">Device Administration API Overview</a>
     <ol>
+      <li><a href="#how">How does it work?</a></li>
       <li><a href="#policies">Policies</a></li>
     </ol>
   </li>
-  <li><a href="#how">How Does It Work?</a></li>
   <li><a href="#sample">Sample Application</a></li>
   <li><a href="#developing">Developing a Device Administration Application</a>
     <ol>
-      <li><a href="#manifest">Creating the Manifest</a></li>
-      <li><a href="#code">Implementing the Code</a>
-      </li>
+      <li><a href="#manifest">Creating the manifest</a></li>
+      <li><a href="#code">Implementing the code</a></li>
     </ol>
+  </li>
+
+ </ol>
+
+    <h2>Key classes</h2>
+    <ol>
+      <li>{@link android.app.admin.DeviceAdminReceiver}</li>
+      <li>{@link android.app.admin.DevicePolicyManager}</li>
+      <li>{@link android.app.admin.DeviceAdminInfo}</li>
     </ol>
-  </div>
+</div>
 </div>
 
 <p>Android 2.2 introduces support for enterprise applications by offering the
@@ -37,7 +46,10 @@
 solutions for Android-powered devices. It discusses the various features
 provided by the Device Administration API to provide stronger security for
 employee devices that are powered by Android.</p>
+
+
 <h2 id="overview">Device Administration API Overview</h2>
+
 <p>Here are examples of the types of applications that might use the Device Administration API:</p>
 <ul>
   <li>Email clients.</li>
@@ -45,14 +57,14 @@
   <li>Device management services and applications.</li>
 </ul>
 
-<h3 id="how">How Does it Work?</h3>
+<h3 id="how">How does it work?</h3>
 <p>You use the Device Administration API to write device admin applications that users
 install on their devices. The device admin application enforces the desired
 policies. Here's how it works:</p> <ul>
   <li>A system administrator writes a device admin application that enforces
 remote/local device security policies. These policies could be hard-coded into
 the app, or the application could dynamically fetch policies from a third-party
-server. </li> 
+server. </li>
 <li>The  application is installed on users' devices. Android does
 not currently have an automated provisioning solution. Some of the ways a sysadmin might
 distribute the application to users are as follows:
@@ -68,7 +80,7 @@
   <li>The system prompts the user to enable the device admin application. How
 and when this happens depends on how the application is implemented.</li>
 <li>Once  users enable the device admin application, they are subject to
-its policies. Complying with those policies typically confers benefits, such as 
+its policies. Complying with those policies typically confers benefits, such as
 access to sensitive systems and data.</li>
 </ul>
 <p>If users do not enable the device admin app, it remains on the device, but in an inactive state. Users will not be subject to its policies, and they will conversely not get any of the application's benefits&mdash;for example, they may not be able to sync data.</p>
@@ -88,12 +100,14 @@
 <p>To uninstall an existing device admin application, users need to
 first unregister the application as an administrator. </p>
 
-<h3 id ="policies">Policies</h3>
+
+<h3 id="policies">Policies</h3>
+
 <p>In an enterprise setting, it's often the case that employee devices must
 adhere to a strict set of policies that govern the use of the device. The
 Device Administration API supports the  policies listed in Table 1.
 Note that the Device Administration API currently only supports passwords for screen
-lock:</p> 
+lock:</p>
 <p class="table-caption"><strong>Table 1.</strong> Policies supported by the Device Administration API.</p>
 <table border="1">
   <tr>
@@ -109,7 +123,7 @@
     <td>Set the required number of characters for the password. For example, you
 can require PIN or passwords to have at least six characters. </td> </tr>
   <tr>
-    <td>Alphanumeric password required</td> 
+    <td>Alphanumeric password required</td>
     <td>Requires that passwords have a
 combination of letters and numbers. They may include symbolic characters.
     </td>
@@ -128,7 +142,9 @@
 need to enter their PIN or passwords again before they can use their devices and
 access data.  The value can be between 1 and 60 minutes.</td> </tr>
 </table>
-<h4>Other Features</h4>
+
+<h4>Other features</h4>
+
 <p>In addition to supporting the policies listed in the above table, the Device
 Administration API lets you do the following:</p> <ul>
   <li>Prompt user to set a new password.</li>
@@ -138,6 +154,7 @@
 
 
 <h2 id="sample">Sample Application</h2>
+
 <p>The examples used in this document are based on the <a
 href="{@docRoot}resources/samples/ApiDemos/src/com/example/
 android/apis/app/DeviceAdminSample.html">Device Administration API
@@ -147,7 +164,7 @@
 Getting the Samples</a>. Here is the  <a
 href="{@docRoot}resources/samples/ApiDemos/src/com/example/
 android/apis/app/DeviceAdminSample.html">complete code</a> for
-the sample. </p> 
+the sample. </p>
 <p>The
 sample application offers a demo of device admin features. It presents users
 with a user interface that lets them enable the device admin application. Once
@@ -169,13 +186,17 @@
 <img src="{@docRoot}images/admin/device-admin-app.png"/>
 <p class="img-caption"><strong>Figure 1.</strong> Screenshot of the Sample Application</p>
 
+
+
 <h2 id="developing">Developing a Device Administration Application</h2>
 
 <p>System administrators can use the Device Administration API to write an application
 that enforces remote/local device security policy enforcement. This section
 summarizes the steps involved in creating a device administration
 application.</p>
-<h3 id="manifest">Creating the Manifest</h3>
+
+<h3 id="manifest">Creating the manifest</h3>
+
 <p>To use the Device Administration API, the application's
 manifest must include the following:</p>
 <ul>
@@ -207,7 +228,7 @@
         &lt;action android:name=&quot;android.app.action.DEVICE_ADMIN_ENABLED&quot; /&gt;
     &lt;/intent-filter&gt;
 &lt;/receiver&gt;</pre>
- 
+
  <p>Note that:</p>
 <ul>
   <li>The activity in the sample application is an {@link android.app.Activity}
@@ -218,7 +239,7 @@
 an inner class; it just is in this example.</li>
 
 <li>The following attributes refer to string resources that for the sample application reside in
-<code>ApiDemos/res/values/strings.xml</code>. For more information about resources, see 
+<code>ApiDemos/res/values/strings.xml</code>. For more information about resources, see
 <a
 href="{@docRoot}guide/topics/resources/index.html">Application Resources</a>.
 <ul>
@@ -234,8 +255,8 @@
 a label.</li>
 </ul>
 
- 
-<li><code>android:permission=&quot;android.permission.BIND_DEVICE_ADMIN&quot; 
+
+<li><code>android:permission=&quot;android.permission.BIND_DEVICE_ADMIN&quot;
 </code> is a permission that a {@link android.app.admin.DeviceAdminReceiver} subclass must
 have, to ensure that only the system can interact with the receiver (no application can be granted this permission). This
 prevents other applications from abusing your device admin app.</li>
@@ -273,11 +294,15 @@
 include all of the policies, just the ones that are relevant for your app.
 </p>
 For more discussion of the manifest file, see the <a
-href="{@docRoot}guide/topics/manifest/manifest-intro.html">Android Developers Guide</a>. 
-<h2 id="code">Implementing the Code</h2>
+href="{@docRoot}guide/topics/manifest/manifest-intro.html">Android Developers Guide</a>.
+
+
+
+<h3 id="code">Implementing the code</h3>
+
 <p>The Device Administration API includes the following classes:</p>
 <dl>
-  <dt>{@link android.app.admin.DeviceAdminReceiver}</dt> 
+  <dt>{@link android.app.admin.DeviceAdminReceiver}</dt>
      <dd>Base class for implementing a device administration component. This class provides
 a convenience for interpreting the raw intent actions   that are sent by the
 system. Your Device Administration application must include a
@@ -287,7 +312,7 @@
 this class must have published a {@link android.app.admin.DeviceAdminReceiver} that the user
 has currently enabled. The {@link android.app.admin.DevicePolicyManager} manages policies for
 one or more {@link android.app.admin.DeviceAdminReceiver} instances</dd>
-  <dt>{@link android.app.admin.DeviceAdminInfo}</dt> 
+  <dt>{@link android.app.admin.DeviceAdminInfo}</dt>
 <dd>This class is used to specify metadata
 for a device administrator component.</dd>
 </dl>
@@ -295,6 +320,7 @@
 The rest of this section describes how you use the {@link
 android.app.admin.DeviceAdminReceiver} and
 {@link android.app.admin.DevicePolicyManager} APIs to write a device admin application.</p>
+
 <h4 id="receiver">Subclassing DeviceAdminReceiver</h4>
 <p>To create a device admin application, you must subclass
 {@link android.app.admin.DeviceAdminReceiver}. The {@link android.app.admin.DeviceAdminReceiver} class
@@ -305,7 +331,7 @@
 events. For example:</p>
 <pre>public class DeviceAdminSample extends DeviceAdminReceiver {
 
-... 
+...
     &#64;Override
     public void onEnabled(Context context, Intent intent) {
         showToast(context, &quot;Sample Device Admin: enabled&quot;);
@@ -331,30 +357,32 @@
     }
 ...
 }</pre>
-<h4 id="enabling">Enabling the Application</h4>
+
+<h4 id="enabling">Enabling the application</h4>
 <p>One of the major events a device admin application has to handle is the user
 enabling the application. The user must explicitly enable the application for
 the policies to be enforced. If the user chooses not to enable the application
 it will still be present on the device, but its policies will not be enforced, and the user will not
 get any of the application's benefits.</p>
 <p>The process of enabling the application begins when the user performs an
-action that triggers the {@link android.app.admin.DevicePolicyManager#ACTION_ADD_DEVICE_ADMIN} 
+action that triggers the {@link android.app.admin.DevicePolicyManager#ACTION_ADD_DEVICE_ADMIN}
 intent. In the
 sample application, this happens when the user clicks the <strong>Enable
 Admin</strong> button. </p>
 <p>When the user clicks the <strong>Enable Admin</strong> button, the display
-changes to prompt the user to enable the device admin application, as shown in <strong>Figure 2</strong>.</p>
+changes to prompt the user to enable the device admin application, as shown in figure
+2.</p>
 
 <img src="{@docRoot}images/admin/device-admin-activate-prompt.png"/>
 <p class="img-caption"><strong>Figure 2.</strong> Sample Application: Activating the Application</p>
 <p>Below  is the code that gets executed when the user clicks the <strong>Enable
-Admin</strong> button shown in <strong>Figure 1</strong>. </p>
+Admin</strong> button shown in figure 1. </p>
 
 <pre> private OnClickListener mEnableListener = new OnClickListener() {
     public void onClick(View v) {
         // Launch the activity to have the user enable our admin.
         Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
-        intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, 
+        intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
                mDeviceAdminSample);
         intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
                &quot;Additional text explaining why this needs to be added.&quot;);
@@ -379,10 +407,10 @@
 }</pre>
 
 <p>The line
-<code>intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, 
+<code>intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
 mDeviceAdminSample)</code> states that <code>mDeviceAdminSample</code> (which is
 a {@link android.app.admin.DeviceAdminReceiver} component) is the target policy.
-This line invokes the user interface shown in <strong>Figure 2</strong>, which guides users through
+This line invokes the user interface shown in figure 2, which guides users through
 adding the device administrator to the system (or allows them to reject it).</p>
 
 <p>When the application needs to perform an operation that is contingent on the
@@ -402,14 +430,16 @@
     // do something else
 }
 </pre>
-<h3 id="admin_ops">Managing Policies</h3>
+
+<h3 id="admin_ops">Managing policies</h3>
 <p>{@link android.app.admin.DevicePolicyManager} is a public class for managing policies
 enforced on a device. {@link android.app.admin.DevicePolicyManager} manages policies for one
 or more {@link android.app.admin.DeviceAdminReceiver} instances. </p>
 <p>You get a handle to the {@link android.app.admin.DevicePolicyManager} as follows: </p>
-<pre>DevicePolicyManager mDPM =
-(DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);<br
-/></pre>
+<pre>
+DevicePolicyManager mDPM =
+    (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
+</pre>
 <p>This section describes how to use {@link android.app.admin.DevicePolicyManager} to perform
  administrative tasks:</p>
 <ul>
@@ -417,26 +447,29 @@
   <li><a href="#lock">Set  device lock</a></li>
   <li><a href="#wipe">Perform data wipe</a></li>
 </ul>
+
 <h4 id="pwd">Set password policies</h4>
 <p>{@link android.app.admin.DevicePolicyManager} includes APIs for setting and enforcing the
 device password policy. In the Device Administration API, the password only applies to
 screen lock. This section describes common password-related tasks.</p>
+
 <h5>Set a password for the device</h5>
 <p>This code displays a user interface prompting the user to set a password:</p>
 <pre>Intent intent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
 startActivity(intent);
 </pre>
+
 <h5>Set the password quality</h5>
 <p>The password quality can be one of the following {@link android.app.admin.DevicePolicyManager} constants: </p>
 <dl>
-  <dt>{@link android.app.admin.DevicePolicyManager#PASSWORD_QUALITY_ALPHABETIC}</dt><dd>The user must enter a  
+  <dt>{@link android.app.admin.DevicePolicyManager#PASSWORD_QUALITY_ALPHABETIC}</dt><dd>The user must enter a
 password containing at least alphabetic (or other symbol) characters.</dd>
-  <dt>{@link android.app.admin.DevicePolicyManager#PASSWORD_QUALITY_ALPHANUMERIC}</dt><dd>The user must enter a  
+  <dt>{@link android.app.admin.DevicePolicyManager#PASSWORD_QUALITY_ALPHANUMERIC}</dt><dd>The user must enter a
 password containing at least <em>both</em> numeric <em>and</em> alphabetic (or
 other symbol) characters.</dd>
   <dt>{@link android.app.admin.DevicePolicyManager#PASSWORD_QUALITY_NUMERIC}</dt><dd>The user must enter a   password
 containing at least numeric characters.</dd>
-  <dt>{@link android.app.admin.DevicePolicyManager#PASSWORD_QUALITY_SOMETHING}</dt><dd>The policy requires some kind  
+  <dt>{@link android.app.admin.DevicePolicyManager#PASSWORD_QUALITY_SOMETHING}</dt><dd>The policy requires some kind
 of password, but doesn't care what it is.</dd>
   <dt>{@link android.app.admin.DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED}</dt><dd>
   The policy has no requirements   for the password. </dd>
@@ -448,6 +481,7 @@
 ...
 mDPM.setPasswordQuality(mDeviceAdminSample, DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC);
 </pre>
+
 <h5>Set the minimum password length</h5>
 <p>You can specify that a password must be at least the specified minimum
 length. For example:</p>
@@ -457,19 +491,21 @@
 ...
 mDPM.setPasswordMinimumLength(mDeviceAdminSample, pwLength);
 </pre>
+
 <h5>Set maximum failed password attempts</h5>
 <p>You can set the maximum number of allowed failed password attempts before the
 device is wiped (that is, reset to factory settings). For example:</p>
-<pre>DevicePolicyManager mDPM; 
-ComponentName mDeviceAdminSample; 
+<pre>DevicePolicyManager mDPM;
+ComponentName mDeviceAdminSample;
 int maxFailedPw;
  ...
 mDPM.setMaximumFailedPasswordsForWipe(mDeviceAdminSample, maxFailedPw);</pre>
+
 <h4 id="lock">Set  device lock</h4>
 <p>You can set the maximum period of user inactivity that can occur before the
 device locks. For example:</p>
 <pre>
-DevicePolicyManager mDPM; 
+DevicePolicyManager mDPM;
 ComponentName mDeviceAdminSample;
 ...
 long timeMs = 1000L*Long.parseLong(mTimeout.getText().toString());
@@ -477,9 +513,11 @@
 </pre>
 <p>You can also programmatically tell the device to lock immediately:</p>
 <pre>
-DevicePolicyManager mDPM; 
+DevicePolicyManager mDPM;
 mDPM.lockNow();</pre>
+
 <h4 id="wipe">Perform data wipe</h4>
+
 <p>You can use the {@link android.app.admin.DevicePolicyManager} method
 {@link android.app.admin.DevicePolicyManager#wipeData wipeData()} to reset the device to factory settings. This is useful
 if the device is lost or stolen. Often the decision to wipe the device is the
@@ -488,7 +526,7 @@
 wiped after a specific number of failed password attempts.</p>
 <p>You wipe data as follows:</p>
 <pre>
-DevicePolicyManager mDPM; 
+DevicePolicyManager mDPM;
 mDPM.wipeData(0);</pre>
 <p>The {@link android.app.admin.DevicePolicyManager#wipeData wipeData()} method takes as its parameter a bit mask of
 additional options. Currently the value must be 0. </p>
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..42a9db5
--- /dev/null
+++ b/docs/html/guide/topics/testing/index.jd
@@ -0,0 +1,76 @@
+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>
+        <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>
+    <li>
+        <a href="{@docRoot}guide/topics/testing/what_to_test.html">What to Test</a>
+        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>
+</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 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/guide/webapps/best-practices.jd b/docs/html/guide/webapps/best-practices.jd
new file mode 100644
index 0000000..1bde5bf
--- /dev/null
+++ b/docs/html/guide/webapps/best-practices.jd
@@ -0,0 +1,90 @@
+page.title=Best Practices for Web Apps
+@jd:body
+
+<style>
+.bold li {
+  font-weight:bold;
+}
+.bold li * {
+  font-weight:normal;
+}
+</style>
+
+<p>Developing web pages and web applications for mobile devices presents a different set of
+challenges compared to developing a web page for the typical
+desktop web browser. To help you get started, the following is a list of practices you should
+follow in order to provide the most effective web application for Android and other mobile
+devices.</p>
+
+<ol class="bold">
+
+<li>Redirect mobile devices to a dedicated mobile version of your web site
+  <p>There are several ways you can redirect requests to the mobile version of your web site, using
+server-side redirects. Most often, this is done by "sniffing" the User Agent
+string provided by the web browser. To determine whether to serve a mobile version of your site, you
+should simply look for the "mobile" string in the User Agent, which matches a wide variety of mobile
+devices. If necessary, you can also identify the specific operating system in the User Agent string
+(such as "Android 2.1").</p>
+</li>
+
+
+<li>Use a valid markup DOCTYPE that's appropriate for mobile devices
+  <p>The most common markup language used for mobile web sites is <a
+href="http://www.w3.org/TR/2008/REC-xhtml-basic-20080729/">XHTML Basic</a>. This standard
+ensures specific markup for your web site that works best on mobile devices. For instance, it does
+not allow HTML frames or nested tables, which perform poorly on mobile devices. Along with the
+DOCTYPE, be sure to declare the appropriate character encoding for the document (such as
+UTF-8).</p>
+  <p>For example:</p>
+<pre>
+&lt;?xml version="1.0" encoding="UTF-8"?&gt;
+&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN"
+    "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd"&gt;
+</pre>
+
+  <p>Also be sure that your web page markup is valid against the declared DOCTYPE. Use a
+validator, such as the one available at
+<a href="http://validator.w3.org/">http://validator.w3.org</a>.</p>
+</li>
+
+
+<li>Use viewport meta data to properly resize your web page
+  <p>In your document {@code &lt;head&gt;}, you should provide meta data that specifies how you
+want the browser's viewport to render your web page. For example, your viewport meta data can
+specify the height and width for the browser's viewport, the initial web page scale and even the
+target screen density.</p>
+  <p>For example:</p>
+<pre>
+&lt;meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"&gt;
+</pre>
+  <p>For more information about how to use viewport meta data for Android-powered devices, read <a
+href="{@docRoot}guide/webapps/targetting.html">Targetting Android Devices</a>.</p>
+</li>
+
+
+<li>Avoid multiple file requests
+  <p>Because mobile devices typically have a connection speed far slower than a desktop
+computer, you should make your web pages load as fast as possible. One way to speed it up is to
+avoid loading extra files such as stylesheets and script files in the {@code
+&lt;head&gt;}. Instead, provide your CSS and JavaScript directly in the &lt;head&gt; (or
+at the end of the &lt;body&gt;, for scripts that you don't need until the page is loaded).
+Alternatively, you should optimize the size and speed of your files by compressing them with tools
+like <a href="http://code.google.com/p/minify/">Minify</a>.</p>
+</li>
+
+
+<li>Use a vertical linear layout
+  <p>Avoid the need for the user to scroll left and right while navigating your web
+page. Scrolling up and down is easier for the user and makes your web page simpler.</p>
+</li>
+
+</ol>
+
+<p>For a more thorough guide to creating great mobile web applications, see the W3C's <a
+href="http://www.w3.org/TR/mobile-bp/">Mobile Web Best Practices</a>. For other guidance on
+improving the speed of your web site (for mobile and desktop), see Yahoo!'s guide to <a
+href="http://developer.yahoo.com/performance/index.html#rules">Exceptional Performance</a> and
+Google's speed tutorials in <a href="http://code.google.com/speed/articles/">Let's make the web
+faster</a>.</p>
+
+
diff --git a/docs/html/guide/webapps/debugging.jd b/docs/html/guide/webapps/debugging.jd
new file mode 100644
index 0000000..098e17c
--- /dev/null
+++ b/docs/html/guide/webapps/debugging.jd
@@ -0,0 +1,158 @@
+page.title=Debugging Web Apps
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+<h2>Quickview</h2>
+<ul>
+  <li>You can debug your web app using console methods in JavaScript</li>
+  <li>If debugging in a custom WebView, you need to implement a callback method to handle debug
+messages</li>
+</ul>
+
+<h2>In this document</h2>
+<ol>
+  <li><a href="#Browser">Using Console APIs in the Android Browser</a></li>
+  <li><a href="#WebView">Using Console APIs in WebView</a></li>
+</ol>
+
+<h2>See also</h2>
+<ol>
+  <li><a href="{@docRoot}guide/developing/debug-tasks.html">Debugging Tasks</a></li>
+</ol>
+
+</div>
+</div>
+
+<p>If you're developing a web application for Android, you can debug your JavaScript
+using the {@code console} JavaScript APIs, which output messages to logcat. If you're familiar with
+debugging web pages with Firebug or Web Inspector, then you're probably familiar
+with using {@code console} (such as {@code console.log()}). Android's WebKit framework supports most
+of the same APIs, so you can receive logs from your web page when debugging in Android's Browser
+or in your own {@link android.webkit.WebView}.</p>
+
+
+
+<h2 id="Browser">Using Console APIs in the Android Browser</h2>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+  <h2>Logcat</h2>
+  <p>Logcat is a tool that dumps a log of system messages. The messages include a stack trace when
+the device throws an error, as well as log messages written from your application and
+those written using JavaScript {@code console} APIs.</p>
+  <p>To run logcat and view messages, execute
+{@code adb logcat} from your Android SDK {@code tools/} directory, or, from DDMS, select
+<strong>Device > Run logcat</strong>. When using the <a href="{@docRoot}sdk/eclipse-adt.html">ADT
+plugin for Eclipse</a>, you can also view logcat messages by opening the Logcat view, available from
+<strong>Window > Show View > Other > Android > Logcat</strong>.</p>
+  <p>See <a href="{@docRoot}guide/developing/debug-tasks.html">Debugging
+Tasks</a> for more information about logcat.</p>
+</div>
+</div>
+
+<p>When you call a {@code console} function (in the DOM's {@code window.console} object),
+the output appears in logcat. For example, if your web page executes the following
+JavaScript:</p>
+<pre>
+console.log("Hello World");
+</pre>
+<p>Then the logcat message looks something like this:</p>
+<pre class="no-pretty-print">
+Console: Hello World http://www.example.com/hello.html :82
+</pre>
+
+<p>The format of the message might appear different depending on which version of Android you're
+using. On Android 2.1 and higher, console messages from the Android Browser
+are tagged with the name "browser". On Android 1.6 and lower, Android Browser
+messages are tagged with the name "WebCore".</p>
+
+<p>Android's WebKit does not implement all of the console APIs available in other desktop browsers.
+You can, however, use the basic text logging functions:</p>
+<ul>
+  <li>{@code console.log(String)}</li>
+  <li>{@code console.info(String)}</li>
+  <li>{@code console.warn(String)}</li>
+  <li>{@code console.error(String)}</li>
+</ul>
+
+<p>Other console functions don't raise errors, but might not behave the same as what you
+expect from other web browsers.</p>
+
+
+
+<h2 id="WebView">Using Console APIs in WebView</h2>
+
+<p>If you've implemented a custom {@link android.webkit.WebView} in your application, all the
+same console APIs are supported when debugging your web page in WebView. On Android
+1.6 and lower, console messages are automatically sent to logcat with the
+"WebCore" logging tag. If you're targetting Android 2.1 (API Level 7) or higher, then you must
+provide a {@link android.webkit.WebChromeClient}
+that implements the {@link android.webkit.WebChromeClient#onConsoleMessage(String,int,String)
+onConsoleMessage()} callback method, in order for console messages to appear in logcat.</p>
+
+<p>Additionally, the {@link
+android.webkit.WebChromeClient#onConsoleMessage(String,int,String)} method introduced in API
+Level 7 has been deprecated in favor of {@link
+android.webkit.WebChromeClient#onConsoleMessage(ConsoleMessage)} in API Level 8.</p>
+
+<p>Whether you're developing for Android 2.1 (API Level 7) or Android 2.2 (API Level 8 or
+greater), you must implement {@link android.webkit.WebChromeClient} and override the appropriate
+{@link
+android.webkit.WebChromeClient#onConsoleMessage(String,int,String) onConsoleMessage()} callback
+method. Then, apply the {@link android.webkit.WebChromeClient} to your {@link
+android.webkit.WebView} with {@link android.webkit.WebView#setWebChromeClient(WebChromeClient)
+setWebChromeClient()}.
+
+<p>Using API Level 7, this is how your code for {@link
+android.webkit.WebChromeClient#onConsoleMessage(String,int,String)} might look:</p>
+
+<pre>
+WebView myWebView = (WebView) findViewById(R.id.webview);
+myWebView.setWebChromeClient(new WebChromeClient() {
+  public void onConsoleMessage(String message, int lineNumber, String sourceID) {
+    Log.d("MyApplication", message + " -- From line "
+                         + lineNumber + " of "
+                         + sourceID);
+  }
+});
+</pre>
+
+<p>With API Level 8 or greater, your code for {@link
+android.webkit.WebChromeClient#onConsoleMessage(ConsoleMessage)} might look like this:</p>
+
+<pre>
+WebView myWebView = (WebView) findViewById(R.id.webview);
+myWebView.setWebChromeClient(new WebChromeClient() {
+  public boolean onConsoleMessage(ConsoleMessage cm) {
+    Log.d("MyApplication", cm.{@link android.webkit.ConsoleMessage#message()} + " -- From line "
+                         + cm.{@link android.webkit.ConsoleMessage#lineNumber()} + " of "
+                         + cm.{@link android.webkit.ConsoleMessage#sourceId()} );
+    return true;
+  }
+});
+</pre>
+
+<p>The {@link android.webkit.ConsoleMessage} also includes a {@link
+android.webkit.ConsoleMessage.MessageLevel MessageLevel} to indicate the type of console message
+being delivered. You can query the message level with {@link
+android.webkit.ConsoleMessage#messageLevel()} to determine the severity of the message, then
+use the appropriate {@link android.util.Log} method or take other appropriate actions.</p>
+
+<p>Whether you're using {@link
+android.webkit.WebChromeClient#onConsoleMessage(String,int,String)} or {@link
+android.webkit.WebChromeClient#onConsoleMessage(ConsoleMessage)}, when you execute a console method
+in your web page, Android calls the appropriate {@link
+android.webkit.WebChromeClient#onConsoleMessage(String,int,String)
+onConsoleMessage()} method so you can report the error. For example, with the example code above,
+a logcat message is printed that looks like this:</p>
+
+<pre class="no-pretty-print">
+Hello World -- From line 82 of http://www.example.com/hello.html
+</pre>
+
+
+
+
+
+
diff --git a/docs/html/guide/webapps/targetting.jd b/docs/html/guide/webapps/targetting.jd
new file mode 100644
index 0000000..844b9ca
--- /dev/null
+++ b/docs/html/guide/webapps/targetting.jd
@@ -0,0 +1,419 @@
+page.title=Targetting Android Devices
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+<h2>Quickview</h2>
+<ul>
+  <li>You can target your web page for different screens using viewport metadata, CSS, and
+JavaScript</li>
+  <li>Techniques in this document work for Android 2.0 and greater</li>
+</ul>
+
+<h2>In this document</h2>
+<ol>
+<li><a href="#Metadata">Using Viewport Metadata</a>
+  <ol>
+    <li><a href="#ViewportSize">Defining the viewport size</a></li>
+    <li><a href="#ViewportScale">Defining the viewport scale</a></li>
+    <li><a href="#ViewportDensity">Defining the viewport target density</a></li>
+  </ol>
+</li>
+<li><a href="#DensityCSS">Targetting Device Density with CSS</a></li>
+<li><a href="#DensityJS">Targetting Device Density with JavaScript</a></li>
+</ol>
+
+</div>
+</div>
+
+
+<p>If you're developing a web application for Android or redesigning one for mobile devices, you
+should account for some factors that affect the way the Android Browser renders your web page by
+default. There are two fundamental factors that you should account for:</p>
+
+<dl>
+  <dt>The size of the viewport and scale of the web page</dt>
+    <dd>When the Android Browser loads a web page, the default behavior is to load the
+page in "overview mode," which provides a zoomed-out perspective of the web page. You can override
+this behavior for your web page by defining the default dimensions of the viewport or the initial
+scale of the viewport. You can also control how much the user can zoom in and out of your web
+page, if at all.
+    <p>However, the user can also disable overview mode in the
+Browser settings, so you should not assume that your page will load in overview mode. You
+should instead customize the viewport size and/or scale as appropriate for your page.</p></dd>
+
+  <dt>The device's screen density</dt>
+    <dd>The screen density (the number of pixels per inch) on an Android-powered device affects
+the resolution and size at which a web page is displayed. (There are three screen density
+categories: low, medium, and high.) The Android Browser compensates for variations in the screen
+density by scaling a web page so that all devices display the web page at the same perceivable size
+as a medium-density screen. If graphics are an important element of your web design, you
+should pay close attention to the scaling that occurs on different densities, because image scaling
+can produce artifacts (blurring and pixelation). 
+      <p>To provide the best visual representation on all
+screen densities, you should control how scaling occurs by providing viewport metadata about
+your web page's target screen density and providing alternative graphics for different screen
+densities, which you can apply to different screens using CSS or JavaScript.</p></dd>
+</dl>
+
+<p>The rest of this document describes how you can account for these effects, and how to target
+your web page for specific screen configurations.</p>
+
+<p class="note"><strong>Note:</strong> The features described in this document are supported
+by the Android Browser application on Android 2.0 and greater. Third-party web browsers running on
+Android might not support these techniques for controlling the viewport size and targetting
+screen densities.</p>
+
+
+
+<h2 id="Metadata">Using Viewport Metadata</h2>
+
+<p>The viewport is the area in which the Android Browser
+draws a web page. Although the viewport's visible area matches the size of the screen,
+the viewport has its own dimensions that determine the number of pixels available to a web page.
+That is, the number of pixels available to a web page before it exceeds the screen area is
+defined by the dimensions of the viewport,
+not the dimensions of the device screen. For example, although a device screen might have a width of
+480 pixels, the viewport can have a width of 800 pixels, so that a web page designed to be 800
+pixels wide is completely visible on the screen.</p>
+
+<p>You can define properties of the viewport for your web page using the {@code "viewport"}
+property in an HTML {@code &lt;meta&gt;} tag (which must
+be placed in your document {@code &lt;head&gt;}). You can define multiple viewport properties in the
+{@code &lt;meta&gt;} tag's {@code content} attribute. For example, you can define the height and
+width of the viewport, the initial scale of the page, and the target screen density.
+Each viewport property in the {@code content} attribute must be separated by a comma.</p>
+
+<p>For example, the following snippet from an HTML document specifies that the viewport width
+should exactly match the device screen width and that the ability to zoom should be disabled:</p>
+
+<pre>
+&lt;head&gt;
+    &lt;title&gt;Example&lt;/title&gt;
+    &lt;meta name="viewport" content="width=device-width, user-scalable=no" /&gt;
+&lt;/head&gt;
+</pre>
+
+<p>That's an example of just two viewport properties. The following syntax shows all of the
+supported viewport properties and the general types of values accepted by each one:</p>
+
+<pre>
+&lt;meta name="viewport"
+      content="
+          <b>height</b> = [<em>pixel_value</em> | device-height] ,
+          <b>width</b> = [<em>pixel_value</em> | device-width ] ,
+          <b>initial-scale</b> = <em>float_value</em> ,
+          <b>minimum-scale</b> = <em>float_value</em> ,
+          <b>maximum-scale</b> = <em>float_value</em> ,
+          <b>user-scalable</b> = [yes | no] ,
+          <b>target-densitydpi</b> = [<em>dpi_value</em> | device-dpi |
+                               high-dpi | medium-dpi | low-dpi]
+          " /&gt;
+</pre>
+
+<p>The following sections discuss how to use each of these viewport properties and exactly what the
+accepted values are.</p>
+
+<div class="figure" style="width:300px">
+  <img src="{@docRoot}images/webapps/compare-default.png" alt="" height="300" />
+  <p class="img-caption"><strong>Figure 1.</strong> A web page with no viewport metadata and an
+image that's 320 pixels wide (the viewport is 800 pixels wide, by default).</p>
+</div>
+
+
+<div class="figure" style="width:300px">
+  <img src="{@docRoot}images/webapps/compare-width400.png" alt="" height="300" />
+  <p class="img-caption"><strong>Figure 2.</strong> A web page with viewport {@code width=400}
+(the image in the web page is 320 pixels wide).</p>
+</div>
+
+
+<h3 id="ViewportSize">Defining the viewport size</h3>
+
+<p>Viewport's {@code height} and {@code width} properties allow you to specify the size of the
+viewport (the number of pixels available to the web page before it goes off screen). By default, the
+Android Browser's minimum viewport width is 800 pixels, so if your web
+page specifies its size to be 320 pixels wide, then your page renders smaller than the visible
+screen (even if the physical screen is 320 pixels wide, because the viewport simulates a
+drawable area that's 800 pixels wide), as shown in figure 1. So, you should explicitly define the
+viewport {@code width} to match the width for which you have designed your web page.</p>
+
+<p class="note"><strong>Note:</strong> Width values that are greater than 10,000 are ignored and
+values less than (or equal to) 320 result in a value equal to the device-width. Height values that
+are greater then 10,000 or less than 200 are also ignored.</p>
+
+<p>For example, if your web page is designed to be exactly 320 pixels wide, then you might
+want to specify that for the viewport width:</p>
+
+<pre>
+&lt;meta name="viewport" content="width=320" /&gt;
+</pre>
+
+<p>In this case, your web page exactly fits the screen width, because the web page width and
+viewport width are the same.</p>
+
+<p>To demonstrate how this property affects the size of
+your web page, figure 2 shows a web page that contains an image that's 320 pixels wide, but with the
+viewport width set to 400.</p>
+
+
+<p class="note"><strong>Note:</strong> If you set the viewport width to match your web page width
+and the device screen width does <em>not</em> match those dimensions, then the web page
+still fits the screen even if the device has a high or low-density screen, because the
+Android Browser scales web pages to match the perceived size on a medium-density
+screen, by default (as you can see in figure 2, when comparing the hdpi device to the mdpi device).
+Screen densities are discussed more in <a href="#ViewportDensity">Defining the viewport target
+density</a>.</p>
+
+
+<h4>Automatic sizing</h4>
+
+<p>As an alternative to specifying the viewport dimensions with exact pixels, you can set the
+viewport size to always match the dimensions of the device screen, by defining the
+viewport properties {@code height}
+and {@code width} with the values {@code device-height} and {@code device-width}, respectively. This
+is appropriate when you're developing a web application that has a fluid width (not fixed width),
+but you want it to appear as if it's fixed (to perfectly fit every screen as
+if the web page width is set to match each screen). For example:</p>
+
+<pre>
+&lt;meta name="viewport" content="width=device-width" /&gt;
+</pre>
+
+<p>This results in the viewport width matching whatever the current screen width is, as shown in
+figure 3. It's important to notice that, this results in images being scaled to fit the screen
+when the current device does not match the <a href="#ViewportDensity">target
+density</a>, which is medium-density if you don't specify otherwise. As a result, the image
+displayed on the high-density device in figure 3 is scaled up in order to match the width
+of a screen with a medium-density screen.</p>
+
+<div class="figure" style="width:300px">
+  <img src="{@docRoot}images/webapps/compare-initialscale.png" alt="" height="300" />
+  <p class="img-caption"><strong>Figure 3.</strong> A web page with viewport {@code
+width=device-width} <em>or</em> {@code initial-scale=1.0}.</p>
+</div>
+
+<p class="note"><strong>Note:</strong> If you instead want {@code
+device-width} and {@code device-height} to match the physical screen pixels for every device,
+instead of scaling your web page to match the target density, then you must also include
+the {@code target-densitydpi} property with a value of {@code device-dpi}. This is discussed more in
+the section about <a href="#ViewportDensity">Defining the viewport density</a>. Otherwise, simply
+using {@code device-height} and {@code device-width} to define the viewport size makes your web page
+fit every device screen, but scaling occurs on your images in order to adjust for different screen
+densities.</p>
+
+
+
+<h3 id="ViewportScale">Defining the viewport scale</h3>
+
+<p>The scale of the viewport defines the level of zoom applied to the web page. Viewport
+properties allow you to specify the scale of your web page in the following ways:</p>
+<dl>
+  <dt>{@code initial-scale}</dt>
+  <dd>The initial scale of the page. The value is a float that indicates a multiplier for your web
+page size, relative to the screen size. For example, if you set the initial scale to "1.0" then the
+web page is displayed to match the resolution of the <a href="#ViewportDensity">target
+density</a> 1-to-1. If set to "2.0", then the page is enlarged (zoomed in) by a factor of 2.
+    <p>The default initial scale is calculated to fit the web page in the viewport size.
+Because the default viewport width is 800 pixels, if the device screen resolution is less than
+800 pixels wide, the initial scale is something less than 1.0, by default, in order to fit the
+800-pixel-wide page on the screen.</p></dd>
+
+  <dt>{@code minimum-scale}</dt>
+  <dd>The minimum scale to allow. The value is a float that indicates the minimum multiplier for
+your web page size, relative to the screen size. For example, if you set this to "1.0", then the
+page can't zoom out because the minimum size is 1-to-1 with the <a href="#ViewportDensity">target
+density</a>.</dd>
+
+  <dt>{@code maximum-scale}</dt>
+  <dd>The maximum scale to allow for the page. The value is a float that indicates the
+maximum multiplier for your web page size,
+relative to the screen size. For example, if you set this to "2.0", then the page can't
+zoom in more than 2 times the target size.</dd>
+
+  <dt>{@code user-scalable}</dt>
+  <dd>Whether the user can change the scale of the page at all (zoom in and out). Set to {@code yes}
+to allow scaling and {@code no} to disallow scaling. The default is {@code yes}. If you set
+this to {@code no}, then the {@code minimum-scale} and {@code maximum-scale} are ignored,
+because scaling is not possible.</dd>
+</dl>
+
+<p>All scale values must be within the range 0.01&ndash;10.</p>
+
+<p>For example:</p>
+
+<pre>
+&lt;meta name="viewport" content="initial-scale=1.0" /&gt;
+</pre>
+
+<p>This metadata sets the initial scale to be full sized, relative to the viewport's target
+density.</p>
+
+
+
+
+<h3 id="ViewportDensity">Defining the viewport target density</h3>
+
+<p>The density of a device's screen is based on the screen resolution. There are three screen
+density categories supported by Android: low (ldpi), medium (mdpi), and high (mdpi). A screen
+with low density has fewer available pixels per inch, whereas a screen with high density has more
+pixels per inch (compared to a medium density screen). The Android Browser targets a medium density 
+screen by default.</p>
+
+
+<div class="figure" style="width:300px">
+  <img src="{@docRoot}images/webapps/compare-initialscale-devicedpi.png" alt="" height="300" />
+  <p class="img-caption"><strong>Figure 4.</strong> A web page with viewport {@code
+width=device-width} and {@code target-densitydpi=device-dpi}.</p>
+</div>
+
+
+<p>Because the default target density is medium, when users have a device with a low or high density
+screen, the Android Browser scales web pages (effectively zooms the pages) so they display at a
+size that matches the perceived appearance on a medium density screen. Specifically, the Android
+Browser applies approximately 1.5x scaling to web pages on a high density screen
+(because its screen pixels are smaller) and approximately 0.75x scaling to pages on a low density
+screen (because its screen pixels are bigger).</p>
+
+<p>Due to this default scaling, figures 1, 2, and 3 show the example web page at the same physical
+size on both the high and medium density device (the high-density device shows the
+web page with a default scale factor that is 1.5 times larger than the actual pixel resolution, to
+match the target density). This can introduce some undesirable artifacts in your images.
+For example, although an image appears the same size on a medium and high-density device, the image
+on the high-density device appears more blurry, because the image is designed to be 320 pixels
+wide, but is drawn with 480 pixels.</p>
+
+<p>You can change the target screen density for your web page using the {@code target-densitydpi}
+viewport property. It accepts the following values:</p>
+
+<ul>
+<li><code>device-dpi</code> - Use the device's native dpi as the target dpi. Default scaling never
+occurs.</li>
+<li><code>high-dpi</code> - Use hdpi as the target dpi. Medium and low density screens scale down
+as appropriate.</li>
+<li><code>medium-dpi</code> - Use mdpi as the target dpi. High density screens scale up and low
+density screens scale down. This is the default target density.</li>
+<li><code>low-dpi</code> - Use ldpi as the target dpi. Medium and high density screens scale up
+as appropriate.</li>
+<li><em><code>&lt;value&gt;</code></em> - Specify a dpi value to use as the target dpi. Values must
+be within the range 70&ndash;400.</li>
+</ul></p>
+
+<p>For example, to prevent the Android Browser from scaling of your web page for different screen
+densities, set
+the {@code target-densitydpi} viewport property to {@code device-dpi}. When you do, the Android
+Browser does not scale the page and, instead, displays your web page to match the current screen
+density. In this case, you should also define the viewport width to match the device width, so your
+web page naturally fits the screen size. For example:</p>
+
+<pre>
+&lt;meta name="viewport" content="target-densitydpi=device-dpi, width=device-width" /&gt;
+</pre>
+
+<p>Figure 4 shows a web page using these viewport settings&mdash;the high-density device
+now displays the page smaller because its physical pixels are smaller than those on the
+medium-density device, so no scaling occurs and the 320-pixel-wide image is drawn using exactly 320
+pixels on both screens. (This is how you should define your viewport if
+you want to customize your web page based on screen density and provide different image assets for
+different densities, <a href="#DensityCSS">with CSS</a> or
+<a href="#DensityJS">with JavaScript</a>.)</p>
+
+
+<h2 id="DensityCSS">Targetting Device Density with CSS</h2>
+
+<p>The Android Browser supports a CSS media feature that allows you to create styles for specific
+screen densities&mdash;the <code>-webkit-device-pixel-ratio</code> CSS media feature. The
+value you apply to this feature should be either
+"0.75", "1", or "1.5", to indicate that the styles are for devices with low density, medium density,
+or high density screens, respectively.</p>
+
+<p>For example, you can create separate stylesheets for each density:</p>
+
+<pre>
+&lt;link rel="stylesheet" media="screen and (-webkit-device-pixel-ratio: 1.5)" href="hdpi.css" /&gt;
+&lt;link rel="stylesheet" media="screen and (-webkit-device-pixel-ratio: 1.0)" href="mdpi.css" /&gt;
+&lt;link rel="stylesheet" media="screen and (-webkit-device-pixel-ratio: 0.75)" href="ldpi.css" /&gt;
+</pre>
+
+
+<div class="figure" style="width:300px">
+  <img src="{@docRoot}images/webapps/compare-width-devicedpi-css.png" alt="" height="300" />
+  <p class="img-caption"><strong>Figure 5.</strong> A web page with CSS that's targetted to
+specific screen densities using the {@code -webkit-device-pixel-ratio} media feature. Notice
+that the hdpi device shows a different image that's applied in CSS.</p>
+</div>
+
+<p>Or, specify the different styles in one stylesheet:</p>
+
+<pre class="no-pretty-print">
+#header {
+    background:url(medium-density-image.png);
+}
+
+&#64;media screen and (-webkit-device-pixel-ratio: 1.5) {
+    // CSS for high-density screens
+    #header {
+        background:url(high-density-image.png);
+    }
+}
+
+&#64;media screen and (-webkit-device-pixel-ratio: 0.75) {
+    // CSS for low-density screens
+    #header {
+        background:url(low-density-image.png);
+    }
+}
+</pre>
+
+<p class="note"><strong>Note:</strong> The default style for {@code #header} applies the image
+designed for medium-density devices in order to support devices running a version of Android less
+than 2.0, which do not support the {@code -webkit-device-pixel-ratio} media feature.</p>
+
+<p>The types of styles you might want to adjust based on the screen density depend on how you've
+defined your viewport properties. To provide fully-customized styles that tailor your web page for
+each of the supported densities, you should set your viewport properties so the viewport width and
+density match the device. That is:</p>
+
+<pre>
+&lt;meta name="viewport" content="target-densitydpi=device-dpi, width=device-width" /&gt;
+</pre>
+
+<p>This way, the Android Browser does not perform scaling on your web page and the viewport width
+matches the screen width exactly. On its own, these viewport properties create results shown in
+figure 4. However, by adding some custom CSS using the {@code -webkit-device-pixel-ratio} media
+feature, you can apply different styles. For example, figure 5 shows a web page with these viewport
+properties and also some CSS added that applies a high-resolution image for high-density
+screens.</p>
+
+
+
+<h2 id="DensityJS">Targetting Device Density with JavaScript</h2>
+
+<p>The Android Browser supports a DOM property that allows you to query the density of the current
+device&mdash;the <code>window.devicePixelRatio</code> DOM property. The value of this property
+specifies the scaling factor used for the current device. For example, if the value
+of <code>window.devicePixelRatio</code> is "1.0", then the device is considered a medium density
+device and no scaling is applied by default; if the value is "1.5", then the device is
+considered a high density device and the page is scaled 1.5x by default; if the value
+is "0.75", then the device is considered a low density device and the page is scaled
+0.75x by default. Of course, the scaling that the Android Browser applies is based on the web page's
+target density&mdash;as described in the section about <a href="#ViewportDensity">Defining the
+viewport target density</a>, the default target is medium-density, but you can change the
+target to affect how your web page is scaled for different screen densities.</p>
+
+<p>For example, here's how you can query the device density with JavaScript:</p>
+
+<pre>
+if (window.devicePixelRatio == 1.5) {
+  alert("This is a high-density screen");
+} else if (window.devicePixelRation == 0.75) {
+  alert("This is a low-density screen");
+}
+</pre>
+
+
+
+
+
+
+
diff --git a/docs/html/guide/webapps/webview.jd b/docs/html/guide/webapps/webview.jd
new file mode 100644
index 0000000..ed28f21
--- /dev/null
+++ b/docs/html/guide/webapps/webview.jd
@@ -0,0 +1,328 @@
+page.title=Building Web Apps in WebView
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+<h2>Quickview</h2>
+<ul>
+  <li>Use {@link android.webkit.WebView} to display web pages in your Android application
+layout</li>
+  <li>You can create interfaces from your JavaScript to your client-side Android code</li>
+</ul>
+
+<h2>In this document</h2>
+<ol>
+  <li><a href="#AddingWebView">Adding a WebView to Your Application</a></li>
+  <li><a href="#UsingJavaScript">Using JavaScript in WebView</a>
+    <ol>
+      <li><a href="#EnablingJavaScript">Enabling JavaScript</a></li>
+      <li><a href="#BindingJavaScript">Binding JavaScript code to Android code</a></li>
+    </ol>
+  </li>
+  <li><a href="#HandlingNavigation">Handling Page Navigation</a>
+    <ol>
+      <li><a href="#NavigatingHistory">Navigating web page history</a></li>
+    </ol>
+  </li>
+</ol>
+
+<h2>Key classes</h2>
+<ol>
+  <li>{@link android.webkit.WebView}</li>
+  <li>{@link android.webkit.WebSettings}</li>
+  <li>{@link android.webkit.WebViewClient}</li>
+</ol>
+
+<h2>Related tutorials</h2>
+<ol>
+  <li><a href="{@docRoot}resources/tutorials/views/hello-webview.html">Web View</a></li>
+</ol>
+
+</div>
+</div>
+
+<p>If you want to deliver a web application (or just a web page) as a part of a client application,
+you can do it using {@link android.webkit.WebView}. The {@link android.webkit.WebView} class is an
+extension of Android's {@link android.view.View} class that allows you to display web pages as a
+part of your activity layout. It does <em>not</em> include any features of a fully developed web
+browser, such as navigation controls or an address bar. All that {@link android.webkit.WebView}
+does, by default, is show a web page.</p>
+
+<p>A common scenario in which using {@link android.webkit.WebView} is helpful is when you want to
+provide information in your application that you might need to update, such as an end-user agreement
+or a user guide. Within your Android application, you can create an {@link android.app.Activity}
+that contains a {@link android.webkit.WebView}, then use that to display your document that's
+hosted online.</p>
+
+<p>Another scenario in which {@link android.webkit.WebView} can help is if your application provides
+data to the user that
+always requires an Internet connection to retrieve data, such as email. In this case, you might
+find that it's easier to build a {@link android.webkit.WebView} in your Android application that
+shows a web page with all
+the user data, rather than performing a network request, then parsing the data and rendering it in
+an Android layout. Instead, you can design a web page that's tailored for Android devices
+and then implement a {@link android.webkit.WebView} in your Android application that loads the web
+page.</p>
+
+<p>This document shows you how to get started with {@link android.webkit.WebView} and how to do some
+additional things, such as handle page navigation and bind JavaScript from your web page to
+client-side code in your Android application.</p>
+
+
+
+<h2 id="AddingWebView">Adding a WebView to Your Application</h2>
+
+<p>To add a {@link android.webkit.WebView} to your Application, simply include the {@code
+&lt;WebView&gt;} element in your activity layout. For example, here's a layout file in which the
+{@link android.webkit.WebView} fills the screen:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;WebView  xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/webview"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+/&gt;
+</pre>
+
+<p>To load a web page in the {@link android.webkit.WebView}, use {@link
+android.webkit.WebView#loadUrl(String) loadUrl()}. For example:</p>
+
+<pre>
+WebView myWebView = (WebView) findViewById(R.id.webview);
+myWebView.loadUrl("http://www.example.com");
+</pre>
+
+<p>Before this will work, however, your application must have access to the Internet. To get
+Internet access, request the {@link android.Manifest.permission#INTERNET} permission in your
+manifest file. For example:</p>
+
+<pre>
+&lt;manifest ... &gt;
+    &lt;uses-permission android:name="android.permission.INTERNET" /&gt;
+    ...
+&lt;/manifest&gt;
+</pre>
+
+<p>That's all you need for a basic {@link android.webkit.WebView} that displays a web page.</p>
+
+
+
+
+<h2 id="UsingJavaScript">Using JavaScript in WebView</h2>
+
+<p>If the web page you plan to load in your {@link android.webkit.WebView} use JavaScript, you
+must enable JavaScript for your {@link android.webkit.WebView}. Once JavaScript is enabled, you can
+also create interfaces between your application code and your JavaScript code.</p>
+
+
+<h3 id="EnablingJavaScript">Enabling JavaScript</h3>
+
+<p>JavaScript is disabled in a {@link android.webkit.WebView} by default. You can enable it
+through the {@link
+android.webkit.WebSettings} attached to your {@link android.webkit.WebView}. You can retrieve {@link
+android.webkit.WebSettings} with {@link android.webkit.WebView#getSettings()}, then enable
+JavaScript with {@link android.webkit.WebSettings#setJavaScriptEnabled(boolean)
+setJavaScriptEnabled()}.</p>
+
+<p>For example:</p>
+
+<pre>
+WebView myWebView = (WebView) findViewById(R.id.webview);
+WebSettings webSettings = myWebView.getSettings();
+webSettings.setJavaScriptEnabled(true);
+</pre>
+
+<p>{@link android.webkit.WebSettings} provides access to a variety of other settings that you might
+find useful. For example, if you're developing a web application
+that's designed specifically for the {@link android.webkit.WebView} in your Android application,
+then you can define a
+custom user agent string with {@link android.webkit.WebSettings#setUserAgentString(String)
+setUserAgentString()}, then query the custom user agent in your web page to verify that the
+client requesting your web page is actually your Android application.</p>
+
+from your Android SDK {@code tools/} directory
+<h3 id="BindingJavaScript">Binding JavaScript code to Android code</h3>
+
+<p>When developing a web application that's designed specifically for the {@link
+android.webkit.WebView} in your Android
+application, you can create interfaces between your JavaScript code and client-side Android code.
+For example, your JavaScript code can call a method in your Android code to display a {@link
+android.app.Dialog}, instead of using JavaScript's {@code alert()} function.</p>
+
+<p>To bind a new interface between your JavaScript and Android code, call {@link
+android.webkit.WebView#addJavascriptInterface(Object,String) addJavascriptInterface()}, passing it
+a class instance to bind to your JavaScript and an interface name that your JavaScript can call to
+access the class.</p>
+
+<p>For example, you can include the following class in your Android application:</p>
+
+<pre>
+public class JavaScriptInterface {
+    Context mContext;
+
+    /** Instantiate the interface and set the context */
+    JavaScriptInterface(Context c) {
+        mContext = c;
+    }
+
+    /** Show a toast from the web page */
+    public void showToast(String toast) {
+        Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
+    }
+}
+</pre>
+
+<p>In this example, the {@code JavaScriptInterface} class allows the web page to create a {@link
+android.widget.Toast} message, using the {@code showToast()} method.</p>
+
+<p>You can bind this class to the JavaScript that runs in your {@link android.webkit.WebView} with
+{@link android.webkit.WebView#addJavascriptInterface(Object,String) addJavascriptInterface()} and
+name the interface {@code Android}. For example:</p>
+
+<pre>
+WebView webView = (WebView) findViewById(R.id.webview);
+webView.addJavascriptInterface(new JavaScriptInterface(this), "Android");
+</pre>
+
+<p>This creates an interface called {@code Android} for JavaScript running in the {@link
+android.webkit.WebView}. At this point, your web application has access to the {@code
+JavaScriptInterface} class. For example, here's some HTML and JavaScript that creates a toast
+message using the new interface when the user clicks a button:</p>
+
+<pre>
+&lt;input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" /&gt;
+
+&lt;script type="text/javascript"&gt;
+    function showAndroidToast(toast) {
+        Android.showToast(toast);
+    }
+&lt;/script&gt;
+</pre>
+
+<p>There's no need to initialize the {@code Android} interface from JavaScript. The {@link
+android.webkit.WebView} automatically makes it
+available to your web page. So, at the click of the button, the {@code showAndroidToast()}
+function uses the {@code Android} interface to call the {@code JavaScriptInterface.showToast()}
+method.</p>
+
+<p class="note"><strong>Note:</strong> The object that is bound to your JavaScript runs in
+another thread and not in the thread in which it was constructed.</p>
+
+<p class="caution"><strong>Caution:</strong> Using {@link
+android.webkit.WebView#addJavascriptInterface(Object,String) addJavascriptInterface()} allows
+JavaScript to control your Android application. This can be a very useful feature or a dangerous
+security issue. When the HTML in the {@link android.webkit.WebView} is untrustworthy (for example,
+part or all of the HTML
+is provided by an unknown person or process), then an attacker can include HTML that executes
+your client-side code and possibly any code of the attacker's choosing. As such, you should not use
+{@link android.webkit.WebView#addJavascriptInterface(Object,String) addJavascriptInterface()} unless
+you wrote all of the HTML and JavaScript that appears in your {@link android.webkit.WebView}. You
+should also not allow the user to
+navigate to other web pages that are not your own, within your {@link android.webkit.WebView}
+(instead, allow the user's
+default browser application to open foreign links&mdash;by default, the user's web browser
+opens all URL links, so be careful only if you handle page navigation as described in the
+following section).</p>
+
+
+
+
+<h2 id="HandlingNavigation">Handling Page Navigation</h2>
+
+<p>When the user clicks a link from a web page in your {@link android.webkit.WebView}, the default
+behavior is
+for Android to launch an application that handles URLs. Usually, the default web browser opens and
+loads the destination URL. However, you can override this behavior for your {@link
+android.webkit.WebView},
+so links open within your {@link android.webkit.WebView}. You can then allow the user to navigate
+backward and forward through their web page history that's maintained by your {@link
+android.webkit.WebView}.</p>
+
+<p>To open links clicked by the user, simply provide a {@link
+android.webkit.WebViewClient} for your {@link android.webkit.WebView}, using {@link
+android.webkit.WebView#setWebViewClient(WebViewClient) setWebViewClient()}. For example:</p>
+
+<pre>
+WebView myWebView = (WebView) findViewById(R.id.webview);
+myWebView.{@link android.webkit.WebView#setWebViewClient(WebViewClient) setWebViewClient}(new WebViewClient());
+</pre>
+
+<p>That's it. Now all links the user clicks load in your {@link android.webkit.WebView}.</p>
+
+<p>If you want more control over where a clicked link load, create your own {@link
+android.webkit.WebViewClient} that overrides the {@link
+android.webkit.WebViewClient#shouldOverrideUrlLoading(WebView,String)
+shouldOverrideUrlLoading()} method. For example:</p>
+
+<pre>
+private class MyWebViewClient extends WebViewClient {
+    &#64;Override
+    public boolean {@link android.webkit.WebViewClient#shouldOverrideUrlLoading(WebView,String) shouldOverrideUrlLoading}(WebView view, String url) {
+        if (Uri.parse(url).getHost().equals("www.example.com")) {
+            // This is my web site, so do not override; let my WebView load the page
+            return false;
+        }
+        // Otherwise, the link is not for a page on my site, so launch another Activity that handles URLs
+        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+        startActivity(intent);
+        return true;
+    }
+}
+</pre>
+
+<p>Then create an instance of this new {@link android.webkit.WebViewClient} for the {@link
+android.webkit.WebView}:</p>
+
+<pre>
+WebView myWebView = (WebView) findViewById(R.id.webview);
+myWebView.{@link android.webkit.WebView#setWebViewClient(WebViewClient) setWebViewClient}(new MyWebViewClient());
+</pre>
+
+<p>Now when the user clicks a link, the system calls
+{@link android.webkit.WebViewClient#shouldOverrideUrlLoading(WebView,String)
+shouldOverrideUrlLoading()}, which checks whether the URL host matches a specific domain (as defined
+above). If it does match, then the method returns false in order to <em>not</em> override the URL
+loading (it allows the {@link android.webkit.WebView} to load the URL as usual). If the URL host
+does not match, then an {@link android.content.Intent} is created to
+launch the default Activity for handling URLs (which resolves to the user's default web
+browser).</p>
+
+
+
+
+<h3 id="NavigatingHistory">Navigating web page history</h3>
+
+<p>When your {@link android.webkit.WebView} overrides URL loading, it automatically accumulates a
+history of visited web
+pages. You can navigate backward and forward through the history with {@link
+android.webkit.WebView#goBack()} and {@link android.webkit.WebView#goForward()}.</p>
+
+<p>For example, here's how your {@link android.app.Activity} can use the device BACK key to navigate
+backward:</p>
+
+<pre>
+&#64;Override
+public boolean {@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown}(int keyCode, KeyEvent event) {
+    // Check if the key event was the BACK key and if there's history
+    if ((keyCode == KeyEvent.KEYCODE_BACK) &amp;&amp; myWebView.{@link android.webkit.WebView#canGoBack() canGoBack}() {
+        myWebView.{@link android.webkit.WebView#goBack() goBack}();
+        return true;
+    }
+    // If it wasn't the BACK key or there's no web page history, bubble up to the default
+    // system behavior (probably exit the activity)
+    return super.onKeyDown(keyCode, event);
+}
+</pre>
+
+<p>The {@link android.webkit.WebView#canGoBack()} method returns
+true if there is actually web page history for the user to visit. Likewise, you can use {@link
+android.webkit.WebView#canGoForward()} to check whether there is a forward history. If you don't
+perform this check, then once the user reaches the end of the history, {@link
+android.webkit.WebView#goBack()} or {@link android.webkit.WebView#goForward()} does nothing.</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/docs/html/images/webapps/compare-default.png b/docs/html/images/webapps/compare-default.png
new file mode 100644
index 0000000..9495a05
--- /dev/null
+++ b/docs/html/images/webapps/compare-default.png
Binary files differ
diff --git a/docs/html/images/webapps/compare-initialscale-devicedpi.png b/docs/html/images/webapps/compare-initialscale-devicedpi.png
new file mode 100644
index 0000000..6bb758a6
--- /dev/null
+++ b/docs/html/images/webapps/compare-initialscale-devicedpi.png
Binary files differ
diff --git a/docs/html/images/webapps/compare-initialscale.png b/docs/html/images/webapps/compare-initialscale.png
new file mode 100644
index 0000000..2232d5b
--- /dev/null
+++ b/docs/html/images/webapps/compare-initialscale.png
Binary files differ
diff --git a/docs/html/images/webapps/compare-width-devicedpi-css.png b/docs/html/images/webapps/compare-width-devicedpi-css.png
new file mode 100644
index 0000000..bb4ab31
--- /dev/null
+++ b/docs/html/images/webapps/compare-width-devicedpi-css.png
Binary files differ
diff --git a/docs/html/images/webapps/compare-width400.png b/docs/html/images/webapps/compare-width400.png
new file mode 100644
index 0000000..669a234
--- /dev/null
+++ b/docs/html/images/webapps/compare-width400.png
Binary files differ
diff --git a/docs/html/sitemap.txt b/docs/html/sitemap.txt
index d5be8f1..7a0b8ac 100644
--- a/docs/html/sitemap.txt
+++ b/docs/html/sitemap.txt
@@ -164,6 +164,11 @@
 http://developer.android.com/guide/practices/design/performance.html
 http://developer.android.com/guide/practices/design/responsiveness.html
 http://developer.android.com/guide/practices/design/seamlessness.html
+http://developer.android.com/guide/webapps/targetting.html
+http://developer.android.com/guide/webapps/webview.html
+http://developer.android.com/guide/webapps/debugging.html
+http://developer.android.com/guide/webapps/best-practices.html
+http://developer.android.com/guide/topics/admin/device-admin.html
 http://developer.android.com/guide/appendix/api-levels.html
 http://developer.android.com/guide/appendix/media-formats.html
 http://developer.android.com/guide/appendix/g-app-intents.html
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 3662983..0521709 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -76,6 +76,7 @@
         virtual uint32_t    latency() const = 0;
         virtual float       msecsPerFrame() const = 0;
         virtual status_t    getPosition(uint32_t *position) = 0;
+        virtual int         getSessionId() = 0;
 
         // If no callback is specified, use the "write" API below to submit
         // audio data.
diff --git a/include/media/Metadata.h b/include/media/Metadata.h
index 241868a..9c915ce 100644
--- a/include/media/Metadata.h
+++ b/include/media/Metadata.h
@@ -91,6 +91,7 @@
     static const Type kPauseAvailable = 29;        // Boolean
     static const Type kSeekBackwardAvailable = 30; // Boolean
     static const Type kSeekForwardAvailable = 31;  // Boolean
+    static const Type kSeekAvailable = 32;         // Boolean
 
     // @param p[inout] The parcel to append the metadata records
     // to. The global metadata header should have been set already.
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/media/stagefright/MediaExtractor.h b/include/media/stagefright/MediaExtractor.h
index 21338ca..16b0a4c 100644
--- a/include/media/stagefright/MediaExtractor.h
+++ b/include/media/stagefright/MediaExtractor.h
@@ -45,13 +45,14 @@
     virtual sp<MetaData> getMetaData();
 
     enum Flags {
-        CAN_SEEK_BACKWARD  = 1,
-        CAN_SEEK_FORWARD   = 2,
+        CAN_SEEK_BACKWARD  = 1,  // the "seek 10secs back button"
+        CAN_SEEK_FORWARD   = 2,  // the "seek 10secs forward button"
         CAN_PAUSE          = 4,
+        CAN_SEEK           = 8,  // the "seek bar"
     };
 
     // If subclasses do _not_ override this, the default is
-    // CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_PAUSE
+    // CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE
     virtual uint32_t flags() const;
 
 protected:
diff --git a/include/storage/IMountService.h b/include/storage/IMountService.h
index 436fc38..51f9aeb 100644
--- a/include/storage/IMountService.h
+++ b/include/storage/IMountService.h
@@ -61,9 +61,9 @@
     virtual void shutdown(const sp<IMountShutdownObserver>& observer) = 0;
     virtual void finishMediaUpdate() = 0;
     virtual void mountObb(const String16& filename, const String16& key,
-            const sp<IObbActionListener>& token) = 0;
+            const sp<IObbActionListener>& token, const int32_t nonce) = 0;
     virtual void unmountObb(const String16& filename, const bool force,
-            const sp<IObbActionListener>& token) = 0;
+            const sp<IObbActionListener>& token, const int32_t nonce) = 0;
     virtual bool isObbMounted(const String16& filename) = 0;
     virtual bool getMountedObbPath(const String16& filename, String16& path) = 0;
 };
diff --git a/include/storage/IObbActionListener.h b/include/storage/IObbActionListener.h
index 1bedcc6..d78273c 100644
--- a/include/storage/IObbActionListener.h
+++ b/include/storage/IObbActionListener.h
@@ -29,7 +29,7 @@
 public:
     DECLARE_META_INTERFACE(ObbActionListener);
 
-    virtual void onObbResult(const String16& filename, const String16& status) = 0;
+    virtual void onObbResult(const String16& filename, const int32_t nonce, const int32_t state) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h
index 6533600..da4d56f 100644
--- a/include/surfaceflinger/ISurfaceComposer.h
+++ b/include/surfaceflinger/ISurfaceComposer.h
@@ -77,6 +77,11 @@
         eOrientationSwapMask    = 0x01
     };
     
+    enum {
+        eElectronBeamAnimationOn  = 0x01,
+        eElectronBeamAnimationOff = 0x10
+    };
+
     // flags for setOrientation
     enum {
         eOrientationAnimationDisable = 0x00000001
@@ -118,6 +123,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 +150,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/ui/Input.h b/include/ui/Input.h
index ee40b85..8c6018b 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -71,6 +71,8 @@
 /*
  * Flags that flow alongside events in the input dispatch system to help with certain
  * policy decisions such as waking from device sleep.
+ *
+ * These flags are also defined in frameworks/base/core/java/android/view/WindowManagerPolicy.java.
  */
 enum {
     /* These flags originate in RawEvents and are generally set in the key map.
@@ -93,6 +95,10 @@
     // Indicates that the input event was injected.
     POLICY_FLAG_INJECTED = 0x01000000,
 
+    // Indicates that the input event is from a trusted source such as a directly attached
+    // input device or an application with system-wide event injection permission.
+    POLICY_FLAG_TRUSTED = 0x02000000,
+
     /* These flags are set by the input reader policy as it intercepts each event. */
 
     // Indicates that the screen was off when the event was received and the event
@@ -102,6 +108,11 @@
     // Indicates that the screen was dim when the event was received and the event
     // should brighten the device.
     POLICY_FLAG_BRIGHT_HERE = 0x20000000,
+
+    // Indicates that the event should be dispatched to applications.
+    // The input event should still be sent to the InputDispatcher so that it can see all
+    // input events received include those that it will not deliver.
+    POLICY_FLAG_PASS_TO_USER = 0x40000000,
 };
 
 /*
diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h
index 47c5326..3599163 100644
--- a/include/ui/InputDispatcher.h
+++ b/include/ui/InputDispatcher.h
@@ -282,10 +282,35 @@
      */
     virtual int32_t getMaxEventsPerSecond() = 0;
 
+    /* Intercepts a key event immediately before queueing it.
+     * The policy can use this method as an opportunity to perform power management functions
+     * and early event preprocessing such as updating policy flags.
+     *
+     * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
+     * should be dispatched to applications.
+     */
+    virtual void interceptKeyBeforeQueueing(nsecs_t when, int32_t deviceId,
+            int32_t action, int32_t& flags, int32_t keyCode, int32_t scanCode,
+            uint32_t& policyFlags) = 0;
+
+    /* Intercepts a generic touch, trackball or other event before queueing it.
+     * The policy can use this method as an opportunity to perform power management functions
+     * and early event preprocessing such as updating policy flags.
+     *
+     * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
+     * should be dispatched to applications.
+     */
+    virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) = 0;
+
     /* Allows the policy a chance to intercept a key before dispatching. */
     virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
             const KeyEvent* keyEvent, uint32_t policyFlags) = 0;
 
+    /* Notifies the policy about switch events.
+     */
+    virtual void notifySwitch(nsecs_t when,
+            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) = 0;
+
     /* Poke user activity for an event dispatched to a window. */
     virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) = 0;
 
@@ -333,6 +358,8 @@
             int32_t metaState, int32_t edgeFlags,
             uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
             float xPrecision, float yPrecision, nsecs_t downTime) = 0;
+    virtual void notifySwitch(nsecs_t when,
+            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) = 0;
 
     /* Injects an input event and optionally waits for sync.
      * The synchronization mode determines whether the method blocks while waiting for
@@ -408,6 +435,8 @@
             int32_t metaState, int32_t edgeFlags,
             uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
             float xPrecision, float yPrecision, nsecs_t downTime);
+    virtual void notifySwitch(nsecs_t when,
+            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) ;
 
     virtual int32_t injectInputEvent(const InputEvent* event,
             int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis);
@@ -447,6 +476,7 @@
         mutable int32_t refCount;
         int32_t type;
         nsecs_t eventTime;
+        uint32_t policyFlags;
         InjectionState* injectionState;
 
         bool dispatchInProgress; // initially false, set to true while dispatching
@@ -460,7 +490,6 @@
     struct KeyEntry : EventEntry {
         int32_t deviceId;
         int32_t source;
-        uint32_t policyFlags;
         int32_t action;
         int32_t flags;
         int32_t keyCode;
@@ -489,7 +518,6 @@
     struct MotionEntry : EventEntry {
         int32_t deviceId;
         int32_t source;
-        uint32_t policyFlags;
         int32_t action;
         int32_t flags;
         int32_t metaState;
@@ -664,7 +692,8 @@
         Pool<DispatchEntry> mDispatchEntryPool;
         Pool<CommandEntry> mCommandEntryPool;
 
-        void initializeEventEntry(EventEntry* entry, int32_t type, nsecs_t eventTime);
+        void initializeEventEntry(EventEntry* entry, int32_t type, nsecs_t eventTime,
+                uint32_t policyFlags);
         void releaseEventEntryInjectionState(EventEntry* entry);
     };
 
@@ -685,21 +714,19 @@
             BROKEN
         };
 
+        // Specifies the sources to cancel.
+        enum CancelationOptions {
+            CANCEL_ALL_EVENTS = 0,
+            CANCEL_POINTER_EVENTS = 1,
+            CANCEL_NON_POINTER_EVENTS = 2,
+        };
+
         InputState();
         ~InputState();
 
         // Returns true if there is no state to be canceled.
         bool isNeutral() const;
 
-        // Returns true if the input state believes it is out of sync.
-        bool isOutOfSync() const;
-
-        // Sets the input state to be out of sync if it is not neutral.
-        void setOutOfSync();
-
-        // Resets the input state out of sync flag.
-        void resetOutOfSync();
-
         // Records tracking information for an event that has just been published.
         // Returns whether the event is consistent with the current input state.
         Consistency trackEvent(const EventEntry* entry);
@@ -712,16 +739,14 @@
         // Returns whether the event is consistent with the current input state.
         Consistency trackMotion(const MotionEntry* entry);
 
-        // Synthesizes cancelation events for the current state.
-        void synthesizeCancelationEvents(Allocator* allocator,
-                Vector<EventEntry*>& outEvents) const;
+        // Synthesizes cancelation events for the current state and resets the tracked state.
+        void synthesizeCancelationEvents(nsecs_t currentTime, Allocator* allocator,
+                Vector<EventEntry*>& outEvents, CancelationOptions options);
 
         // Clears the current state.
         void clear();
 
     private:
-        bool mIsOutOfSync;
-
         struct KeyMemento {
             int32_t deviceId;
             int32_t source;
@@ -745,6 +770,8 @@
 
         Vector<KeyMemento> mKeyMementos;
         Vector<MotionMemento> mMotionMementos;
+
+        static bool shouldCancelEvent(int32_t eventSource, CancelationOptions options);
     };
 
     /* Manages the dispatch state associated with a single input channel. */
@@ -794,6 +821,13 @@
         status_t initialize();
     };
 
+    enum DropReason {
+        DROP_REASON_NOT_DROPPED = 0,
+        DROP_REASON_POLICY = 1,
+        DROP_REASON_APP_SWITCH = 2,
+        DROP_REASON_DISABLED = 3,
+    };
+
     sp<InputDispatcherPolicyInterface> mPolicy;
 
     Mutex mLock;
@@ -813,12 +847,16 @@
     // Enqueues an inbound event.  Returns true if mLooper->wake() should be called.
     bool enqueueInboundEventLocked(EventEntry* entry);
 
+    // Cleans up input state when dropping an inbound event.
+    void dropInboundEventLocked(EventEntry* entry, DropReason dropReason);
+
     // App switch latency optimization.
+    bool mAppSwitchSawKeyDown;
     nsecs_t mAppSwitchDueTime;
 
-    static bool isAppSwitchKey(int32_t keyCode);
+    static bool isAppSwitchKeyCode(int32_t keyCode);
+    bool isAppSwitchKeyEventLocked(KeyEntry* keyEntry);
     bool isAppSwitchPendingLocked();
-    bool detectPendingAppSwitchLocked(KeyEntry* inboundKeyEntry);
     void resetPendingAppSwitchLocked(bool handled);
 
     // All registered connections mapped by receive pipe file descriptor.
@@ -840,7 +878,7 @@
 
     // Event injection and synchronization.
     Condition mInjectionResultAvailableCondition;
-    EventEntry* createEntryFromInjectedInputEventLocked(const InputEvent* event);
+    bool hasInjectionPermission(int32_t injectorPid, int32_t injectorUid);
     void setInjectionResultLocked(EventEntry* entry, int32_t injectionResult);
 
     Condition mInjectionSyncFinishedCondition;
@@ -875,7 +913,6 @@
     void drainInboundQueueLocked();
     void releasePendingEventLocked();
     void releaseInboundEventLocked(EventEntry* entry);
-    bool isEventFromReliableSourceLocked(EventEntry* entry);
 
     // Dispatch state.
     bool mDispatchEnabled;
@@ -922,10 +959,10 @@
             nsecs_t currentTime, ConfigurationChangedEntry* entry);
     bool dispatchKeyLocked(
             nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
-            bool dropEvent, nsecs_t* nextWakeupTime);
+            DropReason* dropReason, nsecs_t* nextWakeupTime);
     bool dispatchMotionLocked(
             nsecs_t currentTime, MotionEntry* entry,
-            bool dropEvent, nsecs_t* nextWakeupTime);
+            DropReason* dropReason, nsecs_t* nextWakeupTime);
     void dispatchEventToCurrentInputTargetsLocked(
             nsecs_t currentTime, EventEntry* entry, bool resumeWithAppendedMotionSample);
 
@@ -984,11 +1021,17 @@
     void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
     void finishDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
     void startNextDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
-    void abortDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
-            bool broken);
+    void abortBrokenDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
     void drainOutboundQueueLocked(Connection* connection);
     static int handleReceiveCallback(int receiveFd, int events, void* data);
 
+    void synthesizeCancelationEventsForAllConnectionsLocked(
+            InputState::CancelationOptions options, const char* reason);
+    void synthesizeCancelationEventsForInputChannelLocked(const sp<InputChannel>& channel,
+            InputState::CancelationOptions options, const char* reason);
+    void synthesizeCancelationEventsForConnectionLocked(const sp<Connection>& connection,
+            InputState::CancelationOptions options, const char* reason);
+
     // Splitting motion events across windows.
     MotionEntry* splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds);
 
diff --git a/include/ui/InputReader.h b/include/ui/InputReader.h
index 3619189..c15e382 100644
--- a/include/ui/InputReader.h
+++ b/include/ui/InputReader.h
@@ -87,49 +87,12 @@
         ROTATION_270 = 3
     };
 
-    /* Actions returned by interceptXXX methods. */
-    enum {
-        // The input dispatcher should do nothing and discard the input unless other
-        // flags are set.
-        ACTION_NONE = 0,
-
-        // The input dispatcher should dispatch the input to the application.
-        ACTION_DISPATCH = 0x00000001,
-    };
-
     /* Gets information about the display with the specified id.
      * Returns true if the display info is available, false otherwise.
      */
     virtual bool getDisplayInfo(int32_t displayId,
             int32_t* width, int32_t* height, int32_t* orientation) = 0;
 
-    /* Intercepts a key event.
-     * The policy can use this method as an opportunity to perform power management functions
-     * and early event preprocessing such as updating policy flags.
-     *
-     * Returns a policy action constant such as ACTION_DISPATCH.
-     */
-    virtual int32_t interceptKey(nsecs_t when, int32_t deviceId,
-            bool down, int32_t keyCode, int32_t scanCode, uint32_t& policyFlags) = 0;
-
-    /* Intercepts a switch event.
-     * The policy can use this method as an opportunity to perform power management functions
-     * and early event preprocessing such as updating policy flags.
-     *
-     * Switches are not dispatched to applications so this method should
-     * usually return ACTION_NONE.
-     */
-    virtual int32_t interceptSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
-            uint32_t& policyFlags) = 0;
-
-    /* Intercepts a generic touch, trackball or other event.
-     * The policy can use this method as an opportunity to perform power management functions
-     * and early event preprocessing such as updating policy flags.
-     *
-     * Returns a policy action constant such as ACTION_DISPATCH.
-     */
-    virtual int32_t interceptGeneric(nsecs_t when, uint32_t& policyFlags) = 0;
-
     /* Determines whether to turn on some hacks we have to improve the touch interaction with a
      * certain device whose screen currently is not all that good.
      */
@@ -403,8 +366,6 @@
 protected:
     InputDevice* mDevice;
     InputReaderContext* mContext;
-
-    bool applyStandardPolicyActions(nsecs_t when, int32_t policyActions);
 };
 
 
@@ -466,8 +427,6 @@
 
     void processKey(nsecs_t when, bool down, int32_t keyCode, int32_t scanCode,
             uint32_t policyFlags);
-    void applyPolicyAndDispatch(nsecs_t when, uint32_t policyFlags,
-            bool down, int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime);
 
     ssize_t findKeyDownLocked(int32_t scanCode);
 };
@@ -525,8 +484,6 @@
     void initializeLocked();
 
     void sync(nsecs_t when);
-    void applyPolicyAndDispatch(nsecs_t when, int32_t motionEventAction,
-            PointerCoords* pointerCoords, nsecs_t downTime);
 };
 
 
@@ -829,10 +786,6 @@
             BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
             int32_t motionEventAction);
 
-    void applyPolicyAndDispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
-            int32_t keyEventAction, int32_t keyEventFlags,
-            int32_t keyCode, int32_t scanCode, nsecs_t downTime);
-
     bool isPointInsideSurfaceLocked(int32_t x, int32_t y);
     const VirtualKey* findVirtualKeyHitLocked(int32_t x, int32_t y);
 
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/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index 43042c0b..ef19579 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -80,9 +80,16 @@
         }
     }
 
+    private Intent createInstallIntent() {
+        Intent intent = new Intent(INSTALL_ACTION);
+        intent.setClassName("com.android.certinstaller",
+                "com.android.certinstaller.CertInstallerMain");
+        return intent;
+    }
+
     public void install(Context context, KeyPair pair) {
         try {
-            Intent intent = new Intent(INSTALL_ACTION);
+            Intent intent = createInstallIntent();
             intent.putExtra(PRIVATE_KEY, pair.getPrivate().getEncoded());
             intent.putExtra(PUBLIC_KEY, pair.getPublic().getEncoded());
             context.startActivity(intent);
@@ -93,7 +100,7 @@
 
     public void install(Context context, String type, byte[] value) {
         try {
-            Intent intent = new Intent(INSTALL_ACTION);
+            Intent intent = createInstallIntent();
             intent.putExtra(type, value);
             context.startActivity(intent);
         } catch (ActivityNotFoundException e) {
@@ -103,7 +110,7 @@
 
     public void installFromSdCard(Context context) {
         try {
-            context.startActivity(new Intent(INSTALL_ACTION));
+            context.startActivity(createInstallIntent());
         } catch (ActivityNotFoundException e) {
             Log.w(LOGTAG, e.toString());
         }
diff --git a/libs/storage/IMountService.cpp b/libs/storage/IMountService.cpp
index 3ad9319..9ff6930 100644
--- a/libs/storage/IMountService.cpp
+++ b/libs/storage/IMountService.cpp
@@ -430,13 +430,14 @@
     }
 
     void mountObb(const String16& filename, const String16& key,
-            const sp<IObbActionListener>& token)
+            const sp<IObbActionListener>& token, int32_t nonce)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
         data.writeString16(filename);
         data.writeString16(key);
         data.writeStrongBinder(token->asBinder());
+        data.writeInt32(nonce);
         if (remote()->transact(TRANSACTION_mountObb, data, &reply) != NO_ERROR) {
             LOGD("mountObb could not contact remote\n");
             return;
@@ -448,12 +449,15 @@
         }
     }
 
-    void unmountObb(const String16& filename, const bool force, const sp<IObbActionListener>& token)
+    void unmountObb(const String16& filename, const bool force,
+            const sp<IObbActionListener>& token, const int32_t nonce)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
         data.writeString16(filename);
         data.writeInt32(force ? 1 : 0);
+        data.writeStrongBinder(token->asBinder());
+        data.writeInt32(nonce);
         if (remote()->transact(TRANSACTION_unmountObb, data, &reply) != NO_ERROR) {
             LOGD("unmountObb could not contact remote\n");
             return;
diff --git a/libs/storage/IObbActionListener.cpp b/libs/storage/IObbActionListener.cpp
index 5bfece7..eaa211e 100644
--- a/libs/storage/IObbActionListener.cpp
+++ b/libs/storage/IObbActionListener.cpp
@@ -30,7 +30,7 @@
         : BpInterface<IObbActionListener>(impl)
     { }
 
-    virtual void onObbResult(const String16& filename, const String16& status) { }
+    virtual void onObbResult(const String16& filename, const int32_t nonce, const int32_t state) { }
 };
 
 IMPLEMENT_META_INTERFACE(ObbActionListener, "IObbActionListener");
@@ -44,8 +44,9 @@
         case TRANSACTION_onObbResult: {
             CHECK_INTERFACE(IObbActionListener, data, reply);
             String16 filename = data.readString16();
-            String16 state = data.readString16();
-            onObbResult(filename, state);
+            int32_t nonce = data.readInt32();
+            int32_t state = data.readInt32();
+            onObbResult(filename, nonce, state);
             reply->writeNoException();
             return NO_ERROR;
         } break;
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/ui/EventHub.cpp b/libs/ui/EventHub.cpp
index c0be3a0..944731d 100644
--- a/libs/ui/EventHub.cpp
+++ b/libs/ui/EventHub.cpp
@@ -439,11 +439,10 @@
             // Since mFDs[0] is used for inotify, we process regular events starting at index 1.
             mInputDeviceIndex += 1;
             if (mInputDeviceIndex >= mFDCount) {
-                mInputDeviceIndex = 0;
                 break;
             }
 
-            const struct pollfd &pfd = mFDs[mInputDeviceIndex];
+            const struct pollfd& pfd = mFDs[mInputDeviceIndex];
             if (pfd.revents & POLLIN) {
                 int32_t readSize = read(pfd.fd, mInputBufferData,
                         sizeof(struct input_event) * INPUT_BUFFER_SIZE);
@@ -460,11 +459,17 @@
             }
         }
 
+#if HAVE_INOTIFY
         // readNotify() will modify mFDs and mFDCount, so this must be done after
         // processing all other events.
         if(mFDs[0].revents & POLLIN) {
             readNotify(mFDs[0].fd);
+            mFDs[0].revents = 0;
+            continue; // report added or removed devices immediately
         }
+#endif
+
+        mInputDeviceIndex = 0;
 
         // Poll for events.  Mind the wake lock dance!
         // We hold a wake lock at all times except during poll().  This works due to some
@@ -482,7 +487,7 @@
 
         if (pollResult <= 0) {
             if (errno != EINTR) {
-                LOGW("select failed (errno=%d)\n", errno);
+                LOGW("poll failed (errno=%d)\n", errno);
                 usleep(100000);
             }
         }
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index fe8555d..6ba19d7 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -95,16 +95,19 @@
     return true;
 }
 
-static bool isValidMotionAction(int32_t action) {
+static bool isValidMotionAction(int32_t action, size_t pointerCount) {
     switch (action & AMOTION_EVENT_ACTION_MASK) {
     case AMOTION_EVENT_ACTION_DOWN:
     case AMOTION_EVENT_ACTION_UP:
     case AMOTION_EVENT_ACTION_CANCEL:
     case AMOTION_EVENT_ACTION_MOVE:
-    case AMOTION_EVENT_ACTION_POINTER_DOWN:
-    case AMOTION_EVENT_ACTION_POINTER_UP:
     case AMOTION_EVENT_ACTION_OUTSIDE:
         return true;
+    case AMOTION_EVENT_ACTION_POINTER_DOWN:
+    case AMOTION_EVENT_ACTION_POINTER_UP: {
+        int32_t index = getMotionEventActionPointerIndex(action);
+        return index >= 0 && size_t(index) < pointerCount;
+    }
     default:
         return false;
     }
@@ -112,7 +115,7 @@
 
 static bool validateMotionEvent(int32_t action, size_t pointerCount,
         const int32_t* pointerIds) {
-    if (! isValidMotionAction(action)) {
+    if (! isValidMotionAction(action, pointerCount)) {
         LOGE("Motion event has invalid action code 0x%x", action);
         return false;
     }
@@ -235,16 +238,6 @@
         resetKeyRepeatLocked();
     }
 
-    // If dispatching is disabled, drop all events in the queue.
-    if (! mDispatchEnabled) {
-        if (mPendingEvent || ! mInboundQueue.isEmpty()) {
-            LOGI("Dropping pending events because input dispatch is disabled.");
-            releasePendingEventLocked();
-            drainInboundQueueLocked();
-        }
-        return;
-    }
-
     // If dispatching is frozen, do not process timeouts or try to deliver any new events.
     if (mDispatchFrozen) {
 #if DEBUG_FOCUS
@@ -294,7 +287,11 @@
             // samples may be appended to this event by the time the throttling timeout
             // expires.
             // TODO Make this smarter and consider throttling per device independently.
-            if (entry->type == EventEntry::TYPE_MOTION) {
+            if (entry->type == EventEntry::TYPE_MOTION
+                    && !isAppSwitchDue
+                    && mDispatchEnabled
+                    && (entry->policyFlags & POLICY_FLAG_PASS_TO_USER)
+                    && !entry->isInjected()) {
                 MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
                 int32_t deviceId = motionEntry->deviceId;
                 uint32_t source = motionEntry->source;
@@ -347,39 +344,43 @@
     // Now we have an event to dispatch.
     assert(mPendingEvent != NULL);
     bool done = false;
+    DropReason dropReason = DROP_REASON_NOT_DROPPED;
+    if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
+        dropReason = DROP_REASON_POLICY;
+    } else if (!mDispatchEnabled) {
+        dropReason = DROP_REASON_DISABLED;
+    }
     switch (mPendingEvent->type) {
     case EventEntry::TYPE_CONFIGURATION_CHANGED: {
         ConfigurationChangedEntry* typedEntry =
                 static_cast<ConfigurationChangedEntry*>(mPendingEvent);
         done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
+        dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped
         break;
     }
 
     case EventEntry::TYPE_KEY: {
         KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
-        bool appSwitchKey = isAppSwitchKey(typedEntry->keyCode);
-        bool dropEvent = isAppSwitchDue && ! appSwitchKey;
-        done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout, dropEvent,
-                nextWakeupTime);
-        if (done) {
-            if (dropEvent) {
-                LOGI("Dropped key because of pending overdue app switch.");
-            } else if (appSwitchKey) {
+        if (isAppSwitchDue) {
+            if (isAppSwitchKeyEventLocked(typedEntry)) {
                 resetPendingAppSwitchLocked(true);
+                isAppSwitchDue = false;
+            } else if (dropReason == DROP_REASON_NOT_DROPPED) {
+                dropReason = DROP_REASON_APP_SWITCH;
             }
         }
+        done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout,
+                &dropReason, nextWakeupTime);
         break;
     }
 
     case EventEntry::TYPE_MOTION: {
         MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
-        bool dropEvent = isAppSwitchDue;
-        done = dispatchMotionLocked(currentTime, typedEntry, dropEvent, nextWakeupTime);
-        if (done) {
-            if (dropEvent) {
-                LOGI("Dropped motion because of pending overdue app switch.");
-            }
+        if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
+            dropReason = DROP_REASON_APP_SWITCH;
         }
+        done = dispatchMotionLocked(currentTime, typedEntry,
+                &dropReason, nextWakeupTime);
         break;
     }
 
@@ -389,6 +390,10 @@
     }
 
     if (done) {
+        if (dropReason != DROP_REASON_NOT_DROPPED) {
+            dropInboundEventLocked(mPendingEvent, dropReason);
+        }
+
         releasePendingEventLocked();
         *nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately
     }
@@ -399,36 +404,85 @@
     mInboundQueue.enqueueAtTail(entry);
 
     switch (entry->type) {
-    case EventEntry::TYPE_KEY:
-        needWake |= detectPendingAppSwitchLocked(static_cast<KeyEntry*>(entry));
+    case EventEntry::TYPE_KEY: {
+        KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
+        if (isAppSwitchKeyEventLocked(keyEntry)) {
+            if (keyEntry->action == AKEY_EVENT_ACTION_DOWN) {
+                mAppSwitchSawKeyDown = true;
+            } else if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
+                if (mAppSwitchSawKeyDown) {
+#if DEBUG_APP_SWITCH
+                    LOGD("App switch is pending!");
+#endif
+                    mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;
+                    mAppSwitchSawKeyDown = false;
+                    needWake = true;
+                }
+            }
+        }
         break;
     }
+    }
 
     return needWake;
 }
 
-bool InputDispatcher::isAppSwitchKey(int32_t keyCode) {
+void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropReason) {
+    const char* reason;
+    switch (dropReason) {
+    case DROP_REASON_POLICY:
+#if DEBUG_INBOUND_EVENT_DETAILS
+        LOGD("Dropped event because policy consumed it.");
+#endif
+        reason = "inbound event was dropped because the policy consumed it";
+        break;
+    case DROP_REASON_DISABLED:
+        LOGI("Dropped event because input dispatch is disabled.");
+        reason = "inbound event was dropped because input dispatch is disabled";
+        break;
+    case DROP_REASON_APP_SWITCH:
+        LOGI("Dropped event because of pending overdue app switch.");
+        reason = "inbound event was dropped because of pending overdue app switch";
+        break;
+    default:
+        assert(false);
+        return;
+    }
+
+    switch (entry->type) {
+    case EventEntry::TYPE_KEY:
+        synthesizeCancelationEventsForAllConnectionsLocked(
+                InputState::CANCEL_NON_POINTER_EVENTS, reason);
+        break;
+    case EventEntry::TYPE_MOTION: {
+        MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
+        if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
+            synthesizeCancelationEventsForAllConnectionsLocked(
+                    InputState::CANCEL_POINTER_EVENTS, reason);
+        } else {
+            synthesizeCancelationEventsForAllConnectionsLocked(
+                    InputState::CANCEL_NON_POINTER_EVENTS, reason);
+        }
+        break;
+    }
+    }
+}
+
+bool InputDispatcher::isAppSwitchKeyCode(int32_t keyCode) {
     return keyCode == AKEYCODE_HOME || keyCode == AKEYCODE_ENDCALL;
 }
 
+bool InputDispatcher::isAppSwitchKeyEventLocked(KeyEntry* keyEntry) {
+    return ! (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED)
+            && isAppSwitchKeyCode(keyEntry->keyCode)
+            && (keyEntry->policyFlags & POLICY_FLAG_TRUSTED)
+            && (keyEntry->policyFlags & POLICY_FLAG_PASS_TO_USER);
+}
+
 bool InputDispatcher::isAppSwitchPendingLocked() {
     return mAppSwitchDueTime != LONG_LONG_MAX;
 }
 
-bool InputDispatcher::detectPendingAppSwitchLocked(KeyEntry* inboundKeyEntry) {
-    if (inboundKeyEntry->action == AKEY_EVENT_ACTION_UP
-            && ! (inboundKeyEntry->flags & AKEY_EVENT_FLAG_CANCELED)
-            && isAppSwitchKey(inboundKeyEntry->keyCode)
-            && isEventFromReliableSourceLocked(inboundKeyEntry)) {
-#if DEBUG_APP_SWITCH
-        LOGD("App switch is pending!");
-#endif
-        mAppSwitchDueTime = inboundKeyEntry->eventTime + APP_SWITCH_TIMEOUT;
-        return true; // need wake
-    }
-    return false;
-}
-
 void InputDispatcher::resetPendingAppSwitchLocked(bool handled) {
     mAppSwitchDueTime = LONG_LONG_MAX;
 
@@ -489,14 +543,6 @@
     mAllocator.releaseEventEntry(entry);
 }
 
-bool InputDispatcher::isEventFromReliableSourceLocked(EventEntry* entry) {
-    InjectionState* injectionState = entry->injectionState;
-    return ! injectionState
-            || injectionState->injectorUid == 0
-            || mPolicy->checkInjectEventsPermissionNonReentrant(
-                    injectionState->injectorPid, injectionState->injectorUid);
-}
-
 void InputDispatcher::resetKeyRepeatLocked() {
     if (mKeyRepeatState.lastKeyEntry) {
         mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
@@ -509,7 +555,8 @@
     KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
 
     // Reuse the repeated key entry if it is otherwise unreferenced.
-    uint32_t policyFlags = entry->policyFlags & POLICY_FLAG_RAW_MASK;
+    uint32_t policyFlags = (entry->policyFlags & POLICY_FLAG_RAW_MASK)
+            | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_TRUSTED;
     if (entry->refCount == 1) {
         mAllocator.recycleKeyEntry(entry);
         entry->eventTime = currentTime;
@@ -558,19 +605,13 @@
 
 bool InputDispatcher::dispatchKeyLocked(
         nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
-        bool dropEvent, nsecs_t* nextWakeupTime) {
+        DropReason* dropReason, nsecs_t* nextWakeupTime) {
     // Give the policy a chance to intercept the key.
     if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
-        bool trusted;
-        if (! dropEvent && mFocusedWindow) {
-            trusted = checkInjectionPermission(mFocusedWindow, entry->injectionState);
-        } else {
-            trusted = isEventFromReliableSourceLocked(entry);
-        }
-        if (trusted) {
+        if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
             CommandEntry* commandEntry = postCommandLocked(
                     & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
-            if (! dropEvent && mFocusedWindow) {
+            if (mFocusedWindow) {
                 commandEntry->inputChannel = mFocusedWindow->inputChannel;
             }
             commandEntry->keyEntry = entry;
@@ -580,15 +621,16 @@
             entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
         }
     } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
-        resetTargetsLocked();
-        setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_SUCCEEDED);
-        return true;
+        if (*dropReason == DROP_REASON_NOT_DROPPED) {
+            *dropReason = DROP_REASON_POLICY;
+        }
     }
 
     // Clean up if dropping the event.
-    if (dropEvent) {
+    if (*dropReason != DROP_REASON_NOT_DROPPED) {
         resetTargetsLocked();
-        setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
+        setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
+                ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
         return true;
     }
 
@@ -598,7 +640,8 @@
 
         if (entry->repeatCount == 0
                 && entry->action == AKEY_EVENT_ACTION_DOWN
-                && ! entry->isInjected()) {
+                && (entry->policyFlags & POLICY_FLAG_TRUSTED)
+                && !entry->isInjected()) {
             if (mKeyRepeatState.lastKeyEntry
                     && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
                 // We have seen two identical key downs in a row which indicates that the device
@@ -663,11 +706,12 @@
 }
 
 bool InputDispatcher::dispatchMotionLocked(
-        nsecs_t currentTime, MotionEntry* entry, bool dropEvent, nsecs_t* nextWakeupTime) {
+        nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
     // Clean up if dropping the event.
-    if (dropEvent) {
+    if (*dropReason != DROP_REASON_NOT_DROPPED) {
         resetTargetsLocked();
-        setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
+        setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
+                ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
         return true;
     }
 
@@ -793,9 +837,11 @@
             prepareDispatchCycleLocked(currentTime, connection, eventEntry, & inputTarget,
                     resumeWithAppendedMotionSample);
         } else {
-            LOGW("Framework requested delivery of an input event to channel '%s' but it "
-                    "is not registered with the input dispatcher.",
+#if DEBUG_FOCUS
+            LOGD("Dropping event delivery to target with channel '%s' because it "
+                    "is no longer registered with the input dispatcher.",
                     inputTarget.inputChannel->getName().string());
+#endif
         }
     }
 }
@@ -876,7 +922,9 @@
             ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
             if (connectionIndex >= 0) {
                 sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
-                connection->inputState.setOutOfSync();
+                synthesizeCancelationEventsForConnectionLocked(
+                        connection, InputState::CANCEL_ALL_EVENTS,
+                        "application not responding");
             }
         }
     }
@@ -1236,7 +1284,9 @@
         } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
             // First pointer went down.
             if (mTouchState.down) {
-                LOGW("Pointer down received while already down.");
+#if DEBUG_FOCUS
+                LOGD("Pointer down received while already down.");
+#endif
             }
         } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
             // One pointer went up.
@@ -1307,23 +1357,19 @@
 bool InputDispatcher::checkInjectionPermission(const InputWindow* window,
         const InjectionState* injectionState) {
     if (injectionState
-            && injectionState->injectorUid > 0
-            && (window == NULL || window->ownerUid != injectionState->injectorUid)) {
-        bool result = mPolicy->checkInjectEventsPermissionNonReentrant(
-                injectionState->injectorPid, injectionState->injectorUid);
-        if (! result) {
-            if (window) {
-                LOGW("Permission denied: injecting event from pid %d uid %d to window "
-                        "with input channel %s owned by uid %d",
-                        injectionState->injectorPid, injectionState->injectorUid,
-                        window->inputChannel->getName().string(),
-                        window->ownerUid);
-            } else {
-                LOGW("Permission denied: injecting event from pid %d uid %d",
-                        injectionState->injectorPid, injectionState->injectorUid);
-            }
-            return false;
+            && (window == NULL || window->ownerUid != injectionState->injectorUid)
+            && !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) {
+        if (window) {
+            LOGW("Permission denied: injecting event from pid %d uid %d to window "
+                    "with input channel %s owned by uid %d",
+                    injectionState->injectorPid, injectionState->injectorUid,
+                    window->inputChannel->getName().string(),
+                    window->ownerUid);
+        } else {
+            LOGW("Permission denied: injecting event from pid %d uid %d",
+                    injectionState->injectorPid, injectionState->injectorUid);
         }
+        return false;
     }
     return true;
 }
@@ -1408,8 +1454,10 @@
     // Skip this event if the connection status is not normal.
     // We don't want to enqueue additional outbound events if the connection is broken.
     if (connection->status != Connection::STATUS_NORMAL) {
-        LOGW("channel '%s' ~ Dropping event because the channel status is %s",
+#if DEBUG_DISPATCH_CYCLE
+        LOGD("channel '%s' ~ Dropping event because the channel status is %s",
                 connection->getInputChannelName(), connection->getStatusLabel());
+#endif
         return;
     }
 
@@ -1508,40 +1556,6 @@
         }
     }
 
-    // Bring the input state back in line with reality in case it drifted off during an ANR.
-    if (connection->inputState.isOutOfSync()) {
-        mTempCancelationEvents.clear();
-        connection->inputState.synthesizeCancelationEvents(& mAllocator, mTempCancelationEvents);
-        connection->inputState.resetOutOfSync();
-
-        if (! mTempCancelationEvents.isEmpty()) {
-            LOGI("channel '%s' ~ Generated %d cancelation events to bring channel back in sync "
-                    "with reality.",
-                    connection->getInputChannelName(), mTempCancelationEvents.size());
-
-            for (size_t i = 0; i < mTempCancelationEvents.size(); i++) {
-                EventEntry* cancelationEventEntry = mTempCancelationEvents.itemAt(i);
-                switch (cancelationEventEntry->type) {
-                case EventEntry::TYPE_KEY:
-                    logOutboundKeyDetailsLocked("  ",
-                            static_cast<KeyEntry*>(cancelationEventEntry));
-                    break;
-                case EventEntry::TYPE_MOTION:
-                    logOutboundMotionDetailsLocked("  ",
-                            static_cast<MotionEntry*>(cancelationEventEntry));
-                    break;
-                }
-
-                DispatchEntry* cancelationDispatchEntry =
-                        mAllocator.obtainDispatchEntry(cancelationEventEntry,
-                        0, inputTarget->xOffset, inputTarget->yOffset); // increments ref
-                connection->outboundQueue.enqueueAtTail(cancelationDispatchEntry);
-
-                mAllocator.releaseEventEntry(cancelationEventEntry);
-            }
-        }
-    }
-
     // This is a new event.
     // Enqueue a new dispatch entry onto the outbound queue for this connection.
     DispatchEntry* dispatchEntry = mAllocator.obtainDispatchEntry(eventEntry, // increments ref
@@ -1635,7 +1649,7 @@
         if (status) {
             LOGE("channel '%s' ~ Could not publish key event, "
                     "status=%d", connection->getInputChannelName(), status);
-            abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
+            abortBrokenDispatchCycleLocked(currentTime, connection);
             return;
         }
         break;
@@ -1685,7 +1699,7 @@
         if (status) {
             LOGE("channel '%s' ~ Could not publish motion event, "
                     "status=%d", connection->getInputChannelName(), status);
-            abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
+            abortBrokenDispatchCycleLocked(currentTime, connection);
             return;
         }
 
@@ -1706,7 +1720,7 @@
                 LOGE("channel '%s' ~ Could not append motion sample "
                         "for a reason other than out of memory, status=%d",
                         connection->getInputChannelName(), status);
-                abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
+                abortBrokenDispatchCycleLocked(currentTime, connection);
                 return;
             }
         }
@@ -1727,7 +1741,7 @@
     if (status) {
         LOGE("channel '%s' ~ Could not send dispatch signal, status=%d",
                 connection->getInputChannelName(), status);
-        abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
+        abortBrokenDispatchCycleLocked(currentTime, connection);
         return;
     }
 
@@ -1764,7 +1778,7 @@
     if (status) {
         LOGE("channel '%s' ~ Could not reset publisher, status=%d",
                 connection->getInputChannelName(), status);
-        abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
+        abortBrokenDispatchCycleLocked(currentTime, connection);
         return;
     }
 
@@ -1806,28 +1820,23 @@
     deactivateConnectionLocked(connection.get());
 }
 
-void InputDispatcher::abortDispatchCycleLocked(nsecs_t currentTime,
-        const sp<Connection>& connection, bool broken) {
+void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime,
+        const sp<Connection>& connection) {
 #if DEBUG_DISPATCH_CYCLE
-    LOGD("channel '%s' ~ abortDispatchCycle - broken=%s",
+    LOGD("channel '%s' ~ abortBrokenDispatchCycle - broken=%s",
             connection->getInputChannelName(), toString(broken));
 #endif
 
-    // Input state will no longer be realistic.
-    connection->inputState.setOutOfSync();
-
     // Clear the outbound queue.
     drainOutboundQueueLocked(connection.get());
 
-    // Handle the case where the connection appears to be unrecoverably broken.
+    // The connection appears to be unrecoverably broken.
     // Ignore already broken or zombie connections.
-    if (broken) {
-        if (connection->status == Connection::STATUS_NORMAL) {
-            connection->status = Connection::STATUS_BROKEN;
+    if (connection->status == Connection::STATUS_NORMAL) {
+        connection->status = Connection::STATUS_BROKEN;
 
-            // Notify other system components.
-            onDispatchCycleBrokenLocked(currentTime, connection);
-        }
+        // Notify other system components.
+        onDispatchCycleBrokenLocked(currentTime, connection);
     }
 }
 
@@ -1862,7 +1871,7 @@
         if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
             LOGE("channel '%s' ~ Consumer closed input channel or an error occurred.  "
                     "events=0x%x", connection->getInputChannelName(), events);
-            d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
+            d->abortBrokenDispatchCycleLocked(currentTime, connection);
             d->runCommandsLockedInterruptible();
             return 0; // remove the callback
         }
@@ -1877,7 +1886,7 @@
         if (status) {
             LOGE("channel '%s' ~ Failed to receive finished signal.  status=%d",
                     connection->getInputChannelName(), status);
-            d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
+            d->abortBrokenDispatchCycleLocked(currentTime, connection);
             d->runCommandsLockedInterruptible();
             return 0; // remove the callback
         }
@@ -1888,6 +1897,77 @@
     } // release lock
 }
 
+void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked(
+        InputState::CancelationOptions options, const char* reason) {
+    for (size_t i = 0; i < mConnectionsByReceiveFd.size(); i++) {
+        synthesizeCancelationEventsForConnectionLocked(
+                mConnectionsByReceiveFd.valueAt(i), options, reason);
+    }
+}
+
+void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked(
+        const sp<InputChannel>& channel, InputState::CancelationOptions options,
+        const char* reason) {
+    ssize_t index = getConnectionIndexLocked(channel);
+    if (index >= 0) {
+        synthesizeCancelationEventsForConnectionLocked(
+                mConnectionsByReceiveFd.valueAt(index), options, reason);
+    }
+}
+
+void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
+        const sp<Connection>& connection, InputState::CancelationOptions options,
+        const char* reason) {
+    nsecs_t currentTime = now();
+
+    mTempCancelationEvents.clear();
+    connection->inputState.synthesizeCancelationEvents(currentTime, & mAllocator,
+            mTempCancelationEvents, options);
+
+    if (! mTempCancelationEvents.isEmpty()
+            && connection->status != Connection::STATUS_BROKEN) {
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+        LOGD("channel '%s' ~ Synthesized %d cancelation events to bring channel back in sync "
+                "with reality: %s, options=%d.",
+                connection->getInputChannelName(), mTempCancelationEvents.size(), reason, options);
+#endif
+        for (size_t i = 0; i < mTempCancelationEvents.size(); i++) {
+            EventEntry* cancelationEventEntry = mTempCancelationEvents.itemAt(i);
+            switch (cancelationEventEntry->type) {
+            case EventEntry::TYPE_KEY:
+                logOutboundKeyDetailsLocked("cancel - ",
+                        static_cast<KeyEntry*>(cancelationEventEntry));
+                break;
+            case EventEntry::TYPE_MOTION:
+                logOutboundMotionDetailsLocked("cancel - ",
+                        static_cast<MotionEntry*>(cancelationEventEntry));
+                break;
+            }
+
+            int32_t xOffset, yOffset;
+            const InputWindow* window = getWindowLocked(connection->inputChannel);
+            if (window) {
+                xOffset = -window->frameLeft;
+                yOffset = -window->frameTop;
+            } else {
+                xOffset = 0;
+                yOffset = 0;
+            }
+
+            DispatchEntry* cancelationDispatchEntry =
+                    mAllocator.obtainDispatchEntry(cancelationEventEntry, // increments ref
+                    0, xOffset, yOffset);
+            connection->outboundQueue.enqueueAtTail(cancelationDispatchEntry);
+
+            mAllocator.releaseEventEntry(cancelationEventEntry);
+        }
+
+        if (!connection->outboundQueue.headSentinel.next->inProgress) {
+            startDispatchCycleLocked(currentTime, connection);
+        }
+    }
+}
+
 InputDispatcher::MotionEntry*
 InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds) {
     assert(pointerIds.value != 0);
@@ -1999,6 +2079,10 @@
         return;
     }
 
+    policyFlags |= POLICY_FLAG_TRUSTED;
+    mPolicy->interceptKeyBeforeQueueing(eventTime, deviceId, action, /*byref*/ flags,
+            keyCode, scanCode, /*byref*/ policyFlags);
+
     bool needWake;
     { // acquire lock
         AutoMutex _l(mLock);
@@ -2041,6 +2125,9 @@
         return;
     }
 
+    policyFlags |= POLICY_FLAG_TRUSTED;
+    mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
+
     bool needWake;
     { // acquire lock
         AutoMutex _l(mLock);
@@ -2165,6 +2252,17 @@
     }
 }
 
+void InputDispatcher::notifySwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
+        uint32_t policyFlags) {
+#if DEBUG_INBOUND_EVENT_DETAILS
+    LOGD("notifySwitch - switchCode=%d, switchValue=%d, policyFlags=0x%x",
+            switchCode, switchValue, policyFlags);
+#endif
+
+    policyFlags |= POLICY_FLAG_TRUSTED;
+    mPolicy->notifySwitch(when, switchCode, switchValue, policyFlags);
+}
+
 int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
         int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
 #if DEBUG_INBOUND_EVENT_DETAILS
@@ -2175,26 +2273,81 @@
 
     nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
 
-    InjectionState* injectionState;
-    bool needWake;
-    { // acquire lock
-        AutoMutex _l(mLock);
+    uint32_t policyFlags = POLICY_FLAG_INJECTED;
+    if (hasInjectionPermission(injectorPid, injectorUid)) {
+        policyFlags |= POLICY_FLAG_TRUSTED;
+    }
 
-        EventEntry* injectedEntry = createEntryFromInjectedInputEventLocked(event);
-        if (! injectedEntry) {
+    EventEntry* injectedEntry;
+    switch (event->getType()) {
+    case AINPUT_EVENT_TYPE_KEY: {
+        const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
+        int32_t action = keyEvent->getAction();
+        if (! validateKeyEvent(action)) {
             return INPUT_EVENT_INJECTION_FAILED;
         }
 
-        injectionState = mAllocator.obtainInjectionState(injectorPid, injectorUid);
-        if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
-            injectionState->injectionIsAsync = true;
+        nsecs_t eventTime = keyEvent->getEventTime();
+        int32_t deviceId = keyEvent->getDeviceId();
+        int32_t flags = keyEvent->getFlags();
+        int32_t keyCode = keyEvent->getKeyCode();
+        int32_t scanCode = keyEvent->getScanCode();
+        mPolicy->interceptKeyBeforeQueueing(eventTime, deviceId, action, /*byref*/ flags,
+                keyCode, scanCode, /*byref*/ policyFlags);
+
+        mLock.lock();
+        injectedEntry = mAllocator.obtainKeyEntry(eventTime, deviceId, keyEvent->getSource(),
+                policyFlags, action, flags, keyCode, scanCode, keyEvent->getMetaState(),
+                keyEvent->getRepeatCount(), keyEvent->getDownTime());
+        break;
+    }
+
+    case AINPUT_EVENT_TYPE_MOTION: {
+        const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
+        int32_t action = motionEvent->getAction();
+        size_t pointerCount = motionEvent->getPointerCount();
+        const int32_t* pointerIds = motionEvent->getPointerIds();
+        if (! validateMotionEvent(action, pointerCount, pointerIds)) {
+            return INPUT_EVENT_INJECTION_FAILED;
         }
 
-        injectionState->refCount += 1;
-        injectedEntry->injectionState = injectionState;
+        nsecs_t eventTime = motionEvent->getEventTime();
+        mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
 
-        needWake = enqueueInboundEventLocked(injectedEntry);
-    } // release lock
+        mLock.lock();
+        const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
+        const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
+        MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
+                motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
+                action, motionEvent->getFlags(),
+                motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
+                motionEvent->getXPrecision(), motionEvent->getYPrecision(),
+                motionEvent->getDownTime(), uint32_t(pointerCount),
+                pointerIds, samplePointerCoords);
+        for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
+            sampleEventTimes += 1;
+            samplePointerCoords += pointerCount;
+            mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
+        }
+        injectedEntry = motionEntry;
+        break;
+    }
+
+    default:
+        LOGW("Cannot inject event of type %d", event->getType());
+        return INPUT_EVENT_INJECTION_FAILED;
+    }
+
+    InjectionState* injectionState = mAllocator.obtainInjectionState(injectorPid, injectorUid);
+    if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
+        injectionState->injectionIsAsync = true;
+    }
+
+    injectionState->refCount += 1;
+    injectedEntry->injectionState = injectionState;
+
+    bool needWake = enqueueInboundEventLocked(injectedEntry);
+    mLock.unlock();
 
     if (needWake) {
         mLooper->wake();
@@ -2260,6 +2413,11 @@
     return injectionResult;
 }
 
+bool InputDispatcher::hasInjectionPermission(int32_t injectorPid, int32_t injectorUid) {
+    return injectorUid == 0
+            || mPolicy->checkInjectEventsPermissionNonReentrant(injectorPid, injectorUid);
+}
+
 void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
     InjectionState* injectionState = entry->injectionState;
     if (injectionState) {
@@ -2310,59 +2468,6 @@
     }
 }
 
-InputDispatcher::EventEntry* InputDispatcher::createEntryFromInjectedInputEventLocked(
-        const InputEvent* event) {
-    switch (event->getType()) {
-    case AINPUT_EVENT_TYPE_KEY: {
-        const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
-        if (! validateKeyEvent(keyEvent->getAction())) {
-            return NULL;
-        }
-
-        uint32_t policyFlags = POLICY_FLAG_INJECTED;
-
-        KeyEntry* keyEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
-                keyEvent->getDeviceId(), keyEvent->getSource(), policyFlags,
-                keyEvent->getAction(), keyEvent->getFlags(),
-                keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
-                keyEvent->getRepeatCount(), keyEvent->getDownTime());
-        return keyEntry;
-    }
-
-    case AINPUT_EVENT_TYPE_MOTION: {
-        const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
-        if (! validateMotionEvent(motionEvent->getAction(),
-                motionEvent->getPointerCount(), motionEvent->getPointerIds())) {
-            return NULL;
-        }
-
-        uint32_t policyFlags = POLICY_FLAG_INJECTED;
-
-        const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
-        const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
-        size_t pointerCount = motionEvent->getPointerCount();
-
-        MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
-                motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
-                motionEvent->getAction(), motionEvent->getFlags(),
-                motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
-                motionEvent->getXPrecision(), motionEvent->getYPrecision(),
-                motionEvent->getDownTime(), uint32_t(pointerCount),
-                motionEvent->getPointerIds(), samplePointerCoords);
-        for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
-            sampleEventTimes += 1;
-            samplePointerCoords += pointerCount;
-            mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
-        }
-        return motionEntry;
-    }
-
-    default:
-        assert(false);
-        return NULL;
-    }
-}
-
 const InputWindow* InputDispatcher::getWindowLocked(const sp<InputChannel>& inputChannel) {
     for (size_t i = 0; i < mWindows.size(); i++) {
         const InputWindow* window = & mWindows[i];
@@ -2381,7 +2486,12 @@
         AutoMutex _l(mLock);
 
         // Clear old window pointers.
-        mFocusedWindow = NULL;
+        sp<InputChannel> oldFocusedWindowChannel;
+        if (mFocusedWindow) {
+            oldFocusedWindowChannel = mFocusedWindow->inputChannel;
+            mFocusedWindow = NULL;
+        }
+
         mWindows.clear();
 
         // Loop over new windows and rebuild the necessary window pointers for
@@ -2397,6 +2507,24 @@
             }
         }
 
+        if (oldFocusedWindowChannel != NULL) {
+            if (!mFocusedWindow || oldFocusedWindowChannel != mFocusedWindow->inputChannel) {
+#if DEBUG_FOCUS
+                LOGD("Focus left window: %s",
+                        oldFocusedWindowChannel->getName().string());
+#endif
+                synthesizeCancelationEventsForInputChannelLocked(oldFocusedWindowChannel,
+                        InputState::CANCEL_NON_POINTER_EVENTS, "focus left window");
+                oldFocusedWindowChannel.clear();
+            }
+        }
+        if (mFocusedWindow && oldFocusedWindowChannel == NULL) {
+#if DEBUG_FOCUS
+            LOGD("Focus entered window: %s",
+                    mFocusedWindow->inputChannel->getName().string());
+#endif
+        }
+
         for (size_t i = 0; i < mTouchState.windows.size(); ) {
             TouchedWindow& touchedWindow = mTouchState.windows.editItemAt(i);
             const InputWindow* window = getWindowLocked(touchedWindow.channel);
@@ -2404,12 +2532,17 @@
                 touchedWindow.window = window;
                 i += 1;
             } else {
+#if DEBUG_FOCUS
+                LOGD("Touched window was removed: %s", touchedWindow.channel->getName().string());
+#endif
                 mTouchState.windows.removeAt(i);
+                synthesizeCancelationEventsForInputChannelLocked(touchedWindow.channel,
+                        InputState::CANCEL_POINTER_EVENTS, "touched window was removed");
             }
         }
 
 #if DEBUG_FOCUS
-        logDispatchStateLocked();
+        //logDispatchStateLocked();
 #endif
     } // release lock
 
@@ -2432,7 +2565,7 @@
         }
 
 #if DEBUG_FOCUS
-        logDispatchStateLocked();
+        //logDispatchStateLocked();
 #endif
     } // release lock
 
@@ -2469,7 +2602,7 @@
         }
 
 #if DEBUG_FOCUS
-        logDispatchStateLocked();
+        //logDispatchStateLocked();
 #endif
     } // release lock
 
@@ -2571,11 +2704,10 @@
         for (size_t i = 0; i < mActiveConnections.size(); i++) {
             const Connection* connection = mActiveConnections[i];
             dump.appendFormat(INDENT2 "%d: '%s', status=%s, outboundQueueLength=%u"
-                    "inputState.isNeutral=%s, inputState.isOutOfSync=%s\n",
+                    "inputState.isNeutral=%s\n",
                     i, connection->getInputChannelName(), connection->getStatusLabel(),
                     connection->outboundQueue.count(),
-                    toString(connection->inputState.isNeutral()),
-                    toString(connection->inputState.isOutOfSync()));
+                    toString(connection->inputState.isNeutral()));
         }
     } else {
         dump.append(INDENT "ActiveConnections: <none>\n");
@@ -2656,7 +2788,7 @@
         mLooper->removeFd(inputChannel->getReceivePipeFd());
 
         nsecs_t currentTime = now();
-        abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
+        abortBrokenDispatchCycleLocked(currentTime, connection);
 
         runCommandsLockedInterruptible();
     } // release lock
@@ -2837,11 +2969,12 @@
 }
 
 void InputDispatcher::Allocator::initializeEventEntry(EventEntry* entry, int32_t type,
-        nsecs_t eventTime) {
+        nsecs_t eventTime, uint32_t policyFlags) {
     entry->type = type;
     entry->refCount = 1;
     entry->dispatchInProgress = false;
     entry->eventTime = eventTime;
+    entry->policyFlags = policyFlags;
     entry->injectionState = NULL;
 }
 
@@ -2855,7 +2988,7 @@
 InputDispatcher::ConfigurationChangedEntry*
 InputDispatcher::Allocator::obtainConfigurationChangedEntry(nsecs_t eventTime) {
     ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
-    initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime);
+    initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime, 0);
     return entry;
 }
 
@@ -2864,11 +2997,10 @@
         int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
         int32_t repeatCount, nsecs_t downTime) {
     KeyEntry* entry = mKeyEntryPool.alloc();
-    initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime);
+    initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime, policyFlags);
 
     entry->deviceId = deviceId;
     entry->source = source;
-    entry->policyFlags = policyFlags;
     entry->action = action;
     entry->flags = flags;
     entry->keyCode = keyCode;
@@ -2887,12 +3019,11 @@
         nsecs_t downTime, uint32_t pointerCount,
         const int32_t* pointerIds, const PointerCoords* pointerCoords) {
     MotionEntry* entry = mMotionEntryPool.alloc();
-    initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime);
+    initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime, policyFlags);
 
     entry->eventTime = eventTime;
     entry->deviceId = deviceId;
     entry->source = source;
-    entry->policyFlags = policyFlags;
     entry->action = action;
     entry->flags = flags;
     entry->metaState = metaState;
@@ -3039,8 +3170,7 @@
 
 // --- InputDispatcher::InputState ---
 
-InputDispatcher::InputState::InputState() :
-        mIsOutOfSync(false) {
+InputDispatcher::InputState::InputState() {
 }
 
 InputDispatcher::InputState::~InputState() {
@@ -3050,20 +3180,6 @@
     return mKeyMementos.isEmpty() && mMotionMementos.isEmpty();
 }
 
-bool InputDispatcher::InputState::isOutOfSync() const {
-    return mIsOutOfSync;
-}
-
-void InputDispatcher::InputState::setOutOfSync() {
-    if (! isNeutral()) {
-        mIsOutOfSync = true;
-    }
-}
-
-void InputDispatcher::InputState::resetOutOfSync() {
-    mIsOutOfSync = false;
-}
-
 InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackEvent(
         const EventEntry* entry) {
     switch (entry->type) {
@@ -3090,9 +3206,6 @@
             switch (action) {
             case AKEY_EVENT_ACTION_UP:
                 mKeyMementos.removeAt(i);
-                if (isNeutral()) {
-                    mIsOutOfSync = false;
-                }
                 return CONSISTENT;
 
             case AKEY_EVENT_ACTION_DOWN:
@@ -3132,9 +3245,6 @@
             case AMOTION_EVENT_ACTION_UP:
             case AMOTION_EVENT_ACTION_CANCEL:
                 mMotionMementos.removeAt(i);
-                if (isNeutral()) {
-                    mIsOutOfSync = false;
-                }
                 return CONSISTENT;
 
             case AMOTION_EVENT_ACTION_DOWN:
@@ -3192,30 +3302,52 @@
     }
 }
 
-void InputDispatcher::InputState::synthesizeCancelationEvents(
-        Allocator* allocator, Vector<EventEntry*>& outEvents) const {
-    for (size_t i = 0; i < mKeyMementos.size(); i++) {
+void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTime,
+        Allocator* allocator, Vector<EventEntry*>& outEvents,
+        CancelationOptions options) {
+    for (size_t i = 0; i < mKeyMementos.size(); ) {
         const KeyMemento& memento = mKeyMementos.itemAt(i);
-        outEvents.push(allocator->obtainKeyEntry(now(),
-                memento.deviceId, memento.source, 0,
-                AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_CANCELED,
-                memento.keyCode, memento.scanCode, 0, 0, memento.downTime));
+        if (shouldCancelEvent(memento.source, options)) {
+            outEvents.push(allocator->obtainKeyEntry(currentTime,
+                    memento.deviceId, memento.source, 0,
+                    AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_CANCELED,
+                    memento.keyCode, memento.scanCode, 0, 0, memento.downTime));
+            mKeyMementos.removeAt(i);
+        } else {
+            i += 1;
+        }
     }
 
-    for (size_t i = 0; i < mMotionMementos.size(); i++) {
+    for (size_t i = 0; i < mMotionMementos.size(); ) {
         const MotionMemento& memento = mMotionMementos.itemAt(i);
-        outEvents.push(allocator->obtainMotionEntry(now(),
-                memento.deviceId, memento.source, 0,
-                AMOTION_EVENT_ACTION_CANCEL, 0, 0, 0,
-                memento.xPrecision, memento.yPrecision, memento.downTime,
-                memento.pointerCount, memento.pointerIds, memento.pointerCoords));
+        if (shouldCancelEvent(memento.source, options)) {
+            outEvents.push(allocator->obtainMotionEntry(currentTime,
+                    memento.deviceId, memento.source, 0,
+                    AMOTION_EVENT_ACTION_CANCEL, 0, 0, 0,
+                    memento.xPrecision, memento.yPrecision, memento.downTime,
+                    memento.pointerCount, memento.pointerIds, memento.pointerCoords));
+            mMotionMementos.removeAt(i);
+        } else {
+            i += 1;
+        }
     }
 }
 
 void InputDispatcher::InputState::clear() {
     mKeyMementos.clear();
     mMotionMementos.clear();
-    mIsOutOfSync = false;
+}
+
+bool InputDispatcher::InputState::shouldCancelEvent(int32_t eventSource,
+        CancelationOptions options) {
+    switch (options) {
+    case CANCEL_POINTER_EVENTS:
+        return eventSource & AINPUT_SOURCE_CLASS_POINTER;
+    case CANCEL_NON_POINTER_EVENTS:
+        return !(eventSource & AINPUT_SOURCE_CLASS_POINTER);
+    default:
+        return true;
+    }
 }
 
 
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
index 8e173aa..0560bb8 100644
--- a/libs/ui/InputReader.cpp
+++ b/libs/ui/InputReader.cpp
@@ -796,10 +796,6 @@
     return 0;
 }
 
-bool InputMapper::applyStandardPolicyActions(nsecs_t when, int32_t policyActions) {
-    return policyActions & InputReaderPolicyInterface::ACTION_DISPATCH;
-}
-
 
 // --- SwitchInputMapper ---
 
@@ -823,11 +819,7 @@
 }
 
 void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
-    uint32_t policyFlags = 0;
-    int32_t policyActions = getPolicy()->interceptSwitch(
-            when, switchCode, switchValue, policyFlags);
-
-    applyStandardPolicyActions(when, policyActions);
+    getDispatcher()->notifySwitch(when, switchCode, switchValue, 0);
 }
 
 int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
@@ -983,29 +975,9 @@
         getContext()->updateGlobalMetaState();
     }
 
-    applyPolicyAndDispatch(when, policyFlags, down, keyCode, scanCode, newMetaState, downTime);
-}
-
-void KeyboardInputMapper::applyPolicyAndDispatch(nsecs_t when, uint32_t policyFlags, bool down,
-        int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
-    int32_t policyActions = getPolicy()->interceptKey(when,
-            getDeviceId(), down, keyCode, scanCode, policyFlags);
-
-    if (! applyStandardPolicyActions(when, policyActions)) {
-        return; // event dropped
-    }
-
-    int32_t keyEventAction = down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP;
-    int32_t keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM;
-    if (policyFlags & POLICY_FLAG_WOKE_HERE) {
-        keyEventFlags |= AKEY_EVENT_FLAG_WOKE_HERE;
-    }
-    if (policyFlags & POLICY_FLAG_VIRTUAL) {
-        keyEventFlags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
-    }
-
     getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
-            keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
+            down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
+            AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
 }
 
 ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
@@ -1215,26 +1187,13 @@
         }
     } // release lock
 
-    applyPolicyAndDispatch(when, motionEventAction, & pointerCoords, downTime);
-
-    mAccumulator.clear();
-}
-
-void TrackballInputMapper::applyPolicyAndDispatch(nsecs_t when, int32_t motionEventAction,
-        PointerCoords* pointerCoords, nsecs_t downTime) {
-    uint32_t policyFlags = 0;
-    int32_t policyActions = getPolicy()->interceptGeneric(when, policyFlags);
-
-    if (! applyStandardPolicyActions(when, policyActions)) {
-        return; // event dropped
-    }
-
     int32_t metaState = mContext->getGlobalMetaState();
     int32_t pointerId = 0;
-
-    getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, policyFlags,
+    getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, 0,
             motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
-            1, & pointerId, pointerCoords, mXPrecision, mYPrecision, downTime);
+            1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
+
+    mAccumulator.clear();
 }
 
 int32_t TrackballInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
@@ -2012,15 +1971,7 @@
 }
 
 void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
-    // Apply generic policy actions.
-
     uint32_t policyFlags = 0;
-    int32_t policyActions = getPolicy()->interceptGeneric(when, policyFlags);
-
-    if (! applyStandardPolicyActions(when, policyActions)) {
-        mLastTouch.clear();
-        return; // event dropped
-    }
 
     // Preprocess pointer data.
 
@@ -2160,24 +2111,11 @@
     } // release lock
 
     // Dispatch virtual key.
-    applyPolicyAndDispatchVirtualKey(when, policyFlags, keyEventAction, keyEventFlags,
-            keyCode, scanCode, downTime);
-    return touchResult;
-}
-
-void TouchInputMapper::applyPolicyAndDispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
-        int32_t keyEventAction, int32_t keyEventFlags,
-        int32_t keyCode, int32_t scanCode, nsecs_t downTime) {
     int32_t metaState = mContext->getGlobalMetaState();
-
     policyFlags |= POLICY_FLAG_VIRTUAL;
-    int32_t policyActions = getPolicy()->interceptKey(when, getDeviceId(),
-            keyEventAction == AKEY_EVENT_ACTION_DOWN, keyCode, scanCode, policyFlags);
-
-    if (applyStandardPolicyActions(when, policyActions)) {
-        getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
-                keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
-    }
+    getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
+            keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
+    return touchResult;
 }
 
 void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
@@ -2447,7 +2385,7 @@
         yPrecision = mLocked.orientedYPrecision;
     } // release lock
 
-    getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TOUCHSCREEN, policyFlags,
+    getDispatcher()->notifyMotion(when, getDeviceId(), getSources(), policyFlags,
             motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
             pointerCount, pointerIds, pointerCoords,
             xPrecision, yPrecision, mDownTime);
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/ZipFileRO.cpp b/libs/utils/ZipFileRO.cpp
index 9b1f82f..5ff1f8f 100644
--- a/libs/utils/ZipFileRO.cpp
+++ b/libs/utils/ZipFileRO.cpp
@@ -32,6 +32,22 @@
 #include <assert.h>
 #include <unistd.h>
 
+#if HAVE_PRINTF_ZD
+#  define ZD "%zd"
+#  define ZD_TYPE ssize_t
+#else
+#  define ZD "%ld"
+#  define ZD_TYPE long
+#endif
+
+/*
+ * We must open binary files using open(path, ... | O_BINARY) under Windows.
+ * Otherwise strange read errors will happen.
+ */
+#ifndef O_BINARY
+#  define O_BINARY  0
+#endif
+
 /*
  * TEMP_FAILURE_RETRY is defined by some, but not all, versions of
  * <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's
@@ -124,7 +140,7 @@
     /*
      * Open and map the specified file.
      */
-    fd = ::open(zipFileName, O_RDONLY);
+    fd = ::open(zipFileName, O_RDONLY | O_BINARY);
     if (fd < 0) {
         LOGW("Unable to open zip '%s': %s\n", zipFileName, strerror(errno));
         return NAME_NOT_FOUND;
@@ -172,8 +188,8 @@
  */
 bool ZipFileRO::mapCentralDirectory(void)
 {
-    size_t readAmount = kMaxEOCDSearch;
-    if (readAmount > (size_t) mFileLength)
+    ssize_t readAmount = kMaxEOCDSearch;
+    if (readAmount > (ssize_t) mFileLength)
         readAmount = mFileLength;
 
     unsigned char* scanBuf = (unsigned char*) malloc(readAmount);
@@ -233,7 +249,8 @@
     }
     actual = TEMP_FAILURE_RETRY(read(mFd, scanBuf, readAmount));
     if (actual != (ssize_t) readAmount) {
-        LOGW("Zip: read %zd failed: %s\n", readAmount, strerror(errno));
+        LOGW("Zip: read " ZD ", expected " ZD ". Failed: %s\n",
+            (ZD_TYPE) actual, (ZD_TYPE) readAmount, strerror(errno));
         free(scanBuf);
         return false;
     }
@@ -292,8 +309,8 @@
     }
 
     if (!mDirectoryMap->create(mFileName, mFd, dirOffset, dirSize, true)) {
-        LOGW("Unable to map '%s' (%zd to %zd): %s\n", mFileName,
-                dirOffset, dirOffset + dirSize, strerror(errno));
+        LOGW("Unable to map '%s' (" ZD " to " ZD "): %s\n", mFileName,
+                (ZD_TYPE) dirOffset, (ZD_TYPE) (dirOffset + dirSize), strerror(errno));
         return false;
     }
 
@@ -350,8 +367,8 @@
 
         ptr += kCDELen + fileNameLen + extraLen + commentLen;
         if ((size_t)(ptr - cdPtr) > cdLength) {
-            LOGW("bad CD advance (%d vs %zd) at entry %d\n",
-                (int) (ptr - cdPtr), cdLength, i);
+            LOGW("bad CD advance (%d vs " ZD ") at entry %d\n",
+                (int) (ptr - cdPtr), (ZD_TYPE) cdLength, i);
             goto bail;
         }
     }
@@ -556,8 +573,8 @@
             if (get4LE(lfhBuf) != kLFHSignature) {
                 off_t actualOffset = lseek(mFd, 0, SEEK_CUR);
                 LOGW("didn't find signature at start of lfh; wanted: offset=%ld data=0x%08x; "
-                        "got: offset=%zd data=0x%08lx\n",
-                        localHdrOffset, kLFHSignature, (size_t)actualOffset, get4LE(lfhBuf));
+                        "got: offset=" ZD " data=0x%08lx\n",
+                        localHdrOffset, kLFHSignature, (ZD_TYPE) actualOffset, get4LE(lfhBuf));
                 return false;
             }
         }
@@ -572,16 +589,16 @@
 
         /* check lengths */
         if ((off_t)(dataOffset + compLen) > cdOffset) {
-            LOGW("bad compressed length in zip (%ld + %zd > %ld)\n",
-                (long) dataOffset, compLen, (long) cdOffset);
+            LOGW("bad compressed length in zip (%ld + " ZD " > %ld)\n",
+                (long) dataOffset, (ZD_TYPE) compLen, (long) cdOffset);
             return false;
         }
 
         if (method == kCompressStored &&
             (off_t)(dataOffset + uncompLen) > cdOffset)
         {
-            LOGE("ERROR: bad uncompressed length in zip (%ld + %zd > %ld)\n",
-                (long) dataOffset, uncompLen, (long) cdOffset);
+            LOGE("ERROR: bad uncompressed length in zip (%ld + " ZD " > %ld)\n",
+                (long) dataOffset, (ZD_TYPE) uncompLen, (long) cdOffset);
             return false;
         }
 
@@ -732,8 +749,8 @@
             LOGE("Write failed: %s\n", strerror(errno));
             goto unmap;
         } else if ((size_t) actual != uncompLen) {
-            LOGE("Partial write during uncompress (%zd of %zd)\n",
-                (size_t)actual, (size_t)uncompLen);
+            LOGE("Partial write during uncompress (" ZD " of " ZD ")\n",
+                (ZD_TYPE) actual, (ZD_TYPE) uncompLen);
             goto unmap;
         } else {
             LOGI("+++ successful write\n");
@@ -802,8 +819,8 @@
 
     /* paranoia */
     if (zstream.total_out != uncompLen) {
-        LOGW("Size mismatch on inflated file (%ld vs %zd)\n",
-            zstream.total_out, uncompLen);
+        LOGW("Size mismatch on inflated file (%ld vs " ZD ")\n",
+            zstream.total_out, (ZD_TYPE) uncompLen);
         goto z_bail;
     }
 
@@ -891,8 +908,8 @@
 
     /* paranoia */
     if (zstream.total_out != uncompLen) {
-        LOGW("Size mismatch on inflated file (%ld vs %zd)\n",
-            zstream.total_out, uncompLen);
+        LOGW("Size mismatch on inflated file (%ld vs " ZD ")\n",
+            zstream.total_out, (ZD_TYPE) uncompLen);
         goto z_bail;
     }
 
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/java/android/media/Metadata.java b/media/java/android/media/Metadata.java
index bd25da2..8d408c2 100644
--- a/media/java/android/media/Metadata.java
+++ b/media/java/android/media/Metadata.java
@@ -102,8 +102,9 @@
     public static final int PAUSE_AVAILABLE = 29;         // Boolean
     public static final int SEEK_BACKWARD_AVAILABLE = 30; // Boolean
     public static final int SEEK_FORWARD_AVAILABLE = 31;  // Boolean
+    public static final int SEEK_AVAILABLE = 32;          // Boolean
 
-    private static final int LAST_SYSTEM = 31;
+    private static final int LAST_SYSTEM = 32;
     private static final int FIRST_CUSTOM = 8192;
 
     // Shorthands to set the MediaPlayer's metadata filter.
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 6f94e8b..49e5e89 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -727,7 +727,7 @@
 }
 
 static void android_media_MediaPlayer_attachAuxEffect(JNIEnv *env,  jobject thiz, jint effectId) {
-    LOGV("attachAuxEffect(): %d", sessionId);
+    LOGV("attachAuxEffect(): %d", effectId);
     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
     if (mp == NULL ) {
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
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/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index c6b2efb..cc41e66 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -56,6 +56,7 @@
     mVideoWidth = mVideoHeight = 0;
     mLockThreadId = 0;
     mAudioSessionId = AudioSystem::newAudioSessionId();
+    mSendLevel = 0;
 }
 
 MediaPlayer::~MediaPlayer()
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/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index d975cb9..c43e9bb 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1546,6 +1546,11 @@
 
 }
 
+int MediaPlayerService::AudioOutput::getSessionId()
+{
+    return mSessionId;
+}
+
 #undef LOG_TAG
 #define LOG_TAG "AudioCache"
 MediaPlayerService::AudioCache::AudioCache(const char* name) :
@@ -1733,4 +1738,9 @@
     p->mSignal.signal();
 }
 
+int MediaPlayerService::AudioCache::getSessionId()
+{
+    return 0;
+}
+
 } // namespace android
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index a967ee2..4492e20 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -77,6 +77,7 @@
         virtual uint32_t        latency() const;
         virtual float           msecsPerFrame() const;
         virtual status_t        getPosition(uint32_t *position);
+        virtual int             getSessionId();
 
         virtual status_t        open(
                 uint32_t sampleRate, int channelCount,
@@ -133,6 +134,7 @@
         virtual uint32_t        latency() const;
         virtual float           msecsPerFrame() const;
         virtual status_t        getPosition(uint32_t *position);
+        virtual int             getSessionId();
 
         virtual status_t        open(
                 uint32_t sampleRate, int channelCount, int format,
diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp
index 2c96d6d..6bded09 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.cpp
+++ b/media/libmediaplayerservice/StagefrightPlayer.cpp
@@ -180,6 +180,10 @@
             Metadata::kSeekForwardAvailable,
             flags & MediaExtractor::CAN_SEEK_FORWARD);
 
+    metadata.appendBool(
+            Metadata::kSeekAvailable,
+            flags & MediaExtractor::CAN_SEEK);
+
     return OK;
 }
 
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/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp
index 71d48b3..c0b1abe 100644
--- a/media/libstagefright/AMRWriter.cpp
+++ b/media/libstagefright/AMRWriter.cpp
@@ -15,7 +15,6 @@
  */
 
 #include <media/stagefright/AMRWriter.h>
-
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaDebug.h>
 #include <media/stagefright/MediaDefs.h>
@@ -23,6 +22,8 @@
 #include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MetaData.h>
 #include <media/mediarecorder.h>
+#include <sys/prctl.h>
+#include <sys/resource.h>
 
 namespace android {
 
@@ -194,6 +195,7 @@
     int64_t maxTimestampUs = 0;
     status_t err = OK;
 
+    prctl(PR_SET_NAME, (unsigned long)"AMRWriter", 0, 0, 0);
     while (!mDone) {
         MediaBuffer *buffer;
         err = mSource->read(&buffer);
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 8c17aab..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)) {
@@ -868,9 +906,7 @@
 }
 
 status_t AwesomePlayer::seekTo(int64_t timeUs) {
-    if (mExtractorFlags
-            & (MediaExtractor::CAN_SEEK_FORWARD
-                | MediaExtractor::CAN_SEEK_BACKWARD)) {
+    if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
         Mutex::Autolock autoLock(mLock);
         return seekTo_l(timeUs);
     }
@@ -878,12 +914,19 @@
     return OK;
 }
 
+// static
+void AwesomePlayer::OnRTSPSeekDoneWrapper(void *cookie) {
+    static_cast<AwesomePlayer *>(cookie)->onRTSPSeekDone();
+}
+
+void AwesomePlayer::onRTSPSeekDone() {
+    notifyListener_l(MEDIA_SEEK_COMPLETE);
+    mSeekNotificationSent = true;
+}
+
 status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
     if (mRTSPController != NULL) {
-        mRTSPController->seek(timeUs);
-
-        notifyListener_l(MEDIA_SEEK_COMPLETE);
-        mSeekNotificationSent = true;
+        mRTSPController->seekAsync(timeUs, OnRTSPSeekDoneWrapper, this);
         return OK;
     }
 
@@ -1338,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/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 6d00d7c..e53b0a0 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -20,8 +20,9 @@
 
 #include <arpa/inet.h>
 
-#include <ctype.h>
 #include <pthread.h>
+#include <sys/prctl.h>
+#include <sys/resource.h>
 
 #include <media/stagefright/MPEG4Writer.h>
 #include <media/stagefright/MediaBuffer.h>
@@ -1104,6 +1105,7 @@
 void MPEG4Writer::threadFunc() {
     LOGV("threadFunc");
 
+    prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
     while (!mDone) {
         {
             Mutex::Autolock autolock(mLock);
@@ -1632,6 +1634,11 @@
     int64_t previousPausedDurationUs = 0;
     int64_t timestampUs;
 
+    if (mIsAudio) {
+        prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
+    } else {
+        prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
+    }
     sp<MetaData> meta_data;
 
     mNumSamples = 0;
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index 9bc94de..8a5fb11 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -41,7 +41,7 @@
 }
 
 uint32_t MediaExtractor::flags() const {
-    return CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_PAUSE;
+    return CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_PAUSE | CAN_SEEK;
 }
 
 // static
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/avc_utils.cpp b/media/libstagefright/avc_utils.cpp
index a8f1104..478e40c 100644
--- a/media/libstagefright/avc_utils.cpp
+++ b/media/libstagefright/avc_utils.cpp
@@ -18,6 +18,9 @@
 
 #include <media/stagefright/foundation/ABitReader.h>
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
 
 namespace android {
 
@@ -41,10 +44,12 @@
     br.skipBits(16);
     parseUE(&br);  // seq_parameter_set_id
 
+    unsigned chroma_format_idc = 1;  // 4:2:0 chroma format
+
     if (profile_idc == 100 || profile_idc == 110
             || profile_idc == 122 || profile_idc == 244
             || profile_idc == 44 || profile_idc == 83 || profile_idc == 86) {
-        unsigned chroma_format_idc = parseUE(&br);
+        chroma_format_idc = parseUE(&br);
         if (chroma_format_idc == 3) {
             br.skipBits(1);  // residual_colour_transform_flag
         }
@@ -85,6 +90,212 @@
 
     *height = (2 - frame_mbs_only_flag)
         * (pic_height_in_map_units_minus1 * 16 + 16);
+
+    if (!frame_mbs_only_flag) {
+        br.getBits(1);  // mb_adaptive_frame_field_flag
+    }
+
+    br.getBits(1);  // direct_8x8_inference_flag
+
+    if (br.getBits(1)) {  // frame_cropping_flag
+        unsigned frame_crop_left_offset = parseUE(&br);
+        unsigned frame_crop_right_offset = parseUE(&br);
+        unsigned frame_crop_top_offset = parseUE(&br);
+        unsigned frame_crop_bottom_offset = parseUE(&br);
+
+        unsigned cropUnitX, cropUnitY;
+        if (chroma_format_idc == 0  /* monochrome */) {
+            cropUnitX = 1;
+            cropUnitY = 2 - frame_mbs_only_flag;
+        } else {
+            unsigned subWidthC = (chroma_format_idc == 3) ? 1 : 2;
+            unsigned subHeightC = (chroma_format_idc == 1) ? 2 : 1;
+
+            cropUnitX = subWidthC;
+            cropUnitY = subHeightC * (2 - frame_mbs_only_flag);
+        }
+
+        LOGV("frame_crop = (%u, %u, %u, %u), cropUnitX = %u, cropUnitY = %u",
+             frame_crop_left_offset, frame_crop_right_offset,
+             frame_crop_top_offset, frame_crop_bottom_offset,
+             cropUnitX, cropUnitY);
+
+        *width -=
+            (frame_crop_left_offset + frame_crop_right_offset) * cropUnitX;
+        *height -=
+            (frame_crop_top_offset + frame_crop_bottom_offset) * cropUnitY;
+    }
+}
+
+status_t getNextNALUnit(
+        const uint8_t **_data, size_t *_size,
+        const uint8_t **nalStart, size_t *nalSize,
+        bool startCodeFollows) {
+    const uint8_t *data = *_data;
+    size_t size = *_size;
+
+    *nalStart = NULL;
+    *nalSize = 0;
+
+    if (size == 0) {
+        return -EAGAIN;
+    }
+
+    // Skip any number of leading 0x00.
+
+    size_t offset = 0;
+    while (offset < size && data[offset] == 0x00) {
+        ++offset;
+    }
+
+    if (offset == size) {
+        return -EAGAIN;
+    }
+
+    // A valid startcode consists of at least two 0x00 bytes followed by 0x01.
+
+    if (offset < 2 || data[offset] != 0x01) {
+        return ERROR_MALFORMED;
+    }
+
+    ++offset;
+
+    size_t startOffset = offset;
+
+    for (;;) {
+        while (offset < size && data[offset] != 0x01) {
+            ++offset;
+        }
+
+        if (offset == size) {
+            if (startCodeFollows) {
+                offset = size + 2;
+                break;
+            }
+
+            return -EAGAIN;
+        }
+
+        if (data[offset - 1] == 0x00 && data[offset - 2] == 0x00) {
+            break;
+        }
+
+        ++offset;
+    }
+
+    size_t endOffset = offset - 2;
+    while (data[endOffset - 1] == 0x00) {
+        --endOffset;
+    }
+
+    *nalStart = &data[startOffset];
+    *nalSize = endOffset - startOffset;
+
+    if (offset + 2 < size) {
+        *_data = &data[offset - 2];
+        *_size = size - offset + 2;
+    } else {
+        *_data = NULL;
+        *_size = 0;
+    }
+
+    return OK;
+}
+
+static sp<ABuffer> FindNAL(
+        const uint8_t *data, size_t size, unsigned nalType,
+        size_t *stopOffset) {
+    const uint8_t *nalStart;
+    size_t nalSize;
+    while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
+        if ((nalStart[0] & 0x1f) == nalType) {
+            sp<ABuffer> buffer = new ABuffer(nalSize);
+            memcpy(buffer->data(), nalStart, nalSize);
+            return buffer;
+        }
+    }
+
+    return NULL;
+}
+
+sp<MetaData> MakeAVCCodecSpecificData(const sp<ABuffer> &accessUnit) {
+    const uint8_t *data = accessUnit->data();
+    size_t size = accessUnit->size();
+
+    sp<ABuffer> seqParamSet = FindNAL(data, size, 7, NULL);
+    if (seqParamSet == NULL) {
+        return NULL;
+    }
+
+    int32_t width, height;
+    FindAVCDimensions(seqParamSet, &width, &height);
+
+    size_t stopOffset;
+    sp<ABuffer> picParamSet = FindNAL(data, size, 8, &stopOffset);
+    CHECK(picParamSet != NULL);
+
+    size_t csdSize =
+        1 + 3 + 1 + 1
+        + 2 * 1 + seqParamSet->size()
+        + 1 + 2 * 1 + picParamSet->size();
+
+    sp<ABuffer> csd = new ABuffer(csdSize);
+    uint8_t *out = csd->data();
+
+    *out++ = 0x01;  // configurationVersion
+    memcpy(out, seqParamSet->data() + 1, 3);  // profile/level...
+    out += 3;
+    *out++ = (0x3f << 2) | 1;  // lengthSize == 2 bytes
+    *out++ = 0xe0 | 1;
+
+    *out++ = seqParamSet->size() >> 8;
+    *out++ = seqParamSet->size() & 0xff;
+    memcpy(out, seqParamSet->data(), seqParamSet->size());
+    out += seqParamSet->size();
+
+    *out++ = 1;
+
+    *out++ = picParamSet->size() >> 8;
+    *out++ = picParamSet->size() & 0xff;
+    memcpy(out, picParamSet->data(), picParamSet->size());
+
+#if 0
+    LOGI("AVC seq param set");
+    hexdump(seqParamSet->data(), seqParamSet->size());
+#endif
+
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+
+    meta->setData(kKeyAVCC, 0, csd->data(), csd->size());
+    meta->setInt32(kKeyWidth, width);
+    meta->setInt32(kKeyHeight, height);
+
+    LOGI("found AVC codec config (%d x %d)", width, height);
+
+    return meta;
+}
+
+bool IsIDR(const sp<ABuffer> &buffer) {
+    const uint8_t *data = buffer->data();
+    size_t size = buffer->size();
+
+    bool foundIDR = false;
+
+    const uint8_t *nalStart;
+    size_t nalSize;
+    while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
+        CHECK_GT(nalSize, 0u);
+
+        unsigned nalType = nalStart[0] & 0x1f;
+
+        if (nalType == 5) {
+            foundIDR = true;
+            break;
+        }
+    }
+
+    return foundIDR;
 }
 
 }  // namespace android
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_reorder.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_reorder.cpp
index 35b6475..286c636 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_reorder.cpp
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_reorder.cpp
@@ -40,7 +40,7 @@
     int32 xr[ ],                rescaled data
     struct gr_info_s *gr_info,  granule structure
     mp3Header *info,            mp3 header info
-    int32  Scratch_mem[168]     for temporary usage
+    int32  Scratch_mem[198]     for temporary usage
 
  Outputs:
 
@@ -120,7 +120,7 @@
                    granuleInfo *gr_info,
                    int32  *used_freq_lines,
                    mp3Header *info,
-                   int32  Scratch_mem[168])
+                   int32  Scratch_mem[198])
 {
     int32 sfreq =  info->version_x + (info->version_x << 1);
     sfreq += info->sampling_frequency;
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_reorder.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_reorder.h
index ba6ec16..5248951 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_reorder.h
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_reorder.h
@@ -89,7 +89,7 @@
     granuleInfo *gr_info,
     int32 *used_freq_lines,
     mp3Header *info,
-    int32  Scratch_mem[168]);
+    int32  Scratch_mem[198]);
 
 #ifdef __cplusplus
 }
diff --git a/media/libstagefright/codecs/mp3dec/src/s_tmp3dec_file.h b/media/libstagefright/codecs/mp3dec/src/s_tmp3dec_file.h
index 805cedb..611e08f 100644
--- a/media/libstagefright/codecs/mp3dec/src/s_tmp3dec_file.h
+++ b/media/libstagefright/codecs/mp3dec/src/s_tmp3dec_file.h
@@ -87,7 +87,7 @@
         int32           num_channels;
         int32           predicted_frame_size;
         int32           frame_start;
-        int32           Scratch_mem[168];
+        int32           Scratch_mem[198];
         tmp3dec_chan    perChan[CHAN];
         mp3ScaleFactors scaleFactors[CHAN];
         mp3SideInfo     sideInfo;
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/ARTSPController.h b/media/libstagefright/include/ARTSPController.h
index 300d8f7..ce7ffe5 100644
--- a/media/libstagefright/include/ARTSPController.h
+++ b/media/libstagefright/include/ARTSPController.h
@@ -33,7 +33,7 @@
     status_t connect(const char *url);
     void disconnect();
 
-    void seek(int64_t timeUs);
+    void seekAsync(int64_t timeUs, void (*seekDoneCb)(void *), void *cookie);
 
     virtual size_t countTracks();
     virtual sp<MediaSource> getTrack(size_t index);
@@ -46,6 +46,14 @@
 
     void onMessageReceived(const sp<AMessage> &msg);
 
+    virtual uint32_t flags() const {
+        // Seeking 10secs forward or backward is a very expensive operation
+        // for rtsp, so let's not enable that.
+        // The user can always use the seek bar.
+
+        return CAN_PAUSE | CAN_SEEK;
+    }
+
 protected:
     virtual ~ARTSPController();
 
@@ -53,6 +61,7 @@
     enum {
         kWhatConnectDone    = 'cdon',
         kWhatDisconnectDone = 'ddon',
+        kWhatSeekDone       = 'sdon',
     };
 
     enum State {
@@ -71,6 +80,10 @@
     sp<MyHandler> mHandler;
     sp<AHandlerReflector<ARTSPController> > mReflector;
 
+    void (*mSeekDoneCb)(void *);
+    void *mSeekDoneCookie;
+    int64_t mLastSeekCompletedTimeUs;
+
     DISALLOW_EVIL_CONSTRUCTORS(ARTSPController);
 };
 
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index bbf482d..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;
 
@@ -251,6 +253,11 @@
 
     static bool ContinuePreparation(void *cookie);
 
+    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/include/avc_utils.h b/media/libstagefright/include/avc_utils.h
index 6602852..62cfc36 100644
--- a/media/libstagefright/include/avc_utils.h
+++ b/media/libstagefright/include/avc_utils.h
@@ -29,6 +29,16 @@
 
 unsigned parseUE(ABitReader *br);
 
+status_t getNextNALUnit(
+        const uint8_t **_data, size_t *_size,
+        const uint8_t **nalStart, size_t *nalSize,
+        bool startCodeFollows = false);
+
+struct MetaData;
+sp<MetaData> MakeAVCCodecSpecificData(const sp<ABuffer> &accessUnit);
+
+bool IsIDR(const sp<ABuffer> &accessUnit);
+
 }  // namespace android
 
 #endif  // AVC_UTILS_H_
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 4a75ee4..b0b9e66 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -40,83 +40,9 @@
     return mFormat;
 }
 
-static status_t getNextNALUnit(
-        const uint8_t **_data, size_t *_size,
-        const uint8_t **nalStart, size_t *nalSize,
-        bool startCodeFollows = false) {
-    const uint8_t *data = *_data;
-    size_t size = *_size;
-
-    *nalStart = NULL;
-    *nalSize = 0;
-
-    if (size == 0) {
-        return -EAGAIN;
-    }
-
-    // Skip any number of leading 0x00.
-
-    size_t offset = 0;
-    while (offset < size && data[offset] == 0x00) {
-        ++offset;
-    }
-
-    if (offset == size) {
-        return -EAGAIN;
-    }
-
-    // A valid startcode consists of at least two 0x00 bytes followed by 0x01.
-
-    if (offset < 2 || data[offset] != 0x01) {
-        return ERROR_MALFORMED;
-    }
-
-    ++offset;
-
-    size_t startOffset = offset;
-
-    for (;;) {
-        while (offset < size && data[offset] != 0x01) {
-            ++offset;
-        }
-
-        if (offset == size) {
-            if (startCodeFollows) {
-                offset = size + 2;
-                break;
-            }
-
-            return -EAGAIN;
-        }
-
-        if (data[offset - 1] == 0x00 && data[offset - 2] == 0x00) {
-            break;
-        }
-
-        ++offset;
-    }
-
-    size_t endOffset = offset - 2;
-    while (data[endOffset - 1] == 0x00) {
-        --endOffset;
-    }
-
-    *nalStart = &data[startOffset];
-    *nalSize = endOffset - startOffset;
-
-    if (offset + 2 < size) {
-        *_data = &data[offset - 2];
-        *_size = size - offset + 2;
-    } else {
-        *_data = NULL;
-        *_size = 0;
-    }
-
-    return OK;
-}
-
 void ElementaryStreamQueue::clear() {
     mBuffer->setRange(0, 0);
+    mTimestamps.clear();
     mFormat.clear();
 }
 
@@ -433,79 +359,4 @@
     return NULL;
 }
 
-static sp<ABuffer> FindNAL(
-        const uint8_t *data, size_t size, unsigned nalType,
-        size_t *stopOffset) {
-    const uint8_t *nalStart;
-    size_t nalSize;
-    while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
-        if ((nalStart[0] & 0x1f) == nalType) {
-            sp<ABuffer> buffer = new ABuffer(nalSize);
-            memcpy(buffer->data(), nalStart, nalSize);
-            return buffer;
-        }
-    }
-
-    return NULL;
-}
-
-sp<MetaData> ElementaryStreamQueue::MakeAVCCodecSpecificData(
-        const sp<ABuffer> &accessUnit) {
-    const uint8_t *data = accessUnit->data();
-    size_t size = accessUnit->size();
-
-    sp<ABuffer> seqParamSet = FindNAL(data, size, 7, NULL);
-    if (seqParamSet == NULL) {
-        return NULL;
-    }
-
-    int32_t width, height;
-    FindAVCDimensions(seqParamSet, &width, &height);
-
-    size_t stopOffset;
-    sp<ABuffer> picParamSet = FindNAL(data, size, 8, &stopOffset);
-    CHECK(picParamSet != NULL);
-
-    size_t csdSize =
-        1 + 3 + 1 + 1
-        + 2 * 1 + seqParamSet->size()
-        + 1 + 2 * 1 + picParamSet->size();
-
-    sp<ABuffer> csd = new ABuffer(csdSize);
-    uint8_t *out = csd->data();
-
-    *out++ = 0x01;  // configurationVersion
-    memcpy(out, seqParamSet->data() + 1, 3);  // profile/level...
-    out += 3;
-    *out++ = (0x3f << 2) | 1;  // lengthSize == 2 bytes
-    *out++ = 0xe0 | 1;
-
-    *out++ = seqParamSet->size() >> 8;
-    *out++ = seqParamSet->size() & 0xff;
-    memcpy(out, seqParamSet->data(), seqParamSet->size());
-    out += seqParamSet->size();
-
-    *out++ = 1;
-
-    *out++ = picParamSet->size() >> 8;
-    *out++ = picParamSet->size() & 0xff;
-    memcpy(out, picParamSet->data(), picParamSet->size());
-
-#if 0
-    LOGI("AVC seq param set");
-    hexdump(seqParamSet->data(), seqParamSet->size());
-#endif
-
-    sp<MetaData> meta = new MetaData;
-    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
-
-    meta->setData(kKeyAVCC, 0, csd->data(), csd->size());
-    meta->setInt32(kKeyWidth, width);
-    meta->setInt32(kKeyHeight, height);
-
-    LOGI("found AVC codec config (%d x %d)", width, height);
-
-    return meta;
-}
-
 }  // namespace android
diff --git a/media/libstagefright/mpeg2ts/ESQueue.h b/media/libstagefright/mpeg2ts/ESQueue.h
index 246c390..9eaf834 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.h
+++ b/media/libstagefright/mpeg2ts/ESQueue.h
@@ -56,9 +56,6 @@
             unsigned profile, unsigned sampling_freq_index,
             unsigned channel_configuration);
 
-    static sp<MetaData> MakeAVCCodecSpecificData(
-            const sp<ABuffer> &accessUnit);
-
     DISALLOW_EVIL_CONSTRUCTORS(ElementaryStreamQueue);
 };
 
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/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp
index 78754e6..10cc88b 100644
--- a/media/libstagefright/rtsp/APacketSource.cpp
+++ b/media/libstagefright/rtsp/APacketSource.cpp
@@ -490,6 +490,8 @@
     : mInitCheck(NO_INIT),
       mFormat(new MetaData),
       mEOSResult(OK),
+      mIsAVC(false),
+      mScanForIDR(true),
       mRTPTimeBase(0),
       mNormalPlayTimeBaseUs(0),
       mLastNormalPlayTimeUs(0) {
@@ -509,6 +511,8 @@
 
     mInitCheck = OK;
     if (!strncmp(desc.c_str(), "H264/", 5)) {
+        mIsAVC = true;
+
         mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
 
         int32_t width, height;
@@ -719,6 +723,20 @@
         return;
     }
 
+    if (mScanForIDR && mIsAVC) {
+        // This pretty piece of code ensures that the first access unit
+        // fed to the decoder after stream-start or seek is guaranteed to
+        // be an IDR frame. This is to workaround limitations of a certain
+        // hardware h.264 decoder that requires this to be the case.
+
+        if (!IsIDR(buffer)) {
+            LOGV("skipping AU while scanning for next IDR frame.");
+            return;
+        }
+
+        mScanForIDR = false;
+    }
+
     Mutex::Autolock autoLock(mLock);
     mBuffers.push_back(buffer);
     mCondition.signal();
@@ -735,6 +753,8 @@
 void APacketSource::flushQueue() {
     Mutex::Autolock autoLock(mLock);
     mBuffers.clear();
+
+    mScanForIDR = true;
 }
 
 int64_t APacketSource::getNormalPlayTimeUs() {
diff --git a/media/libstagefright/rtsp/APacketSource.h b/media/libstagefright/rtsp/APacketSource.h
index 076ddc47..7a77fc6 100644
--- a/media/libstagefright/rtsp/APacketSource.h
+++ b/media/libstagefright/rtsp/APacketSource.h
@@ -65,6 +65,9 @@
     List<sp<ABuffer> > mBuffers;
     status_t mEOSResult;
 
+    bool mIsAVC;
+    bool mScanForIDR;
+
     uint32_t mClockRate;
 
     uint32_t mRTPTimeBase;
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/ARTSPController.cpp b/media/libstagefright/rtsp/ARTSPController.cpp
index 4c53639..a7563ff 100644
--- a/media/libstagefright/rtsp/ARTSPController.cpp
+++ b/media/libstagefright/rtsp/ARTSPController.cpp
@@ -27,7 +27,10 @@
 
 ARTSPController::ARTSPController(const sp<ALooper> &looper)
     : mState(DISCONNECTED),
-      mLooper(looper) {
+      mLooper(looper),
+      mSeekDoneCb(NULL),
+      mSeekDoneCookie(NULL),
+      mLastSeekCompletedTimeUs(-1) {
     mReflector = new AHandlerReflector<ARTSPController>(this);
     looper->registerHandler(mReflector);
 }
@@ -80,14 +83,31 @@
     mHandler.clear();
 }
 
-void ARTSPController::seek(int64_t timeUs) {
+void ARTSPController::seekAsync(
+        int64_t timeUs,
+        void (*seekDoneCb)(void *), void *cookie) {
     Mutex::Autolock autoLock(mLock);
 
-    if (mState != CONNECTED) {
+    CHECK(seekDoneCb != NULL);
+    CHECK(mSeekDoneCb == NULL);
+
+    // Ignore seek requests that are too soon after the previous one has
+    // completed, we don't want to swamp the server.
+
+    bool tooEarly =
+        mLastSeekCompletedTimeUs >= 0
+            && ALooper::GetNowUs() < mLastSeekCompletedTimeUs + 500000ll;
+
+    if (mState != CONNECTED || tooEarly) {
+        (*seekDoneCb)(cookie);
         return;
     }
 
-    mHandler->seek(timeUs);
+    mSeekDoneCb = seekDoneCb;
+    mSeekDoneCookie = cookie;
+
+    sp<AMessage> msg = new AMessage(kWhatSeekDone, mReflector->id());
+    mHandler->seek(timeUs, msg);
 }
 
 size_t ARTSPController::countTracks() {
@@ -132,6 +152,19 @@
             break;
         }
 
+        case kWhatSeekDone:
+        {
+            LOGI("seek done");
+
+            mLastSeekCompletedTimeUs = ALooper::GetNowUs();
+
+            void (*seekDoneCb)(void *) = mSeekDoneCb;
+            mSeekDoneCb = NULL;
+
+            (*seekDoneCb)(mSeekDoneCookie);
+            break;
+        }
+
         default:
             TRESPASS();
             break;
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index a31b2b2..1bc9925 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -28,6 +28,7 @@
 #include "ASessionDescription.h"
 
 #include <ctype.h>
+#include <cutils/properties.h>
 
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -35,6 +36,9 @@
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/MediaErrors.h>
 
+#include <arpa/inet.h>
+#include <sys/socket.h>
+
 // If no access units are received within 3 secs, assume that the rtp
 // stream has ended and signal end of stream.
 static int64_t kAccessUnitTimeoutUs = 3000000ll;
@@ -45,6 +49,19 @@
 
 namespace android {
 
+static void MakeUserAgentString(AString *s) {
+    s->setTo("stagefright/1.1 (Linux;Android ");
+
+#if (PROPERTY_VALUE_MAX < 8)
+#error "PROPERTY_VALUE_MAX must be at least 8"
+#endif
+
+    char value[PROPERTY_VALUE_MAX];
+    property_get("ro.build.version.release", value, "Unknown");
+    s->append(value);
+    s->append(")");
+}
+
 static bool GetAttribute(const char *s, const char *key, AString *value) {
     value->clear();
 
@@ -86,8 +103,12 @@
           mFirstAccessUnitNTP(0),
           mNumAccessUnitsReceived(0),
           mCheckPending(false),
+          mCheckGeneration(0),
           mTryTCPInterleaving(false),
-          mReceivedFirstRTCPPacket(false) {
+          mTryFakeRTCP(false),
+          mReceivedFirstRTCPPacket(false),
+          mReceivedFirstRTPPacket(false),
+          mSeekable(false) {
         mNetLooper->setName("rtsp net");
         mNetLooper->start(false /* runOnCallingThread */,
                           false /* canCallJava */,
@@ -114,9 +135,10 @@
         (new AMessage('abor', id()))->post();
     }
 
-    void seek(int64_t timeUs) {
+    void seek(int64_t timeUs, const sp<AMessage> &doneMsg) {
         sp<AMessage> msg = new AMessage('seek', id());
         msg->setInt64("time", timeUs);
+        msg->setMessage("doneMsg", doneMsg);
         msg->post();
     }
 
@@ -134,6 +156,131 @@
         return maxTimeUs;
     }
 
+    static void addRR(const sp<ABuffer> &buf) {
+        uint8_t *ptr = buf->data() + buf->size();
+        ptr[0] = 0x80 | 0;
+        ptr[1] = 201;  // RR
+        ptr[2] = 0;
+        ptr[3] = 1;
+        ptr[4] = 0xde;  // SSRC
+        ptr[5] = 0xad;
+        ptr[6] = 0xbe;
+        ptr[7] = 0xef;
+
+        buf->setRange(0, buf->size() + 8);
+    }
+
+    static void addSDES(int s, const sp<ABuffer> &buffer) {
+        struct sockaddr_in addr;
+        socklen_t addrSize = sizeof(addr);
+        CHECK_EQ(0, getsockname(s, (sockaddr *)&addr, &addrSize));
+
+        uint8_t *data = buffer->data() + buffer->size();
+        data[0] = 0x80 | 1;
+        data[1] = 202;  // SDES
+        data[4] = 0xde;  // SSRC
+        data[5] = 0xad;
+        data[6] = 0xbe;
+        data[7] = 0xef;
+
+        size_t offset = 8;
+
+        data[offset++] = 1;  // CNAME
+
+        AString cname = "stagefright@";
+        cname.append(inet_ntoa(addr.sin_addr));
+        data[offset++] = cname.size();
+
+        memcpy(&data[offset], cname.c_str(), cname.size());
+        offset += cname.size();
+
+        data[offset++] = 6;  // TOOL
+
+        AString tool;
+        MakeUserAgentString(&tool);
+
+        data[offset++] = tool.size();
+
+        memcpy(&data[offset], tool.c_str(), tool.size());
+        offset += tool.size();
+
+        data[offset++] = 0;
+
+        if ((offset % 4) > 0) {
+            size_t count = 4 - (offset % 4);
+            switch (count) {
+                case 3:
+                    data[offset++] = 0;
+                case 2:
+                    data[offset++] = 0;
+                case 1:
+                    data[offset++] = 0;
+            }
+        }
+
+        size_t numWords = (offset / 4) - 1;
+        data[2] = numWords >> 8;
+        data[3] = numWords & 0xff;
+
+        buffer->setRange(buffer->offset(), buffer->size() + offset);
+    }
+
+    // In case we're behind NAT, fire off two UDP packets to the remote
+    // rtp/rtcp ports to poke a hole into the firewall for future incoming
+    // packets. We're going to send an RR/SDES RTCP packet to both of them.
+    void pokeAHole(int rtpSocket, int rtcpSocket, const AString &transport) {
+        AString source;
+        AString server_port;
+        if (!GetAttribute(transport.c_str(),
+                          "source",
+                          &source)
+                || !GetAttribute(transport.c_str(),
+                                 "server_port",
+                                 &server_port)) {
+            return;
+        }
+
+        int rtpPort, rtcpPort;
+        if (sscanf(server_port.c_str(), "%d-%d", &rtpPort, &rtcpPort) != 2
+                || rtpPort <= 0 || rtpPort > 65535
+                || rtcpPort <=0 || rtcpPort > 65535
+                || rtcpPort != rtpPort + 1
+                || (rtpPort & 1) != 0) {
+            return;
+        }
+
+        struct sockaddr_in addr;
+        memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
+        addr.sin_family = AF_INET;
+        addr.sin_addr.s_addr = inet_addr(source.c_str());
+
+        if (addr.sin_addr.s_addr == INADDR_NONE) {
+            return;
+        }
+
+        // Make up an RR/SDES RTCP packet.
+        sp<ABuffer> buf = new ABuffer(65536);
+        buf->setRange(0, 0);
+        addRR(buf);
+        addSDES(rtpSocket, buf);
+
+        addr.sin_port = htons(rtpPort);
+
+        ssize_t n = sendto(
+                rtpSocket, buf->data(), buf->size(), 0,
+                (const sockaddr *)&addr, sizeof(addr));
+        CHECK_EQ(n, (ssize_t)buf->size());
+
+        addr.sin_port = htons(rtcpPort);
+
+        n = sendto(
+                rtcpSocket, buf->data(), buf->size(), 0,
+                (const sockaddr *)&addr, sizeof(addr));
+        CHECK_EQ(n, (ssize_t)buf->size());
+
+        LOGV("successfully poked holes.");
+    }
+
     virtual void onMessageReceived(const sp<AMessage> &msg) {
         switch (msg->what()) {
             case 'conn':
@@ -282,6 +429,17 @@
                         sp<AMessage> notify = new AMessage('accu', id());
                         notify->setSize("track-index", trackIndex);
 
+                        i = response->mHeaders.indexOfKey("transport");
+                        CHECK_GE(i, 0);
+
+                        if (!track->mUsingInterleavedTCP) {
+                            AString transport = response->mHeaders.valueAt(i);
+
+                            pokeAHole(track->mRTPSocket,
+                                      track->mRTCPSocket,
+                                      transport);
+                        }
+
                         mRTPConn->addStream(
                                 track->mRTPSocket, track->mRTCPSocket,
                                 mSessionDesc, index,
@@ -378,6 +536,8 @@
                 mFirstAccessUnitNTP = 0;
                 mNumAccessUnitsReceived = 0;
                 mReceivedFirstRTCPPacket = false;
+                mReceivedFirstRTPPacket = false;
+                mSeekable = false;
 
                 sp<AMessage> reply = new AMessage('tear', id());
 
@@ -434,6 +594,13 @@
 
             case 'chek':
             {
+                int32_t generation;
+                CHECK(msg->findInt32("generation", &generation));
+                if (generation != mCheckGeneration) {
+                    // This is an outdated message. Ignore.
+                    break;
+                }
+
                 if (mNumAccessUnitsReceived == 0) {
                     LOGI("stream ended? aborting.");
                     (new AMessage('abor', id()))->post();
@@ -447,20 +614,20 @@
 
             case 'accu':
             {
-                int32_t firstRTCP;
-                if (msg->findInt32("first-rtcp", &firstRTCP)) {
+                int32_t first;
+                if (msg->findInt32("first-rtcp", &first)) {
                     mReceivedFirstRTCPPacket = true;
                     break;
                 }
 
-                ++mNumAccessUnitsReceived;
-
-                if (!mCheckPending) {
-                    mCheckPending = true;
-                    sp<AMessage> check = new AMessage('chek', id());
-                    check->post(kAccessUnitTimeoutUs);
+                if (msg->findInt32("first-rtp", &first)) {
+                    mReceivedFirstRTPPacket = true;
+                    break;
                 }
 
+                ++mNumAccessUnitsReceived;
+                postAccessUnitTimeoutCheck();
+
                 size_t trackIndex;
                 CHECK(msg->findSize("track-index", &trackIndex));
 
@@ -548,7 +715,17 @@
 
             case 'seek':
             {
+                sp<AMessage> doneMsg;
+                CHECK(msg->findMessage("doneMsg", &doneMsg));
+
                 if (mSeekPending) {
+                    doneMsg->post();
+                    break;
+                }
+
+                if (!mSeekable) {
+                    LOGW("This is a live stream, ignoring seek request.");
+                    doneMsg->post();
                     break;
                 }
 
@@ -557,6 +734,11 @@
 
                 mSeekPending = true;
 
+                // Disable the access unit timeout until we resumed
+                // playback again.
+                mCheckPending = true;
+                ++mCheckGeneration;
+
                 AString request = "PAUSE ";
                 request.append(mSessionURL);
                 request.append(" RTSP/1.0\r\n");
@@ -569,6 +751,7 @@
 
                 sp<AMessage> reply = new AMessage('see1', id());
                 reply->setInt64("time", timeUs);
+                reply->setMessage("doneMsg", doneMsg);
                 mConn->sendRequest(request.c_str(), reply);
                 break;
             }
@@ -597,7 +780,11 @@
 
                 request.append("\r\n");
 
+                sp<AMessage> doneMsg;
+                CHECK(msg->findMessage("doneMsg", &doneMsg));
+
                 sp<AMessage> reply = new AMessage('see2', id());
+                reply->setMessage("doneMsg", doneMsg);
                 mConn->sendRequest(request.c_str(), reply);
                 break;
             }
@@ -612,6 +799,9 @@
                 LOGI("PLAY completed with result %d (%s)",
                      result, strerror(-result));
 
+                mCheckPending = false;
+                postAccessUnitTimeoutCheck();
+
                 if (result == OK) {
                     sp<RefBase> obj;
                     CHECK(msg->findObject("response", &obj));
@@ -633,6 +823,11 @@
                 }
 
                 mSeekPending = false;
+
+                sp<AMessage> doneMsg;
+                CHECK(msg->findMessage("doneMsg", &doneMsg));
+
+                doneMsg->post();
                 break;
             }
 
@@ -652,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.");
 
@@ -674,6 +877,17 @@
         }
     }
 
+    void postAccessUnitTimeoutCheck() {
+        if (mCheckPending) {
+            return;
+        }
+
+        mCheckPending = true;
+        sp<AMessage> check = new AMessage('chek', id());
+        check->setInt32("generation", mCheckGeneration);
+        check->post(kAccessUnitTimeoutUs);
+    }
+
     static void SplitString(
             const AString &s, const char *separator, List<AString> *items) {
         items->clear();
@@ -692,6 +906,8 @@
     }
 
     void parsePlayResponse(const sp<ARTSPResponse> &response) {
+        mSeekable = false;
+
         ssize_t i = response->mHeaders.indexOfKey("range");
         if (i < 0) {
             // Server doesn't even tell use what range it is going to
@@ -755,6 +971,8 @@
 
             ++n;
         }
+
+        mSeekable = true;
     }
 
     sp<APacketSource> getPacketSource(size_t index) {
@@ -783,8 +1001,12 @@
     uint64_t mFirstAccessUnitNTP;
     int64_t mNumAccessUnitsReceived;
     bool mCheckPending;
+    int32_t mCheckGeneration;
     bool mTryTCPInterleaving;
+    bool mTryFakeRTCP;
     bool mReceivedFirstRTCPPacket;
+    bool mReceivedFirstRTPPacket;
+    bool mSeekable;
 
     struct TrackInfo {
         AString mURL;
diff --git a/media/tests/MediaFrameworkTest/AndroidManifest.xml b/media/tests/MediaFrameworkTest/AndroidManifest.xml
index f70a145..5c20811 100644
--- a/media/tests/MediaFrameworkTest/AndroidManifest.xml
+++ b/media/tests/MediaFrameworkTest/AndroidManifest.xml
@@ -21,6 +21,7 @@
     <uses-permission android:name="android.permission.CAMERA" />
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
     <application>    
         <uses-library android:name="android.test.runner" />
         <activity android:label="@string/app_name"
diff --git a/native/android/storage_manager.cpp b/native/android/storage_manager.cpp
index 2f20641..a4233e7 100644
--- a/native/android/storage_manager.cpp
+++ b/native/android/storage_manager.cpp
@@ -21,10 +21,13 @@
 
 #include <binder/Binder.h>
 #include <binder/IServiceManager.h>
+#include <utils/Atomic.h>
 #include <utils/Log.h>
 #include <utils/RefBase.h>
 #include <utils/String8.h>
 #include <utils/String16.h>
+#include <utils/Vector.h>
+#include <utils/threads.h>
 
 
 using namespace android;
@@ -38,20 +41,46 @@
             mStorageManager(mgr)
     {}
 
-    virtual void onObbResult(const android::String16& filename, const android::String16& state);
+    virtual void onObbResult(const android::String16& filename, const int32_t nonce,
+            const int32_t state);
+};
+
+class ObbCallback {
+public:
+    ObbCallback(int32_t _nonce, AStorageManager_obbCallbackFunc _cb, void* _data)
+            : nonce(_nonce)
+            , cb(_cb)
+            , data(_data)
+    {}
+
+    int32_t nonce;
+    AStorageManager_obbCallbackFunc cb;
+    void* data;
 };
 
 struct AStorageManager : public RefBase {
 protected:
-    AStorageManager_obbCallbackFunc mObbCallback;
-    void* mObbCallbackData;
+    Mutex mCallbackLock;
+    Vector<ObbCallback*> mCallbacks;
+    volatile int32_t mNextNonce;
     sp<ObbActionListener> mObbActionListener;
     sp<IMountService> mMountService;
 
+    int32_t getNextNonce() {
+        return android_atomic_inc(&mNextNonce);
+    }
+
+    ObbCallback* registerObbCallback(AStorageManager_obbCallbackFunc func, void* data) {
+        ObbCallback* cb = new ObbCallback(getNextNonce(), func, data);
+        {
+            AutoMutex _l(mCallbackLock);
+            mCallbacks.push(cb);
+        }
+        return cb;
+    }
+
 public:
     AStorageManager()
-            : mObbCallback(NULL)
-            , mObbCallbackData(NULL)
     {
     }
 
@@ -73,26 +102,40 @@
         return true;
     }
 
-    void setObbCallback(AStorageManager_obbCallbackFunc cb, void* data) {
-        mObbCallback = cb;
-        mObbCallbackData = data;
-    }
+    void fireCallback(const char* filename, const int32_t nonce, const int32_t state) {
+        ObbCallback* target = NULL;
+        {
+            AutoMutex _l(mCallbackLock);
+            int N = mCallbacks.size();
+            for (int i = 0; i < N; i++) {
+                ObbCallback* cb = mCallbacks.editItemAt(i);
+                if (cb->nonce == nonce) {
+                    target = cb;
+                    mCallbacks.removeAt(i);
+                    break;
+                }
+            }
+        }
 
-    void fireCallback(const char* filename, const char* state) {
-        if (mObbCallback != NULL) {
-            mObbCallback(filename, state, mObbCallbackData);
+        if (target != NULL) {
+            target->cb(filename, state, target->data);
+            delete target;
+        } else {
+            LOGI("Didn't find the callback handler for: %s\n", filename);
         }
     }
 
-    void mountObb(const char* filename, const char* key) {
+    void mountObb(const char* filename, const char* key, AStorageManager_obbCallbackFunc func, void* data) {
+        ObbCallback* cb = registerObbCallback(func, data);
         String16 filename16(filename);
         String16 key16(key);
-        mMountService->mountObb(filename16, key16, mObbActionListener);
+        mMountService->mountObb(filename16, key16, mObbActionListener, cb->nonce);
     }
 
-    void unmountObb(const char* filename, const bool force) {
+    void unmountObb(const char* filename, const bool force, AStorageManager_obbCallbackFunc func, void* data) {
+        ObbCallback* cb = registerObbCallback(func, data);
         String16 filename16(filename);
-        mMountService->unmountObb(filename16, force, mObbActionListener);
+        mMountService->unmountObb(filename16, force, mObbActionListener, cb->nonce);
     }
 
     int isObbMounted(const char* filename) {
@@ -111,8 +154,8 @@
     }
 };
 
-void ObbActionListener::onObbResult(const android::String16& filename, const android::String16& state) {
-    mStorageManager->fireCallback(String8(filename).string(), String8(state).string());
+void ObbActionListener::onObbResult(const android::String16& filename, const int32_t nonce, const int32_t state) {
+    mStorageManager->fireCallback(String8(filename).string(), nonce, state);
 }
 
 
@@ -131,16 +174,14 @@
     }
 }
 
-void AStorageManager_setObbCallback(AStorageManager* mgr, AStorageManager_obbCallbackFunc cb, void* data) {
-    mgr->setObbCallback(cb, data);
+void AStorageManager_mountObb(AStorageManager* mgr, const char* filename, const char* key,
+        AStorageManager_obbCallbackFunc cb, void* data) {
+    mgr->mountObb(filename, key, cb, data);
 }
 
-void AStorageManager_mountObb(AStorageManager* mgr, const char* filename, const char* key) {
-    mgr->mountObb(filename, key);
-}
-
-void AStorageManager_unmountObb(AStorageManager* mgr, const char* filename, const int force) {
-    mgr->unmountObb(filename, force != 0);
+void AStorageManager_unmountObb(AStorageManager* mgr, const char* filename, const int force,
+        AStorageManager_obbCallbackFunc cb, void* data) {
+    mgr->unmountObb(filename, force != 0, cb, data);
 }
 
 int AStorageManager_isObbMounted(AStorageManager* mgr, const char* filename) {
diff --git a/native/include/android/storage_manager.h b/native/include/android/storage_manager.h
index 6f925c1..bad24913 100644
--- a/native/include/android/storage_manager.h
+++ b/native/include/android/storage_manager.h
@@ -18,6 +18,8 @@
 #ifndef ANDROID_STORAGE_MANAGER_H
 #define ANDROID_STORAGE_MANAGER_H
 
+#include <stdint.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -25,6 +27,60 @@
 struct AStorageManager;
 typedef struct AStorageManager AStorageManager;
 
+enum {
+    /*
+     * The OBB container is now mounted and ready for use. Can be returned
+     * as the status for callbacks made during asynchronous OBB actions.
+     */
+    AOBB_STATE_MOUNTED = 1,
+
+    /*
+     * The OBB container is now unmounted and not usable. Can be returned
+     * as the status for callbacks made during asynchronous OBB actions.
+     */
+    AOBB_STATE_UNMOUNTED = 2,
+
+    /*
+     * There was an internal system error encountered while trying to
+     * mount the OBB. Can be returned as the status for callbacks made
+     * during asynchronous OBB actions.
+     */
+    AOBB_STATE_ERROR_INTERNAL = 20,
+
+    /*
+     * The OBB could not be mounted by the system. Can be returned as the
+     * status for callbacks made during asynchronous OBB actions.
+     */
+    AOBB_STATE_ERROR_COULD_NOT_MOUNT = 21,
+
+    /*
+     * The OBB could not be unmounted. This most likely indicates that a
+     * file is in use on the OBB. Can be returned as the status for
+     * callbacks made during asynchronous OBB actions.
+     */
+    AOBB_STATE_ERROR_COULD_NOT_UNMOUNT = 22,
+
+    /*
+     * A call was made to unmount the OBB when it was not mounted. Can be
+     * returned as the status for callbacks made during asynchronous OBB
+     * actions.
+     */
+    AOBB_STATE_ERROR_NOT_MOUNTED = 23,
+
+    /*
+     * The OBB has already been mounted. Can be returned as the status for
+     * callbacks made during asynchronous OBB actions.
+     */
+    AOBB_STATE_ERROR_ALREADY_MOUNTED = 24,
+
+    /*
+     * 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,
+};
 
 /**
  * Obtains a new instance of AStorageManager.
@@ -39,22 +95,19 @@
 /**
  * Callback function for asynchronous calls made on OBB files.
  */
-typedef void (*AStorageManager_obbCallbackFunc)(const char* filename, const char* state, void* data);
-
-/**
- * Callback to call when requested asynchronous OBB operation is complete.
- */
-void AStorageManager_setObbCallback(AStorageManager* mgr, AStorageManager_obbCallbackFunc cb, void* data);
+typedef void (*AStorageManager_obbCallbackFunc)(const char* filename, const int32_t state, void* data);
 
 /**
  * Attempts to mount an OBB file. This is an asynchronous operation.
  */
-void AStorageManager_mountObb(AStorageManager* mgr, const char* filename, const char* key);
+void AStorageManager_mountObb(AStorageManager* mgr, const char* filename, const char* key,
+        AStorageManager_obbCallbackFunc cb, void* data);
 
 /**
  * Attempts to unmount an OBB file. This is an asynchronous operation.
  */
-void AStorageManager_unmountObb(AStorageManager* mgr, const char* filename, const int force);
+void AStorageManager_unmountObb(AStorageManager* mgr, const char* filename, const int force,
+        AStorageManager_obbCallbackFunc cb, void* data);
 
 /**
  * Check whether an OBB is mounted.
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 0fccbe7..7995869 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -20,6 +20,10 @@
         <activity android:name=".usb.UsbStorageActivity"
                 android:excludeFromRecents="true">
         </activity>
+        <activity android:name="com.android.internal.app.ExternalMediaFormatActivity"
+                android:theme="@*android:style/Theme.Dialog.Alert"
+                android:excludeFromRecents="true">
+        </activity>
 
     </application>
 </manifest>
diff --git a/packages/SystemUI/res/drawable-hdpi/battery_low_battery.png b/packages/SystemUI/res/drawable-hdpi/battery_low_battery.png
index e74c22f..2c7a0d4 100644
--- a/packages/SystemUI/res/drawable-hdpi/battery_low_battery.png
+++ b/packages/SystemUI/res/drawable-hdpi/battery_low_battery.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_gps_acquiring.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_gps_acquiring.png
index c43fc3b..150c9fc 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_gps_acquiring.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_gps_acquiring.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/statusbar_background.9.png b/packages/SystemUI/res/drawable-hdpi/statusbar_background.9.png
index 98e5487..a933833 100644
--- a/packages/SystemUI/res/drawable-hdpi/statusbar_background.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/statusbar_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_gps_acquiring.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_gps_acquiring.png
index 31bc94e..07f0a0a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_gps_acquiring.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_gps_acquiring.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/statusbar_background.9.png b/packages/SystemUI/res/drawable-mdpi/statusbar_background.9.png
index 4b5dbe3..6c588f7 100644
--- a/packages/SystemUI/res/drawable-mdpi/statusbar_background.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/statusbar_background.9.png
Binary files differ
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
index f3da2a3..b1c6ad8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
@@ -294,6 +294,7 @@
         mScrollView = (ScrollView)expanded.findViewById(R.id.scroll);
         mNotificationLinearLayout = expanded.findViewById(R.id.notificationLinearLayout);
 
+        mExpandedView.setVisibility(View.GONE);
         mOngoingTitle.setVisibility(View.GONE);
         mLatestTitle.setVisibility(View.GONE);
 
@@ -335,7 +336,7 @@
                 PixelFormat.RGBX_8888);
         lp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL;
         lp.setTitle("StatusBar");
-        // TODO lp.windowAnimations = R.style.Animation_StatusBar;
+        lp.windowAnimations = com.android.internal.R.style.Animation_StatusBar;
 
         WindowManagerImpl.getDefault().addView(view, lp);
     }
@@ -691,6 +692,7 @@
         mExpandedDialog.getWindow().setAttributes(mExpandedParams);
         mExpandedView.requestFocus(View.FOCUS_FORWARD);
         mTrackingView.setVisibility(View.VISIBLE);
+        mExpandedView.setVisibility(View.VISIBLE);
 
         if (!mTicking) {
             setDateViewVisibility(true, com.android.internal.R.anim.fade_in);
@@ -767,6 +769,7 @@
         mExpandedParams.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
         mExpandedDialog.getWindow().setAttributes(mExpandedParams);
         mTrackingView.setVisibility(View.GONE);
+        mExpandedView.setVisibility(View.GONE);
 
         if ((mDisabled & StatusBarManager.DISABLE_NOTIFICATION_ICONS) == 0) {
             setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
@@ -1323,29 +1326,26 @@
             mExpandedContents.getLocationInWindow(mPositionTmp);
             final int contentsBottom = mPositionTmp[1] + mExpandedContents.getHeight();
 
-            mExpandedParams.y = pos + mTrackingView.getHeight()
-                    - (mTrackingParams.height-closePos) - contentsBottom;
-            int max = h;
-            if (mExpandedParams.y > max) {
-                mExpandedParams.y = max;
-            }
-            int min = mTrackingPosition;
-            if (mExpandedParams.y < min) {
-                mExpandedParams.y = min;
-            }
-
-            boolean visible = (mTrackingPosition + mTrackingView.getHeight()) > h;
-            if (!visible) {
-                // if the contents aren't visible, move the expanded view way off screen
-                // because the window itself extends below the content view.
-                mExpandedParams.y = -disph;
-            }
-            mExpandedDialog.getWindow().setAttributes(mExpandedParams);
-
-            // As long as this isn't just a repositioning that's not supposed to affect
-            // the user's perception of what's showing, call to say that the visibility
-            // has changed. (Otherwise, someone else will call to do that).
             if (expandedPosition != EXPANDED_LEAVE_ALONE) {
+                mExpandedParams.y = pos + mTrackingView.getHeight()
+                        - (mTrackingParams.height-closePos) - contentsBottom;
+                int max = h;
+                if (mExpandedParams.y > max) {
+                    mExpandedParams.y = max;
+                }
+                int min = mTrackingPosition;
+                if (mExpandedParams.y < min) {
+                    mExpandedParams.y = min;
+                }
+
+                boolean visible = (mTrackingPosition + mTrackingView.getHeight()) > h;
+                if (!visible) {
+                    // if the contents aren't visible, move the expanded view way off screen
+                    // because the window itself extends below the content view.
+                    mExpandedParams.y = -disph;
+                }
+                mExpandedDialog.getWindow().setAttributes(mExpandedParams);
+
                 if (SPEW) Slog.d(TAG, "updateExpandedViewPos visibilityChanged(" + visible + ")");
                 visibilityChanged(visible);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index b9e915a4..47ed7da 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -16,33 +16,17 @@
 
 package com.android.systemui.usb;
 
-import android.app.Activity;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.DialogInterface;
 import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
 import android.content.res.Resources;
-import android.os.Bundle;
 import android.os.Environment;
-import android.os.Handler;
-import android.os.storage.IMountService;
-import android.os.Message;
-import android.os.ServiceManager;
 import android.os.storage.StorageEventListener;
 import android.os.storage.StorageManager;
-import android.os.storage.StorageResultCode;
 import android.provider.Settings;
 import android.util.Slog;
-import android.view.View;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.TextView;
-import android.widget.Toast;
 
 public class StorageNotification extends StorageEventListener {
     private static final String TAG = "StorageNotification";
@@ -165,10 +149,16 @@
                      * Show safe to unmount media notification, and enable UMS
                      * notification if connected.
                      */
-                    setMediaStorageNotification(
-                            com.android.internal.R.string.ext_media_safe_unmount_notification_title,
-                            com.android.internal.R.string.ext_media_safe_unmount_notification_message,
-                            com.android.internal.R.drawable.stat_notify_sdcard, true, true, null);
+                    if (Environment.isExternalStorageRemovable()) {
+                        setMediaStorageNotification(
+                                com.android.internal.R.string.ext_media_safe_unmount_notification_title,
+                                com.android.internal.R.string.ext_media_safe_unmount_notification_message,
+                                com.android.internal.R.drawable.stat_notify_sdcard, true, true, null);
+                    } else {
+                        // This device does not have removable storage, so
+                        // don't tell the user they can remove it.
+                        setMediaStorageNotification(0, 0, 0, false, false, null);
+                    }
                     updateUsbMassStorageNotification(mUmsAvailable);
                 }
             } else {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index f21d357..3cf4360 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -1083,7 +1083,7 @@
                 if (!down) {
                     mHomePressed = false;
                     
-                    if (! canceled) {
+                    if (!canceled) {
                         // If an incoming call is ringing, HOME is totally disabled.
                         // (The user is already on the InCallScreen at this point,
                         // and his ONLY options are to answer or reject the call.)
@@ -1735,10 +1735,21 @@
     public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down,
             int policyFlags, boolean isScreenOn) {
         int result = ACTION_PASS_TO_USER;
-        
+
+        if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0) {
+            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
+        }
+
         final boolean isWakeKey = (policyFlags
                 & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
-        
+
+        // If the key is injected, pretend that the screen is on and don't let the
+        // device go to sleep.  This feature is mainly used for testing purposes.
+        final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
+        if (isInjected) {
+            isScreenOn = true;
+        }
+
         // If screen is off then we treat the case where the keyguard is open but hidden
         // the same as if it were open and in front.
         // This will prevent any keys other than the power button from waking the screen
@@ -1837,7 +1848,7 @@
                         || (handled && hungUp && keyCode == KeyEvent.KEYCODE_POWER)) {
                     mShouldTurnOffOnKeyUp = false;
                 } else {
-                    // only try to turn off the screen if we didn't already hang up
+                    // Only try to turn off the screen if we didn't already hang up.
                     mShouldTurnOffOnKeyUp = true;
                     mHandler.postDelayed(mPowerLongPress,
                             ViewConfiguration.getGlobalActionKeyTimeout());
@@ -1860,12 +1871,14 @@
                     if (keyguardActive
                             || (sleeps && !gohome)
                             || (gohome && !goHome() && sleeps)) {
-                        // they must already be on the keyguad or home screen,
-                        // go to sleep instead
-                        Log.d(TAG, "I'm tired mEndcallBehavior=0x"
-                                + Integer.toHexString(mEndcallBehavior));
-                        result &= ~ACTION_POKE_USER_ACTIVITY;
-                        result |= ACTION_GO_TO_SLEEP;
+                        // They must already be on the keyguard or home screen,
+                        // go to sleep instead unless the event was injected.
+                        if (!isInjected) {
+                            Log.d(TAG, "I'm tired mEndcallBehavior=0x"
+                                    + Integer.toHexString(mEndcallBehavior));
+                            result &= ~ACTION_POKE_USER_ACTIVITY;
+                            result |= ACTION_GO_TO_SLEEP;
+                        }
                     }
                     result &= ~ACTION_PASS_TO_USER;
                 }
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/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index aa87f29..50b3abe 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -84,7 +84,7 @@
 
 class BackupManagerService extends IBackupManager.Stub {
     private static final String TAG = "BackupManagerService";
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = true;
 
     // How often we perform a backup pass.  Privileged external callers can
     // trigger an immediate pass.
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 8114be9..a663c3a 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -1038,10 +1038,8 @@
                 if (mNetAttributes[checkType] == null) continue;
                 if (mNetAttributes[checkType].mRadio == ConnectivityManager.TYPE_MOBILE &&
                         noMobileData) {
-                    if (DBG) {
-                        Slog.d(TAG, "not failing over to mobile type " + checkType +
-                                " because Mobile Data Disabled");
-                    }
+                    Slog.e(TAG, "not failing over to mobile type " + checkType +
+                            " because Mobile Data Disabled");
                     continue;
                 }
                 if (mNetAttributes[checkType].isDefault()) {
@@ -1089,6 +1087,8 @@
                     newNet = null; // not officially avail..  try anyway, but
                                    // report no failover
                 }
+            } else {
+                Slog.e(TAG, "Network failover failing.");
             }
         }
 
@@ -1131,16 +1131,13 @@
         String reason = info.getReason();
         String extraInfo = info.getExtraInfo();
 
-        if (DBG) {
-            String reasonText;
-            if (reason == null) {
-                reasonText = ".";
-            } else {
-                reasonText = " (" + reason + ").";
-            }
-            Slog.v(TAG, "Attempt to connect to " + info.getTypeName() +
-                    " failed" + reasonText);
+        String reasonText;
+        if (reason == null) {
+            reasonText = ".";
+        } else {
+            reasonText = " (" + reason + ").";
         }
+        Slog.e(TAG, "Attempt to connect to " + info.getTypeName() + " failed" + reasonText);
 
         Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
         intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
@@ -1164,9 +1161,9 @@
             if (newNet != null) {
                 NetworkInfo switchTo = newNet.getNetworkInfo();
                 if (!switchTo.isConnected()) {
-                    // if the other net is connected they've already reset this and perhaps even gotten
-                    // a positive report we don't want to overwrite, but if not we need to clear this now
-                    // to turn our cellular sig strength white
+                    // if the other net is connected they've already reset this and perhaps
+                    // even gotten a positive report we don't want to overwrite, but if not
+                    // we need to clear this now to turn our cellular sig strength white
                     mDefaultInetConditionPublished = 0;
                 }
                 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java
index 29ca9a4..df41264 100644
--- a/services/java/com/android/server/InputManager.java
+++ b/services/java/com/android/server/InputManager.java
@@ -49,6 +49,8 @@
 public class InputManager {
     static final String TAG = "InputManager";
     
+    private static final boolean DEBUG = false;
+
     private final Callbacks mCallbacks;
     private final Context mContext;
     private final WindowManagerService mWindowManagerService;
@@ -129,7 +131,9 @@
             throw new IllegalArgumentException("Invalid display id or dimensions.");
         }
         
-        Slog.i(TAG, "Setting display #" + displayId + " size to " + width + "x" + height);
+        if (DEBUG) {
+            Slog.d(TAG, "Setting display #" + displayId + " size to " + width + "x" + height);
+        }
         nativeSetDisplaySize(displayId, width, height);
     }
     
@@ -138,7 +142,9 @@
             throw new IllegalArgumentException("Invalid rotation.");
         }
         
-        Slog.i(TAG, "Setting display #" + displayId + " orientation to " + rotation);
+        if (DEBUG) {
+            Slog.d(TAG, "Setting display #" + displayId + " orientation to " + rotation);
+        }
         nativeSetDisplayOrientation(displayId, rotation);
     }
     
@@ -353,11 +359,6 @@
         private static final String CALIBRATION_DIR_PATH = "usr/idc/";
         
         @SuppressWarnings("unused")
-        public void virtualKeyDownFeedback() {
-            mWindowManagerService.mInputMonitor.virtualKeyDownFeedback();
-        }
-        
-        @SuppressWarnings("unused")
         public void notifyConfigurationChanged(long whenNanos) {
             mWindowManagerService.sendNewConfiguration();
         }
diff --git a/services/java/com/android/server/Installer.java b/services/java/com/android/server/Installer.java
index 1f34eba..85eca60 100644
--- a/services/java/com/android/server/Installer.java
+++ b/services/java/com/android/server/Installer.java
@@ -327,4 +327,33 @@
     public int moveFiles() {
         return execute("movefiles");
     }
+
+    public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath) {
+        if (dataPath == null) {
+            Slog.e(TAG, "unlinkNativeLibraryDirectory dataPath is null");
+            return -1;
+        } else if (nativeLibPath == null) {
+            Slog.e(TAG, "unlinkNativeLibraryDirectory nativeLibPath is null");
+            return -1;
+        }
+
+        StringBuilder builder = new StringBuilder("linklib ");
+        builder.append(dataPath);
+        builder.append(' ');
+        builder.append(nativeLibPath);
+
+        return execute(builder.toString());
+    }
+
+    public int unlinkNativeLibraryDirectory(String dataPath) {
+        if (dataPath == null) {
+            Slog.e(TAG, "unlinkNativeLibraryDirectory dataPath is null");
+            return -1;
+        }
+
+        StringBuilder builder = new StringBuilder("unlinklib ");
+        builder.append(dataPath);
+
+        return execute(builder.toString());
+    }
 }
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 361cd3b..84024b8 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -130,6 +130,7 @@
 
     // Handler messages
     private static final int MESSAGE_LOCATION_CHANGED = 1;
+    private static final int MESSAGE_PACKAGE_UPDATED = 2;
 
     // wakelock variables
     private final static String WAKELOCK_KEY = "LocationManagerService";
@@ -1826,6 +1827,19 @@
                             handleLocationChangedLocked(location, passive);
                         }
                     }
+                } else if (msg.what == MESSAGE_PACKAGE_UPDATED) {
+                    String packageName = (String) msg.obj;
+                    String packageDot = packageName + ".";
+
+                    // reconnect to external providers after their packages have been updated
+                    if (mNetworkLocationProvider != null &&
+                        mNetworkLocationProviderPackageName.startsWith(packageDot)) {
+                        mNetworkLocationProvider.reconnect();
+                    }
+                    if (mGeocodeProvider != null &&
+                        mGeocodeProviderPackageName.startsWith(packageDot)) {
+                        mGeocodeProvider.reconnect();
+                    }
                 }
             } catch (Exception e) {
                 // Log, don't crash!
@@ -1928,17 +1942,8 @@
     private final PackageMonitor mPackageMonitor = new PackageMonitor() {
         @Override
         public void onPackageUpdateFinished(String packageName, int uid) {
-            String packageDot = packageName + ".";
-
-            // reconnect to external providers after their packages have been updated
-            if (mNetworkLocationProvider != null &&
-                    mNetworkLocationProviderPackageName.startsWith(packageDot)) {
-                mNetworkLocationProvider.reconnect();
-            }
-            if (mGeocodeProvider != null &&
-                    mGeocodeProviderPackageName.startsWith(packageDot)) {
-                mGeocodeProvider.reconnect();
-            }
+            // Called by main thread; divert work to LocationWorker.
+            Message.obtain(mLocationHandler, MESSAGE_PACKAGE_UPDATED, packageName).sendToTarget();
         }
     };
 
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 3b2d836..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;
@@ -44,16 +43,18 @@
 import android.os.storage.IMountServiceListener;
 import android.os.storage.IMountShutdownObserver;
 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.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -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.
      */
@@ -161,25 +178,25 @@
     final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>();
 
     class ObbState implements IBinder.DeathRecipient {
-        public ObbState(String filename, IObbActionListener token, int callerUid)
+        public ObbState(String filename, int callerUid, IObbActionListener token, int nonce)
                 throws RemoteException {
             this.filename = filename;
-            this.token = token;
             this.callerUid = callerUid;
-            mounted = false;
+            this.token = token;
+            this.nonce = nonce;
         }
 
         // OBB source filename
-        final String filename;
-
-        // Token of remote Binder caller
-        final IObbActionListener token;
+        String filename;
 
         // Binder.callingUid()
         final public int callerUid;
 
-        // Whether this is mounted currently.
-        boolean mounted;
+        // Token of remote Binder caller
+        final IObbActionListener token;
+
+        // Identifier to pass back to the token
+        final int nonce;
 
         public IBinder getBinder() {
             return token.asBinder();
@@ -208,8 +225,6 @@
             sb.append(token.toString());
             sb.append(",callerUid=");
             sb.append(callerUid);
-            sb.append(",mounted=");
-            sb.append(mounted);
             sb.append('}');
             return sb.toString();
         }
@@ -223,6 +238,7 @@
     private static final int OBB_MCS_BOUND = 2;
     private static final int OBB_MCS_UNBIND = 3;
     private static final int OBB_MCS_RECONNECT = 4;
+    private static final int OBB_FLUSH_MOUNT_STATE = 5;
 
     /*
      * Default Container Service information
@@ -500,40 +516,23 @@
             Slog.w(TAG, String.format("Duplicate state transition (%s -> %s)", mLegacyState, state));
             return;
         }
-        // Update state on PackageManager
+
         if (Environment.MEDIA_UNMOUNTED.equals(state)) {
+            // Tell the package manager the media is gone.
             mPms.updateExternalMediaStatus(false, false);
+
+            /*
+             * Some OBBs might have been unmounted when this volume was
+             * unmounted, so send a message to the handler to let it know to
+             * remove those from the list of mounted OBBS.
+             */
+            mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_FLUSH_MOUNT_STATE,
+                    path));
         } else if (Environment.MEDIA_MOUNTED.equals(state)) {
+            // Tell the package manager the media is available for use.
             mPms.updateExternalMediaStatus(true, false);
         }
 
-        // Remove all OBB mappings and listeners from this path
-        synchronized (mObbMounts) {
-            final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>();
-
-            final Iterator<Entry<String, ObbState>> i = mObbPathToStateMap.entrySet().iterator();
-            while (i.hasNext()) {
-                final Entry<String, ObbState> obbEntry = i.next();
-
-                // If this entry's source file is in the volume path that got
-                // unmounted, remove it because it's no longer valid.
-                if (obbEntry.getKey().startsWith(path)) {
-                    obbStatesToRemove.add(obbEntry.getValue());
-                }
-            }
-
-            for (final ObbState obbState : obbStatesToRemove) {
-                removeObbState(obbState);
-
-                try {
-                    obbState.token.onObbResult(obbState.filename, Environment.MEDIA_UNMOUNTED);
-                } catch (RemoteException e) {
-                    Slog.i(TAG, "Couldn't send unmount notification for  OBB: "
-                            + obbState.filename);
-                }
-            }
-        }
-
         String oldState = mLegacyState;
         mLegacyState = state;
 
@@ -1530,6 +1529,10 @@
     }
 
     public String getMountedObbPath(String filename) {
+        if (filename == null) {
+            throw new IllegalArgumentException("filename cannot be null");
+        }
+
         waitForReady();
         warnOnNotMounted();
 
@@ -1552,164 +1555,98 @@
     }
 
     public boolean isObbMounted(String filename) {
-        synchronized (mObbMounts) {
-            final ObbState obbState = mObbPathToStateMap.get(filename);
-            if (obbState != null) {
-                synchronized (obbState) {
-                    return obbState.mounted;
-                }
-            }
+        if (filename == null) {
+            throw new IllegalArgumentException("filename cannot be null");
         }
-        return false;
+
+        synchronized (mObbMounts) {
+            return mObbPathToStateMap.containsKey(filename);
+        }
     }
 
-    public void mountObb(String filename, String key, IObbActionListener token)
+    public void mountObb(String filename, String key, IObbActionListener token, int nonce)
             throws RemoteException {
-        waitForReady();
-        warnOnNotMounted();
-
         if (filename == null) {
             throw new IllegalArgumentException("filename cannot be null");
-        } else if (token == null) {
+        }
+
+        if (token == null) {
             throw new IllegalArgumentException("token cannot be null");
         }
 
-        final ObbState obbState;
-
-        synchronized (mObbMounts) {
-            if (isObbMounted(filename)) {
-                try {
-                    token.onObbResult(filename, Environment.MEDIA_MOUNTED);
-                } catch (RemoteException e) {
-                    Slog.d(TAG, "Could not send unmount notification for: " + filename);
-                }
-                return;
-            }
-
-            final int callerUid = Binder.getCallingUid();
-            obbState = new ObbState(filename, token, callerUid);
-            addObbState(obbState);
-        }
-
-        String hashedKey = null;
-        if (key != null) {
-            final MessageDigest md;
-            try {
-                md = MessageDigest.getInstance("MD5");
-            } catch (NoSuchAlgorithmException e) {
-                Slog.e(TAG, "Could not load MD5 algorithm", e);
-                try {
-                    token.onObbResult(filename, Environment.MEDIA_UNMOUNTED);
-                } catch (RemoteException e1) {
-                    Slog.d(TAG, "Could not send unmount notification for: " + filename);
-                }
-                return;
-            }
-
-            hashedKey = HexDump.toHexString(md.digest(key.getBytes()));
-        }
-
-        ObbAction action = new MountObbAction(obbState, hashedKey);
+        final int callerUid = Binder.getCallingUid();
+        final ObbState obbState = new ObbState(filename, callerUid, token, nonce);
+        final ObbAction action = new MountObbAction(obbState, key);
         mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
 
         if (DEBUG_OBB)
             Slog.i(TAG, "Send to OBB handler: " + action.toString());
     }
 
-    public void unmountObb(String filename, boolean force, IObbActionListener token) {
+    public void unmountObb(String filename, boolean force, IObbActionListener token, int nonce)
+            throws RemoteException {
         if (filename == null) {
             throw new IllegalArgumentException("filename cannot be null");
-        } else if (token == null) {
-            throw new IllegalArgumentException("token cannot be null");
         }
 
-        final ObbState obbState;
-
-        synchronized (mObbMounts) {
-            if (!isObbMounted(filename)) {
-                try {
-                    token.onObbResult(filename, Environment.MEDIA_UNMOUNTED);
-                } catch (RemoteException e) {
-                    Slog.d(TAG, "Could not send unmount notification for: " + filename);
-                }
-                return;
-            }
-
-            obbState = mObbPathToStateMap.get(filename);
-
-            if (Binder.getCallingUid() != obbState.callerUid) {
-                throw new SecurityException("caller UID does not match original mount caller UID");
-            } else if (!token.asBinder().equals(obbState.getBinder())) {
-                throw new SecurityException("caller does not match original mount caller");
-            }
-        }
-
-        ObbAction action = new UnmountObbAction(obbState, force);
+        final int callerUid = Binder.getCallingUid();
+        final ObbState obbState = new ObbState(filename, callerUid, token, nonce);
+        final ObbAction action = new UnmountObbAction(obbState, force);
         mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
 
         if (DEBUG_OBB)
             Slog.i(TAG, "Send to OBB handler: " + action.toString());
     }
 
-    private void addObbState(ObbState obbState) throws RemoteException {
-        synchronized (mObbMounts) {
-            final IBinder binder = obbState.getBinder();
-            List<ObbState> obbStates = mObbMounts.get(binder);
-            final boolean unique;
+    private void addObbStateLocked(ObbState obbState) throws RemoteException {
+        final IBinder binder = obbState.getBinder();
+        List<ObbState> obbStates = mObbMounts.get(binder);
 
-            if (obbStates == null) {
-                obbStates = new ArrayList<ObbState>();
-                mObbMounts.put(binder, obbStates);
-                unique = true;
-            } else {
-                unique = obbStates.contains(obbState);
-            }
-
-            if (unique) {
-                obbStates.add(obbState);
-                try {
-                    obbState.link();
-                } catch (RemoteException e) {
-                    /*
-                     * The binder died before we could link it, so clean up our
-                     * state and return failure.
-                     */
-                    obbStates.remove(obbState);
-                    if (obbStates.isEmpty()) {
-                        mObbMounts.remove(binder);
-                    }
-
-                    // Rethrow the error so mountObb can get it
-                    throw e;
+        if (obbStates == null) {
+            obbStates = new ArrayList<ObbState>();
+            mObbMounts.put(binder, obbStates);
+        } else {
+            for (final ObbState o : obbStates) {
+                if (o.filename.equals(obbState.filename)) {
+                    throw new IllegalStateException("Attempt to add ObbState twice. "
+                            + "This indicates an error in the MountService logic.");
                 }
             }
-
-            mObbPathToStateMap.put(obbState.filename, obbState);
         }
+
+        obbStates.add(obbState);
+        try {
+            obbState.link();
+        } catch (RemoteException e) {
+            /*
+             * The binder died before we could link it, so clean up our state
+             * and return failure.
+             */
+            obbStates.remove(obbState);
+            if (obbStates.isEmpty()) {
+                mObbMounts.remove(binder);
+            }
+
+            // Rethrow the error so mountObb can get it
+            throw e;
+        }
+
+        mObbPathToStateMap.put(obbState.filename, obbState);
     }
 
-    private void removeObbState(ObbState obbState) {
-        synchronized (mObbMounts) {
-            final IBinder binder = obbState.getBinder();
-            final List<ObbState> obbStates = mObbMounts.get(binder);
-            if (obbStates != null) {
-                if (obbStates.remove(obbState)) {
-                    obbState.unlink();
-                }
-                if (obbStates.isEmpty()) {
-                    mObbMounts.remove(binder);
-                }
+    private void removeObbStateLocked(ObbState obbState) {
+        final IBinder binder = obbState.getBinder();
+        final List<ObbState> obbStates = mObbMounts.get(binder);
+        if (obbStates != null) {
+            if (obbStates.remove(obbState)) {
+                obbState.unlink();
             }
-
-            mObbPathToStateMap.remove(obbState.filename);
+            if (obbStates.isEmpty()) {
+                mObbMounts.remove(binder);
+            }
         }
-    }
 
-    private void replaceObbState(ObbState oldObbState, ObbState newObbState) throws RemoteException {
-        synchronized (mObbMounts) {
-            removeObbState(oldObbState);
-            addObbState(newObbState);
-        }
+        mObbPathToStateMap.remove(obbState.filename);
     }
 
     private class ObbActionHandler extends Handler {
@@ -1808,6 +1745,47 @@
                     }
                     break;
                 }
+                case OBB_FLUSH_MOUNT_STATE: {
+                    final String path = (String) msg.obj;
+
+                    if (DEBUG_OBB)
+                        Slog.i(TAG, "Flushing all OBB state for path " + path);
+
+                    synchronized (mObbMounts) {
+                        final List<ObbState> obbStatesToRemove = new LinkedList<ObbState>();
+
+                        final Iterator<Entry<String, ObbState>> i =
+                                mObbPathToStateMap.entrySet().iterator();
+                        while (i.hasNext()) {
+                            final Entry<String, ObbState> obbEntry = i.next();
+
+                            /*
+                             * If this entry's source file is in the volume path
+                             * that got unmounted, remove it because it's no
+                             * longer valid.
+                             */
+                            if (obbEntry.getKey().startsWith(path)) {
+                                obbStatesToRemove.add(obbEntry.getValue());
+                            }
+                        }
+
+                        for (final ObbState obbState : obbStatesToRemove) {
+                            if (DEBUG_OBB)
+                                Slog.i(TAG, "Removing state for " + obbState.filename);
+
+                            removeObbStateLocked(obbState);
+
+                            try {
+                                obbState.token.onObbResult(obbState.filename, obbState.nonce,
+                                        OnObbStateChangeListener.UNMOUNTED);
+                            } catch (RemoteException e) {
+                                Slog.i(TAG, "Couldn't send unmount notification for  OBB: "
+                                        + obbState.filename);
+                            }
+                        }
+                    }
+                    break;
+                }
             }
         }
 
@@ -1886,9 +1864,13 @@
             return obbInfo;
         }
 
-        protected void sendNewStatusOrIgnore(String filename, String status) {
+        protected void sendNewStatusOrIgnore(int status) {
+            if (mObbState == null || mObbState.token == null) {
+                return;
+            }
+
             try {
-                mObbState.token.onObbResult(filename, status);
+                mObbState.token.onObbResult(mObbState.filename, mObbState.nonce, status);
             } catch (RemoteException e) {
                 Slog.w(TAG, "MountServiceListener went away while calling onObbStateChanged");
             }
@@ -1904,89 +1886,87 @@
         }
 
         public void handleExecute() throws IOException, RemoteException {
+            waitForReady();
+            warnOnNotMounted();
+
             final ObbInfo obbInfo = getObbInfo();
 
-            /*
-             * If someone tried to trick us with some weird characters, rectify
-             * it here.
-             */
-            if (!mObbState.filename.equals(obbInfo.filename)) {
-                if (DEBUG_OBB)
-                    Slog.i(TAG, "OBB filename " + mObbState.filename + " is actually "
-                            + obbInfo.filename);
-
-                synchronized (mObbMounts) {
-                    /*
-                     * If the real filename is already mounted, discard this
-                     * state and notify the caller that the OBB is already
-                     * mounted.
-                     */
-                    if (isObbMounted(obbInfo.filename)) {
-                        if (DEBUG_OBB)
-                            Slog.i(TAG, "OBB already mounted as " + obbInfo.filename);
-
-                        removeObbState(mObbState);
-                        sendNewStatusOrIgnore(obbInfo.filename, Environment.MEDIA_MOUNTED);
-                        return;
-                    }
-
-                    /*
-                     * It's not already mounted, so we have to replace the state
-                     * with the state containing the actual filename.
-                     */
-                    ObbState newObbState = new ObbState(obbInfo.filename, mObbState.token,
-                            mObbState.callerUid);
-                    replaceObbState(mObbState, newObbState);
-                    mObbState = newObbState;
-                }
-            }
-
             if (!isUidOwnerOfPackageOrSystem(obbInfo.packageName, mObbState.callerUid)) {
-                throw new IllegalArgumentException("Caller package does not match OBB file");
+                Slog.w(TAG, "Denied attempt to mount OBB " + obbInfo.filename
+                        + " which is owned by " + obbInfo.packageName);
+                sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
+                return;
             }
 
-            boolean mounted = false;
-            int rc;
-            synchronized (mObbState) {
-                if (mObbState.mounted) {
-                    sendNewStatusOrIgnore(mObbState.filename, Environment.MEDIA_MOUNTED);
+            final boolean isMounted;
+            synchronized (mObbMounts) {
+                isMounted = mObbPathToStateMap.containsKey(obbInfo.filename);
+            }
+            if (isMounted) {
+                Slog.w(TAG, "Attempt to mount OBB which is already mounted: " + obbInfo.filename);
+                sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_ALREADY_MOUNTED);
+                return;
+            }
+
+            /*
+             * The filename passed in might not be the canonical name, so just
+             * set the filename to the canonicalized version.
+             */
+            mObbState.filename = obbInfo.filename;
+
+            final String hashedKey;
+            if (mKey == null) {
+                hashedKey = "none";
+            } else {
+                try {
+                    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 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;
                 }
+            }
 
-                rc = StorageResultCode.OperationSucceeded;
-                String cmd = String.format("obb mount %s %s %d", mObbState.filename,
-                        mKey != null ? mKey : "none",
-                        mObbState.callerUid);
-                try {
-                    mConnector.doCommand(cmd);
-                } catch (NativeDaemonConnectorException e) {
-                    int code = e.getCode();
-                    if (code != VoldResponseCode.OpFailedStorageBusy) {
-                        rc = StorageResultCode.OperationFailedInternalError;
-                    }
-                }
-
-                if (rc == StorageResultCode.OperationSucceeded) {
-                    mObbState.mounted = mounted = true;
+            int rc = StorageResultCode.OperationSucceeded;
+            String cmd = String.format("obb mount %s %s %d", mObbState.filename, hashedKey,
+                    mObbState.callerUid);
+            try {
+                mConnector.doCommand(cmd);
+            } catch (NativeDaemonConnectorException e) {
+                int code = e.getCode();
+                if (code != VoldResponseCode.OpFailedStorageBusy) {
+                    rc = StorageResultCode.OperationFailedInternalError;
                 }
             }
 
-            if (mounted) {
-                sendNewStatusOrIgnore(mObbState.filename, Environment.MEDIA_MOUNTED);
+            if (rc == StorageResultCode.OperationSucceeded) {
+                if (DEBUG_OBB)
+                    Slog.d(TAG, "Successfully mounted OBB " + mObbState.filename);
+
+                synchronized (mObbMounts) {
+                    addObbStateLocked(mObbState);
+                }
+
+                sendNewStatusOrIgnore(OnObbStateChangeListener.MOUNTED);
             } else {
                 Slog.e(TAG, "Couldn't mount OBB file: " + rc);
 
-                // We didn't succeed, so remove this from the mount-set.
-                removeObbState(mObbState);
-
-                sendNewStatusOrIgnore(mObbState.filename, Environment.MEDIA_UNMOUNTED);
+                sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_COULD_NOT_MOUNT);
             }
         }
 
         public void handleError() {
-            removeObbState(mObbState);
-
-            sendNewStatusOrIgnore(mObbState.filename, Environment.MEDIA_BAD_REMOVAL);
+            sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
         }
 
         @Override
@@ -1999,6 +1979,8 @@
             sb.append(mObbState.callerUid);
             sb.append(",token=");
             sb.append(mObbState.token != null ? mObbState.token.toString() : "NULL");
+            sb.append(",binder=");
+            sb.append(mObbState.token != null ? mObbState.getBinder().toString() : "null");
             sb.append('}');
             return sb.toString();
         }
@@ -2013,68 +1995,61 @@
         }
 
         public void handleExecute() throws IOException {
+            waitForReady();
+            warnOnNotMounted();
+
             final ObbInfo obbInfo = getObbInfo();
 
-            /*
-             * If someone tried to trick us with some weird characters, rectify
-             * it here.
-             */
+            final ObbState obbState;
             synchronized (mObbMounts) {
-                if (!isObbMounted(obbInfo.filename)) {
-                    removeObbState(mObbState);
-                    sendNewStatusOrIgnore(mObbState.filename, Environment.MEDIA_UNMOUNTED);
-                    return;
-                }
+                obbState = mObbPathToStateMap.get(obbInfo.filename);
+            }
 
-                if (!mObbState.filename.equals(obbInfo.filename)) {
-                    removeObbState(mObbState);
-                    mObbState = mObbPathToStateMap.get(obbInfo.filename);
+            if (obbState == null) {
+                sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_NOT_MOUNTED);
+                return;
+            }
+
+            if (obbState.callerUid != mObbState.callerUid) {
+                Slog.w(TAG, "Permission denied attempting to unmount OBB " + obbInfo.filename
+                        + " (owned by " + obbInfo.packageName + ")");
+                sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
+                return;
+            }
+
+            mObbState.filename = obbInfo.filename;
+
+            int rc = StorageResultCode.OperationSucceeded;
+            String cmd = String.format("obb unmount %s%s", mObbState.filename,
+                    (mForceUnmount ? " force" : ""));
+            try {
+                mConnector.doCommand(cmd);
+            } catch (NativeDaemonConnectorException e) {
+                int code = e.getCode();
+                if (code == VoldResponseCode.OpFailedStorageBusy) {
+                    rc = StorageResultCode.OperationFailedStorageBusy;
+                } else if (code == VoldResponseCode.OpFailedStorageNotFound) {
+                    // If it's not mounted then we've already won.
+                    rc = StorageResultCode.OperationSucceeded;
+                } else {
+                    rc = StorageResultCode.OperationFailedInternalError;
                 }
             }
 
-            boolean unmounted = false;
-            synchronized (mObbState) {
-                if (!mObbState.mounted) {
-                    sendNewStatusOrIgnore(obbInfo.filename, Environment.MEDIA_UNMOUNTED);
-                    return;
+            if (rc == StorageResultCode.OperationSucceeded) {
+                synchronized (mObbMounts) {
+                    removeObbStateLocked(obbState);
                 }
 
-                int rc = StorageResultCode.OperationSucceeded;
-                String cmd = String.format("obb unmount %s%s", mObbState.filename,
-                        (mForceUnmount ? " force" : ""));
-                try {
-                    mConnector.doCommand(cmd);
-                } catch (NativeDaemonConnectorException e) {
-                    int code = e.getCode();
-                    if (code == VoldResponseCode.OpFailedStorageBusy) {
-                        rc = StorageResultCode.OperationFailedStorageBusy;
-                    } else if (code == VoldResponseCode.OpFailedStorageNotFound) {
-                        // If it's not mounted then we've already won.
-                        rc = StorageResultCode.OperationSucceeded;
-                    } else {
-                        rc = StorageResultCode.OperationFailedInternalError;
-                    }
-                }
-
-                if (rc == StorageResultCode.OperationSucceeded) {
-                    mObbState.mounted = false;
-                    unmounted = true;
-                }
-            }
-
-            if (unmounted) {
-                removeObbState(mObbState);
-
-                sendNewStatusOrIgnore(mObbState.filename, Environment.MEDIA_UNMOUNTED);
+                sendNewStatusOrIgnore(OnObbStateChangeListener.UNMOUNTED);
             } else {
-                sendNewStatusOrIgnore(mObbState.filename, Environment.MEDIA_MOUNTED);
+                Slog.w(TAG, "Could not mount OBB: " + mObbState.filename);
+                sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_COULD_NOT_UNMOUNT);
             }
         }
 
         public void handleError() {
-            removeObbState(mObbState);
-
-            sendNewStatusOrIgnore(mObbState.filename, Environment.MEDIA_BAD_REMOVAL);
+            sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
         }
 
         @Override
@@ -2090,7 +2065,7 @@
             sb.append(",token=");
             sb.append(mObbState.token != null ? mObbState.token.toString() : "null");
             sb.append(",binder=");
-            sb.append(mObbState.getBinder().toString());
+            sb.append(mObbState.token != null ? mObbState.getBinder().toString() : "null");
             sb.append('}');
             return sb.toString();
         }
@@ -2105,16 +2080,27 @@
             return;
         }
 
-        pw.println("  mObbMounts:");
-
         synchronized (mObbMounts) {
-            final Collection<List<ObbState>> obbStateLists = mObbMounts.values();
+            pw.println("  mObbMounts:");
 
-            for (final List<ObbState> obbStates : obbStateLists) {
+            final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet().iterator();
+            while (binders.hasNext()) {
+                Entry<IBinder, List<ObbState>> e = binders.next();
+                pw.print("    Key="); pw.println(e.getKey().toString());
+                final List<ObbState> obbStates = e.getValue();
                 for (final ObbState obbState : obbStates) {
-                    pw.print("    "); pw.println(obbState.toString());
+                    pw.print("      "); pw.println(obbState.toString());
                 }
             }
+
+            pw.println("");
+            pw.println("  mObbPathToStateMap:");
+            final Iterator<Entry<String, ObbState>> maps = mObbPathToStateMap.entrySet().iterator();
+            while (maps.hasNext()) {
+                final Entry<String, ObbState> e = maps.next();
+                pw.print("    "); pw.print(e.getKey());
+                pw.print(" -> "); pw.println(e.getValue().toString());
+            }
         }
     }
 }
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 050e0c8..9d7c58e 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -183,11 +183,14 @@
     static final int SCAN_UPDATE_SIGNATURE = 1<<3;
     static final int SCAN_NEW_INSTALL = 1<<4;
     static final int SCAN_NO_PATHS = 1<<5;
+    static final int SCAN_UPDATE_TIME = 1<<6;
 
     static final int REMOVE_CHATTY = 1<<16;
-    
+
+    static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
+
     static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
-            "com.android.defcontainer",
+            DEFAULT_CONTAINER_PACKAGE,
             "com.android.defcontainer.DefaultContainerService");
 
     private static final String LIB_DIR_NAME = "lib";
@@ -921,7 +924,7 @@
             mFrameworkInstallObserver.startWatching();
             scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM
                     | PackageParser.PARSE_IS_SYSTEM_DIR,
-                    scanMode | SCAN_NO_DEX);
+                    scanMode | SCAN_NO_DEX, 0);
             
             // Collect all system packages.
             mSystemAppDir = new File(Environment.getRootDirectory(), "app");
@@ -929,7 +932,7 @@
                 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
             mSystemInstallObserver.startWatching();
             scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM
-                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode);
+                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
             
             // Collect all vendor packages.
             mVendorAppDir = new File("/vendor/app");
@@ -937,7 +940,7 @@
                 mVendorAppDir.getPath(), OBSERVER_EVENTS, true);
             mVendorInstallObserver.startWatching();
             scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM
-                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode);
+                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
 
             if (mInstaller != null) {
                 if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
@@ -984,12 +987,13 @@
             mAppInstallObserver = new AppDirObserver(
                 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
             mAppInstallObserver.startWatching();
-            scanDirLI(mAppInstallDir, 0, scanMode);
+            scanDirLI(mAppInstallDir, 0, scanMode, 0);
 
             mDrmAppInstallObserver = new AppDirObserver(
                 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
             mDrmAppInstallObserver.startWatching();
-            scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK, scanMode);
+            scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
+                    scanMode, 0);
 
             EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
                     SystemClock.uptimeMillis());
@@ -1317,14 +1321,15 @@
     PackageInfo generatePackageInfo(PackageParser.Package p, int flags) {
         if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
             // The package has been uninstalled but has retained data and resources.
-            return PackageParser.generatePackageInfo(p, null, flags);
+            return PackageParser.generatePackageInfo(p, null, flags, 0, 0);
         }
         final PackageSetting ps = (PackageSetting)p.mExtras;
         if (ps == null) {
             return null;
         }
         final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
-        return PackageParser.generatePackageInfo(p, gp.gids, flags);
+        return PackageParser.generatePackageInfo(p, gp.gids, flags,
+                ps.firstInstallTime, ps.lastUpdateTime);
     }
 
     public PackageInfo getPackageInfo(String packageName, int flags) {
@@ -2483,7 +2488,7 @@
         return finalList;
     }
 
-    private void scanDirLI(File dir, int flags, int scanMode) {
+    private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
         String[] files = dir.list();
         if (files == null) {
             Log.d(TAG, "No files in app dir " + dir);
@@ -2500,7 +2505,7 @@
                 continue;
             }
             PackageParser.Package pkg = scanPackageLI(file,
-                    flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
+                    flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime);
             // Don't mess around with apps in system partition.
             if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
                     mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {
@@ -2568,7 +2573,7 @@
      *  Returns null in case of errors and the error code is stored in mLastScanError
      */
     private PackageParser.Package scanPackageLI(File scanFile,
-            int parseFlags, int scanMode) {
+            int parseFlags, int scanMode, long currentTime) {
         mLastScanError = PackageManager.INSTALL_SUCCEEDED;
         String scanPath = scanFile.getPath();
         parseFlags |= mDefParseFlags;
@@ -2668,7 +2673,7 @@
         // Set application objects path explicitly.
         setApplicationInfoPaths(pkg, codePath, resPath);
         // Note that we invoke the following method only if we are about to unpack an application
-        return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
+        return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE, currentTime);
     }
 
     private static void setApplicationInfoPaths(PackageParser.Package pkg, String destCodePath,
@@ -2799,7 +2804,7 @@
     }
     
     private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
-            int parseFlags, int scanMode) {
+            int parseFlags, int scanMode, long currentTime) {
         File scanFile = new File(pkg.mScanPath);
         if (scanFile == null || pkg.applicationInfo.sourceDir == null ||
                 pkg.applicationInfo.publicSourceDir == null) {
@@ -3132,7 +3137,7 @@
             }
         }
         
-        long scanFileTime = scanFile.lastModified();
+        final long scanFileTime = scanFile.lastModified();
         final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
         final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.timeStamp;
         pkg.applicationInfo.processName = fixProcessName(
@@ -3290,7 +3295,11 @@
                     }
                 } else if (!isExternal(pkg)) {
                     Log.i(TAG, path + " changed; unpacking");
+                    mInstaller.unlinkNativeLibraryDirectory(dataPath.getPath());
                     NativeLibraryHelper.copyNativeBinariesLI(scanFile, sharedLibraryDir);
+                } else {
+                    mInstaller.linkNativeLibraryDirectory(dataPath.getPath(),
+                            pkg.applicationInfo.nativeLibraryDir);
                 }
             }
             pkg.mScanPath = path;
@@ -3328,6 +3337,24 @@
             // Make sure we don't accidentally delete its data.
             mSettings.mPackagesToBeCleaned.remove(pkgName);
             
+            // Take care of first install / last update times.
+            if (currentTime != 0) {
+                if (pkgSetting.firstInstallTime == 0) {
+                    pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime;
+                } else if ((scanMode&SCAN_UPDATE_TIME) != 0) {
+                    pkgSetting.lastUpdateTime = currentTime;
+                }
+            } else if (pkgSetting.firstInstallTime == 0) {
+                // We need *something*.  Take time time stamp of the file.
+                pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;
+            } else if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
+                if (scanFileTime != pkgSetting.timeStamp) {
+                    // A package on the system image has changed; consider this
+                    // to be an update.
+                    pkgSetting.lastUpdateTime = scanFileTime;
+                }
+            }
+
             int N = pkg.providers.size();
             StringBuilder r = null;
             int i;
@@ -3906,17 +3933,22 @@
                     allowed = false;
                 } else if (bp.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
                         || bp.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
-                    allowed = (checkSignaturesLP(bp.packageSetting.signatures.mSignatures, pkg.mSignatures)
+                    allowed = (checkSignaturesLP(
+                            bp.packageSetting.signatures.mSignatures, pkg.mSignatures)
                                     == PackageManager.SIGNATURE_MATCH)
                             || (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures)
                                     == PackageManager.SIGNATURE_MATCH);
-                    if (bp.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
+                    if (!allowed && bp.protectionLevel
+                            == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
                         if (isSystemApp(pkg)) {
                             // For updated system applications, the signatureOrSystem permission
                             // is granted only if it had been defined by the original application.
                             if (isUpdatedSystemApp(pkg)) {
-                                PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
-                                if(sysPs.grantedPermissions.contains(perm)) {
+                                PackageSetting sysPs = mSettings.getDisabledSystemPkg(
+                                        pkg.packageName);
+                                final GrantedPermissions origGp = sysPs.sharedUser != null
+                                        ? sysPs.sharedUser : sysPs;
+                                if (origGp.grantedPermissions.contains(perm)) {
                                     allowed = true;
                                 } else {
                                     allowed = false;
@@ -4467,7 +4499,8 @@
                                         | PackageParser.PARSE_IS_SYSTEM_DIR: 0) |
                                 PackageParser.PARSE_CHATTY |
                                 PackageParser.PARSE_MUST_BE_APK,
-                                SCAN_MONITOR | SCAN_NO_PATHS);
+                                SCAN_MONITOR | SCAN_NO_PATHS | SCAN_UPDATE_TIME,
+                                System.currentTimeMillis());
                         if (p != null) {
                             synchronized (mPackages) {
                                 updatePermissionsLP(p.packageName, p,
@@ -4743,7 +4776,15 @@
                 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
             } else {
                 // Remote call to find out default install location
-                PackageInfoLite pkgLite = mContainerService.getMinimalPackageInfo(packageURI, flags);
+                final PackageInfoLite pkgLite;
+                try {
+                    mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
+                            Intent.FLAG_GRANT_READ_URI_PERMISSION);
+                    pkgLite = mContainerService.getMinimalPackageInfo(packageURI, flags);
+                } finally {
+                    mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
+                }
+
                 int loc = pkgLite.recommendedInstallLocation;
                 if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION){
                     ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
@@ -4958,8 +4999,14 @@
             libraryPath = new File(dataDir, LIB_DIR_NAME).getPath();
         }
 
-        boolean  checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
-            return imcs.checkFreeStorage(false, packageURI);
+        boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
+            try {
+                mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
+                        Intent.FLAG_GRANT_READ_URI_PERMISSION);
+                return imcs.checkFreeStorage(false, packageURI);
+            } finally {
+                mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            }
         }
 
         String getCodePath() {
@@ -5003,15 +5050,14 @@
             // Copy the resource now
             int ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
             try {
+                mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
+                        Intent.FLAG_GRANT_READ_URI_PERMISSION);
                 if (imcs.copyResource(packageURI, out)) {
                     ret = PackageManager.INSTALL_SUCCEEDED;
                 }
             } finally {
                 try { if (out != null) out.close(); } catch (IOException e) {}
-            }
-
-            if (!temp) {
-                NativeLibraryHelper.copyNativeBinariesLI(codeFile, new File(libraryPath));
+                mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
             }
 
             return ret;
@@ -5110,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() {
@@ -5182,17 +5225,31 @@
             cid = getTempContainerId();
         }
 
-        boolean  checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
-            return imcs.checkFreeStorage(true, packageURI);
+        boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
+            try {
+                mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
+                        Intent.FLAG_GRANT_READ_URI_PERMISSION);
+                return imcs.checkFreeStorage(true, packageURI);
+            } finally {
+                mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            }
         }
 
         int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
             if (temp) {
                 createCopyFile();
             }
-            String newCachePath = imcs.copyResourceToContainer(
-                    packageURI, cid,
-                    getEncryptKey(), RES_FILE_NAME);
+
+            final String newCachePath;
+            try {
+                mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
+                        Intent.FLAG_GRANT_READ_URI_PERMISSION);
+                newCachePath = imcs.copyResourceToContainer(packageURI, cid,
+                        getEncryptKey(), RES_FILE_NAME);
+            } finally {
+                mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            }
+
             if (newCachePath != null) {
                 setCachePath(newCachePath);
                 return PackageManager.INSTALL_SUCCEEDED;
@@ -5460,7 +5517,8 @@
             }
         }
         mLastScanError = PackageManager.INSTALL_SUCCEEDED;
-        PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode);
+        PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode,
+                System.currentTimeMillis());
         if (newPackage == null) {
             Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
             if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
@@ -5523,16 +5581,24 @@
             oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
         }
 
+        long origUpdateTime;
+        if (pkg.mExtras != null) {
+            origUpdateTime = ((PackageSetting)pkg.mExtras).lastUpdateTime;
+        } else {
+            origUpdateTime = 0;
+        }
+
         // First delete the existing package while retaining the data directory
         if (!deletePackageLI(pkgName, true, PackageManager.DONT_DELETE_DATA,
                 res.removedInfo, true)) {
-            // If the existing package was'nt successfully deleted
+            // If the existing package wasn't successfully deleted
             res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
             deletedPkg = false;
         } else {
             // Successfully deleted the old package. Now proceed with re-installation
             mLastScanError = PackageManager.INSTALL_SUCCEEDED;
-            newPackage = scanPackageLI(pkg, parseFlags, scanMode);
+            newPackage = scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_TIME,
+                    System.currentTimeMillis());
             if (newPackage == null) {
                 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
                 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
@@ -5570,8 +5636,10 @@
                 int oldParseFlags  = mDefParseFlags | PackageParser.PARSE_CHATTY |
                         (isForwardLocked(deletedPackage) ? PackageParser.PARSE_FORWARD_LOCK : 0) |
                         (oldOnSd ? PackageParser.PARSE_ON_SDCARD : 0);
-                int oldScanMode = (oldOnSd ? 0 : SCAN_MONITOR) | SCAN_UPDATE_SIGNATURE;
-                if (scanPackageLI(restoreFile, oldParseFlags, oldScanMode) == null) {
+                int oldScanMode = (oldOnSd ? 0 : SCAN_MONITOR) | SCAN_UPDATE_SIGNATURE
+                        | SCAN_UPDATE_TIME;
+                if (scanPackageLI(restoreFile, oldParseFlags, oldScanMode,
+                        origUpdateTime) == null) {
                     Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade");
                     return;
                 }
@@ -5622,13 +5690,18 @@
         // Successfully disabled the old package. Now proceed with re-installation
         mLastScanError = PackageManager.INSTALL_SUCCEEDED;
         pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
-        newPackage = scanPackageLI(pkg, parseFlags, scanMode);
+        newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0);
         if (newPackage == null) {
             Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
             if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
                 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
             }
         } else {
+            if (newPackage.mExtras != null) {
+                final PackageSetting newPkgSetting = (PackageSetting)newPackage.mExtras;
+                newPkgSetting.firstInstallTime = oldPkgSetting.firstInstallTime;
+                newPkgSetting.lastUpdateTime = System.currentTimeMillis();
+            }
             updateSettingsLI(newPackage, installerPackageName, res);
             updatedSettings = true;
         }
@@ -5640,12 +5713,10 @@
                 removePackageLI(newPackage, true);
             }
             // Add back the old system package
-            scanPackageLI(oldPkg, parseFlags,
-                    SCAN_MONITOR
-                    | SCAN_UPDATE_SIGNATURE);
+            scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0);
             // Restore the old system information in Settings
             synchronized(mPackages) {
-                if(updatedSettings) {
+                if (updatedSettings) {
                     mSettings.enableSystemPackageLP(packageName);
                     mSettings.setInstallerPackageName(packageName,
                             oldPkgSetting.installerPackageName);
@@ -5659,7 +5730,6 @@
                 PackageSetting ps = mSettings.getDisabledSystemPkg(packageName);
                 if (ps != null && ps.codePathString != null &&
                         !ps.codePathString.equals(oldPkgSetting.codePathString)) {
-                    int installFlags = 0;
                     res.removedInfo.args = createInstallArgs(0, oldPkgSetting.codePathString,
                             oldPkgSetting.resourcePathString, oldPkgSetting.nativeLibraryPathString);
                 }
@@ -6194,7 +6264,7 @@
         // Install the system package
         PackageParser.Package newPkg = scanPackageLI(ps.codePath,
                 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
-                SCAN_MONITOR | SCAN_NO_PATHS);
+                SCAN_MONITOR | SCAN_NO_PATHS, 0);
 
         if (newPkg == null) {
             Slog.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
@@ -7047,6 +7117,8 @@
             printedSomething = false;
             SharedUserSetting packageSharedUser = null;
             if (dumpStar || dumpPackages) {
+                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                Date date = new Date();
                 for (PackageSetting ps : mSettings.mPackages.values()) {
                     if (packageName != null && !packageName.equals(ps.realName)
                             && !packageName.equals(ps.name)) {
@@ -7121,13 +7193,20 @@
                         }
                     }
                     pw.println("]");
-                    pw.print("    timeStamp="); pw.println(String.valueOf(ps.timeStamp));
+                    pw.print("    timeStamp=");
+                            date.setTime(ps.timeStamp); pw.println(sdf.format(date));
+                    pw.print("    firstInstallTime=");
+                            date.setTime(ps.firstInstallTime); pw.println(sdf.format(date));
+                    pw.print("    lastUpdateTime=");
+                            date.setTime(ps.lastUpdateTime); pw.println(sdf.format(date));
                     pw.print("    signatures="); pw.println(ps.signatures);
                     pw.print("    permissionsFixed="); pw.print(ps.permissionsFixed);
                             pw.print(" haveGids="); pw.println(ps.haveGids);
                     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) {
@@ -7632,6 +7711,8 @@
         String nativeLibraryPathString;
         String obbPathString;
         long timeStamp;
+        long firstInstallTime;
+        long lastUpdateTime;
         int versionCode;
 
         boolean uidError;
@@ -7696,6 +7777,8 @@
             gids = base.gids;
 
             timeStamp = base.timeStamp;
+            firstInstallTime = base.firstInstallTime;
+            lastUpdateTime = base.lastUpdateTime;
             signatures = base.signatures;
             permissionsFixed = base.permissionsFixed;
             haveGids = base.haveGids;
@@ -8565,7 +8648,9 @@
                 serializer.attribute(null, "realName", pkg.realName);
             }
             serializer.attribute(null, "codePath", pkg.codePathString);
-            serializer.attribute(null, "ts", String.valueOf(pkg.timeStamp));
+            serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp));
+            serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime));
+            serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime));
             serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
             if (!pkg.resourcePathString.equals(pkg.codePathString)) {
                 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
@@ -8617,7 +8702,9 @@
             }
             serializer.attribute(null, "flags",
                     Integer.toString(pkg.pkgFlags));
-            serializer.attribute(null, "ts", String.valueOf(pkg.timeStamp));
+            serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp));
+            serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime));
+            serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime));
             serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
             if (pkg.sharedUser == null) {
                 serializer.attribute(null, "userId",
@@ -8973,13 +9060,36 @@
             pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
             PackageSetting ps = new PackageSetting(name, realName, new File(codePathStr),
                     new File(resourcePathStr), nativeLibraryPathStr, versionCode, pkgFlags);
-            String timeStampStr = parser.getAttributeValue(null, "ts");
+            String timeStampStr = parser.getAttributeValue(null, "ft");
             if (timeStampStr != null) {
                 try {
-                    long timeStamp = Long.parseLong(timeStampStr);
+                    long timeStamp = Long.parseLong(timeStampStr, 16);
                     ps.setTimeStamp(timeStamp);
                 } catch (NumberFormatException e) {
                 }
+            } else {
+                timeStampStr = parser.getAttributeValue(null, "ts");
+                if (timeStampStr != null) {
+                    try {
+                        long timeStamp = Long.parseLong(timeStampStr);
+                        ps.setTimeStamp(timeStamp);
+                    } catch (NumberFormatException e) {
+                    }
+                }
+            }
+            timeStampStr = parser.getAttributeValue(null, "it");
+            if (timeStampStr != null) {
+                try {
+                    ps.firstInstallTime = Long.parseLong(timeStampStr, 16);
+                } catch (NumberFormatException e) {
+                }
+            }
+            timeStampStr = parser.getAttributeValue(null, "ut");
+            if (timeStampStr != null) {
+                try {
+                    ps.lastUpdateTime = Long.parseLong(timeStampStr, 16);
+                } catch (NumberFormatException e) {
+                }
             }
             String idStr = parser.getAttributeValue(null, "userId");
             ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
@@ -9026,6 +9136,8 @@
             String uidError = null;
             int pkgFlags = 0;
             long timeStamp = 0;
+            long firstInstallTime = 0;
+            long lastUpdateTime = 0;
             PackageSettingBase packageSetting = null;
             String version = null;
             int versionCode = 0;
@@ -9065,10 +9177,32 @@
                         pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
                     }
                 }
-                final String timeStampStr = parser.getAttributeValue(null, "ts");
+                String timeStampStr = parser.getAttributeValue(null, "ft");
                 if (timeStampStr != null) {
                     try {
-                        timeStamp = Long.parseLong(timeStampStr);
+                        timeStamp = Long.parseLong(timeStampStr, 16);
+                    } catch (NumberFormatException e) {
+                    }
+                } else {
+                    timeStampStr = parser.getAttributeValue(null, "ts");
+                    if (timeStampStr != null) {
+                        try {
+                            timeStamp = Long.parseLong(timeStampStr);
+                        } catch (NumberFormatException e) {
+                        }
+                    }
+                }
+                timeStampStr = parser.getAttributeValue(null, "it");
+                if (timeStampStr != null) {
+                    try {
+                        firstInstallTime = Long.parseLong(timeStampStr, 16);
+                    } catch (NumberFormatException e) {
+                    }
+                }
+                timeStampStr = parser.getAttributeValue(null, "ut");
+                if (timeStampStr != null) {
+                    try {
+                        lastUpdateTime = Long.parseLong(timeStampStr, 16);
                     } catch (NumberFormatException e) {
                     }
                 }
@@ -9102,6 +9236,8 @@
                                 + parser.getPositionDescription());
                     } else {
                         packageSetting.setTimeStamp(timeStamp);
+                        packageSetting.firstInstallTime = firstInstallTime;
+                        packageSetting.lastUpdateTime = lastUpdateTime;
                     }
                 } else if (sharedIdStr != null) {
                     userId = sharedIdStr != null
@@ -9111,6 +9247,8 @@
                                 new File(codePathStr), new File(resourcePathStr),
                                 nativeLibraryPathStr, userId, versionCode, pkgFlags);
                         packageSetting.setTimeStamp(timeStamp);
+                        packageSetting.firstInstallTime = firstInstallTime;
+                        packageSetting.lastUpdateTime = lastUpdateTime;
                         mPendingPackages.add((PendingPackage) packageSetting);
                         if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
                                 + ": sharedUserId=" + userId + " pkg="
@@ -9669,7 +9807,7 @@
                doGc = true;
                synchronized (mInstallLock) {
                    final PackageParser.Package pkg =  scanPackageLI(new File(codePath),
-                           parseFlags, 0);
+                           parseFlags, 0, 0);
                    // Scan the package
                    if (pkg != null) {
                        synchronized (mPackages) {
@@ -9894,10 +10032,10 @@
                            synchronized (mPackages) {
                                PackageParser.Package pkg = mPackages.get(mp.packageName);
                                // Recheck for package again.
-                               if (pkg == null ) {
-                                   Slog.w(TAG, " Package " + mp.packageName +
-                                   " doesn't exist. Aborting move");
-                                   returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
+                                if (pkg == null) {
+                                    Slog.w(TAG, " Package " + mp.packageName
+                                            + " doesn't exist. Aborting move");
+                                    returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
                                } else if (!mp.srcArgs.getCodePath().equals(pkg.applicationInfo.sourceDir)) {
                                    Slog.w(TAG, "Package " + mp.packageName + " code path changed from " +
                                            mp.srcArgs.getCodePath() + " to " + pkg.applicationInfo.sourceDir +
@@ -9908,15 +10046,34 @@
                                    final String newCodePath = mp.targetArgs.getCodePath();
                                    final String newResPath = mp.targetArgs.getResourcePath();
                                    final String newNativePath = mp.targetArgs.getNativeLibraryPath();
-                                   pkg.mPath = newCodePath;
-                                   // Move dex files around
-                                   if (moveDexFilesLI(pkg)
-                                           != PackageManager.INSTALL_SUCCEEDED) {
-                                       // Moving of dex files failed. Set
-                                       // error code and abort move.
-                                       pkg.mPath = pkg.mScanPath;
-                                       returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
-                                   } else {
+
+                                    if ((mp.flags & PackageManager.INSTALL_EXTERNAL) == 0) {
+                                        if (mInstaller
+                                                .unlinkNativeLibraryDirectory(pkg.applicationInfo.dataDir) < 0) {
+                                            returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
+                                        } else {
+                                            NativeLibraryHelper.copyNativeBinariesLI(
+                                                    new File(newCodePath), new File(newNativePath));
+                                        }
+                                    } else {
+                                        if (mInstaller.linkNativeLibraryDirectory(
+                                                pkg.applicationInfo.dataDir, newNativePath) < 0) {
+                                            returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
+                                        }
+                                    }
+
+                                    if (returnCode == PackageManager.MOVE_SUCCEEDED) {
+                                        pkg.mPath = newCodePath;
+                                        // Move dex files around
+                                        if (moveDexFilesLI(pkg) != PackageManager.INSTALL_SUCCEEDED) {
+                                            // Moving of dex files failed. Set
+                                            // error code and abort move.
+                                            pkg.mPath = pkg.mScanPath;
+                                            returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
+                                        }
+                                    }
+
+                                    if (returnCode == PackageManager.MOVE_SUCCEEDED) {
                                        pkg.mScanPath = newCodePath;
                                        pkg.applicationInfo.sourceDir = newCodePath;
                                        pkg.applicationInfo.publicSourceDir = newResPath;
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 496c665..b90b4bf 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -65,6 +65,8 @@
 import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
 import static android.provider.Settings.System.STAY_ON_WHILE_PLUGGED_IN;
+import static android.provider.Settings.System.WINDOW_ANIMATION_SCALE;
+import static android.provider.Settings.System.TRANSITION_ANIMATION_SCALE;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -141,9 +143,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 +201,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;
@@ -245,6 +242,14 @@
     private int[] mButtonBacklightValues;
     private int[] mKeyboardBacklightValues;
     private int mLightSensorWarmupTime;
+    boolean mUnplugTurnsOnScreen;
+    private int mWarningSpewThrottleCount;
+    private long mWarningSpewThrottleTime;
+    private int mAnimationSetting = ANIM_SETTING_OFF;
+
+    // Must match with the ISurfaceComposer constants in C++.
+    private static final int ANIM_SETTING_ON = 0x01;
+    private static final int ANIM_SETTING_OFF = 0x10;
 
     // Used when logging number and duration of touch-down cycles
     private long mTotalTouchDownTime;
@@ -258,6 +263,7 @@
     
     private native void nativeInit();
     private native void nativeSetPowerState(boolean screenOn, boolean screenBright);
+    private native void nativeStartSurfaceFlingerAnimation(int mode);
 
     /*
     static PrintStream mLog;
@@ -364,8 +370,12 @@
                     // user activity when screen was already on.
                     // temporarily set mUserActivityAllowed to true so this will work
                     // even when the keyguard is on.
+                    // However, you can also set config_unplugTurnsOnScreen to have it
+                    // turn on.  Some devices want this because they don't have a
+                    // charging LED.
                     synchronized (mLocks) {
-                        if (!wasPowered || (mPowerState & SCREEN_ON_BIT) != 0) {
+                        if (!wasPowered || (mPowerState & SCREEN_ON_BIT) != 0 ||
+                                mUnplugTurnsOnScreen) {
                             forceUserActivityLocked();
                         }
                     }
@@ -423,6 +433,12 @@
             return iVal != null ? iVal : defValue;
         }
 
+        private float getFloat(String name, float defValue) {
+            ContentValues values = mSettings.getValues(name);
+            Float fVal = values != null ? values.getAsFloat(Settings.System.VALUE) : null;
+            return fVal != null ? fVal : defValue;
+        }
+
         public void update(Observable o, Object arg) {
             synchronized (mLocks) {
                 // STAY_ON_WHILE_PLUGGED_IN, default to when plugged into AC
@@ -433,7 +449,7 @@
                 // SCREEN_OFF_TIMEOUT, default to 15 seconds
                 mScreenOffTimeoutSetting = getInt(SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT);
 
-                 // DIM_SCREEN
+                // DIM_SCREEN
                 //mDimScreen = getInt(DIM_SCREEN) != 0;
 
                 // SCREEN_BRIGHTNESS_MODE, default to manual
@@ -442,6 +458,17 @@
 
                 // recalculate everything
                 setScreenOffTimeoutsLocked();
+
+                final float windowScale = getFloat(WINDOW_ANIMATION_SCALE, 1.0f);
+                final float transitionScale = getFloat(TRANSITION_ANIMATION_SCALE, 1.0f);
+                mAnimationSetting = 0;
+                if (windowScale > 0.5f) {
+                    mAnimationSetting |= ANIM_SETTING_OFF;
+                }
+                if (transitionScale > 0.5f) {
+                    // Uncomment this if you want the screen-on animation.
+                    // mAnimationSetting |= ANIM_SETTING_ON;
+                }
             }
         }
     }
@@ -478,6 +505,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() {
@@ -524,6 +580,12 @@
 
         Resources resources = mContext.getResources();
 
+        mAnimateScreenLights = resources.getBoolean(
+                com.android.internal.R.bool.config_animateScreenLights);
+
+        mUnplugTurnsOnScreen = resources.getBoolean(
+                com.android.internal.R.bool.config_unplugTurnsOnScreen);
+
         // read settings for auto-brightness
         mUseSoftwareAutoBrightness = resources.getBoolean(
                 com.android.internal.R.bool.config_automatic_brightness_available);
@@ -545,9 +607,11 @@
                 "(" + Settings.System.NAME + "=?) or ("
                         + Settings.System.NAME + "=?) or ("
                         + Settings.System.NAME + "=?) or ("
+                        + Settings.System.NAME + "=?) or ("
+                        + Settings.System.NAME + "=?) or ("
                         + Settings.System.NAME + "=?)",
                 new String[]{STAY_ON_WHILE_PLUGGED_IN, SCREEN_OFF_TIMEOUT, DIM_SCREEN,
-                        SCREEN_BRIGHTNESS_MODE},
+                        SCREEN_BRIGHTNESS_MODE, WINDOW_ANIMATION_SCALE, TRANSITION_ANIMATION_SCALE},
                 null);
         mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mHandler);
         SettingsObserver settingsObserver = new SettingsObserver();
@@ -1083,8 +1147,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();
@@ -1714,7 +1776,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) {
@@ -1744,145 +1807,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) {
@@ -1924,7 +1937,7 @@
         }
     }
 
-    class BrightnessState {
+    class BrightnessState implements Runnable {
         final int mask;
 
         boolean initialized;
@@ -1944,13 +1957,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 -
@@ -1964,7 +1977,12 @@
                         + noticeMe);
             }
             animating = true;
-            return true;
+
+            if (mSpew) {
+                Slog.i(TAG, "scheduling light animator");
+            }
+            mScreenOffHandler.removeCallbacks(this);
+            mScreenOffHandler.post(this);
         }
 
         boolean stepLocked() {
@@ -1990,32 +2008,55 @@
                     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) {
+                    // TODO: I think it's possible that if you sleep & wake multiple times
+                    // quickly for different reasons, mScreenOffReason for the first animation
+                    // might get stomped on as it starts the second animation.
+                    nativeStartSurfaceFlingerAnimation(
+                            mScreenOffReason == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR
+                            ? 0 : mAnimationSetting);
                 }
+                mScreenBrightness.jumpToTarget();
             }
         }
     }
@@ -2095,6 +2136,21 @@
         return (mScreenBrightness.animating && mScreenBrightness.targetValue == 0);
     }
 
+    private boolean shouldLog(long time) {
+        synchronized (mLocks) {
+            if (time > (mWarningSpewThrottleTime + (60*60*1000))) {
+                mWarningSpewThrottleTime = time;
+                mWarningSpewThrottleCount = 0;
+                return true;
+            } else if (mWarningSpewThrottleCount < 30) {
+                mWarningSpewThrottleCount++;
+                return true;
+            } else {
+                return false;
+            }
+        }
+    }
+
     private void forceUserActivityLocked() {
         if (isScreenTurningOffLocked()) {
             // cancel animation so userActivity will succeed
@@ -2112,7 +2168,15 @@
     }
 
     public void userActivity(long time, boolean noChangeLights) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER)
+                != PackageManager.PERMISSION_GRANTED) {
+            if (shouldLog(time)) {
+                Slog.w(TAG, "Caller does not have DEVICE_POWER permission.  pid="
+                        + Binder.getCallingPid() + " uid=" + Binder.getCallingUid());
+            }
+            return;
+        }
+
         userActivity(time, -1, noChangeLights, OTHER_EVENT, false);
     }
 
@@ -2310,49 +2374,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);
                 }
             }
         }
@@ -2720,6 +2750,7 @@
         }
     }
 
+    // for watchdog
     public void monitor() {
         synchronized (mLocks) { }
     }
@@ -2739,34 +2770,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 7f42429..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;
@@ -35,7 +36,12 @@
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.media.AudioService;
-import android.os.*;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.StrictMode;
+import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.provider.Contacts.People;
 import android.provider.Settings;
 import android.server.BluetoothA2dpService;
@@ -84,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);
@@ -573,6 +597,10 @@
     static Timer timer;
     static final long SNAPSHOT_INTERVAL = 60 * 60 * 1000; // 1hr
 
+    // The earliest supported time.  We pick one day into 1970, to
+    // give any timezone code room without going into negative time.
+    private static final long EARLIEST_SUPPORTED_TIME = 86400 * 1000;
+
     /**
      * This method is called from Zygote to initialize the system. This will cause the native
      * services (SurfaceFlinger, AudioFlinger, etc..) to be started. After that it will call back
@@ -581,6 +609,16 @@
     native public static void init1(String[] args);
 
     public static void main(String[] args) {
+        if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
+            // If a device's clock is before 1970 (before 0), a lot of
+            // APIs crash dealing with negative numbers, notably
+            // java.io.File#setLastModified, so instead we fake it and
+            // hope that time from cell towers or NTP fixes it
+            // shortly.
+            Slog.w(TAG, "System clock is before 1970; setting to 1970.");
+            SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
+        }
+
         if (SamplingProfilerIntegration.isEnabled()) {
             SamplingProfilerIntegration.start();
             timer = new Timer();
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 3d95bf0..a63b3d8 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -2163,12 +2163,12 @@
             if (DBG) throw new IllegalArgumentException("lockMode=" + lockMode);
             return false;
         }
-        if (ws != null) {
-            enforceWakeSourcePermission(Binder.getCallingUid(), Binder.getCallingPid());
-        }
         if (ws != null && ws.size() == 0) {
             ws = null;
         }
+        if (ws != null) {
+            enforceWakeSourcePermission(Binder.getCallingUid(), Binder.getCallingPid());
+        }
         if (ws == null) {
             ws = new WorkSource(Binder.getCallingUid());
         }
@@ -2227,17 +2227,18 @@
                 ++mScanLocksAcquired;
                 break;
             }
+
+            // Be aggressive about adding new locks into the accounted state...
+            // we want to over-report rather than under-report.
+            reportStartWorkSource();
+
+            updateWifiState();
+            return true;
         } catch (RemoteException e) {
+            return false;
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
-
-        // Be aggressive about adding new locks into the accounted state...
-        // we want to over-report rather than under-report.
-        reportStartWorkSource();
-
-        updateWifiState();
-        return true;
     }
 
     public void updateWifiLockWorkSource(IBinder lock, WorkSource ws) {
@@ -2283,9 +2284,9 @@
 
         hadLock = (wifiLock != null);
 
-        if (hadLock) {
-            long ident = Binder.clearCallingIdentity();
-            try {
+        long ident = Binder.clearCallingIdentity();
+        try {
+            if (hadLock) {
                 noteAcquireWifiLock(wifiLock);
                 switch(wifiLock.mMode) {
                     case WifiManager.WIFI_MODE_FULL:
@@ -2298,13 +2299,16 @@
                         ++mScanLocksReleased;
                         break;
                 }
-            } catch (RemoteException e) {
-            } finally {
-                Binder.restoreCallingIdentity(ident);
             }
+
+            // TODO - should this only happen if you hadLock?
+            updateWifiState();
+
+        } catch (RemoteException e) {
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
-        // TODO - should this only happen if you hadLock?
-        updateWifiState();
+
         return hadLock;
     }
 
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 0de57ab..42fffb0 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -5243,13 +5243,6 @@
             mTempInputWindows.clear();
         }
         
-        /* Provides feedback for a virtual key down. */
-        public void virtualKeyDownFeedback() {
-            synchronized (mWindowMap) {
-                mPolicy.performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
-            }
-        }
-        
         /* Notifies that the lid switch changed state. */
         public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
             mPolicy.notifyLidSwitchChanged(whenNanos, lidOpen);
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/android/server/location/GeocoderProxy.java b/services/java/com/android/server/location/GeocoderProxy.java
index d9b49fd..e3131fe 100644
--- a/services/java/com/android/server/location/GeocoderProxy.java
+++ b/services/java/com/android/server/location/GeocoderProxy.java
@@ -41,8 +41,8 @@
 
     private final Context mContext;
     private final Intent mIntent;
-    private final Connection mServiceConnection = new Connection();
-    private IGeocodeProvider mProvider;
+    private final Object mMutex = new Object();  // synchronizes access to mServiceConnection
+    private Connection mServiceConnection = new Connection();  // never null
 
     public GeocoderProxy(Context context, String serviceName) {
         mContext = context;
@@ -50,34 +50,48 @@
         mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
     }
 
+    /**
+     * When unbundled NetworkLocationService package is updated, we
+     * need to unbind from the old version and re-bind to the new one.
+     */
     public void reconnect() {
-        synchronized (mServiceConnection) {
+        synchronized (mMutex) {
             mContext.unbindService(mServiceConnection);
+            mServiceConnection = new Connection();
             mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
         }
     }
 
     private class Connection implements ServiceConnection {
+
+        private IGeocodeProvider mProvider;
+
         public void onServiceConnected(ComponentName className, IBinder service) {
             Log.d(TAG, "onServiceConnected " + className);
-            synchronized (mServiceConnection) {
+            synchronized (this) {
                 mProvider = IGeocodeProvider.Stub.asInterface(service);
             }
         }
 
         public void onServiceDisconnected(ComponentName className) {
             Log.d(TAG, "onServiceDisconnected " + className);
-            synchronized (mServiceConnection) {
+            synchronized (this) {
                 mProvider = null;
             }
         }
+
+        public IGeocodeProvider getProvider() {
+            synchronized (this) {
+                return mProvider;
+            }
+        }
     }
 
     public String getFromLocation(double latitude, double longitude, int maxResults,
             GeocoderParams params, List<Address> addrs) {
         IGeocodeProvider provider;
-        synchronized (mServiceConnection) {
-            provider = mProvider;
+        synchronized (mMutex) {
+            provider = mServiceConnection.getProvider();
         }
         if (provider != null) {
             try {
@@ -95,8 +109,8 @@
             double upperRightLatitude, double upperRightLongitude, int maxResults,
             GeocoderParams params, List<Address> addrs) {
         IGeocodeProvider provider;
-        synchronized (mServiceConnection) {
-            provider = mProvider;
+        synchronized (mMutex) {
+            provider = mServiceConnection.getProvider();
         }
         if (provider != null) {
             try {
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index e9eb4f0..f9c1679 100755
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -493,6 +493,11 @@
                 + " info: " + info);
         }
 
+        if (info != null) {
+            native_update_network_state(info.isConnected(), info.getType(),
+                    info.isRoaming(), info.getExtraInfo());
+        }
+
         if (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE_SUPL
                 && mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
             String apnName = info.getExtraInfo();
@@ -1228,6 +1233,7 @@
     private void reportAGpsStatus(int type, int status) {
         switch (status) {
             case GPS_REQUEST_AGPS_DATA_CONN:
+                if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN");
                 // Set mAGpsDataConnectionState before calling startUsingNetworkFeature
                 //  to avoid a race condition with handleUpdateNetworkState()
                 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
@@ -1250,6 +1256,7 @@
                 }
                 break;
             case GPS_RELEASE_AGPS_DATA_CONN:
+                if (DEBUG) Log.d(TAG, "GPS_RELEASE_AGPS_DATA_CONN");
                 if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
                     mConnMgr.stopUsingNetworkFeature(
                             ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
@@ -1258,13 +1265,13 @@
                 }
                 break;
             case GPS_AGPS_DATA_CONNECTED:
-                // Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
+                if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
                 break;
             case GPS_AGPS_DATA_CONN_DONE:
-                // Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
+                if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
                 break;
             case GPS_AGPS_DATA_CONN_FAILED:
-                // Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
+                if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
                 break;
         }
     }
@@ -1599,4 +1606,7 @@
     private native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc,
             int lac, int cid);
     private native void native_agps_set_id(int type, String setid);
+
+    private native void native_update_network_state(boolean connected, int type,
+            boolean roaming, String extraInfo);
 }
diff --git a/services/java/com/android/server/location/LocationProviderProxy.java b/services/java/com/android/server/location/LocationProviderProxy.java
index ef2056b..1a1a170 100644
--- a/services/java/com/android/server/location/LocationProviderProxy.java
+++ b/services/java/com/android/server/location/LocationProviderProxy.java
@@ -45,10 +45,10 @@
 
     private final Context mContext;
     private final String mName;
-    private final String mServiceName;
-    private ILocationProvider mProvider;
-    private Handler mHandler;
-    private final Connection mServiceConnection = new Connection();
+    private final Intent mIntent;
+    private final Handler mHandler;
+    private final Object mMutex = new Object();  // synchronizes access to non-final members
+    private Connection mServiceConnection = new Connection();  // never null
 
     // cached values set by the location manager
     private boolean mLocationTracking = false;
@@ -58,89 +58,105 @@
     private int mNetworkState;
     private NetworkInfo mNetworkInfo;
 
-    // for caching requiresNetwork, requiresSatellite, etc.
-    private DummyLocationProvider mCachedAttributes;
-
     // constructor for proxying location providers implemented in a separate service
     public LocationProviderProxy(Context context, String name, String serviceName,
             Handler handler) {
         mContext = context;
         mName = name;
-        mServiceName = serviceName;
+        mIntent = new Intent(serviceName);
         mHandler = handler;
-        mContext.bindService(new Intent(serviceName), mServiceConnection, Context.BIND_AUTO_CREATE);
+        mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
     }
 
+    /**
+     * When unbundled NetworkLocationService package is updated, we
+     * need to unbind from the old version and re-bind to the new one.
+     */
     public void reconnect() {
-        synchronized (mServiceConnection) {
-            // unbind first
+        synchronized (mMutex) {
             mContext.unbindService(mServiceConnection);
-            mContext.bindService(new Intent(mServiceName), mServiceConnection,
-                Context.BIND_AUTO_CREATE);
+            mServiceConnection = new Connection();
+            mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
         }
     }
 
-    private class Connection implements ServiceConnection {
+    private class Connection implements ServiceConnection, Runnable {
+
+        private ILocationProvider mProvider;
+
+        // for caching requiresNetwork, requiresSatellite, etc.
+        private DummyLocationProvider mCachedAttributes;  // synchronized by mMutex
+
         public void onServiceConnected(ComponentName className, IBinder service) {
             Log.d(TAG, "LocationProviderProxy.onServiceConnected " + className);
-            synchronized (mServiceConnection) {
+            synchronized (this) {
                 mProvider = ILocationProvider.Stub.asInterface(service);
                 if (mProvider != null) {
-                    mHandler.post(mServiceConnectedTask);
+                    mHandler.post(this);
                 }
             }
         }
 
         public void onServiceDisconnected(ComponentName className) {
             Log.d(TAG, "LocationProviderProxy.onServiceDisconnected " + className);
-            synchronized (mServiceConnection) {
+            synchronized (this) {
                 mProvider = null;
             }
         }
-    }
 
-    private Runnable mServiceConnectedTask = new Runnable() {
+        public synchronized ILocationProvider getProvider() {
+            return mProvider;
+        }
+
+        public synchronized DummyLocationProvider getCachedAttributes() {
+            return mCachedAttributes;
+        }
+
         public void run() {
-            ILocationProvider provider;
-            synchronized (mServiceConnection) {
-                provider = mProvider;
+            synchronized (mMutex) {
+                if (mServiceConnection != this) {
+                    // This ServiceConnection no longer the one we want to bind to.
+                    return;
+                }
+                ILocationProvider provider = getProvider();
                 if (provider == null) {
                     return;
                 }
-            }
 
-            if (mCachedAttributes == null) {
+                // resend previous values from the location manager if the service has restarted
                 try {
-                    mCachedAttributes = new DummyLocationProvider(mName, null);
-                    mCachedAttributes.setRequiresNetwork(provider.requiresNetwork());
-                    mCachedAttributes.setRequiresSatellite(provider.requiresSatellite());
-                    mCachedAttributes.setRequiresCell(provider.requiresCell());
-                    mCachedAttributes.setHasMonetaryCost(provider.hasMonetaryCost());
-                    mCachedAttributes.setSupportsAltitude(provider.supportsAltitude());
-                    mCachedAttributes.setSupportsSpeed(provider.supportsSpeed());
-                    mCachedAttributes.setSupportsBearing(provider.supportsBearing());
-                    mCachedAttributes.setPowerRequirement(provider.getPowerRequirement());
-                    mCachedAttributes.setAccuracy(provider.getAccuracy());
+                    if (mEnabled) {
+                        provider.enable();
+                    }
+                    if (mLocationTracking) {
+                        provider.enableLocationTracking(true);
+                    }
+                    if (mMinTime >= 0) {
+                        provider.setMinTime(mMinTime, mMinTimeSource);
+                    }
+                    if (mNetworkInfo != null) {
+                        provider.updateNetworkState(mNetworkState, mNetworkInfo);
+                    }
                 } catch (RemoteException e) {
-                    mCachedAttributes = null;
                 }
-            }
 
-            // resend previous values from the location manager if the service has restarted
-            try {
-                if (mEnabled) {
-                    provider.enable();
+                // init cache of parameters
+                if (mCachedAttributes == null) {
+                    try {
+                        mCachedAttributes = new DummyLocationProvider(mName, null);
+                        mCachedAttributes.setRequiresNetwork(provider.requiresNetwork());
+                        mCachedAttributes.setRequiresSatellite(provider.requiresSatellite());
+                        mCachedAttributes.setRequiresCell(provider.requiresCell());
+                        mCachedAttributes.setHasMonetaryCost(provider.hasMonetaryCost());
+                        mCachedAttributes.setSupportsAltitude(provider.supportsAltitude());
+                        mCachedAttributes.setSupportsSpeed(provider.supportsSpeed());
+                        mCachedAttributes.setSupportsBearing(provider.supportsBearing());
+                        mCachedAttributes.setPowerRequirement(provider.getPowerRequirement());
+                        mCachedAttributes.setAccuracy(provider.getAccuracy());
+                    } catch (RemoteException e) {
+                        mCachedAttributes = null;
+                    }
                 }
-                if (mLocationTracking) {
-                    provider.enableLocationTracking(true);
-                }
-                if (mMinTime >= 0) {
-                    provider.setMinTime(mMinTime, mMinTimeSource);
-                }
-                if (mNetworkInfo != null) {
-                    provider.updateNetworkState(mNetworkState, mNetworkInfo);
-                }
-            } catch (RemoteException e) {
             }
         }
     };
@@ -149,79 +165,101 @@
         return mName;
     }
 
+    private DummyLocationProvider getCachedAttributes() {
+        synchronized (mMutex) {
+            return mServiceConnection.getCachedAttributes();
+        }
+    }
+
     public boolean requiresNetwork() {
-        if (mCachedAttributes != null) {
-            return mCachedAttributes.requiresNetwork();
+        DummyLocationProvider cachedAttributes = getCachedAttributes();
+        if (cachedAttributes != null) {
+            return cachedAttributes.requiresNetwork();
         } else {
             return false;
         }
     }
 
     public boolean requiresSatellite() {
-        if (mCachedAttributes != null) {
-            return mCachedAttributes.requiresSatellite();
+        DummyLocationProvider cachedAttributes = getCachedAttributes();
+        if (cachedAttributes != null) {
+            return cachedAttributes.requiresSatellite();
         } else {
             return false;
         }
     }
 
     public boolean requiresCell() {
-        if (mCachedAttributes != null) {
-            return mCachedAttributes.requiresCell();
+        DummyLocationProvider cachedAttributes = getCachedAttributes();
+        if (cachedAttributes != null) {
+            return cachedAttributes.requiresCell();
         } else {
             return false;
         }
     }
 
     public boolean hasMonetaryCost() {
-        if (mCachedAttributes != null) {
-            return mCachedAttributes.hasMonetaryCost();
+        DummyLocationProvider cachedAttributes = getCachedAttributes();
+        if (cachedAttributes != null) {
+            return cachedAttributes.hasMonetaryCost();
         } else {
             return false;
         }
     }
 
     public boolean supportsAltitude() {
-        if (mCachedAttributes != null) {
-            return mCachedAttributes.supportsAltitude();
+        DummyLocationProvider cachedAttributes = getCachedAttributes();
+        if (cachedAttributes != null) {
+            return cachedAttributes.supportsAltitude();
         } else {
             return false;
         }
     }
 
     public boolean supportsSpeed() {
-        if (mCachedAttributes != null) {
-            return mCachedAttributes.supportsSpeed();
+        DummyLocationProvider cachedAttributes = getCachedAttributes();
+        if (cachedAttributes != null) {
+            return cachedAttributes.supportsSpeed();
         } else {
             return false;
         }
     }
 
      public boolean supportsBearing() {
-        if (mCachedAttributes != null) {
-            return mCachedAttributes.supportsBearing();
+        DummyLocationProvider cachedAttributes = getCachedAttributes();
+        if (cachedAttributes != null) {
+            return cachedAttributes.supportsBearing();
         } else {
             return false;
         }
     }
 
     public int getPowerRequirement() {
-        if (mCachedAttributes != null) {
-            return mCachedAttributes.getPowerRequirement();
+        DummyLocationProvider cachedAttributes = getCachedAttributes();
+        if (cachedAttributes != null) {
+            return cachedAttributes.getPowerRequirement();
+        } else {
+            return -1;
+        }
+    }
+
+    public int getAccuracy() {
+        DummyLocationProvider cachedAttributes = getCachedAttributes();
+        if (cachedAttributes != null) {
+            return cachedAttributes.getAccuracy();
         } else {
             return -1;
         }
     }
 
     public boolean meetsCriteria(Criteria criteria) {
-       ILocationProvider provider;
-        synchronized (mServiceConnection) {
-            provider = mProvider;
-        }
-        if (provider != null) {
-            try {
-                return provider.meetsCriteria(criteria);
-            } catch (RemoteException e) {
+        synchronized (mMutex) {
+            ILocationProvider provider = mServiceConnection.getProvider();
+            if (provider != null) {
+                try {
+                    return provider.meetsCriteria(criteria);
+                } catch (RemoteException e) {
+                }
             }
         }
         // default implementation if we lost connection to the provider
@@ -246,50 +284,42 @@
         return true;
     }
 
-    public int getAccuracy() {
-        if (mCachedAttributes != null) {
-            return mCachedAttributes.getAccuracy();
-        } else {
-            return -1;
-        }
-    }
-
     public void enable() {
-        mEnabled = true;
-        ILocationProvider provider;
-        synchronized (mServiceConnection) {
-            provider = mProvider;
-        }
-        if (provider != null) {
-            try {
-                provider.enable();
-            } catch (RemoteException e) {
+        synchronized (mMutex) {
+            mEnabled = true;
+            ILocationProvider provider = mServiceConnection.getProvider();
+            if (provider != null) {
+                try {
+                    provider.enable();
+                } catch (RemoteException e) {
+                }
             }
         }
     }
 
     public void disable() {
-        mEnabled = false;
-        ILocationProvider provider;
-        synchronized (mServiceConnection) {
-            provider = mProvider;
-        }
-        if (provider != null) {
-            try {
-                provider.disable();
-            } catch (RemoteException e) {
+        synchronized (mMutex) {
+            mEnabled = false;
+            ILocationProvider provider = mServiceConnection.getProvider();
+            if (provider != null) {
+                try {
+                    provider.disable();
+                } catch (RemoteException e) {
+                }
             }
         }
     }
 
     public boolean isEnabled() {
-        return mEnabled;
+        synchronized (mMutex) {
+            return mEnabled;
+        }
     }
 
     public int getStatus(Bundle extras) {
         ILocationProvider provider;
-        synchronized (mServiceConnection) {
-            provider = mProvider;
+        synchronized (mMutex) {
+            provider = mServiceConnection.getProvider();
         }
         if (provider != null) {
             try {
@@ -301,9 +331,9 @@
     }
 
     public long getStatusUpdateTime() {
-         ILocationProvider provider;
-        synchronized (mServiceConnection) {
-            provider = mProvider;
+        ILocationProvider provider;
+        synchronized (mMutex) {
+            provider = mServiceConnection.getProvider();
         }
         if (provider != null) {
             try {
@@ -315,32 +345,39 @@
      }
 
     public String getInternalState() {
-        try {
-            return mProvider.getInternalState();
-        } catch (RemoteException e) {
-            Log.e(TAG, "getInternalState failed", e);
-            return null;
-        }
-    }
-
-    public boolean isLocationTracking() {
-        return mLocationTracking;
-    }
-
-    public void enableLocationTracking(boolean enable) {
-        mLocationTracking = enable;
-        if (!enable) {
-            mMinTime = -1;
-            mMinTimeSource.clear();
-        }
         ILocationProvider provider;
-        synchronized (mServiceConnection) {
-            provider = mProvider;
+        synchronized (mMutex) {
+            provider = mServiceConnection.getProvider();
         }
         if (provider != null) {
             try {
-                provider.enableLocationTracking(enable);
+                return provider.getInternalState();
             } catch (RemoteException e) {
+                Log.e(TAG, "getInternalState failed", e);
+            }
+        }
+        return null;
+    }
+
+    public boolean isLocationTracking() {
+        synchronized (mMutex) {
+            return mLocationTracking;
+        }
+    }
+
+    public void enableLocationTracking(boolean enable) {
+        synchronized (mMutex) {
+            mLocationTracking = enable;
+            if (!enable) {
+                mMinTime = -1;
+                mMinTimeSource.clear();
+            }
+            ILocationProvider provider = mServiceConnection.getProvider();
+            if (provider != null) {
+                try {
+                    provider.enableLocationTracking(enable);
+                } catch (RemoteException e) {
+                }
             }
         }
     }
@@ -350,88 +387,84 @@
     }
 
     public long getMinTime() {
-        return mMinTime;
+        synchronized (mMutex) {
+            return mMinTime;
+        }
     }
 
     public void setMinTime(long minTime, WorkSource ws) {
-        mMinTime = minTime;
-        mMinTimeSource.set(ws);
-        ILocationProvider provider;
-        synchronized (mServiceConnection) {
-            provider = mProvider;
-        }
-        if (provider != null) {
-            try {
-                provider.setMinTime(minTime, ws);
-            } catch (RemoteException e) {
+        synchronized (mMutex) {
+            mMinTime = minTime;
+            mMinTimeSource.set(ws);
+            ILocationProvider provider = mServiceConnection.getProvider();
+            if (provider != null) {
+                try {
+                    provider.setMinTime(minTime, ws);
+                } catch (RemoteException e) {
+                }
             }
         }
     }
 
     public void updateNetworkState(int state, NetworkInfo info) {
-        mNetworkState = state;
-        mNetworkInfo = info;
-        ILocationProvider provider;
-        synchronized (mServiceConnection) {
-            provider = mProvider;
-        }
-        if (provider != null) {
-            try {
-                provider.updateNetworkState(state, info);
-            } catch (RemoteException e) {
+        synchronized (mMutex) {
+            mNetworkState = state;
+            mNetworkInfo = info;
+            ILocationProvider provider = mServiceConnection.getProvider();
+            if (provider != null) {
+                try {
+                    provider.updateNetworkState(state, info);
+                } catch (RemoteException e) {
+                }
             }
         }
     }
 
     public void updateLocation(Location location) {
-        ILocationProvider provider;
-        synchronized (mServiceConnection) {
-            provider = mProvider;
-        }
-        if (provider != null) {
-            try {
-                provider.updateLocation(location);
-            } catch (RemoteException e) {
+        synchronized (mMutex) {
+            ILocationProvider provider = mServiceConnection.getProvider();
+            if (provider != null) {
+                try {
+                    provider.updateLocation(location);
+                } catch (RemoteException e) {
+                }
             }
         }
     }
 
     public boolean sendExtraCommand(String command, Bundle extras) {
-        ILocationProvider provider;
-        synchronized (mServiceConnection) {
-            provider = mProvider;
-        }
-        if (provider != null) {
-            try {
-                provider.sendExtraCommand(command, extras);
-            } catch (RemoteException e) {
+        synchronized (mMutex) {
+            ILocationProvider provider = mServiceConnection.getProvider();
+            if (provider != null) {
+                try {
+                    return provider.sendExtraCommand(command, extras);
+                } catch (RemoteException e) {
+                }
             }
         }
         return false;
     }
 
     public void addListener(int uid) {
-        ILocationProvider provider;
-        synchronized (mServiceConnection) {
-            provider = mProvider;
-        }
-        if (provider != null) {
-            try {
-                provider.addListener(uid);
-            } catch (RemoteException e) {
+        synchronized (mMutex) {
+            ILocationProvider provider = mServiceConnection.getProvider();
+            if (provider != null) {
+                try {
+                    provider.addListener(uid);
+                } catch (RemoteException e) {
+                }
             }
         }
     }
 
     public void removeListener(int uid) {
-        ILocationProvider provider;
-        synchronized (mServiceConnection) {
-            provider = mProvider;
-        }
-        if (provider != null) {
-            try {
-                provider.removeListener(uid);
-            } catch (RemoteException e) {
+        synchronized (mMutex) {
+            ILocationProvider provider = mServiceConnection.getProvider();
+            if (provider != null) {
+                try {
+                    provider.removeListener(uid);
+                } catch (RemoteException e) {
+                }
             }
         }
     }
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_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 8e7be44..1bd1874 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -50,7 +50,6 @@
     jmethodID notifyLidSwitchChanged;
     jmethodID notifyInputChannelBroken;
     jmethodID notifyANR;
-    jmethodID virtualKeyDownFeedback;
     jmethodID interceptKeyBeforeQueueing;
     jmethodID interceptKeyBeforeDispatching;
     jmethodID checkInjectEventsPermission;
@@ -182,11 +181,6 @@
 
     virtual bool getDisplayInfo(int32_t displayId,
             int32_t* width, int32_t* height, int32_t* orientation);
-    virtual int32_t interceptKey(nsecs_t when, int32_t deviceId,
-            bool down, int32_t keyCode, int32_t scanCode, uint32_t& policyFlags);
-    virtual int32_t interceptSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
-            uint32_t& policyFlags);
-    virtual int32_t interceptGeneric(nsecs_t when, uint32_t& policyFlags);
     virtual bool filterTouchEvents();
     virtual bool filterJumpyTouchEvents();
     virtual void getVirtualKeyDefinitions(const String8& deviceName,
@@ -197,6 +191,8 @@
 
     /* --- InputDispatcherPolicyInterface implementation --- */
 
+    virtual void notifySwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
+            uint32_t policyFlags);
     virtual void notifyConfigurationChanged(nsecs_t when);
     virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
             const sp<InputChannel>& inputChannel);
@@ -204,6 +200,10 @@
     virtual nsecs_t getKeyRepeatTimeout();
     virtual nsecs_t getKeyRepeatDelay();
     virtual int32_t getMaxEventsPerSecond();
+    virtual void interceptKeyBeforeQueueing(nsecs_t when, int32_t deviceId,
+            int32_t action, int32_t& flags, int32_t keyCode, int32_t scanCode,
+            uint32_t& policyFlags);
+    virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
     virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
             const KeyEvent* keyEvent, uint32_t policyFlags);
     virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType);
@@ -254,7 +254,6 @@
 
     static bool populateWindow(JNIEnv* env, jobject windowObj, InputWindow& outWindow);
 
-    static bool isPolicyKey(int32_t keyCode, bool isScreenOn);
     static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
 
     static inline JNIEnv* jniEnv() {
@@ -290,37 +289,6 @@
     dump.append("\n");
 }
 
-bool NativeInputManager::isPolicyKey(int32_t keyCode, bool isScreenOn) {
-    // Special keys that the WindowManagerPolicy might care about.
-    switch (keyCode) {
-    case AKEYCODE_VOLUME_UP:
-    case AKEYCODE_VOLUME_DOWN:
-    case AKEYCODE_ENDCALL:
-    case AKEYCODE_POWER:
-    case AKEYCODE_CALL:
-    case AKEYCODE_HOME:
-    case AKEYCODE_MENU:
-    case AKEYCODE_SEARCH:
-        // media keys
-    case AKEYCODE_HEADSETHOOK:
-    case AKEYCODE_MEDIA_PLAY_PAUSE:
-    case AKEYCODE_MEDIA_STOP:
-    case AKEYCODE_MEDIA_NEXT:
-    case AKEYCODE_MEDIA_PREVIOUS:
-    case AKEYCODE_MEDIA_REWIND:
-    case AKEYCODE_MEDIA_FAST_FORWARD:
-        // The policy always cares about these keys.
-        return true;
-    default:
-        // We need to pass all keys to the policy in the following cases:
-        // - screen is off
-        // - keyguard is visible
-        // - policy is performing key chording
-        //return ! isScreenOn || keyguardVisible || chording;
-        return true; // XXX stubbed out for now
-    }
-}
-
 bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
     if (env->ExceptionCheck()) {
         LOGE("An exception was thrown by callback '%s'.", methodName);
@@ -453,115 +421,6 @@
     return result;
 }
 
-bool NativeInputManager::isScreenOn() {
-    return android_server_PowerManagerService_isScreenOn();
-}
-
-bool NativeInputManager::isScreenBright() {
-    return android_server_PowerManagerService_isScreenBright();
-}
-
-int32_t NativeInputManager::interceptKey(nsecs_t when,
-        int32_t deviceId, bool down, int32_t keyCode, int32_t scanCode, uint32_t& policyFlags) {
-#if DEBUG_INPUT_READER_POLICY
-    LOGD("interceptKey - when=%lld, deviceId=%d, down=%d, keyCode=%d, scanCode=%d, "
-            "policyFlags=0x%x",
-            when, deviceId, down, keyCode, scanCode, policyFlags);
-#endif
-
-    if (down && (policyFlags & POLICY_FLAG_VIRTUAL)) {
-        JNIEnv* env = jniEnv();
-        env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.virtualKeyDownFeedback);
-        checkAndClearExceptionFromCallback(env, "virtualKeyDownFeedback");
-    }
-
-    const int32_t WM_ACTION_PASS_TO_USER = 1;
-    const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2;
-    const int32_t WM_ACTION_GO_TO_SLEEP = 4;
-
-    bool isScreenOn = this->isScreenOn();
-    bool isScreenBright = this->isScreenBright();
-
-    jint wmActions = 0;
-    if (isPolicyKey(keyCode, isScreenOn)) {
-        JNIEnv* env = jniEnv();
-
-        wmActions = env->CallIntMethod(mCallbacksObj,
-                gCallbacksClassInfo.interceptKeyBeforeQueueing,
-                when, keyCode, down, policyFlags, isScreenOn);
-        if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
-            wmActions = 0;
-        }
-    } else {
-        wmActions = WM_ACTION_PASS_TO_USER;
-    }
-
-    int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
-    if (! isScreenOn) {
-        // Key presses and releases wake the device.
-        policyFlags |= POLICY_FLAG_WOKE_HERE;
-    }
-
-    if (! isScreenBright) {
-        // Key presses and releases brighten the screen if dimmed.
-        policyFlags |= POLICY_FLAG_BRIGHT_HERE;
-    }
-
-    if (wmActions & WM_ACTION_GO_TO_SLEEP) {
-        android_server_PowerManagerService_goToSleep(when);
-    }
-
-    if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
-        android_server_PowerManagerService_userActivity(when, POWER_MANAGER_BUTTON_EVENT);
-    }
-
-    if (wmActions & WM_ACTION_PASS_TO_USER) {
-        actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
-    }
-
-    return actions;
-}
-
-int32_t NativeInputManager::interceptGeneric(nsecs_t when, uint32_t& policyFlags) {
-#if DEBUG_INPUT_READER_POLICY
-    LOGD("interceptGeneric - when=%lld, policyFlags=0x%x", when, policyFlags);
-#endif
-
-    int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
-    if (isScreenOn()) {
-        // Only dispatch events when the device is awake.
-        // Do not wake the device.
-        actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
-
-        if (! isScreenBright()) {
-            // Brighten the screen if dimmed.
-            policyFlags |= POLICY_FLAG_BRIGHT_HERE;
-        }
-    }
-
-    return actions;
-}
-
-int32_t NativeInputManager::interceptSwitch(nsecs_t when, int32_t switchCode,
-        int32_t switchValue, uint32_t& policyFlags) {
-#if DEBUG_INPUT_READER_POLICY
-    LOGD("interceptSwitch - when=%lld, switchCode=%d, switchValue=%d, policyFlags=0x%x",
-            when, switchCode, switchValue, policyFlags);
-#endif
-
-    JNIEnv* env = jniEnv();
-
-    switch (switchCode) {
-    case SW_LID:
-        env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyLidSwitchChanged,
-                when, switchValue == 0);
-        checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged");
-        break;
-    }
-
-    return InputReaderPolicyInterface::ACTION_NONE;
-}
-
 bool NativeInputManager::filterTouchEvents() {
     if (mFilterTouchEvents < 0) {
         JNIEnv* env = jniEnv();
@@ -691,6 +550,24 @@
     }
 }
 
+void NativeInputManager::notifySwitch(nsecs_t when, int32_t switchCode,
+        int32_t switchValue, uint32_t policyFlags) {
+#if DEBUG_INPUT_DISPATCHER_POLICY
+    LOGD("notifySwitch - when=%lld, switchCode=%d, switchValue=%d, policyFlags=0x%x",
+            when, switchCode, switchValue, policyFlags);
+#endif
+
+    JNIEnv* env = jniEnv();
+
+    switch (switchCode) {
+    case SW_LID:
+        env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyLidSwitchChanged,
+                when, switchValue == 0);
+        checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged");
+        break;
+    }
+}
+
 void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
 #if DEBUG_INPUT_DISPATCHER_POLICY
     LOGD("notifyConfigurationChanged - when=%lld", when);
@@ -943,26 +820,121 @@
     mInputManager->getDispatcher()->setInputDispatchMode(enabled, frozen);
 }
 
-bool NativeInputManager::interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
-        const KeyEvent* keyEvent, uint32_t policyFlags) {
-    bool isScreenOn = this->isScreenOn();
-    if (! isPolicyKey(keyEvent->getKeyCode(), isScreenOn)) {
-        return false;
+bool NativeInputManager::isScreenOn() {
+    return android_server_PowerManagerService_isScreenOn();
+}
+
+bool NativeInputManager::isScreenBright() {
+    return android_server_PowerManagerService_isScreenBright();
+}
+
+void NativeInputManager::interceptKeyBeforeQueueing(nsecs_t when,
+        int32_t deviceId, int32_t action, int32_t &flags,
+        int32_t keyCode, int32_t scanCode, uint32_t& policyFlags) {
+#if DEBUG_INPUT_DISPATCHER_POLICY
+    LOGD("interceptKeyBeforeQueueing - when=%lld, deviceId=%d, action=%d, flags=%d, "
+            "keyCode=%d, scanCode=%d, policyFlags=0x%x",
+            when, deviceId, action, flags, keyCode, scanCode, policyFlags);
+#endif
+
+    if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {
+        policyFlags |= POLICY_FLAG_VIRTUAL;
+        flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
     }
 
-    JNIEnv* env = jniEnv();
+    // Policy:
+    // - Ignore untrusted events and pass them along.
+    // - Ask the window manager what to do with normal events and trusted injected events.
+    // - For normal events wake and brighten the screen if currently off or dim.
+    if ((policyFlags & POLICY_FLAG_TRUSTED)) {
+        const int32_t WM_ACTION_PASS_TO_USER = 1;
+        const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2;
+        const int32_t WM_ACTION_GO_TO_SLEEP = 4;
 
-    // Note: inputChannel may be null.
-    jobject inputChannelObj = getInputChannelObjLocal(env, inputChannel);
-    jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
-            gCallbacksClassInfo.interceptKeyBeforeDispatching,
-            inputChannelObj, keyEvent->getAction(), keyEvent->getFlags(),
-            keyEvent->getKeyCode(), keyEvent->getMetaState(),
-            keyEvent->getRepeatCount(), policyFlags);
-    bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
+        bool isScreenOn = this->isScreenOn();
+        bool isScreenBright = this->isScreenBright();
 
-    env->DeleteLocalRef(inputChannelObj);
-    return consumed && ! error;
+        JNIEnv* env = jniEnv();
+        jint wmActions = env->CallIntMethod(mCallbacksObj,
+                gCallbacksClassInfo.interceptKeyBeforeQueueing,
+                when, keyCode, action == AKEY_EVENT_ACTION_DOWN, policyFlags, isScreenOn);
+        if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
+            wmActions = 0;
+        }
+
+        if (!(flags & POLICY_FLAG_INJECTED)) {
+            if (!isScreenOn) {
+                policyFlags |= POLICY_FLAG_WOKE_HERE;
+                flags |= AKEY_EVENT_FLAG_WOKE_HERE;
+            }
+
+            if (!isScreenBright) {
+                policyFlags |= POLICY_FLAG_BRIGHT_HERE;
+            }
+        }
+
+        if (wmActions & WM_ACTION_GO_TO_SLEEP) {
+            android_server_PowerManagerService_goToSleep(when);
+        }
+
+        if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
+            android_server_PowerManagerService_userActivity(when, POWER_MANAGER_BUTTON_EVENT);
+        }
+
+        if (wmActions & WM_ACTION_PASS_TO_USER) {
+            policyFlags |= POLICY_FLAG_PASS_TO_USER;
+        }
+    } else {
+        policyFlags |= POLICY_FLAG_PASS_TO_USER;
+    }
+}
+
+void NativeInputManager::interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
+#if DEBUG_INPUT_DISPATCHER_POLICY
+    LOGD("interceptGenericBeforeQueueing - when=%lld, policyFlags=0x%x", when, policyFlags);
+#endif
+
+    // Policy:
+    // - Ignore untrusted events and pass them along.
+    // - No special filtering for injected events required at this time.
+    // - Filter normal events based on screen state.
+    // - For normal events brighten (but do not wake) the screen if currently dim.
+    if ((policyFlags & POLICY_FLAG_TRUSTED) && !(policyFlags & POLICY_FLAG_INJECTED)) {
+        if (isScreenOn()) {
+            policyFlags |= POLICY_FLAG_PASS_TO_USER;
+
+            if (!isScreenBright()) {
+                policyFlags |= POLICY_FLAG_BRIGHT_HERE;
+            }
+        }
+    } else {
+        policyFlags |= POLICY_FLAG_PASS_TO_USER;
+    }
+}
+
+bool NativeInputManager::interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
+        const KeyEvent* keyEvent, uint32_t policyFlags) {
+    // Policy:
+    // - Ignore untrusted events and pass them along.
+    // - Filter normal events and trusted injected events through the window manager policy to
+    //   handle the HOME key and the like.
+    if (policyFlags & POLICY_FLAG_TRUSTED) {
+        JNIEnv* env = jniEnv();
+
+        // Note: inputChannel may be null.
+        jobject inputChannelObj = getInputChannelObjLocal(env, inputChannel);
+        jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
+                gCallbacksClassInfo.interceptKeyBeforeDispatching,
+                inputChannelObj, keyEvent->getAction(), keyEvent->getFlags(),
+                keyEvent->getKeyCode(), keyEvent->getMetaState(),
+                keyEvent->getRepeatCount(), policyFlags);
+        bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
+
+        env->DeleteLocalRef(inputChannelObj);
+        return consumed && ! error;
+    } else {
+        return false;
+    }
 }
 
 void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
@@ -1364,9 +1336,6 @@
     GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz,
             "notifyANR", "(Ljava/lang/Object;Landroid/view/InputChannel;)J");
 
-    GET_METHOD_ID(gCallbacksClassInfo.virtualKeyDownFeedback, gCallbacksClassInfo.clazz,
-            "virtualKeyDownFeedback", "()V");
-
     GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
             "interceptKeyBeforeQueueing", "(JIZIZ)I");
 
diff --git a/services/jni/com_android_server_PowerManagerService.cpp b/services/jni/com_android_server_PowerManagerService.cpp
index 146c177..705be60 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, jint mode) {
+    sp<ISurfaceComposer> s(ComposerService::getComposerService());
+    s->turnElectronBeamOff(mode);
+}
+
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod gPowerManagerServiceMethods[] = {
@@ -127,6 +138,8 @@
             (void*) android_server_PowerManagerService_nativeInit },
     { "nativeSetPowerState", "(ZZ)V",
             (void*) android_server_PowerManagerService_nativeSetPowerState },
+    { "nativeStartSurfaceFlingerAnimation", "(I)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 71c7aba..1d93f82 100755
--- a/services/jni/com_android_server_location_GpsLocationProvider.cpp
+++ b/services/jni/com_android_server_location_GpsLocationProvider.cpp
@@ -238,45 +238,57 @@
     return interface;
 }
 
-static const AGpsInterface* GetAGpsInterface()
-{
-    if (!sGpsInterface)
+static const GpsInterface* GetGpsInterface(JNIEnv* env, jobject obj) {
+    // this must be set before calling into the HAL library
+    if (!mCallbacksObj)
+        mCallbacksObj = env->NewGlobalRef(obj);
+
+    if (!sGpsInterface) {
         sGpsInterface = get_gps_interface();
-    if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)
+        if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0) {
+            sGpsInterface = NULL;
+            return NULL;
+        }
+    }
+    return sGpsInterface;
+}
+
+static const AGpsInterface* GetAGpsInterface(JNIEnv* env, jobject obj)
+{
+    const GpsInterface* interface = GetGpsInterface(env, obj);
+    if (!interface)
         return NULL;
 
     if (!sAGpsInterface) {
-        sAGpsInterface = (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
+        sAGpsInterface = (const AGpsInterface*)interface->get_extension(AGPS_INTERFACE);
         if (sAGpsInterface)
             sAGpsInterface->init(&sAGpsCallbacks);
     }
     return sAGpsInterface;
 }
 
-static const GpsNiInterface* GetNiInterface()
+static const GpsNiInterface* GetNiInterface(JNIEnv* env, jobject obj)
 {
-    if (!sGpsInterface)
-        sGpsInterface = get_gps_interface();
-    if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)
+    const GpsInterface* interface = GetGpsInterface(env, obj);
+    if (!interface)
         return NULL;
 
     if (!sGpsNiInterface) {
-       sGpsNiInterface = (const GpsNiInterface*)sGpsInterface->get_extension(GPS_NI_INTERFACE);
+       sGpsNiInterface = (const GpsNiInterface*)interface->get_extension(GPS_NI_INTERFACE);
         if (sGpsNiInterface)
            sGpsNiInterface->init(&sGpsNiCallbacks);
     }
     return sGpsNiInterface;
 }
 
-static const AGpsRilInterface* GetAGpsRilInterface()
+static const AGpsRilInterface* GetAGpsRilInterface(JNIEnv* env, jobject obj)
 {
-    if (!sGpsInterface)
-        sGpsInterface = get_gps_interface();
-    if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)
+    const GpsInterface* interface = GetGpsInterface(env, obj);
+    if (!interface)
         return NULL;
 
     if (!sAGpsRilInterface) {
-       sAGpsRilInterface = (const AGpsRilInterface*)sGpsInterface->get_extension(AGPS_RIL_INTERFACE);
+       sAGpsRilInterface = (const AGpsRilInterface*)interface->get_extension(AGPS_RIL_INTERFACE);
         if (sAGpsRilInterface)
             sAGpsRilInterface->init(&sAGpsRilCallbacks);
     }
@@ -297,53 +309,62 @@
 }
 
 static jboolean android_location_GpsLocationProvider_is_supported(JNIEnv* env, jclass clazz) {
-    if (!sGpsInterface)
-        sGpsInterface = get_gps_interface();
-    return (sGpsInterface != NULL);
+    return (sGpsInterface != NULL || get_gps_interface() != NULL);
 }
 
 static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject obj)
 {
-    // this must be set before calling into the HAL library
-    if (!mCallbacksObj)
-        mCallbacksObj = env->NewGlobalRef(obj);
-
-    if (!sGpsInterface)
-        sGpsInterface = get_gps_interface();
-    if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)
+    const GpsInterface* interface = GetGpsInterface(env, obj);
+    if (!interface)
         return false;
 
     if (!sGpsDebugInterface)
-       sGpsDebugInterface = (const GpsDebugInterface*)sGpsInterface->get_extension(GPS_DEBUG_INTERFACE);
+       sGpsDebugInterface = (const GpsDebugInterface*)interface->get_extension(GPS_DEBUG_INTERFACE);
 
     return true;
 }
 
 static void android_location_GpsLocationProvider_cleanup(JNIEnv* env, jobject obj)
 {
-    sGpsInterface->cleanup();
+    const GpsInterface* interface = GetGpsInterface(env, obj);
+    if (interface)
+        interface->cleanup();
 }
 
 static jboolean android_location_GpsLocationProvider_set_position_mode(JNIEnv* env, jobject obj,
         jint mode, jint recurrence, jint min_interval, jint preferred_accuracy, jint preferred_time)
 {
-    return (sGpsInterface->set_position_mode(mode, recurrence, min_interval, preferred_accuracy,
-            preferred_time) == 0);
+    const GpsInterface* interface = GetGpsInterface(env, obj);
+    if (interface)
+        return (interface->set_position_mode(mode, recurrence, min_interval, preferred_accuracy,
+                preferred_time) == 0);
+    else
+        return false;
 }
 
 static jboolean android_location_GpsLocationProvider_start(JNIEnv* env, jobject obj)
 {
-    return (sGpsInterface->start() == 0);
+    const GpsInterface* interface = GetGpsInterface(env, obj);
+    if (interface)
+        return (interface->start() == 0);
+    else
+        return false;
 }
 
 static jboolean android_location_GpsLocationProvider_stop(JNIEnv* env, jobject obj)
 {
-    return (sGpsInterface->stop() == 0);
+    const GpsInterface* interface = GetGpsInterface(env, obj);
+    if (interface)
+        return (interface->stop() == 0);
+    else
+        return false;
 }
 
 static void android_location_GpsLocationProvider_delete_aiding_data(JNIEnv* env, jobject obj, jint flags)
 {
-    sGpsInterface->delete_aiding_data(flags);
+    const GpsInterface* interface = GetGpsInterface(env, obj);
+    if (interface)
+        interface->delete_aiding_data(flags);
 }
 
 static jint android_location_GpsLocationProvider_read_sv_status(JNIEnv* env, jobject obj,
@@ -381,7 +402,7 @@
         jobject obj, jint type, jint mcc, jint mnc, jint lac, jint cid)
 {
     AGpsRefLocation location;
-    const AGpsRilInterface* interface = GetAGpsRilInterface();
+    const AGpsRilInterface* interface = GetAGpsRilInterface(env, obj);
     if (!interface) {
         LOGE("no AGPS RIL interface in agps_set_reference_location_cellid");
         return;
@@ -408,7 +429,7 @@
         jobject obj, jbyteArray ni_msg, jint size)
 {
     size_t sz;
-    const AGpsRilInterface* interface = GetAGpsRilInterface();
+    const AGpsRilInterface* interface = GetAGpsRilInterface(env, obj);
     if (!interface) {
         LOGE("no AGPS RIL interface in send_ni_message");
         return;
@@ -424,7 +445,7 @@
 static void android_location_GpsLocationProvider_agps_set_id(JNIEnv *env,
         jobject obj, jint type, jstring  setid_string)
 {
-    const AGpsRilInterface* interface = GetAGpsRilInterface();
+    const AGpsRilInterface* interface = GetAGpsRilInterface(env, obj);
     if (!interface) {
         LOGE("no AGPS RIL interface in agps_set_id");
         return;
@@ -451,19 +472,26 @@
 static void android_location_GpsLocationProvider_inject_time(JNIEnv* env, jobject obj,
         jlong time, jlong timeReference, jint uncertainty)
 {
-    sGpsInterface->inject_time(time, timeReference, uncertainty);
+    const GpsInterface* interface = GetGpsInterface(env, obj);
+    if (interface)
+        interface->inject_time(time, timeReference, uncertainty);
 }
 
 static void android_location_GpsLocationProvider_inject_location(JNIEnv* env, jobject obj,
         jdouble latitude, jdouble longitude, jfloat accuracy)
 {
-    sGpsInterface->inject_location(latitude, longitude, accuracy);
+    const GpsInterface* interface = GetGpsInterface(env, obj);
+    if (interface)
+        interface->inject_location(latitude, longitude, accuracy);
 }
 
 static jboolean android_location_GpsLocationProvider_supports_xtra(JNIEnv* env, jobject obj)
 {
     if (!sGpsXtraInterface) {
-        sGpsXtraInterface = (const GpsXtraInterface*)sGpsInterface->get_extension(GPS_XTRA_INTERFACE);
+        const GpsInterface* interface = GetGpsInterface(env, obj);
+        if (!interface)
+            return false;
+        sGpsXtraInterface = (const GpsXtraInterface*)interface->get_extension(GPS_XTRA_INTERFACE);
         if (sGpsXtraInterface) {
             int result = sGpsXtraInterface->init(&sGpsXtraCallbacks);
             if (result) {
@@ -485,7 +513,7 @@
 
 static void android_location_GpsLocationProvider_agps_data_conn_open(JNIEnv* env, jobject obj, jstring apn)
 {
-    const AGpsInterface* interface = GetAGpsInterface();
+    const AGpsInterface* interface = GetAGpsInterface(env, obj);
     if (!interface) {
         LOGE("no AGPS interface in agps_data_conn_open");
         return;
@@ -501,7 +529,7 @@
 
 static void android_location_GpsLocationProvider_agps_data_conn_closed(JNIEnv* env, jobject obj)
 {
-    const AGpsInterface* interface = GetAGpsInterface();
+    const AGpsInterface* interface = GetAGpsInterface(env, obj);
     if (!interface) {
         LOGE("no AGPS interface in agps_data_conn_open");
         return;
@@ -511,7 +539,7 @@
 
 static void android_location_GpsLocationProvider_agps_data_conn_failed(JNIEnv* env, jobject obj)
 {
-    const AGpsInterface* interface = GetAGpsInterface();
+    const AGpsInterface* interface = GetAGpsInterface(env, obj);
     if (!interface) {
         LOGE("no AGPS interface in agps_data_conn_open");
         return;
@@ -522,7 +550,7 @@
 static void android_location_GpsLocationProvider_set_agps_server(JNIEnv* env, jobject obj,
         jint type, jstring hostname, jint port)
 {
-    const AGpsInterface* interface = GetAGpsInterface();
+    const AGpsInterface* interface = GetAGpsInterface(env, obj);
     if (!interface) {
         LOGE("no AGPS interface in agps_data_conn_open");
         return;
@@ -535,7 +563,7 @@
 static void android_location_GpsLocationProvider_send_ni_response(JNIEnv* env, jobject obj,
       jint notifId, jint response)
 {
-    const GpsNiInterface* interface = GetNiInterface();
+    const GpsNiInterface* interface = GetNiInterface(env, obj);
     if (!interface) {
         LOGE("no NI interface in send_ni_response");
         return;
@@ -558,6 +586,21 @@
     return result;
 }
 
+static void android_location_GpsLocationProvider_update_network_state(JNIEnv* env, jobject obj,
+        jboolean connected, int type, jboolean roaming, jstring extraInfo)
+{
+    const AGpsRilInterface* interface = GetAGpsRilInterface(env, obj);
+    if (interface && interface->update_network_state) {
+        if (extraInfo) {
+            const char *extraInfoStr = env->GetStringUTFChars(extraInfo, NULL);
+            interface->update_network_state(connected, type, roaming, extraInfoStr);
+            env->ReleaseStringUTFChars(extraInfo, extraInfoStr);
+        } else {
+            interface->update_network_state(connected, type, roaming, NULL);
+        }
+    }
+}
+
 static JNINativeMethod sMethods[] = {
      /* name, signature, funcPtr */
     {"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native},
@@ -583,6 +626,7 @@
     {"native_send_ni_response", "(II)V", (void*)android_location_GpsLocationProvider_send_ni_response},
     {"native_agps_ni_message", "([BI)V", (void *)android_location_GpsLocationProvider_agps_send_ni_message},
     {"native_get_internal_state", "()Ljava/lang/String;", (void*)android_location_GpsLocationProvider_get_internal_state},
+    {"native_update_network_state", "(ZIZLjava/lang/String;)V", (void*)android_location_GpsLocationProvider_update_network_state },
 };
 
 int register_android_server_location_GpsLocationProvider(JNIEnv* env)
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/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index 758b408..069b85a 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -444,11 +444,11 @@
     }
     if (transform & HAL_TRANSFORM_FLIP_V) {
         swap(vLT, vLB);
-        swap(vRB, vRT);
+        swap(vRT, vRB);
     }
     if (transform & HAL_TRANSFORM_FLIP_H) {
-        swap(vLT, vRB);
-        swap(vLB, vRT);
+        swap(vLT, vRT);
+        swap(vLB, vRB);
     }
 
     TexCoords texCoords[4];
diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp
index d668e88..aebe1b8 100644
--- a/services/surfaceflinger/MessageQueue.cpp
+++ b/services/surfaceflinger/MessageQueue.cpp
@@ -72,14 +72,6 @@
             nsecs_t now = systemTime();
             nsecs_t nextEventTime = -1;
 
-            // invalidate messages are always handled first
-            if (mInvalidate) {
-                mInvalidate = false;
-                mInvalidateMessage->when = now;
-                result = mInvalidateMessage;
-                break;
-            }
-
             LIST::iterator cur(mMessages.begin());
             if (cur != mMessages.end()) {
                 result = *cur;
@@ -91,17 +83,29 @@
                     mMessages.remove(cur);
                     break;
                 }
-                if (timeout>=0 && timeoutTime < now) {
-                    // we timed-out, return a NULL message
-                    result = 0;
-                    break;
-                }
                 nextEventTime = result->when;
                 result = 0;
             }
 
-            if (timeout >= 0 && nextEventTime > 0) {
-                if (nextEventTime > timeoutTime) {
+            // see if we have an invalidate message
+            if (mInvalidate) {
+                mInvalidate = false;
+                mInvalidateMessage->when = now;
+                result = mInvalidateMessage;
+                break;
+            }
+
+            if (timeout >= 0) {
+                if (timeoutTime < now) {
+                    // we timed-out, return a NULL message
+                    result = 0;
+                    break;
+                }
+                if (nextEventTime > 0) {
+                    if (nextEventTime > timeoutTime) {
+                        nextEventTime = timeoutTime;
+                    }
+                } else {
                     nextEventTime = timeoutTime;
                 }
             }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e5e87c6..a9b3965 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -80,6 +80,7 @@
         mVisibleRegionsDirty(false),
         mDeferReleaseConsole(false),
         mFreezeDisplay(false),
+        mElectronBeamAnimationMode(0),
         mFreezeCount(0),
         mFreezeDisplayTime(0),
         mDebugRegion(0),
@@ -421,16 +422,19 @@
     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
+        SurfaceFlinger::turnElectronBeamOn(mElectronBeamAnimationMode);
     }
 
-    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 +1460,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 +1552,457 @@
 
 // ---------------------------------------------------------------------------
 
+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) {
+        while ( 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 12 frames
+    int nbFrames = 8;
+    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);
+    }
+
+    nbFrames = 4;
+    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(int32_t mode)
+{
+    DisplayHardware& hw(graphicPlane(0).editDisplayHardware());
+    if (!hw.canDraw()) {
+        // we're already off
+        return NO_ERROR;
+    }
+    if (mode & ISurfaceComposer::eElectronBeamAnimationOff) {
+        electronBeamOffAnimationImplLocked();
+    }
+
+    // always clear the whole screen at the end of the animation
+    glClearColor(0,0,0,1);
+    glDisable(GL_SCISSOR_TEST);
+    glClear(GL_COLOR_BUFFER_BIT);
+    glEnable(GL_SCISSOR_TEST);
+    hw.flip( Region(hw.bounds()) );
+
+    hw.setCanDraw(false);
+    return NO_ERROR;
+}
+
+status_t SurfaceFlinger::turnElectronBeamOff(int32_t mode)
+{
+    class MessageTurnElectronBeamOff : public MessageBase {
+        SurfaceFlinger* flinger;
+        int32_t mode;
+        status_t result;
+    public:
+        MessageTurnElectronBeamOff(SurfaceFlinger* flinger, int32_t mode)
+            : flinger(flinger), mode(mode), result(PERMISSION_DENIED) {
+        }
+        status_t getResult() const {
+            return result;
+        }
+        virtual bool handler() {
+            Mutex::Autolock _l(flinger->mStateLock);
+            result = flinger->turnElectronBeamOffImplLocked(mode);
+            return true;
+        }
+    };
+
+    sp<MessageBase> msg = new MessageTurnElectronBeamOff(this, mode);
+    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
+        mElectronBeamAnimationMode = mode;
+    }
+    return res;
+}
+
+// ---------------------------------------------------------------------------
+
+status_t SurfaceFlinger::turnElectronBeamOnImplLocked(int32_t mode)
+{
+    DisplayHardware& hw(graphicPlane(0).editDisplayHardware());
+    if (hw.canDraw()) {
+        // we're already on
+        return NO_ERROR;
+    }
+    if (mode & ISurfaceComposer::eElectronBeamAnimationOn) {
+        electronBeamOnAnimationImplLocked();
+    }
+    hw.setCanDraw(true);
+
+    // make sure to redraw the whole screen when the animation is done
+    mDirtyRegion.set(hw.bounds());
+    signalEvent();
+
+    return NO_ERROR;
+}
+
+status_t SurfaceFlinger::turnElectronBeamOn(int32_t mode)
+{
+    class MessageTurnElectronBeamOn : public MessageBase {
+        SurfaceFlinger* flinger;
+        int32_t mode;
+        status_t result;
+    public:
+        MessageTurnElectronBeamOn(SurfaceFlinger* flinger, int32_t mode)
+            : flinger(flinger), mode(mode), result(PERMISSION_DENIED) {
+        }
+        status_t getResult() const {
+            return result;
+        }
+        virtual bool handler() {
+            Mutex::Autolock _l(flinger->mStateLock);
+            result = flinger->turnElectronBeamOnImplLocked(mode);
+            return true;
+        }
+    };
+
+    postMessageAsync( new MessageTurnElectronBeamOn(this, mode) );
+    return NO_ERROR;
+}
+
+// ---------------------------------------------------------------------------
+
 status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy,
         sp<IMemoryHeap>* heap,
         uint32_t* w, uint32_t* h, PixelFormat* f,
@@ -2005,6 +2462,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..4262175 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(int32_t mode);
+            status_t turnElectronBeamOnImplLocked(int32_t mode);
+            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;
+                int32_t                     mElectronBeamAnimationMode;
                 int32_t                     mFreezeCount;
                 nsecs_t                     mFreezeDisplayTime;
                 Vector< sp<LayerBase> >     mVisibleLayersSortedByZ;
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index b4a3c95..5542c42 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1649,12 +1649,19 @@
     }
 
     /**
+     * Determines if the specified number is actually a URI
+     * (i.e. a SIP address) rather than a regular PSTN phone number,
+     * based on whether or not the number contains an "@" character.
+     *
      * @hide
      * @param number
      * @return true if number contains @
      */
     public static boolean isUriNumber(String number) {
-        return number != null && number.contains("@");
+        // Note we allow either "@" or "%40" to indicate a URI, in case
+        // the passed-in string is URI-escaped.  (Neither "@" nor "%40"
+        // will ever be found in a legal PSTN number.)
+        return number != null && (number.contains("@") || number.contains("%40"));
     }
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/CallManager.java b/telephony/java/com/android/internal/telephony/CallManager.java
index 7a026fa..3f0ec0a 100644
--- a/telephony/java/com/android/internal/telephony/CallManager.java
+++ b/telephony/java/com/android/internal/telephony/CallManager.java
@@ -56,7 +56,7 @@
 
     private static final String LOG_TAG ="CallManager";
     private static final boolean DBG = true;
-    private static final boolean VDBG = true;
+    private static final boolean VDBG = false;
 
     private static final int EVENT_DISCONNECT = 100;
     private static final int EVENT_PRECISE_CALL_STATE_CHANGED = 101;
@@ -292,7 +292,7 @@
 
         if (basePhone != null && !mPhones.contains(basePhone)) {
 
-            if (VDBG) {
+            if (DBG) {
                 Log.d(LOG_TAG, "registerPhone(" +
                         phone.getPhoneName() + " " + phone + ")");
             }
@@ -319,7 +319,7 @@
 
         if (basePhone != null && mPhones.contains(basePhone)) {
 
-            if (VDBG) {
+            if (DBG) {
                 Log.d(LOG_TAG, "unregisterPhone(" +
                         phone.getPhoneName() + " " + phone + ")");
             }
@@ -487,7 +487,7 @@
             boolean hasBgCall = ! (activePhone.getBackgroundCall().isIdle());
             boolean sameChannel = (activePhone == ringingPhone);
 
-            if (DBG) {
+            if (VDBG) {
                 Log.d(LOG_TAG, "hasBgCall: "+ hasBgCall + "sameChannel:" + sameChannel);
             }
 
@@ -925,7 +925,7 @@
         }
 
         if (hasActiveFgCall()) {
-            getActiveFgCall().getPhone().sendDtmf(c);
+            getActiveFgCall().getPhone().startDtmf(c);
             result = true;
         }
 
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/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java b/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java
index dc4b27b..d546a08 100644
--- a/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java
@@ -56,8 +56,8 @@
     private DisconnectCause mCause = DisconnectCause.NOT_DISCONNECTED;
     private PostDialState postDialState = PostDialState.NOT_STARTED;
 
-    SipConnectionBase(String calleeSipUri) {
-        dialString = calleeSipUri;
+    SipConnectionBase(String dialString) {
+        this.dialString = dialString;
 
         postDialString = PhoneNumberUtils.extractPostDialPortion(dialString);
 
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhone.java b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
index 02af0ed..1968552 100755
--- a/telephony/java/com/android/internal/telephony/sip/SipPhone.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.net.rtp.AudioGroup;
-import android.net.rtp.AudioStream;
 import android.net.sip.SipAudioCall;
 import android.net.sip.SipErrorCode;
 import android.net.sip.SipException;
@@ -29,11 +28,9 @@
 import android.os.Message;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.ServiceState;
-import android.text.TextUtils;
 import android.util.Log;
 
 import com.android.internal.telephony.Call;
-import com.android.internal.telephony.CallerInfo;
 import com.android.internal.telephony.CallStateException;
 import com.android.internal.telephony.Connection;
 import com.android.internal.telephony.Phone;
@@ -382,40 +379,6 @@
             }
         }
 
-        private CallerInfo createCallerInfo(String number, SipProfile callee) {
-            SipProfile p = callee;
-            String name = p.getDisplayName();
-            if (TextUtils.isEmpty(name)) name = p.getUserName();
-            CallerInfo info = new CallerInfo();
-            info.name = name;
-            info.phoneNumber = number;
-            if (DEBUG) {
-                Log.d(LOG_TAG, "create caller info from scratch:");
-                Log.d(LOG_TAG, "     name: " + info.name);
-                Log.d(LOG_TAG, "     numb: " + info.phoneNumber);
-            }
-            return info;
-        }
-
-        // from contacts
-        private CallerInfo findCallerInfo(String number) {
-            CallerInfo info = CallerInfo.getCallerInfo(mContext, number);
-            if ((info == null) || (info.name == null)) return null;
-            if (DEBUG) {
-                Log.d(LOG_TAG, "got caller info from contact:");
-                Log.d(LOG_TAG, "     name: " + info.name);
-                Log.d(LOG_TAG, "     numb: " + info.phoneNumber);
-                Log.d(LOG_TAG, "     pres: " + info.numberPresentation);
-            }
-            return info;
-        }
-
-        private CallerInfo getCallerInfo(String number, SipProfile callee) {
-            CallerInfo info = findCallerInfo(number);
-            if (info == null) info = createCallerInfo(number, callee);
-            return info;
-        }
-
         Connection dial(String originalNumber) throws SipException {
             String calleeSipUri = originalNumber;
             if (!calleeSipUri.contains("@")) {
@@ -424,8 +387,8 @@
             try {
                 SipProfile callee =
                         new SipProfile.Builder(calleeSipUri).build();
-                CallerInfo info = getCallerInfo(originalNumber, callee);
-                SipConnection c = new SipConnection(this, callee, info);
+                SipConnection c = new SipConnection(this, callee,
+                        originalNumber);
                 connections.add(c);
                 c.dial();
                 setState(Call.State.DIALING);
@@ -461,10 +424,7 @@
 
         void initIncomingCall(SipAudioCall sipAudioCall, boolean makeCallWait) {
             SipProfile callee = sipAudioCall.getPeerProfile();
-            CallerInfo info = findCallerInfo(getUriString(callee));
-            if (info == null) info = findCallerInfo(callee.getUserName());
-            if (info == null) info = findCallerInfo(callee.getDisplayName());
-            SipConnection c = new SipConnection(this, callee, info);
+            SipConnection c = new SipConnection(this, callee);
             connections.add(c);
 
             Call.State newState = makeCallWait ? State.WAITING : State.INCOMING;
@@ -619,6 +579,7 @@
         private SipAudioCall mSipAudioCall;
         private Call.State mState = Call.State.IDLE;
         private SipProfile mPeer;
+        private String mOriginalNumber; // may be a PSTN number
         private boolean mIncoming = false;
 
         private SipAudioCallAdapter mAdapter = new SipAudioCallAdapter() {
@@ -701,11 +662,15 @@
         };
 
         public SipConnection(SipCall owner, SipProfile callee,
-                CallerInfo info) {
-            super(getUriString(callee));
+                String originalNumber) {
+            super(originalNumber);
             mOwner = owner;
             mPeer = callee;
-            setUserData(info);
+            mOriginalNumber = originalNumber;
+        }
+
+        public SipConnection(SipCall owner, SipProfile callee) {
+            this(owner, callee, getUriString(callee));
         }
 
         void initIncomingCall(SipAudioCall sipAudioCall, Call.State newState) {
@@ -778,7 +743,10 @@
 
         @Override
         public String getAddress() {
-            return getUriString(mPeer);
+            // Phone app uses this to query caller ID. Return the original dial
+            // number (which may be a PSTN number) instead of the peer's SIP
+            // URI.
+            return mOriginalNumber;
         }
 
         @Override
diff --git a/telephony/mockril/Android.mk b/telephony/mockril/Android.mk
new file mode 100644
index 0000000..7c39cb1
--- /dev/null
+++ b/telephony/mockril/Android.mk
@@ -0,0 +1,31 @@
+#
+# 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.
+#
+#
+
+LOCAL_PATH:=$(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := core framework
+
+LOCAL_STATIC_JAVA_LIBRARIES := librilproto-java
+
+LOCAL_MODULE_TAGS := debug
+LOCAL_MODULE := mockrilcontroller
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/telephony/mockril/src/com/android/internal/telephony/mockril/MockRilController.java b/telephony/mockril/src/com/android/internal/telephony/mockril/MockRilController.java
new file mode 100644
index 0000000..99f0abe
--- /dev/null
+++ b/telephony/mockril/src/com/android/internal/telephony/mockril/MockRilController.java
@@ -0,0 +1,218 @@
+/*
+ * 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.android.internal.telephony.mockril;
+
+import android.os.Bundle;
+import android.util.Log;
+import android.telephony.PhoneNumberUtils;
+
+import com.android.internal.communication.MsgHeader;
+import com.android.internal.communication.Msg;
+import com.android.internal.telephony.RilChannel;
+import com.android.internal.telephony.ril_proto.RilCtrlCmds;
+import com.android.internal.telephony.ril_proto.RilCmds;
+import com.google.protobuf.micro.MessageMicro;
+
+import java.io.IOException;
+
+/**
+ * Contain a list of commands to control Mock RIL. Before using these commands the devices
+ * needs to be set with Mock RIL. Refer to hardware/ril/mockril/README.txt for details.
+ *
+ */
+public class MockRilController {
+    private static final String TAG = "MockRILController";
+    private RilChannel mRilChannel = null;
+    private Msg mMessage = null;
+
+    public MockRilController() throws IOException {
+        mRilChannel = RilChannel.makeRilChannel();
+    }
+
+    /**
+     * Close the channel after the communication is done.
+     * This method has to be called after the test is finished.
+     */
+    public void closeChannel() {
+        mRilChannel.close();
+    }
+
+    /**
+     * Send commands and return true on success
+     * @param cmd for MsgHeader
+     * @param token for MsgHeader
+     * @param status for MsgHeader
+     * @param pbData for Msg data
+     * @return true if command is sent successfully, false if it fails
+     */
+    private boolean sendCtrlCommand(int cmd, long token, int status, MessageMicro pbData) {
+        try {
+            Msg.send(mRilChannel, cmd, token, status, pbData);
+        } catch (IOException e) {
+            Log.v(TAG, "send command : %d failed: " + e.getStackTrace());
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Get control response
+     * @return Msg if response is received, else return null.
+     */
+    private Msg getCtrlResponse() {
+        Msg response = null;
+        try {
+            response = Msg.recv(mRilChannel);
+        } catch (IOException e) {
+            Log.v(TAG, "receive response for getRadioState() error: " + e.getStackTrace());
+            return null;
+        }
+        return response;
+    }
+
+    /**
+     * @return the radio state if it is valid, otherwise return -1
+     */
+    public int getRadioState() {
+        if (!sendCtrlCommand(RilCtrlCmds.CTRL_CMD_GET_RADIO_STATE, 0, 0, null)) {
+            return -1;
+        }
+        Msg response = getCtrlResponse();
+        if (response == null) {
+            Log.v(TAG, "failed to get response");
+            return -1;
+        }
+        response.printHeader(TAG);
+        RilCtrlCmds.CtrlRspRadioState resp =
+            response.getDataAs(RilCtrlCmds.CtrlRspRadioState.class);
+        int state = resp.getState();
+        if ((state >= RilCmds.RADIOSTATE_OFF) && (state <= RilCmds.RADIOSTATE_NV_READY))
+            return state;
+        else
+            return -1;
+    }
+
+    /**
+     * Set the radio state of mock ril to the given state
+     * @param state for given radio state
+     * @return true if the state is set successful, false if it fails
+     */
+    public boolean setRadioState(int state) {
+        RilCtrlCmds.CtrlReqRadioState req = new RilCtrlCmds.CtrlReqRadioState();
+        if (state < 0 || state > RilCmds.RADIOSTATE_NV_READY) {
+            Log.v(TAG, "the give radio state is not valid.");
+            return false;
+        }
+        req.setState(state);
+        if (!sendCtrlCommand(RilCtrlCmds.CTRL_CMD_SET_RADIO_STATE, 0, 0, req)) {
+            Log.v(TAG, "send set radio state request failed.");
+            return false;
+        }
+        Msg response = getCtrlResponse();
+        if (response == null) {
+            Log.v(TAG, "failed to get response for setRadioState");
+            return false;
+        }
+        response.printHeader(TAG);
+        RilCtrlCmds.CtrlRspRadioState resp =
+            response.getDataAs(RilCtrlCmds.CtrlRspRadioState.class);
+        int curstate = resp.getState();
+        return curstate == state;
+    }
+
+    /**
+     * Start an incoming call for the given phone number
+     *
+     * @param phoneNumber is the number to show as incoming call
+     * @return true if the incoming call is started successfully, false if it fails.
+     */
+    public boolean startIncomingCall(String phoneNumber) {
+        RilCtrlCmds.CtrlReqSetMTCall req = new RilCtrlCmds.CtrlReqSetMTCall();
+
+        req.setPhoneNumber(phoneNumber);
+        if (!sendCtrlCommand(RilCtrlCmds.CTRL_CMD_SET_MT_CALL, 0, 0, req)) {
+            Log.v(TAG, "send CMD_SET_MT_CALL request failed");
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Hang up a connection remotelly for the given call fail cause
+     *
+     * @param connectionID is the connection to be hung up
+     * @param failCause is the call fail cause defined in ril.h
+     * @return true if the hangup is successful, false if it fails
+     */
+    public boolean hangupRemote(int connectionId, int failCause) {
+        RilCtrlCmds.CtrlHangupConnRemote req = new RilCtrlCmds.CtrlHangupConnRemote();
+        req.setConnectionId(connectionId);
+        req.setCallFailCause(failCause);
+
+        if (!sendCtrlCommand(RilCtrlCmds.CTRL_CMD_HANGUP_CONN_REMOTE, 0, 0, req)) {
+            Log.v(TAG, "send CTRL_CMD_HANGUP_CONN_REMOTE request failed");
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Set call transition flag to the Mock Ril
+     *
+     * @param flag is a boolean value for the call transiton flag
+     *             true: call transition: dialing->alert, alert->active is controlled
+     *             false: call transition is automatically handled by Mock Ril
+     * @return true if the request is successful, false if it failed to set the flag
+     */
+    public boolean setCallTransitionFlag(boolean flag) {
+        RilCtrlCmds.CtrlSetCallTransitionFlag req = new RilCtrlCmds.CtrlSetCallTransitionFlag();
+
+        req.setFlag(flag);
+
+        if (!sendCtrlCommand(RilCtrlCmds.CTRL_CMD_SET_CALL_TRANSITION_FLAG, 0, 0, req)) {
+            Log.v(TAG, "send CTRL_CMD_SET_CALL_TRANSITION_FLAG request failed");
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Set the dialing call to alert if the call transition flag is true
+     *
+     * @return true if the call transition is successful, false if it fails
+     */
+    public boolean setDialCallToAlert() {
+        if (!sendCtrlCommand(RilCtrlCmds.CTRL_CMD_SET_CALL_ALERT, 0, 0, null)) {
+            Log.v(TAG, "send CTRL_CMD_SET_CALL_ALERT request failed");
+            return false;
+        }
+        return true;
+   }
+
+   /**
+    * Set the alert call to active if the call transition flag is true
+    *
+    * @return true if the call transition is successful, false if it fails
+    */
+   public boolean setAlertCallToActive() {
+        if (!sendCtrlCommand(RilCtrlCmds.CTRL_CMD_SET_CALL_ACTIVE, 0, 0, null)) {
+            Log.v(TAG, "send CTRL_CMD_SET_CALL_ACTIVE request failed");
+            return false;
+        }
+        return true;
+   }
+}
diff --git a/telephony/tests/telephonytests/Android.mk b/telephony/tests/telephonytests/Android.mk
index 45e265a..98e4403 100644
--- a/telephony/tests/telephonytests/Android.mk
+++ b/telephony/tests/telephonytests/Android.mk
@@ -5,6 +5,8 @@
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
+LOCAL_STATIC_JAVA_LIBRARIES := librilproto-java
+
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
 LOCAL_PACKAGE_NAME := FrameworksTelephonyTests
diff --git a/telephony/tests/telephonytests/AndroidManifest.xml b/telephony/tests/telephonytests/AndroidManifest.xml
index 6a97423..ba1d957 100644
--- a/telephony/tests/telephonytests/AndroidManifest.xml
+++ b/telephony/tests/telephonytests/AndroidManifest.xml
@@ -32,6 +32,13 @@
         android:targetPackage="com.android.frameworks.telephonytests"
         android:label="Frameworks Telephony Tests">
     </instrumentation>
+
+    <instrumentation android:name=".TelephonyMockRilTestRunner"
+        android:targetPackage="com.android.frameworks.telephonytests"
+        android:label="Test Runner for Mock Ril Tests"
+    />
+
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+    <uses-permission android:name="android.permission.INTERNET" />
 
 </manifest>
diff --git a/telephony/tests/telephonytests/src/com/android/frameworks/telephonytests/TelephonyMockRilTestRunner.java b/telephony/tests/telephonytests/src/com/android/frameworks/telephonytests/TelephonyMockRilTestRunner.java
new file mode 100644
index 0000000..9192f57
--- /dev/null
+++ b/telephony/tests/telephonytests/src/com/android/frameworks/telephonytests/TelephonyMockRilTestRunner.java
@@ -0,0 +1,93 @@
+/*
+ * 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.android.frameworks.telephonytests;
+
+import android.os.Bundle;
+
+import android.test.InstrumentationTestRunner;
+import android.test.InstrumentationTestSuite;
+import android.util.Log;
+
+import java.io.IOException;
+
+import com.android.internal.telephony.RilChannel;
+import com.android.internal.telephony.mockril.MockRilTest;
+
+import junit.framework.TestSuite;
+
+public class TelephonyMockRilTestRunner extends InstrumentationTestRunner {
+
+    public RilChannel mMockRilChannel;
+
+    @Override
+    public TestSuite getAllTests() {
+        log("getAllTests E");
+        TestSuite suite = new InstrumentationTestSuite(this);
+        suite.addTestSuite(MockRilTest.class);
+        log("getAllTests X");
+        return suite;
+    }
+
+    @Override
+    public ClassLoader getLoader() {
+        log("getLoader EX");
+        return TelephonyMockRilTestRunner.class.getClassLoader();
+    }
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        log("onCreate E");
+        try {
+            mMockRilChannel = RilChannel.makeRilChannel();
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        log("onCreate X");
+
+        super.onCreate(icicle);
+    }
+
+    @Override
+    public void onDestroy() {
+        // I've not seen this called
+        log("onDestroy EX");
+        super.onDestroy();
+    }
+
+    @Override
+    public void onStart() {
+        // Called when the instrumentation thread is started.
+        // At the moment we don't need the thread so return
+        // which will shut down this unused thread.
+        log("onStart EX");
+        super.onStart();
+    }
+
+    @Override
+    public void finish(int resultCode, Bundle results) {
+        // Called when complete so I ask the mMockRilChannel to quit.
+        log("finish E");
+        mMockRilChannel.close();
+        log("finish X");
+        super.finish(resultCode, results);
+    }
+
+    private void log(String s) {
+        Log.e("TelephonyMockRilTestRunner", s);
+    }
+}
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/mockril/MockRilTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/mockril/MockRilTest.java
new file mode 100644
index 0000000..3149ee1
--- /dev/null
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/mockril/MockRilTest.java
@@ -0,0 +1,304 @@
+/*
+ * 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.android.internal.telephony.mockril;
+
+import android.util.Log;
+import android.test.InstrumentationTestCase;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import com.android.internal.communication.MsgHeader;
+import com.android.internal.communication.Msg;
+import com.android.internal.telephony.RilChannel;
+import com.android.internal.telephony.ril_proto.RilCtrlCmds;
+import com.android.internal.telephony.ril_proto.RilCmds;
+
+import com.android.frameworks.telephonytests.TelephonyMockRilTestRunner;
+import com.google.protobuf.micro.InvalidProtocolBufferMicroException;
+
+// Test suite for test ril
+public class MockRilTest extends InstrumentationTestCase {
+    private static final String TAG = "MockRilTest";
+
+    RilChannel mMockRilChannel;
+    TelephonyMockRilTestRunner mRunner;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mRunner = (TelephonyMockRilTestRunner)getInstrumentation();
+        mMockRilChannel = mRunner.mMockRilChannel;
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    static void log(String s) {
+        Log.v(TAG, s);
+    }
+
+    /**
+     * Test Case 1: Test protobuf serialization and deserialization
+     * @throws InvalidProtocolBufferMicroException
+     */
+    public void testProtobufSerDes() throws InvalidProtocolBufferMicroException {
+        log("testProtobufSerdes E");
+
+        RilCtrlCmds.CtrlRspRadioState rs = new RilCtrlCmds.CtrlRspRadioState();
+        assertTrue(String.format("expected rs.state == 0 was %d", rs.getState()),
+                rs.getState() == 0);
+        rs.setState(1);
+        assertTrue(String.format("expected rs.state == 1 was %d", rs.getState()),
+                rs.getState() == 1);
+
+        byte[] rs_ser = rs.toByteArray();
+        RilCtrlCmds.CtrlRspRadioState rsNew = RilCtrlCmds.CtrlRspRadioState.parseFrom(rs_ser);
+        assertTrue(String.format("expected rsNew.state == 1 was %d", rs.getState()),
+                rs.getState() == 1);
+
+        log("testProtobufSerdes X");
+    }
+
+    /**
+     * Test case 2: Test echo command works using writeMsg & readMsg
+     */
+    public void testEchoMsg() throws IOException {
+        log("testEchoMsg E");
+
+        MsgHeader mh = new MsgHeader();
+        mh.setCmd(0);
+        mh.setToken(1);
+        mh.setStatus(2);
+        ByteBuffer data = ByteBuffer.allocate(3);
+        data.put((byte)3);
+        data.put((byte)4);
+        data.put((byte)5);
+        Msg.send(mMockRilChannel, mh, data);
+
+        Msg respMsg = Msg.recv(mMockRilChannel);
+        assertTrue(String.format("expected mhd.header.cmd == 0 was %d",respMsg.getCmd()),
+                respMsg.getCmd() == 0);
+        assertTrue(String.format("expected mhd.header.token == 1 was %d",respMsg.getToken()),
+                respMsg.getToken() == 1);
+        assertTrue(String.format("expected mhd.header.status == 2 was %d", respMsg.getStatus()),
+                respMsg.getStatus() == 2);
+        assertTrue(String.format("expected mhd.data[0] == 3 was %d", respMsg.getData(0)),
+                respMsg.getData(0) == 3);
+        assertTrue(String.format("expected mhd.data[1] == 4 was %d", respMsg.getData(1)),
+                respMsg.getData(1) == 4);
+        assertTrue(String.format("expected mhd.data[2] == 5 was %d", respMsg.getData(2)),
+                respMsg.getData(2) == 5);
+
+        log("testEchoMsg X");
+    }
+
+    /**
+     * Test case 3: Test get as
+     */
+    public void testGetAs() {
+        log("testGetAs E");
+
+        // Use a message header as the protobuf data content
+        MsgHeader mh = new MsgHeader();
+        mh.setCmd(12345);
+        mh.setToken(9876);
+        mh.setStatus(7654);
+        mh.setLengthData(4321);
+        byte[] data = mh.toByteArray();
+        MsgHeader mhResult = Msg.getAs(MsgHeader.class, data);
+
+        assertTrue(String.format("expected cmd == 12345 was %d", mhResult.getCmd()),
+                mhResult.getCmd() == 12345);
+        assertTrue(String.format("expected token == 9876 was %d", mhResult.getToken()),
+                mhResult.getToken() == 9876);
+        assertTrue(String.format("expected status == 7654 was %d", mhResult.getStatus()),
+                mhResult.getStatus() == 7654);
+        assertTrue(String.format("expected lengthData == 4321 was %d", mhResult.getLengthData()),
+                mhResult.getLengthData() == 4321);
+
+        Msg msg = Msg.obtain();
+        msg.setData(ByteBuffer.wrap(data));
+
+        mhResult = msg.getDataAs(MsgHeader.class);
+
+        assertTrue(String.format("expected cmd == 12345 was %d", mhResult.getCmd()),
+                mhResult.getCmd() == 12345);
+        assertTrue(String.format("expected token == 9876 was %d", mhResult.getToken()),
+                mhResult.getToken() == 9876);
+        assertTrue(String.format("expected status == 7654 was %d", mhResult.getStatus()),
+                mhResult.getStatus() == 7654);
+        assertTrue(String.format("expected lengthData == 4321 was %d", mhResult.getLengthData()),
+                mhResult.getLengthData() == 4321);
+
+        log("testGetAs X");
+    }
+
+    /**
+     * Test case 3: test get radio state
+     */
+    public void testGetRadioState() throws IOException {
+        log("testGetRadioState E");
+
+        Msg.send(mMockRilChannel, 1, 9876, 0, null);
+
+        Msg resp = Msg.recv(mMockRilChannel);
+        //resp.printHeader("testGetRadioState");
+
+        assertTrue(String.format("expected cmd == 1 was %d", resp.getCmd()),
+                resp.getCmd() == 1);
+        assertTrue(String.format("expected token == 9876 was %d", resp.getToken()),
+                resp.getToken() == 9876);
+        assertTrue(String.format("expected status == 0 was %d", resp.getStatus()),
+                resp.getStatus() == 0);
+
+        RilCtrlCmds.CtrlRspRadioState rsp = resp.getDataAs(RilCtrlCmds.CtrlRspRadioState.class);
+
+        int state = rsp.getState();
+        log("testGetRadioState state=" + state);
+        assertTrue(String.format("expected RadioState >= 0 && RadioState <= 9 was %d", state),
+                ((state >= 0) && (state <= 9)));
+
+        log("testGetRadioState X");
+    }
+
+    /**
+     * Test case 5: test set radio state
+     */
+    public void testSetRadioState() throws IOException {
+        log("testSetRadioState E");
+
+        RilCtrlCmds.CtrlReqRadioState cmdrs = new RilCtrlCmds.CtrlReqRadioState();
+        assertEquals(0, cmdrs.getState());
+
+        cmdrs.setState(RilCmds.RADIOSTATE_SIM_NOT_READY);
+        assertEquals(2, cmdrs.getState());
+
+        Msg.send(mMockRilChannel, RilCtrlCmds.CTRL_CMD_SET_RADIO_STATE, 0, 0, cmdrs);
+
+        Msg resp = Msg.recv(mMockRilChannel);
+        log("get response status :" + resp.getStatus());
+        log("get response for command: " + resp.getCmd());
+        log("get command token: " + resp.getToken());
+
+        RilCtrlCmds.CtrlRspRadioState rsp = resp.getDataAs(RilCtrlCmds.CtrlRspRadioState.class);
+
+        int state = rsp.getState();
+        log("get response for testSetRadioState: " + state);
+        assertTrue(RilCmds.RADIOSTATE_SIM_NOT_READY == state);
+    }
+
+    /**
+     * Test case 6: test start incoming call and hangup it.
+     */
+    public void testStartIncomingCallAndHangup() throws IOException {
+        log("testStartIncomingCallAndHangup");
+        RilCtrlCmds.CtrlReqSetMTCall cmd = new RilCtrlCmds.CtrlReqSetMTCall();
+        String incomingCall = "6502889108";
+        // set the MT call
+        cmd.setPhoneNumber(incomingCall);
+        Msg.send(mMockRilChannel, RilCtrlCmds.CTRL_CMD_SET_MT_CALL, 0, 0, cmd);
+        // get response
+        Msg resp = Msg.recv(mMockRilChannel);
+        log("Get response status: " + resp.getStatus());
+        assertTrue("The ril is not in a proper state to set MT calls.",
+                   resp.getStatus() == RilCtrlCmds.CTRL_STATUS_OK);
+
+        // allow the incoming call alerting for some time
+        try {
+            Thread.sleep(5000);
+        } catch (InterruptedException e) {}
+
+        // we are playing a trick to assume the current is 1
+        RilCtrlCmds.CtrlHangupConnRemote hangupCmd = new RilCtrlCmds.CtrlHangupConnRemote();
+        hangupCmd.setConnectionId(1);
+        hangupCmd.setCallFailCause(16);   // normal hangup
+        Msg.send(mMockRilChannel, RilCtrlCmds.CTRL_CMD_HANGUP_CONN_REMOTE, 0, 0, hangupCmd);
+
+        // get response
+        resp = Msg.recv(mMockRilChannel);
+        log("Get response for hangup connection: " + resp.getStatus());
+        assertTrue("CTRL_CMD_HANGUP_CONN_REMOTE failed",
+                   resp.getStatus() == RilCtrlCmds.CTRL_STATUS_OK);
+    }
+
+    /**
+     * Test case 7: test set call transition flag
+     */
+    public void testSetCallTransitionFlag() throws IOException {
+        log("testSetCallTransitionFlag");
+        // Set flag to true:
+        RilCtrlCmds.CtrlSetCallTransitionFlag cmd = new RilCtrlCmds.CtrlSetCallTransitionFlag();
+        cmd.setFlag(true);
+        Msg.send(mMockRilChannel, RilCtrlCmds.CTRL_CMD_SET_CALL_TRANSITION_FLAG, 0, 0, cmd);
+
+        Msg resp = Msg.recv(mMockRilChannel);
+        log("Get response status: " + resp.getStatus());
+        assertTrue("Set call transition flag failed",
+                   resp.getStatus() == RilCtrlCmds.CTRL_STATUS_OK);
+
+        // add a dialing call
+        RilCtrlCmds.CtrlReqAddDialingCall cmdDialCall = new RilCtrlCmds.CtrlReqAddDialingCall();
+        String phoneNumber = "5102345678";
+        cmdDialCall.setPhoneNumber(phoneNumber);
+        Msg.send(mMockRilChannel, RilCtrlCmds.CTRL_CMD_ADD_DIALING_CALL, 0, 0, cmdDialCall);
+        resp = Msg.recv(mMockRilChannel);
+        log("Get response status for adding a dialing call: " + resp.getStatus());
+        assertTrue("add dialing call failed",
+                   resp.getStatus() == RilCtrlCmds.CTRL_STATUS_OK);
+        try {
+            Thread.sleep(5000);
+        } catch (InterruptedException e) {}
+
+        // send command to force call state change
+        Msg.send(mMockRilChannel, RilCtrlCmds.CTRL_CMD_SET_CALL_ALERT, 0, 0, null);
+        resp = Msg.recv(mMockRilChannel);
+        log("Get response status: " + resp.getStatus());
+        assertTrue("Set call alert failed",
+                   resp.getStatus() == RilCtrlCmds.CTRL_STATUS_OK);
+
+        try {
+            Thread.sleep(2000);
+        } catch (InterruptedException e) {}
+
+        // send command to force call state change
+        Msg.send(mMockRilChannel, RilCtrlCmds.CTRL_CMD_SET_CALL_ACTIVE, 0, 0, null);
+        resp = Msg.recv(mMockRilChannel);
+        log("Get response status: " + resp.getStatus());
+        assertTrue("Set call active failed",
+                   resp.getStatus() == RilCtrlCmds.CTRL_STATUS_OK);
+
+        // hangup the active all remotely
+        RilCtrlCmds.CtrlHangupConnRemote hangupCmd = new RilCtrlCmds.CtrlHangupConnRemote();
+        hangupCmd.setConnectionId(1);
+        hangupCmd.setCallFailCause(16);   // normal hangup
+        Msg.send(mMockRilChannel, RilCtrlCmds.CTRL_CMD_HANGUP_CONN_REMOTE, 0, 0, hangupCmd);
+        resp = Msg.recv(mMockRilChannel);
+        log("Get response for hangup connection: " + resp.getStatus());
+        assertTrue("CTRL_CMD_HANGUP_CONN_REMOTE failed",
+                   resp.getStatus() == RilCtrlCmds.CTRL_STATUS_OK);
+
+        // set the flag to false
+        cmd.setFlag(false);
+        Msg.send(mMockRilChannel, RilCtrlCmds.CTRL_CMD_SET_CALL_TRANSITION_FLAG, 0, 0, cmd);
+        resp = Msg.recv(mMockRilChannel);
+        assertTrue("Set call transition flag failed",
+                   resp.getStatus() == RilCtrlCmds.CTRL_STATUS_OK);
+    }
+}
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/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 9c5fcda2..c8ba904 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -835,7 +835,9 @@
     bool hasErrors = false;
 
     if (drawables != NULL) {
-        err = preProcessImages(bundle, assets, drawables);
+        if (bundle->getOutputAPKFile() != NULL) {
+            err = preProcessImages(bundle, assets, drawables);
+        }
         if (err == NO_ERROR) {
             err = makeFileResources(bundle, assets, &table, drawables, "drawable");
             if (err != NO_ERROR) {
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/android/net/sip/SipAudioCall.java b/voip/java/android/net/sip/SipAudioCall.java
index c23da20..f55bade 100644
--- a/voip/java/android/net/sip/SipAudioCall.java
+++ b/voip/java/android/net/sip/SipAudioCall.java
@@ -43,9 +43,11 @@
 import java.util.Map;
 
 /**
- * Class that handles an audio call over SIP.
+ * Class that handles an Internet audio call over SIP. {@link SipManager}
+ * facilitates instantiating a {@code SipAudioCall} object for making/receiving
+ * calls. See {@link SipManager#makeAudioCall} and
+ * {@link SipManager#takeAudioCall}.
  */
-/** @hide */
 public class SipAudioCall {
     private static final String TAG = SipAudioCall.class.getSimpleName();
     private static final boolean RELEASE_SOCKET = true;
@@ -56,7 +58,7 @@
     public static class Listener {
         /**
          * Called when the call object is ready to make another call.
-         * The default implementation calls {@link #onChange}.
+         * The default implementation calls {@link #onChanged}.
          *
          * @param call the call object that is ready to make another call
          */
@@ -66,7 +68,7 @@
 
         /**
          * Called when a request is sent out to initiate a new call.
-         * The default implementation calls {@link #onChange}.
+         * The default implementation calls {@link #onChanged}.
          *
          * @param call the call object that carries out the audio call
          */
@@ -76,7 +78,7 @@
 
         /**
          * Called when a new call comes in.
-         * The default implementation calls {@link #onChange}.
+         * The default implementation calls {@link #onChanged}.
          *
          * @param call the call object that carries out the audio call
          * @param caller the SIP profile of the caller
@@ -87,7 +89,7 @@
 
         /**
          * Called when a RINGING response is received for the INVITE request
-         * sent. The default implementation calls {@link #onChange}.
+         * sent. The default implementation calls {@link #onChanged}.
          *
          * @param call the call object that carries out the audio call
          */
@@ -97,7 +99,7 @@
 
         /**
          * Called when the session is established.
-         * The default implementation calls {@link #onChange}.
+         * The default implementation calls {@link #onChanged}.
          *
          * @param call the call object that carries out the audio call
          */
@@ -107,7 +109,7 @@
 
         /**
          * Called when the session is terminated.
-         * The default implementation calls {@link #onChange}.
+         * The default implementation calls {@link #onChanged}.
          *
          * @param call the call object that carries out the audio call
          */
@@ -117,7 +119,7 @@
 
         /**
          * Called when the peer is busy during session initialization.
-         * The default implementation calls {@link #onChange}.
+         * The default implementation calls {@link #onChanged}.
          *
          * @param call the call object that carries out the audio call
          */
@@ -127,7 +129,7 @@
 
         /**
          * Called when the call is on hold.
-         * The default implementation calls {@link #onChange}.
+         * The default implementation calls {@link #onChanged}.
          *
          * @param call the call object that carries out the audio call
          */
@@ -257,8 +259,10 @@
      *
      * @return true if the call is established
      */
-    public synchronized boolean isInCall() {
-        return mInCall;
+    public boolean isInCall() {
+        synchronized (this) {
+            return mInCall;
+        }
     }
 
     /**
@@ -266,8 +270,10 @@
      *
      * @return true if the call is on hold
      */
-    public synchronized boolean isOnHold() {
-        return mHold;
+    public boolean isOnHold() {
+        synchronized (this) {
+            return mHold;
+        }
     }
 
     /**
@@ -299,8 +305,10 @@
      *
      * @return the local SIP profile
      */
-    public synchronized SipProfile getLocalProfile() {
-        return mLocalProfile;
+    public SipProfile getLocalProfile() {
+        synchronized (this) {
+            return mLocalProfile;
+        }
     }
 
     /**
@@ -308,8 +316,10 @@
      *
      * @return the peer's SIP profile
      */
-    public synchronized SipProfile getPeerProfile() {
-        return (mSipSession == null) ? null : mSipSession.getPeerProfile();
+    public SipProfile getPeerProfile() {
+        synchronized (this) {
+            return (mSipSession == null) ? null : mSipSession.getPeerProfile();
+        }
     }
 
     /**
@@ -318,9 +328,11 @@
      *
      * @return the session state
      */
-    public synchronized int getState() {
-        if (mSipSession == null) return SipSession.State.READY_TO_CALL;
-        return mSipSession.getState();
+    public int getState() {
+        synchronized (this) {
+            if (mSipSession == null) return SipSession.State.READY_TO_CALL;
+            return mSipSession.getState();
+        }
     }
 
 
@@ -330,8 +342,10 @@
      * @return the session object that carries this call
      * @hide
      */
-    public synchronized SipSession getSipSession() {
-        return mSipSession;
+    public SipSession getSipSession() {
+        synchronized (this) {
+            return mSipSession;
+        }
     }
 
     private SipSession.Listener createListener() {
@@ -364,22 +378,25 @@
             }
 
             @Override
-            public synchronized void onRinging(SipSession session,
+            public void onRinging(SipSession session,
                     SipProfile peerProfile, String sessionDescription) {
-                if ((mSipSession == null) || !mInCall
-                        || !session.getCallId().equals(mSipSession.getCallId())) {
-                    // should not happen
-                    session.endCall();
-                    return;
-                }
+                synchronized (SipAudioCall.this) {
+                    if ((mSipSession == null) || !mInCall
+                            || !session.getCallId().equals(
+                                    mSipSession.getCallId())) {
+                        // should not happen
+                        session.endCall();
+                        return;
+                    }
 
-                // session changing request
-                try {
-                    String answer = createAnswer(sessionDescription).encode();
-                    mSipSession.answerCall(answer, SESSION_TIMEOUT);
-                } catch (Throwable e) {
-                    Log.e(TAG, "onRinging()", e);
-                    session.endCall();
+                    // session changing request
+                    try {
+                        String answer = createAnswer(sessionDescription).encode();
+                        mSipSession.answerCall(answer, SESSION_TIMEOUT);
+                    } catch (Throwable e) {
+                        Log.e(TAG, "onRinging()", e);
+                        session.endCall();
+                    }
                 }
             }
 
@@ -508,18 +525,22 @@
      * @throws SipException if the SIP service fails to attach this object to
      *        the session
      */
-    public synchronized void attachCall(SipSession session,
-            String sessionDescription) throws SipException {
-        mSipSession = session;
-        mPeerSd = sessionDescription;
-        Log.v(TAG, "attachCall()" + mPeerSd);
-        try {
-            session.setListener(createListener());
+    public void attachCall(SipSession session, String sessionDescription)
+            throws SipException {
+        synchronized (this) {
+            mSipSession = session;
+            mPeerSd = sessionDescription;
+            Log.v(TAG, "attachCall()" + mPeerSd);
+            try {
+                session.setListener(createListener());
 
-            if (getState() == SipSession.State.INCOMING_CALL) startRinging();
-        } catch (Throwable e) {
-            Log.e(TAG, "attachCall()", e);
-            throwSipException(e);
+                if (getState() == SipSession.State.INCOMING_CALL) {
+                    startRinging();
+                }
+            } catch (Throwable e) {
+                Log.e(TAG, "attachCall()", e);
+                throwSipException(e);
+            }
         }
     }
 
@@ -529,7 +550,7 @@
      * and {@code Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
      * will be called.
      *
-     * @param callee the SIP profile to make the call to
+     * @param peerProfile the SIP profile to make the call to
      * @param sipSession the {@link SipSession} for carrying out the call
      * @param timeout the timeout value in seconds. Default value (defined by
      *        SIP protocol) is used if {@code timeout} is zero or negative.
@@ -537,15 +558,19 @@
      * @throws SipException if the SIP service fails to create a session for the
      *        call
      */
-    public synchronized void makeCall(SipProfile peerProfile,
-            SipSession sipSession, int timeout) throws SipException {
-        mSipSession = sipSession;
-        try {
-            mAudioStream = new AudioStream(InetAddress.getByName(getLocalIp()));
-            sipSession.setListener(createListener());
-            sipSession.makeCall(peerProfile, createOffer().encode(), timeout);
-        } catch (IOException e) {
-            throw new SipException("makeCall()", e);
+    public void makeCall(SipProfile peerProfile, SipSession sipSession,
+            int timeout) throws SipException {
+        synchronized (this) {
+            mSipSession = sipSession;
+            try {
+                mAudioStream = new AudioStream(InetAddress.getByName(
+                        getLocalIp()));
+                sipSession.setListener(createListener());
+                sipSession.makeCall(peerProfile, createOffer().encode(),
+                        timeout);
+            } catch (IOException e) {
+                throw new SipException("makeCall()", e);
+            }
         }
     }
 
@@ -553,13 +578,15 @@
      * Ends a call.
      * @throws SipException if the SIP service fails to end the call
      */
-    public synchronized void endCall() throws SipException {
-        stopRinging();
-        stopCall(RELEASE_SOCKET);
-        mInCall = false;
+    public void endCall() throws SipException {
+        synchronized (this) {
+            stopRinging();
+            stopCall(RELEASE_SOCKET);
+            mInCall = false;
 
-        // perform the above local ops first and then network op
-        if (mSipSession != null) mSipSession.endCall();
+            // perform the above local ops first and then network op
+            if (mSipSession != null) mSipSession.endCall();
+        }
     }
 
     /**
@@ -574,13 +601,15 @@
      * @see Listener.onError
      * @throws SipException if the SIP service fails to hold the call
      */
-    public synchronized void holdCall(int timeout) throws SipException {
+    public void holdCall(int timeout) throws SipException {
+        synchronized (this) {
         if (mHold) return;
-        mSipSession.changeCall(createHoldOffer().encode(), timeout);
-        mHold = true;
+            mSipSession.changeCall(createHoldOffer().encode(), timeout);
+            mHold = true;
 
-        AudioGroup audioGroup = getAudioGroup();
-        if (audioGroup != null) audioGroup.setMode(AudioGroup.MODE_ON_HOLD);
+            AudioGroup audioGroup = getAudioGroup();
+            if (audioGroup != null) audioGroup.setMode(AudioGroup.MODE_ON_HOLD);
+        }
     }
 
     /**
@@ -594,13 +623,16 @@
      * @see Listener.onError
      * @throws SipException if the SIP service fails to answer the call
      */
-    public synchronized void answerCall(int timeout) throws SipException {
-        stopRinging();
-        try {
-            mAudioStream = new AudioStream(InetAddress.getByName(getLocalIp()));
-            mSipSession.answerCall(createAnswer(mPeerSd).encode(), timeout);
-        } catch (IOException e) {
-            throw new SipException("answerCall()", e);
+    public void answerCall(int timeout) throws SipException {
+        synchronized (this) {
+            stopRinging();
+            try {
+                mAudioStream = new AudioStream(InetAddress.getByName(
+                        getLocalIp()));
+                mSipSession.answerCall(createAnswer(mPeerSd).encode(), timeout);
+            } catch (IOException e) {
+                throw new SipException("answerCall()", e);
+            }
         }
     }
 
@@ -616,12 +648,14 @@
      * @see Listener.onError
      * @throws SipException if the SIP service fails to unhold the call
      */
-    public synchronized void continueCall(int timeout) throws SipException {
-        if (!mHold) return;
-        mSipSession.changeCall(createContinueOffer().encode(), timeout);
-        mHold = false;
-        AudioGroup audioGroup = getAudioGroup();
-        if (audioGroup != null) audioGroup.setMode(AudioGroup.MODE_NORMAL);
+    public void continueCall(int timeout) throws SipException {
+        synchronized (this) {
+            if (!mHold) return;
+            mSipSession.changeCall(createContinueOffer().encode(), timeout);
+            mHold = false;
+            AudioGroup audioGroup = getAudioGroup();
+            if (audioGroup != null) audioGroup.setMode(AudioGroup.MODE_NORMAL);
+        }
     }
 
     private SimpleSessionDescription createOffer() {
@@ -739,12 +773,15 @@
     }
 
     /** Toggles mute. */
-    public synchronized void toggleMute() {
-        AudioGroup audioGroup = getAudioGroup();
-        if (audioGroup != null) {
-            audioGroup.setMode(
-                    mMuted ? AudioGroup.MODE_NORMAL : AudioGroup.MODE_MUTED);
-            mMuted = !mMuted;
+    public void toggleMute() {
+        synchronized (this) {
+            AudioGroup audioGroup = getAudioGroup();
+            if (audioGroup != null) {
+                audioGroup.setMode(mMuted
+                        ? AudioGroup.MODE_NORMAL
+                        : AudioGroup.MODE_MUTED);
+                mMuted = !mMuted;
+            }
         }
     }
 
@@ -753,14 +790,18 @@
      *
      * @return true if the call is muted
      */
-    public synchronized boolean isMuted() {
-        return mMuted;
+    public boolean isMuted() {
+        synchronized (this) {
+            return mMuted;
+        }
     }
 
     /** Puts the device to speaker mode. */
-    public synchronized void setSpeakerMode(boolean speakerMode) {
-        ((AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE))
-                .setSpeakerphoneOn(speakerMode);
+    public void setSpeakerMode(boolean speakerMode) {
+        synchronized (this) {
+            ((AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE))
+                    .setSpeakerphoneOn(speakerMode);
+        }
     }
 
     /**
@@ -785,14 +826,16 @@
      *        inputs.
      * @param result the result message to send when done
      */
-    public synchronized void sendDtmf(int code, Message result) {
-        AudioGroup audioGroup = getAudioGroup();
-        if ((audioGroup != null) && (mSipSession != null)
-                && (SipSession.State.IN_CALL == getState())) {
-            Log.v(TAG, "send DTMF: " + code);
-            audioGroup.sendDtmf(code);
+    public void sendDtmf(int code, Message result) {
+        synchronized (this) {
+            AudioGroup audioGroup = getAudioGroup();
+            if ((audioGroup != null) && (mSipSession != null)
+                    && (SipSession.State.IN_CALL == getState())) {
+                Log.v(TAG, "send DTMF: " + code);
+                audioGroup.sendDtmf(code);
+            }
+            if (result != null) result.sendToTarget();
         }
-        if (result != null) result.sendToTarget();
     }
 
     /**
@@ -806,8 +849,10 @@
      *      yet been set up
      * @hide
      */
-    public synchronized AudioStream getAudioStream() {
-        return mAudioStream;
+    public AudioStream getAudioStream() {
+        synchronized (this) {
+            return mAudioStream;
+        }
     }
 
     /**
@@ -824,9 +869,11 @@
      * @see #getAudioStream
      * @hide
      */
-    public synchronized AudioGroup getAudioGroup() {
-        if (mAudioGroup != null) return mAudioGroup;
-        return ((mAudioStream == null) ? null : mAudioStream.getGroup());
+    public AudioGroup getAudioGroup() {
+        synchronized (this) {
+            if (mAudioGroup != null) return mAudioGroup;
+            return ((mAudioStream == null) ? null : mAudioStream.getGroup());
+        }
     }
 
     /**
@@ -837,11 +884,13 @@
      * @see #getAudioStream
      * @hide
      */
-    public synchronized void setAudioGroup(AudioGroup group) {
-        if ((mAudioStream != null) && (mAudioStream.getGroup() != null)) {
-            mAudioStream.join(group);
+    public void setAudioGroup(AudioGroup group) {
+        synchronized (this) {
+            if ((mAudioStream != null) && (mAudioStream.getGroup() != null)) {
+                mAudioStream.join(group);
+            }
+            mAudioGroup = group;
         }
-        mAudioGroup = group;
     }
 
     /**
@@ -981,8 +1030,10 @@
      *
      * @param enabled true to enable; false to disable
      */
-    public synchronized void setRingbackToneEnabled(boolean enabled) {
-        mRingbackToneEnabled = enabled;
+    public void setRingbackToneEnabled(boolean enabled) {
+        synchronized (this) {
+            mRingbackToneEnabled = enabled;
+        }
     }
 
     /**
@@ -990,8 +1041,10 @@
      *
      * @param enabled true to enable; false to disable
      */
-    public synchronized void setRingtoneEnabled(boolean enabled) {
-        mRingtoneEnabled = enabled;
+    public void setRingtoneEnabled(boolean enabled) {
+        synchronized (this) {
+            mRingtoneEnabled = enabled;
+        }
     }
 
     private void startRingbackTone() {
diff --git a/voip/java/android/net/sip/SipErrorCode.java b/voip/java/android/net/sip/SipErrorCode.java
index a55ab25..6aee5f1 100644
--- a/voip/java/android/net/sip/SipErrorCode.java
+++ b/voip/java/android/net/sip/SipErrorCode.java
@@ -19,10 +19,9 @@
 /**
  * Defines error code returned in
  * {@link SipRegistrationListener#onRegistrationFailed},
- * {@link ISipSessionListener#onError},
- * {@link ISipSessionListener#onCallChangeFailed} and
- * {@link ISipSessionListener#onRegistrationFailed}.
- * @hide
+ * {@link SipSession.Listener#onError},
+ * {@link SipSession.Listener#onCallChangeFailed} and
+ * {@link SipSession.Listener#onRegistrationFailed}.
  */
 public class SipErrorCode {
     /** Not an error. */
diff --git a/voip/java/android/net/sip/SipException.java b/voip/java/android/net/sip/SipException.java
index f0d846b..225b94f 100644
--- a/voip/java/android/net/sip/SipException.java
+++ b/voip/java/android/net/sip/SipException.java
@@ -18,7 +18,6 @@
 
 /**
  * General SIP-related exception class.
- * @hide
  */
 public class SipException extends Exception {
     public SipException() {
diff --git a/voip/java/android/net/sip/SipManager.java b/voip/java/android/net/sip/SipManager.java
index 8c32aa0..ee0e3cd 100644
--- a/voip/java/android/net/sip/SipManager.java
+++ b/voip/java/android/net/sip/SipManager.java
@@ -48,7 +48,8 @@
  * <li>process SIP events directly with a {@link SipSession} created by
  *      {@link #createSipSession}.</li>
  * </ul>
- * @hide
+ * {@code SipManager} can only be instantiated if SIP API is supported by the
+ * device. (See {@link #isApiSupported}).
  */
 public class SipManager {
     /**
@@ -58,10 +59,17 @@
      */
     public static final int INCOMING_CALL_RESULT_CODE = 101;
 
-    /** Part of the incoming call intent. */
+    /**
+     * Key to retrieve the call ID from an incoming call intent.
+     * @see #open(SipProfile, PendingIntent, SipRegistrationListener)
+     */
     public static final String EXTRA_CALL_ID = "android:sipCallID";
 
-    /** Part of the incoming call intent. */
+    /**
+     * Key to retrieve the offered session description from an incoming call
+     * intent.
+     * @see #open(SipProfile, PendingIntent, SipRegistrationListener)
+     */
     public static final String EXTRA_OFFER_SD = "android:sipOfferSD";
 
     /**
@@ -178,7 +186,11 @@
      * make subsequent calls through {@link #makeAudioCall}. If the
      * auto-registration option is enabled in the profile, the SIP service
      * will register the profile to the corresponding SIP provider periodically
-     * in order to receive calls from the provider.
+     * in order to receive calls from the provider. When the SIP service
+     * receives a new call, it will send out an intent with the provided action
+     * string. The intent contains a call ID extra and an offer session
+     * description string extra. Use {@link #getCallId} and
+     * {@link #getOfferSessionDescription} to retrieve those extras.
      *
      * @param localProfile the SIP profile to receive incoming calls for
      * @param incomingCallPendingIntent When an incoming call is received, the
@@ -194,6 +206,9 @@
      * @throws NullPointerException if {@code incomingCallPendingIntent} is null
      * @throws SipException if the profile contains incorrect settings or
      *      calling the SIP service results in an error
+     * @see #isIncomingCallIntent
+     * @see #getCallId
+     * @see #getOfferSessionDescription
      */
     public void open(SipProfile localProfile,
             PendingIntent incomingCallPendingIntent,
@@ -291,7 +306,8 @@
      * @param peerProfile the SIP profile to make the call to
      * @param listener to listen to the call events from {@link SipAudioCall};
      *      can be null
-     * @param timeout the timeout value in seconds
+     * @param timeout the timeout value in seconds. Default value (defined by
+     *        SIP protocol) is used if {@code timeout} is zero or negative.
      * @return a {@link SipAudioCall} object
      * @throws SipException if calling the SIP service results in an error
      * @see SipAudioCall.Listener.onError
@@ -321,7 +337,8 @@
      * @param peerProfileUri URI of the SIP profile to make the call to
      * @param listener to listen to the call events from {@link SipAudioCall};
      *      can be null
-     * @param timeout the timeout value in seconds
+     * @param timeout the timeout value in seconds. Default value (defined by
+     *        SIP protocol) is used if {@code timeout} is zero or negative.
      * @return a {@link SipAudioCall} object
      * @throws SipException if calling the SIP service results in an error
      * @see SipAudioCall.Listener.onError
@@ -489,7 +506,7 @@
     }
 
     /**
-     * Gets the {@link ISipSession} that handles the incoming call. For audio
+     * Gets the {@link SipSession} that handles the incoming call. For audio
      * calls, consider to use {@link SipAudioCall} to handle the incoming call.
      * See {@link #takeAudioCall}. Note that the method may be called only once
      * for the same intent. For subsequent calls on the same intent, the method
@@ -498,11 +515,12 @@
      * @param incomingCallIntent the incoming call broadcast intent
      * @return the session object that handles the incoming call
      */
-    public ISipSession getSessionFor(Intent incomingCallIntent)
+    public SipSession getSessionFor(Intent incomingCallIntent)
             throws SipException {
         try {
             String callId = getCallId(incomingCallIntent);
-            return mSipService.getPendingSession(callId);
+            ISipSession s = mSipService.getPendingSession(callId);
+            return new SipSession(s);
         } catch (RemoteException e) {
             throw new SipException("getSessionFor()", e);
         }
@@ -514,8 +532,8 @@
     }
 
     /**
-     * Creates a {@link ISipSession} with the specified profile. Use other
-     * methods, if applicable, instead of interacting with {@link ISipSession}
+     * Creates a {@link SipSession} with the specified profile. Use other
+     * methods, if applicable, instead of interacting with {@link SipSession}
      * directly.
      *
      * @param localProfile the SIP profile the session is associated with
diff --git a/voip/java/android/net/sip/SipProfile.java b/voip/java/android/net/sip/SipProfile.java
index 6d5cb3c..dddb07d 100644
--- a/voip/java/android/net/sip/SipProfile.java
+++ b/voip/java/android/net/sip/SipProfile.java
@@ -33,7 +33,6 @@
 
 /**
  * Class containing a SIP account, domain and server information.
- * @hide
  */
 public class SipProfile implements Parcelable, Serializable, Cloneable {
     private static final long serialVersionUID = 1L;
diff --git a/voip/java/android/net/sip/SipRegistrationListener.java b/voip/java/android/net/sip/SipRegistrationListener.java
index 37c9ce2..e1f35ad 100644
--- a/voip/java/android/net/sip/SipRegistrationListener.java
+++ b/voip/java/android/net/sip/SipRegistrationListener.java
@@ -18,7 +18,6 @@
 
 /**
  * Listener class to listen to SIP registration events.
- * @hide
  */
 public interface SipRegistrationListener {
     /**
diff --git a/voip/java/android/net/sip/SipSession.java b/voip/java/android/net/sip/SipSession.java
index 0cc7206..9c08e46 100644
--- a/voip/java/android/net/sip/SipSession.java
+++ b/voip/java/android/net/sip/SipSession.java
@@ -22,14 +22,12 @@
 /**
  * A SIP session that is associated with a SIP dialog or a standalone
  * transaction not within a dialog.
- * @hide
  */
 public final class SipSession {
     private static final String TAG = "SipSession";
 
     /**
      * Defines {@link SipSession} states.
-     * @hide
      */
     public static class State {
         /** When session is ready to initiate a call or transaction. */
@@ -101,7 +99,6 @@
 
     /**
      * Listener class that listens to {@link SipSession} events.
-     * @hide
      */
     public static class Listener {
         /**
@@ -281,7 +278,7 @@
 
     /**
      * Gets the session state. The value returned must be one of the states in
-     * {@link SipSessionState}.
+     * {@link State}.
      *
      * @return the session state
      */
@@ -339,7 +336,7 @@
      * Performs registration to the server specified by the associated local
      * profile. The session listener is called back upon success or failure of
      * registration. The method is only valid to call when the session state is
-     * in {@link SipSessionState#READY_TO_CALL}.
+     * in {@link State#READY_TO_CALL}.
      *
      * @param duration duration in second before the registration expires
      * @see Listener
@@ -357,7 +354,7 @@
      * profile. Unregistration is technically the same as registration with zero
      * expiration duration. The session listener is called back upon success or
      * failure of unregistration. The method is only valid to call when the
-     * session state is in {@link SipSessionState#READY_TO_CALL}.
+     * session state is in {@link State#READY_TO_CALL}.
      *
      * @see Listener
      */
@@ -372,7 +369,7 @@
     /**
      * Initiates a call to the specified profile. The session listener is called
      * back upon defined session events. The method is only valid to call when
-     * the session state is in {@link SipSessionState#READY_TO_CALL}.
+     * the session state is in {@link State#READY_TO_CALL}.
      *
      * @param callee the SIP profile to make the call to
      * @param sessionDescription the session description of this call
@@ -393,7 +390,7 @@
     /**
      * Answers an incoming call with the specified session description. The
      * method is only valid to call when the session state is in
-     * {@link SipSessionState#INCOMING_CALL}.
+     * {@link State#INCOMING_CALL}.
      *
      * @param sessionDescription the session description to answer this call
      * @param timeout the session will be timed out if the call is not
@@ -411,10 +408,10 @@
     /**
      * Ends an established call, terminates an outgoing call or rejects an
      * incoming call. The method is only valid to call when the session state is
-     * in {@link SipSessionState#IN_CALL},
-     * {@link SipSessionState#INCOMING_CALL},
-     * {@link SipSessionState#OUTGOING_CALL} or
-     * {@link SipSessionState#OUTGOING_CALL_RING_BACK}.
+     * in {@link State#IN_CALL},
+     * {@link State#INCOMING_CALL},
+     * {@link State#OUTGOING_CALL} or
+     * {@link State#OUTGOING_CALL_RING_BACK}.
      */
     public void endCall() {
         try {
@@ -426,7 +423,7 @@
 
     /**
      * Changes the session description during a call. The method is only valid
-     * to call when the session state is in {@link SipSessionState#IN_CALL}.
+     * to call when the session state is in {@link State#IN_CALL}.
      *
      * @param sessionDescription the new session description
      * @param timeout the session will be timed out if the call is not
diff --git a/voip/java/com/android/server/sip/SipHelper.java b/voip/java/com/android/server/sip/SipHelper.java
index 050eddc..2514262 100644
--- a/voip/java/com/android/server/sip/SipHelper.java
+++ b/voip/java/com/android/server/sip/SipHelper.java
@@ -238,6 +238,8 @@
         ClientTransaction tid = responseEvent.getClientTransaction();
         ClientTransaction ct = authenticationHelper.handleChallenge(
                 responseEvent.getResponse(), tid, mSipProvider, 5);
+        if (DEBUG) Log.d(TAG, "send request with challenge response: "
+                + ct.getRequest());
         ct.sendRequest();
         return ct;
     }
diff --git a/voip/java/com/android/server/sip/SipService.java b/voip/java/com/android/server/sip/SipService.java
index 1fa2400..1df08c0 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;
@@ -65,8 +66,8 @@
  * @hide
  */
 public final class SipService extends ISipService.Stub {
-    private static final String TAG = "SipService";
-    private static final boolean DEBUGV = false;
+    static final String TAG = "SipService";
+    static final boolean DEBUGV = false;
     private static final boolean DEBUG = true;
     private static final boolean DEBUG_TIMER = DEBUG && false;
     private static final int EXPIRY_TIME = 3600;
@@ -92,6 +93,8 @@
             new HashMap<String, ISipSession>();
 
     private ConnectivityReceiver mConnectivityReceiver;
+    private boolean mWifiEnabled;
+    private SipWakeLock mMyWakeLock;
 
     /**
      * Starts the SIP service. Do nothing if the SIP API is not supported on the
@@ -111,11 +114,38 @@
         mConnectivityReceiver = new ConnectivityReceiver();
         context.registerReceiver(mConnectivityReceiver,
                 new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
+        context.registerReceiver(mWifiStateReceiver,
+                new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION));
+        mMyWakeLock = new SipWakeLock((PowerManager)
+                context.getSystemService(Context.POWER_SERVICE));
 
         mTimer = new WakeupTimer(context);
         mWifiOnly = SipManager.isSipWifiOnly(context);
     }
 
+    BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            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;
+                    }
+                }
+            }
+        }
+    };
+
     private MyExecutor getExecutor() {
         // create mExecutor lazily
         if (mExecutor == null) mExecutor = new MyExecutor();
@@ -123,6 +153,8 @@
     }
 
     public synchronized SipProfile[] getListOfProfiles() {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.USE_SIP, null);
         boolean isCallerRadio = isCallerRadio();
         ArrayList<SipProfile> profiles = new ArrayList<SipProfile>();
         for (SipSessionGroupExt group : mSipGroups.values()) {
@@ -134,6 +166,8 @@
     }
 
     public void open(SipProfile localProfile) {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.USE_SIP, null);
         localProfile.setCallingUid(Binder.getCallingUid());
         try {
             createGroup(localProfile);
@@ -146,6 +180,8 @@
     public synchronized void open3(SipProfile localProfile,
             PendingIntent incomingCallPendingIntent,
             ISipSessionListener listener) {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.USE_SIP, null);
         localProfile.setCallingUid(Binder.getCallingUid());
         if (incomingCallPendingIntent == null) {
             Log.w(TAG, "incomingCallPendingIntent cannot be null; "
@@ -159,7 +195,7 @@
                     incomingCallPendingIntent, listener);
             if (localProfile.getAutoRegistration()) {
                 group.openToReceiveCalls();
-                if (isWifiOn()) grabWifiLock();
+                if (mWifiEnabled) grabWifiLock();
             }
         } catch (SipException e) {
             Log.e(TAG, "openToReceiveCalls()", e);
@@ -181,6 +217,8 @@
     }
 
     public synchronized void close(String localProfileUri) {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.USE_SIP, null);
         SipSessionGroupExt group = mSipGroups.get(localProfileUri);
         if (group == null) return;
         if (!isCallerCreatorOrRadio(group)) {
@@ -191,10 +229,16 @@
         group = mSipGroups.remove(localProfileUri);
         notifyProfileRemoved(group.getLocalProfile());
         group.close();
-        if (isWifiOn() && !anyOpened()) releaseWifiLock();
+
+        if (!anyOpened()) {
+            releaseWifiLock();
+            mMyWakeLock.reset(); // in case there's leak
+        }
     }
 
     public synchronized boolean isOpened(String localProfileUri) {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.USE_SIP, null);
         SipSessionGroupExt group = mSipGroups.get(localProfileUri);
         if (group == null) return false;
         if (isCallerCreatorOrRadio(group)) {
@@ -206,6 +250,8 @@
     }
 
     public synchronized boolean isRegistered(String localProfileUri) {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.USE_SIP, null);
         SipSessionGroupExt group = mSipGroups.get(localProfileUri);
         if (group == null) return false;
         if (isCallerCreatorOrRadio(group)) {
@@ -218,6 +264,8 @@
 
     public synchronized void setRegistrationListener(String localProfileUri,
             ISipSessionListener listener) {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.USE_SIP, null);
         SipSessionGroupExt group = mSipGroups.get(localProfileUri);
         if (group == null) return;
         if (isCallerCreator(group)) {
@@ -229,6 +277,8 @@
 
     public synchronized ISipSession createSession(SipProfile localProfile,
             ISipSessionListener listener) {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.USE_SIP, null);
         localProfile.setCallingUid(Binder.getCallingUid());
         if (!mConnected) return null;
         try {
@@ -241,6 +291,8 @@
     }
 
     public synchronized ISipSession getPendingSession(String callId) {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.USE_SIP, null);
         if (callId == null) return null;
         return mPendingSessions.get(callId);
     }
@@ -314,7 +366,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);
@@ -324,17 +376,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 isWifiOn() {
-        return "WIFI".equalsIgnoreCase(mNetworkType);
-        //return (mConnected && "WIFI".equalsIgnoreCase(mNetworkType));
-    }
-
     private synchronized void onConnectivityChanged(
             String type, boolean connected) {
         if (DEBUG) Log.d(TAG, "onConnectivityChanged(): "
@@ -348,11 +395,6 @@
         boolean isWifi = "WIFI".equalsIgnoreCase(type);
         boolean wifiOff = (isWifi && !connected) || (wasWifi && !sameType);
         boolean wifiOn = isWifi && connected;
-        if (wifiOff) {
-            releaseWifiLock();
-        } else if (wifiOn) {
-            if (anyOpened()) grabWifiLock();
-        }
 
         try {
             boolean wasConnected = mConnected;
@@ -371,8 +413,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);
         }
@@ -415,7 +458,8 @@
         private SipSessionGroup createSipSessionGroup(String localIp,
                 SipProfile localProfile, String password) throws SipException {
             try {
-                return new SipSessionGroup(localIp, localProfile, password);
+                return new SipSessionGroup(localIp, localProfile, password,
+                        mMyWakeLock);
             } catch (IOException e) {
                 // network disconnected
                 Log.w(TAG, "createSipSessionGroup(): network disconnected?");
@@ -502,6 +546,7 @@
         @Override
         public void onRinging(ISipSession s, SipProfile caller,
                 String sessionDescription) {
+            if (DEBUGV) Log.d(TAG, "<<<<< onRinging()");
             SipSessionGroup.SipSessionImpl session =
                     (SipSessionGroup.SipSessionImpl) s;
             synchronized (SipService.this) {
@@ -548,7 +593,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;
@@ -567,43 +612,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
@@ -634,6 +669,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());
@@ -643,8 +679,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) {
@@ -701,29 +740,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);
+                }
             }
         }
 
@@ -773,6 +801,7 @@
         private boolean notCurrentSession(ISipSession session) {
             if (session != mSession) {
                 ((SipSessionGroup.SipSessionImpl) session).setListener(null);
+                mMyWakeLock.release(session);
                 return true;
             }
             return !mRunning;
@@ -809,6 +838,7 @@
                             mKeepAliveProcess.start();
                         }
                     }
+                    mMyWakeLock.release(session);
                 } else {
                     mRegistered = false;
                     mExpiryTime = -1L;
@@ -831,6 +861,7 @@
                     case SipErrorCode.SERVER_UNREACHABLE:
                         if (DEBUG) Log.d(TAG, "   pause auto-registration");
                         stop();
+                        break;
                     default:
                         restartLater();
                 }
@@ -838,6 +869,7 @@
                 mErrorCode = errorCode;
                 mErrorMessage = message;
                 mProxy.onRegistrationFailed(session, errorCode, message);
+                mMyWakeLock.release(session);
             }
         }
 
@@ -850,6 +882,7 @@
                 mErrorCode = SipErrorCode.TIME_OUT;
                 mProxy.onRegistrationTimeout(session);
                 restartLater();
+                mMyWakeLock.release(session);
             }
         }
 
@@ -868,7 +901,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();
@@ -936,11 +978,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);
                 }
@@ -960,7 +1004,7 @@
             @Override
             public void run() {
                 // delegate to mExecutor
-                getExecutor().addTask(new Runnable() {
+                getExecutor().execute(new Runnable() {
                     public void run() {
                         realRun();
                     }
@@ -978,6 +1022,7 @@
                     if (DEBUG) Log.d(TAG, " deliver change for " + mNetworkType
                             + (mConnected ? " CONNECTED" : "DISCONNECTED"));
                     onConnectivityChanged(mNetworkType, mConnected);
+                    mMyWakeLock.release(this);
                 }
             }
         }
@@ -985,7 +1030,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.
@@ -1175,7 +1219,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)) {
@@ -1202,7 +1247,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;
@@ -1214,9 +1259,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");
@@ -1280,29 +1324,41 @@
         }
     }
 
-    // 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);
+            }
+        }
     }
 }
diff --git a/voip/java/com/android/server/sip/SipSessionGroup.java b/voip/java/com/android/server/sip/SipSessionGroup.java
index 57b3710..d861fa5 100644
--- a/voip/java/com/android/server/sip/SipSessionGroup.java
+++ b/voip/java/com/android/server/sip/SipSessionGroup.java
@@ -84,6 +84,7 @@
     private static final String ANONYMOUS = "anonymous";
     private static final int EXPIRY_TIME = 3600; // in seconds
     private static final int CANCEL_CALL_TIMER = 3; // in seconds
+    private static final long WAKE_LOCK_HOLDING_TIME = 500; // in milliseconds
 
     private static final EventObject DEREGISTER = new EventObject("Deregister");
     private static final EventObject END_CALL = new EventObject("End call");
@@ -101,6 +102,8 @@
     private SipSessionImpl mCallReceiverSession;
     private String mLocalIp;
 
+    private SipWakeLock mWakeLock;
+
     // call-id-to-SipSession map
     private Map<String, SipSessionImpl> mSessionMap =
             new HashMap<String, SipSessionImpl>();
@@ -110,10 +113,11 @@
      * @param password the password of the profile
      * @throws IOException if cannot assign requested address
      */
-    public SipSessionGroup(String localIp, SipProfile myself, String password)
-            throws SipException, IOException {
+    public SipSessionGroup(String localIp, SipProfile myself, String password,
+            SipWakeLock wakeLock) throws SipException, IOException {
         mLocalProfile = myself;
         mPassword = password;
+        mWakeLock = wakeLock;
         reset(localIp);
     }
 
@@ -153,7 +157,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");
         }
@@ -265,7 +275,14 @@
         }
     }
 
-    public void processRequest(RequestEvent event) {
+    public void processRequest(final RequestEvent event) {
+        if (isRequestEvent(Request.INVITE, event)) {
+            if (DEBUG) Log.d(TAG, "<<<<< got INVITE, thread:"
+                    + Thread.currentThread());
+            // Acquire a wake lock and keep it for WAKE_LOCK_HOLDING_TIME;
+            // should be large enough to bring up the app.
+            mWakeLock.acquire(WAKE_LOCK_HOLDING_TIME);
+        }
         process(event);
     }
 
@@ -541,8 +558,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/voip/java/com/android/server/sip/SipWakeLock.java b/voip/java/com/android/server/sip/SipWakeLock.java
new file mode 100644
index 0000000..52bc094
--- /dev/null
+++ b/voip/java/com/android/server/sip/SipWakeLock.java
@@ -0,0 +1,71 @@
+/*
+ * 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.android.server.sip;
+
+import android.os.PowerManager;
+import android.util.Log;
+
+import java.util.HashSet;
+
+class SipWakeLock {
+    private static final boolean DEBUGV = SipService.DEBUGV;
+    private static final String TAG = SipService.TAG;
+    private PowerManager mPowerManager;
+    private PowerManager.WakeLock mWakeLock;
+    private PowerManager.WakeLock mTimerWakeLock;
+    private HashSet<Object> mHolders = new HashSet<Object>();
+
+    SipWakeLock(PowerManager powerManager) {
+        mPowerManager = powerManager;
+    }
+
+    synchronized void reset() {
+        mHolders.clear();
+        release(null);
+        if (DEBUGV) Log.v(TAG, "~~~ hard reset wakelock");
+    }
+
+    synchronized void acquire(long timeout) {
+        if (mTimerWakeLock == null) {
+            mTimerWakeLock = mPowerManager.newWakeLock(
+                    PowerManager.PARTIAL_WAKE_LOCK, "SipWakeLock.timer");
+            mTimerWakeLock.setReferenceCounted(true);
+        }
+        mTimerWakeLock.acquire(timeout);
+    }
+
+    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/jni/rtp/EchoSuppressor.cpp b/voip/jni/rtp/EchoSuppressor.cpp
index a1a7aed..ad63cd6 100644
--- a/voip/jni/rtp/EchoSuppressor.cpp
+++ b/voip/jni/rtp/EchoSuppressor.cpp
@@ -157,11 +157,12 @@
     if (correlation > 0.3f) {
         float factor = 1.0f - correlation;
         factor *= factor;
+        factor /= 2.0; // suppress harder
         for (int i = 0; i < mSampleCount; ++i) {
             recorded[i] *= factor;
         }
     }
-//    LOGI("latency %5d, correlation %.10f", latency, correlation);
+    //LOGI("latency %5d, correlation %.10f", latency, correlation);
 
 
     // Increase RecordOffset.
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index 9d27bde..06f6696 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -862,15 +862,7 @@
                 mIsAnyNetworkDisabled.set(false);
                 requestConnectionInfo();
                 SupplicantState supplState = mWifiInfo.getSupplicantState();
-                /**
-                 * The MAC address isn't going to change, so just request it
-                 * once here.
-                 */
-                String macaddr = getMacAddress();
 
-                if (macaddr != null) {
-                    mWifiInfo.setMacAddress(macaddr);
-                }
                 if (LOCAL_LOGD) Log.v(TAG, "Connection to supplicant established, state=" +
                     supplState);
                 // Wi-Fi supplicant connection state changed:
@@ -1289,15 +1281,17 @@
                      */
                     setNumAllowedChannels();
                     synchronized (this) {
-                        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);
-                            }
+                        String macaddr = WifiNative.getMacAddressCommand();
+                        if (macaddr != null) {
+                            mWifiInfo.setMacAddress(macaddr);
+                        }
+                        mRunState = RUN_STATE_RUNNING;
+                        if (!mIsScanOnly) {
+                            reconnectCommand();
+                        } else {
+                            // In some situations, supplicant needs to be kickstarted to
+                            // start the background scanning
+                            scan(true);
                         }
                     }
                     break;
@@ -1617,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;
     }
@@ -2010,18 +2002,6 @@
     }
 
     /**
-     * Get MAC address of radio
-     *
-     * @return MAC address, null on failure
-     */
-    public synchronized String getMacAddress() {
-        if (mWifiState.get() != WIFI_STATE_ENABLED || isDriverStopped()) {
-            return null;
-        }
-        return WifiNative.getMacAddressCommand();
-    }
-
-    /**
      * Start driver
      *
      * @return {@code true} if the operation succeeds, {@code false} otherwise